[BUG] claude --remote-control collapses into an implicit --print mode and exits immediately when no pseudo-terminal is present (e.g. under systemd)
Environment
- Claude Code CLI v2.1.210
- Linux, headless (no Desktop app, no tmux/screen, no
script) - Auth: claude.ai subscription login (not API key)
Summary
claude --remote-control "<name>" only works when stdin/stdout/stderr are connected to a real pseudo-terminal (a real terminal, or one provided via script, tmux, screen, etc.). Without any PTY at all — e.g. when launched directly as a systemd Type=simple service, or with all three file descriptors redirected to files//dev/null — the process does not start the Remote Control UI. Instead it appears to fall back to an implicit --print/non-interactive mode and exits immediately with an unrelated error message, rather than the interactive Remote Control session the flag requests.
Steps to reproduce
Minimal, fully isolated repro (no systemd needed):
cd ~ # or any project directory
claude --remote-control "test" < /dev/null > /tmp/out.log 2>&1 &
wait
cat /tmp/out.log
Observed behavior
Error: Input must be provided either through stdin or as a prompt argument when using --print
Exit code 1, immediately (well under a second). No Remote Control session is created, no session URL is printed.
The identical command run under a systemd Type=simple unit (ExecStart=/path/to/claude --remote-control "name", default systemd stdio — none of stdin/stdout/stderr are a TTY) fails the same way, with the same error, confirming this is not systemd-specific but purely about the absence of a PTY.
Contrast case (works correctly)
Wrapping the exact same command in a PTY makes it work as expected:
script -qefc 'claude --remote-control "test"' /tmp/out.log
This starts normally and prints a working https://claude.ai/code/session_... URL.
Expected behavior
Either:
--remote-controlshould work without requiring a real PTY (this is presumably how it needs to run under any process supervisor — systemd, Docker, etc. — none of which normally allocate a TTY for a service), or- if a PTY is a hard requirement for Remote Control, that requirement should be documented, and the CLI should fail with a clear, specific error naming the actual problem ("Remote Control requires a TTY") instead of silently and confusingly falling back to
--printsemantics and printing an error that talks about--print, a flag the user never passed.
Impact
This is what forces anyone who wants to run --remote-control under a process supervisor (systemd, Docker, any unattended/headless environment) to work around it via a manual PTY shim like script -qefc '...' logfile, which is undocumented, fragile, and not obviously the "supported" way to run Remote Control unattended. It's also the root cause that makes the "silent hang on --resume with an expired session" bug (reported separately) harder to diagnose, since the underlying command's TTY requirement isn't surfaced anywhere in the docs.
Related (found while searching for duplicates before filing)
- #39970 — Desktop-app-focused, closed as "not planned", touches on remote session resume/timeout but not this specific CLI/no-PTY collapse.
- #60790 — Desktop-app-focused, closed as duplicate, same broader "waits indefinitely instead of failing/reconnecting cleanly" pattern but a different code path (Desktop bridge, not CLI
--remote-controlinvocation).
Neither covers the CLI-only, no-Desktop, no-PTY case described here.
3 Comments
Filed alongside a related, independent bug found during the same investigation: #77749 (silent indefinite hang on
--resume <uuid>when the Remote Control session has expired server-side but the local conversation still exists). That one reproduces even with a PTY present, so it's unrelated to the no-PTY collapse described here — but the fix here is what removes the need for thescriptworkaround that was used to reproduce it.Reproduced exactly as described on v2.1.233 (Linux, fresh config):
exits 1 in under a second with
Error: Input must be provided either through stdin or as a prompt argument when using --print— even though--printwas never passed — while the identical command wrapped in a PTY (script -qefc ...) starts the interactive session normally. Your analysis matches what we observed: with no PTY on stdin, the CLI infers non-interactive print mode before the--remote-controlflag is taken into account, and the resulting error message talks about a flag you never used. Agreed that this should either work headless or fail with a clear message naming the actual requirement.Two notes that may help in the meantime:
claude remote-control(the subcommand, server mode) is the documented way to run Remote Control without a local interactive session — see https://code.claude.com/docs/en/remote-control. In our testing it does not hit this no-PTY collapse (it proceeds to its normal startup checks without a terminal), so it's likely the better fit for systemd/Docker than PTY-shimming--remote-control. We couldn't verify a full end-to-end session from our test environment, so please report back if server mode also misbehaves under systemd.--remote-controlstarts a normal interactive terminal session with remote access added on top, so it inherently expects a terminal today — but the misleading--printerror is a real defect regardless.Flagging this for the team as a reproduced bug in mode selection/error messaging for headless invocations.
🤖 Generated with Claude Code
For your information: the label
reproducedon this issue does not prevent it from becoming stale and eventually auto-closed. See https://github.com/anthropics/claude-code/issues/87647 for details, and consider upvoting that for visibility.