Bug
Every interactive session start shows:
● Remote Control failed to connect: Session creation failed — see debug log
Following the prompt to "see debug log" leads to ~/.claude/debug/<session-id>.txt, which only contains Query.streamInput lines. No [bridge:*] entries are written to the session debug log on the at-startup failure path — so the actual cause (HTTP status, auth-state details) is unrecoverable from the user-visible logging path. The error tells you to look somewhere that has nothing useful.
Reproducible secondary symptom
In the same session, /remote-control immediately replies:
Remote Control requires a full-scope login token. Long-lived tokens (from `claude setup-token` or
CLAUDE_CODE_OAUTH_TOKEN) are limited to inference-only for security reasons. Run `claude auth login`
to use Remote Control.
…even though the credentials already contain the full scope set Claude Code's OAuth flow requests.
Investigation
Credentials are at the documented "full" set
After claude auth login (claude.ai flow), ~/.claude/.credentials.json contains:
scopes: user:file_upload, user:inference, user:mcp_servers, user:profile, user:sessions:claude_code
subscriptionType: max
expiresAt: <future, ~6h ahead>
refreshToken: <present>
Decompiling the binary (v2.1.133), the claude.ai flow's requested scope set is exactly these five:
gN$ = ["user:profile", "user:inference", "user:sessions:claude_code", "user:mcp_servers", "user:file_upload"]
There is no user:bridge, user:remote_control, or other "bridge" scope string anywhere in the binary. The user already has the maximum scope set the OAuth flow can grant. claude auth login cannot improve this.
Neither ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL, CLAUDE_CODE_OAUTH_TOKEN, nor any proxy var is set in the environment. The user is on Max plan (rateLimitTier: default_claude_max_20x).
claude remote-control (standalone) works fine with the same credentials
[bridge:api] POST /v1/environments/bridge -> 200 environment_id=env_*
[bridge:init] Created initial session session_*
[bridge:work] Starting poll loop
[bridge:api] GET .../work/poll -> 200
Server accepts the credentials and the bridge runs normally end-to-end.
So the /remote-control rejection looks like a client-side scope/state check disagreeing with the actual server entitlement
In getBridgeDisabledReason (I36 in the minified binary):
if(!eH8()) return "Remote Control requires a claude.ai subscription. Run `claude auth login`...";
if(!p97()) return "Remote Control requires a full-scope login token...";
eH8() = hasClaudeAIInferenceScope (passes — user:inference present).
p97() = hasProfileScope (calls W0(); reportedly fails despite user:profile being in scopes).
The "full-scope login token" wording is also misleading because the token is not long-lived — it has refreshToken and a near-future expiresAt, and was minted via claude auth login, not claude setup-token. The tengu_oauth_tokens_inference_only telemetry event is gated on !H.refreshToken || !H.expiresAt, so it shouldn't even fire here.
Asks
- Write
[bridge:*] log lines to the session debug log on the at-startup failure path — at minimum the line "see debug log" points at. Without it, the warning is undebuggable for users.
- Fix or refine the in-session scope check so it doesn't reject tokens that were just produced by
claude auth login and that the bridge endpoint itself accepts. If a client-side check is intended, it should match what the server accepts, or include getBridgeAuthDebugInfo output in the rejection message.
- Improve the "long-lived tokens" error wording — it implies
setup-token or CLAUDE_CODE_OAUTH_TOKEN is the only way to land in this state. With neither set, this dead-ends a user's debugging.
Environment
- Claude Code: 2.1.133 (Linux x86_64)
- Auth:
claude.ai, Max subscription
- No
ANTHROPIC_*, CLAUDE_CODE_OAUTH_TOKEN, or proxy env vars set
Repro
- Run
claude auth login, choose claude.ai.
- Verify scopes:
jq '.claudeAiOauth.scopes' ~/.claude/.credentials.json returns exactly the 5 scopes above.
- Start
claude interactively — observe the warning on the first lines.
- Run
/remote-control in-session — observe the "full-scope login token" rejection.
- Run
claude remote-control --verbose --debug-file /tmp/rc.log from a separate shell — observe successful registration and polling against the same credentials.
- Inspect the session's own debug log (
~/.claude/debug/<id>.txt) — note absence of any [bridge:*] lines despite the warning telling you to look there.
Bug
Every interactive session start shows:
Following the prompt to "see debug log" leads to
~/.claude/debug/<session-id>.txt, which only containsQuery.streamInputlines. No[bridge:*]entries are written to the session debug log on the at-startup failure path — so the actual cause (HTTP status, auth-state details) is unrecoverable from the user-visible logging path. The error tells you to look somewhere that has nothing useful.Reproducible secondary symptom
In the same session,
/remote-controlimmediately replies:…even though the credentials already contain the full scope set Claude Code's OAuth flow requests.
Investigation
Credentials are at the documented "full" set
After
claude auth login(claude.ai flow),~/.claude/.credentials.jsoncontains:Decompiling the binary (v2.1.133), the
claude.aiflow's requested scope set is exactly these five:There is no
user:bridge,user:remote_control, or other "bridge" scope string anywhere in the binary. The user already has the maximum scope set the OAuth flow can grant.claude auth logincannot improve this.Neither
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,ANTHROPIC_BASE_URL,CLAUDE_CODE_OAUTH_TOKEN, nor any proxy var is set in the environment. The user is on Max plan (rateLimitTier: default_claude_max_20x).claude remote-control(standalone) works fine with the same credentialsServer accepts the credentials and the bridge runs normally end-to-end.
So the
/remote-controlrejection looks like a client-side scope/state check disagreeing with the actual server entitlementIn
getBridgeDisabledReason(I36in the minified binary):eH8()=hasClaudeAIInferenceScope(passes —user:inferencepresent).p97()=hasProfileScope(callsW0(); reportedly fails despiteuser:profilebeing in scopes).The "full-scope login token" wording is also misleading because the token is not long-lived — it has
refreshTokenand a near-futureexpiresAt, and was minted viaclaude auth login, notclaude setup-token. Thetengu_oauth_tokens_inference_onlytelemetry event is gated on!H.refreshToken || !H.expiresAt, so it shouldn't even fire here.Asks
[bridge:*]log lines to the session debug log on the at-startup failure path — at minimum the line "see debug log" points at. Without it, the warning is undebuggable for users.claude auth loginand that the bridge endpoint itself accepts. If a client-side check is intended, it should match what the server accepts, or includegetBridgeAuthDebugInfooutput in the rejection message.setup-tokenorCLAUDE_CODE_OAUTH_TOKENis the only way to land in this state. With neither set, this dead-ends a user's debugging.Environment
claude.ai, Max subscriptionANTHROPIC_*,CLAUDE_CODE_OAUTH_TOKEN, or proxy env vars setRepro
claude auth login, choose claude.ai.jq '.claudeAiOauth.scopes' ~/.claude/.credentials.jsonreturns exactly the 5 scopes above.claudeinteractively — observe the warning on the first lines./remote-controlin-session — observe the "full-scope login token" rejection.claude remote-control --verbose --debug-file /tmp/rc.logfrom a separate shell — observe successful registration and polling against the same credentials.~/.claude/debug/<id>.txt) — note absence of any[bridge:*]lines despite the warning telling you to look there.