Repository navigation
fix(server): relay the Remote Control bridge with the client's own credential - #499
Merged
MagicalTux merged 2 commits intoOct 3, 2026
Conversation
…edential Claude Code 2.1.287 fixed `claude remote-control` failing to register behind an HTTP proxy (anthropics/claude-code#97352). With HTTPS_PROXY set to this proxy, the bridge's control calls now reach the request listener, where only /v1/code/ and /api/oauth/ kept the client's credential. The rest went out with a rotated fleet token. Observed on a live machine: - POST /v1/environments/bridge registered the machine under whichever account rotation picked: five organization ids, in round-robin order, over ~22 restarts in 4h. - Creating the session then answered 404. - The work poll drew a 401 from every account in turn. Its bearer is the environment secret that registration returned, not an OAuth token, so a fleet token in its place can only be refused; ack and heartbeat carry the work's session-ingress token the same way. The proxy logged 1286 "token rejected" lines in the 4h after the update, against 31 in the 24h before. - The daemon dropped ~5s after "Ready", retried for ~11 min and exited. The phone could not reach the machine. Add /v1/environments/, /v1/sessions/, /v2/session_ingress/ and /v2/ccr-sessions/ to CLIENT_CREDENTIAL_PATHS, the whole prefix as with /api/oauth/ in KarpelesLab#245. An entry ends in '/', so it stops at a segment boundary (/v1/sessionsX still rotates), and the entry without that slash, the collection itself, matches too: a session is created with a bare POST /v1/sessions, and the classified path carries no query string. The rule moves into isClientCredentialPath; it also takes the bare /v1/code and /api/oauth, which no client sends. The two /v1 prefixes also serve the public Managed Agents API. Its environments and sessions belong to the organization that created them, so rotation could not serve them across a multi-org pool; a client that calls it through the proxy now sends its own key, as on /api/oauth/*.
# Conflicts: # src/server.js
MagicalTux
added a commit
that referenced
this pull request
Oct 3, 2026
test/server-warmup-schedule.test.js carried its own bind-a-port-then-spawn harness, the shape #486 replaced everywhere else: it lost the port race to a neighbouring test on a loaded runner ("Port 39521 is already in use", node 20 on #499's run). It now uses test-helpers/spawn-server.js, which verifies the port by the child's pid and respawns on a lost race, and the one-second AbortSignal on the post-reload quota fetch is gone — the runner's timeout is the bound for a wedged endpoint. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Merged
MagicalTux
added a commit
that referenced
this pull request
Oct 4, 2026
Fifteen commits since 1.1.22. Two change what an existing install does without an opt-in (#514, #503); the rest is additive or display. Behaviour changes #514 the TUI quota-bar percentage (`quotaBarPercent`) is off unless set: a bar carries its countdown, and its fill is the percentage. The switch (g → Bar percentage) is unchanged; a config without the key now reads as off #503 with Codex accounts in the pool, a request on the intercepted chatgpt.com that is not Codex inference (codex-cli 0.156's workspace discovery, plugin, MCP and settings calls) is passed through to chatgpt.com with the client's own login instead of reaching the Anthropic pool and a 404; the Codex Responses WebSocket is refused (501) so the CLI falls back to HTTPS, where the pool serves it (#492) #502 `login --api` adds a key at priority 100, a last resort behind the subscriptions, with `--priority <n>` to place it; existing entries are untouched (#497) Fixes #498 artifacts (`/api/frame/*`) are relayed with the client's own credential, so publishing and reading them works behind a rotated pool #499 the Remote Control bridge (`/v1/environments/*`, `/v1/sessions/*`, `/v2/session_ingress/*`, `/v2/ccr-sessions/*`), which Claude Code 2.1.287 sends through HTTPS_PROXY, is relayed with the client's own credential; registration no longer lands in a rotated account's org #488 keep-warm works on Windows: the warm-up client is spawned through a shell, so npm's `claude.cmd` shim is found #489 Node 24.6's undefined HTTP/2 keep-alive buffer no longer crashes the MITM tunnel with a NaN timeout #490 on a very wide terminal the two provider panes sit together and their bars grow to the list's cap instead of padding half the screen Features #496 `accountSort` orders the TUI account list by the soonest reset of a window (session, weekly, S7, F7) inside each provider group; cycled from the settings screen, display only #494 a z.ai GLM Coding Plan backend account shows its 5-hour and weekly windows in `teamclaude status` #495 a NanoGPT backend account shows its daily and weekly windows and NanoGPT's own billing advice (`billing balance`, `balance not allowed`) #500 each dashboard account card lists the models the account served in the last 15 minutes Docs #505 what a cross-organization switch costs a Sonnet 5.5 conversation: the API drops the earlier thinking blocks silently; same-org pools are unaffected (#491) Tests #501 #504 two tests that raced the wall clock or a shared port now assert the mechanism, and the last private server-spawn harness is gone Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude Code 2.1.287: "Fixed
claude remote-controlfailing to register behind an HTTP proxy" (anthropics/claude-code#97352). WithHTTPS_PROXYpointing at TeamClaude, the bridge's control calls now reach the request listener.CLIENT_CREDENTIAL_PATHSrelays only/v1/code/and/api/oauth/with the client's own credential, so everything else the bridge sends gets a rotated fleet token. A daemon cannot opt out per process:settings.jsonenvis applied over the process environment, andremote-controlrefuses a root--settings.Symptom - one machine running
claude remote-controlunder systemd, in the 4h after the update:POST /v1/environments/bridgeregistered the machine under whichever account rotation picked: fiveorganization_uuidvalues in round-robin order over ~22 restarts. The login's own org appeared only when rotation landed on it.404 Not found.Change - add
/v1/environments/,/v1/sessions/,/v2/session_ingress/and/v2/ccr-sessions/toCLIENT_CREDENTIAL_PATHS, the whole prefix as with/api/oauth/in #245. The paths are from the 2.1.287 bundle:/v1/environments/bridge,/bridge/{id}/offline,/{id}/bridge/reconnect,/{id}/work/poll,/{id}/work/{work}/ack|heartbeat|stop;POST /v1/sessions,/v1/sessions/{id},/events; the session MCP endpoints/v2/session_ingress/shttp/mcp/{id}and/v2/ccr-sessions/-/meta/mcp./, so it stops at a segment boundary (/v1/sessionsXstill rotates). The entry without that slash, the collection itself, matches too: a session is created with a barePOST /v1/sessions, andclassificationPath()has already dropped the?beta=true. The rule moves intoisClientCredentialPath(). It also takes the bare/v1/codeand/api/oauth, which no client sends./v2/session_ingress/mcp/ws/{id}) already keep the client's headers throughrelayUpgrade; this covers the plain requests./api/oauth/*since fix(server): relay all /api/oauth/* with the client's own credential #245, a client with no login of its own now gets a 401 on these paths instead of a rotated token. The two/v1prefixes also serve the public Managed Agents API (managed-agents-2026-04-01). Its environments and sessions belong to the organization that created them, so rotation could not serve them across a multi-org pool anyway.CLIENT_CREDENTIAL_PATHSline. Whichever lands second rebases: keep both comments and the union of entries./api/frame/works unchanged under the new predicate.Tested -
npm test: 2592 pass, 0 fail, 5 skipped (as on master). 15 new tests intest/remote-control-bridge-relay.test.js:/v1/sessionsXand/v1/environmentsX/bridgestill rotate. Both fail if the entries are spelled without the trailing slash.Inference rotating is already covered in
test/oauth-client-credential.test.js.npm run lint,npm run typecheckand the strict ratchet (1703, unchanged) are clean on Node 22.12.0.Live, the same prefixes as a hotfix on 1.1.22 on the affected machine (spelled there as plain
/v1/environmentsand/v1/sessions): registration landed in the login's own org while the proxy's active account was a different one. Reconnect, poll, ack and heartbeat all answered 200, with no 401s.🤖 Generated with Claude Code