remote-control fails with 'Unknown argument' when launched via wrapper that injects --session-id

Resolved 💬 2 comments Opened Apr 2, 2026 by ray-amjad Closed Apr 2, 2026

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

  1. Wrapper transforms the command. A wrapper injects flags before the user's args:

``
real-claude --session-id <uuid> --settings <json> remote-control
``

  1. cli.tsx fast-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 because args[0] is "--session-id".
  1. Falls through to Commander in main.tsx. Commander correctly parses --session-id and --settings as root-level options, then recognizes "remote-control" as a registered subcommand and dispatches to its action handler.
  1. The "unreachable" fallback runs. The remote-control subcommand 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));
});
``

  1. Hardcoded slice(3) produces wrong args. With the injected flags, process.argv is:

``
[node, script, --session-id, <uuid>, --settings, <json>, remote-control]
`
slice(3) yields ["<uuid>", "--settings", "<json>", "remote-control"]` — the UUID value is the first element.

  1. bridgeMain's arg parser rejects the UUID. The parser in bridgeMain.ts (line ~1822) only accepts named flags. The bare UUID hits the catch-all else clause:

``typescript
return makeError(
Unknown argument: ${arg}\nRun 'claude remote-control --help' for usage.)
``

Reproduction

  1. Have any wrapper/shim earlier in $PATH that injects --session-id <uuid> before user args (e.g., for session tracking)
  2. Run claude remote-control
  3. 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-id and --settings flags

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗