remote-control fails with 'Unknown argument' when launched via wrapper that injects --session-id
Bug
claude remote-control fails with:
Error: Unknown argument: dada1ca7-c4ba-4055-af3f-542ce655336a
Run 'claude remote-control --help' for usage.
No UUID is being passed by the user — claude remote-control is run bare.
Root cause
When Claude Code is invoked through a wrapper script (e.g., a desktop app) that injects --session-id <uuid> before the user's arguments, the remote-control subcommand's fast-path in cli.tsx is bypassed, and execution falls into a "unreachable" fallback path with a hardcoded process.argv.slice(3) that produces garbled arguments.
Detailed trace
- Wrapper transforms the command. A wrapper injects flags before the user's args:
````
real-claude --session-id <uuid> --settings <json> remote-control
cli.tsxfast-path is skipped.args = process.argv.slice(2)gives["--session-id", "<uuid>", "--settings", "<json>", "remote-control"]. The fast-path check at line 112 (args[0] === 'remote-control') fails becauseargs[0]is"--session-id".
- Falls through to Commander in
main.tsx. Commander correctly parses--session-idand--settingsas root-level options, then recognizes"remote-control"as a registered subcommand and dispatches to its action handler.
- The "unreachable" fallback runs. The
remote-controlsubcommand action (line ~4325) was written with the assumption it would never execute:
``typescript``
.action(async () => {
// Unreachable — cli.tsx fast-path handles this command before main.tsx loads.
const { bridgeMain } = await import('./bridge/bridgeMain.js');
await bridgeMain(process.argv.slice(3));
});
- Hardcoded
slice(3)produces wrong args. With the injected flags,process.argvis:
```
[node, script, --session-id, <uuid>, --settings, <json>, remote-control]
slice(3)
yields ["<uuid>", "--settings", "<json>", "remote-control"]` — the UUID value is the first element.
bridgeMain's arg parser rejects the UUID. The parser inbridgeMain.ts(line ~1822) only accepts named flags. The bare UUID hits the catch-allelseclause:
``typescriptUnknown argument: ${arg}\nRun 'claude remote-control --help' for usage.
return makeError()``
Reproduction
- Have any wrapper/shim earlier in
$PATHthat injects--session-id <uuid>before user args (e.g., for session tracking) - Run
claude remote-control - The fast-path is bypassed, the "unreachable" Commander fallback runs with garbled args, and the UUID is rejected
A fresh UUID appears each time (generated by the wrapper), confirming it's not user-supplied.
Suggested fixes
Option A (in main.tsx): Make the "unreachable" fallback resilient — dynamically find the subcommand position instead of hardcoding slice(3):
const rcIndex = process.argv.indexOf('remote-control');
await bridgeMain(process.argv.slice(rcIndex + 1));
Option B (in cli.tsx): Make the fast-path scan all args for the subcommand, not just args[0]:
const subcommand = args.find(a => !a.startsWith('-') && !prevWasFlag);
if (feature('BRIDGE_MODE') && (subcommand === 'remote-control' || ...))
Option C (in bridgeMain): Accept a bare UUID-shaped positional arg as an implicit --session-id for resilience.
Environment
- macOS (Darwin 25.3.0)
- Claude Code CLI invoked via desktop app wrapper that prepends
--session-idand--settingsflags
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗