Remote Control: sessionTimeoutSeconds schema field is unwired (no CLI flag, no env var, no consumer)
Summary
In @anthropic-ai/claude-code@2.1.144 (also reproduced in 2.1.143), the claude remote-control Zod config schema declares an optional sessionTimeoutSeconds: number field, but it has no kebab-case CLI flag, no env-var binding, and no consumer site in the binary. Long-running Remote Control sessions therefore have no upstream-supported way to auto-close. Operators have to enforce session age-out externally.
Reproduction (jack-mac, macOS 26.5 build 25F71, Apple Silicon M2 Pro, claude-code 2.1.144 from npm)
1. The schema declares the field
strings -n 6 .../claude-code-darwin-arm64/claude | grep -F sessionTimeoutSeconds returns one effective definition site:
y.object({
dir: y.string(),
name: y.string().optional(),
spawnMode: y.enum(["same-dir","worktree"]).default("same-dir"),
capacity: y.number().int().positive().default(32),
permissionMode: y.enum(...).optional(),
sandbox: y.boolean().default(false),
sessionTimeoutSeconds: y.number().int().positive().optional(), // <-- declared here
createSessionOnStart: y.boolean().default(false)
}).strict()
2. The manual CLI arg parser has no branch for it
The parser handles --help, --verbose, --sandbox, --no-sandbox, --debug-file, etc. There is no --session-timeout-seconds (or any kebab-case variant). grep -F "session-timeout" strings.txt returns zero hits.
For comparison: --sandbox is hidden from --help too, but IS wired in the parser:
if(P==="--sandbox")q=!0;
else if(P==="--no-sandbox")q=!1;
No equivalent branch exists for the timeout field.
3. No env-var binding
grep -oE "CLAUDE_REMOTE_CONTROL_[A-Z_]+" strings.txt | sort -u returns only CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX. No timeout-related env var.
4. --help doesn't mention it
$ claude remote-control --help
OPTIONS
--name <name>
--remote-control-session-name-prefix <prefix>
--permission-mode <mode>
--debug-file <path>
-v, --verbose
-h, --help
--spawn <mode>
--capacity <N>
--[no-]create-session-in-dir
5. No consumer
grep -c sessionTimeoutSeconds strings.txt = 2, both occurrences are the schema definition (one declaration, one referenced in the same schema-builder line). There is no other site that reads the parsed value. If you compare to the other schema fields (spawnMode, capacity, etc), they all have additional read-sites in the same dump.
Real-world impact (why we noticed)
A Remote Control session was wedged on jack-mac for 50+ minutes after a Bash-tool pipe deadlock (the claude.exe parent stopped draining the child shell's pipe, the child blocked on write() against a full 64 KB pipe buffer). Anthropic's relay surfaced "stopped responding mid-turn" to the Claude mobile app.
While investigating, we found a second session that had been alive for 25+ hours and which we expected the bridge to have aged out automatically. It hadn't. That's what led to verifying the schema field is unwired.
Capacity: N/32 slowly drifts up over a bridge's uptime as idle sessions accumulate, until either:
- A wedged session triggers a relay-reconnect loop that requires
launchctl kickstartto fully recover, or - The operator manually kills sessions.
Workaround we deployed
External cron + script that:
- Lists
claude.exe ... --session-id cse_...processes (the per-session children). - Excludes the bridge process whose argv is
claude remote-control --name ... --spawn same-dir(no.exe, no--session-id). - SIGTERMs anything with elapsed time over the threshold; SIGKILL escalation after 5 s grace.
*/15 * * * * /path/to/claude-rc-session-watchdog.sh does the job, but the bridge owning this seems like the right place for it.
Suggested fixes (any one)
- Wire it up. Add
--session-timeout-seconds Nto the arg parser, expose it in--help, and have the daemon enforce it. MatchingCLAUDE_REMOTE_CONTROL_SESSION_TIMEOUTenv var would be a bonus. - Server-side enforcement. If the relay is supposed to enforce timeouts and tell the bridge to close, document the policy and the relay's expectations.
- Drop the schema field if the feature isn't shipping. Right now it parses successfully via the strict schema's optional contract, which silently swallows a config value that does nothing.
- At minimum, document the absence in
claude remote-control --helpand in the docs so operators don't have to reverse-engineer the binary to find out.
Environment
@anthropic-ai/claude-code: 2.1.144 (also reproduces on 2.1.143)- Platform binary:
@anthropic-ai/claude-code-darwin-arm64@2.1.144, 207,919,008 bytes - macOS: 26.5 (build 25F71), Apple Silicon M2 Pro
- Node: 22.22.3 via nvm
- Bridge invocation in our LaunchAgent:
claude remote-control --name jack-mac --permission-mode bypassPermissions --spawn same-dir
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗