[FEATURE] Remote Control: failure-resistant session model — survive hibernation, auto-reattach, mobile-side recovery
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Remote Control's value proposition is "walk away from your desk and keep working." Every documented failure mode currently requires walking back to the desk. A remote-access feature whose only recovery path is physical access to the machine defeats its own purpose.
Firsthand incident (2026-07-18, Windows desktop + iOS app):
- Desktop hibernated overnight with an active Remote Control session bound to the iPhone app.
- After wake, the phone showed the session only under Archived; unarchiving produced a frozen view still claiming a running process.
- Permission prompts appeared at the desktop only — never delivered to the phone, no disconnect indicator on either side.
/remote-controlfailed with:Remote Control failed to disconnect: Cannot read properties of undefined (reading 'session_url')— registration record gone, disconnect path crashes on absent state (filed separately as a bug).- Recovery required desktop access, fresh registration, and manually distinguishing the new session from the dead one on the phone.
Systemic, not anecdotal — same architecture-level gaps across the tracker:
- #34255 auto-reconnect never recovers (manual disconnect/re-register always works → protocol fine, recovery path broken)
- #34531 / #28571 / #29313 lost sync is permanent; /rc cannot restore; only fix is a new session
- #34119 after compaction, phone stays welded to the dead session; disconnect is desktop-TUI-only
- #41128 idle sessions resumable from CLI but not mobile/web
- #61525 dead "Disconnected" sessions accumulate, no delete, no reconnect
- #60790 owner process gone after restart → "remote control disconnected" instead of transcript adoption
Common root cause: session identity is bound to an ephemeral process + websocket, and every layer assumes the connection never dies. On laptops and phones, connections die constantly.
Proposed Solution
- Durable session identity, brokered server-side. Decouple the logical session (transcript, permission state, running tasks) from transport and owner process. Remote client binds to a session ID; server rebinds it to whatever live process owns that transcript. Compaction, restart, hibernation become transparent to the phone.
- Idempotent, self-healing registration.
/remote-controlnever crashes on missing state — absent session_url means "not registered": clean up, register fresh. On wake-from-sleep, detect dead registration and re-register automatically, migrating existing mobile bindings. - Mobile-side disconnect and reattach: detach from stale session, list live registrations, attach — no desktop interaction.
- Honest connection state, both ends: dead link visible within seconds ("disconnected — tap to reattach"), never a frozen view impersonating a live one.
- Transcript-based resync on reattach: replay the delta from the server, not a cached stream. Post-disconnect history must never be unreachable.
- Queued interaction across gaps: permission prompts and user messages queue while the link is down, deliver on reconnect (extend the v2.1.207 status-update queueing to prompts and input).
- Push-notification recovery hooks: on session migration, push a one-tap deep link to the successor session; expose remote URL in SessionStart hook input meanwhile.
- Non-interactive CLI:
claude remote-control --status | --disconnect | --reconnect [name]so recovery is scriptable from wake hooks. - Session hygiene: deletable dead sessions; a new registration for the same project supersedes the stale listing.
Acceptance test: laptop hibernates overnight mid-task with a phone attached. On wake, with zero user action at the laptop, the phone shows the session live within a minute, full history intact, pending permission prompts delivered.
Alternative Solutions
- Manual /remote-control disconnect/re-register at the terminal (works, but requires desktop access — the thing Remote Control exists to avoid)
- ntfy.sh push hooks on SessionStart(compact) (#34119) — notification without a recovery path
- tmux + scripted TUI keystrokes — brittle, rejected in #34255
- Claude Code on the web — sidesteps the problem but abandons the local filesystem/MCP/trust boundary, i.e. the reason to use Remote Control
Priority
High - Significant impact on productivity
Feature Category
Interactive mode (TUI)
Use Case Example
_No response_
Additional Context
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
I would separate three pieces of identity here, otherwise recovery keeps turning into UI state repair:
Then hibernation/restart becomes a lease/rebind problem instead of a "dead mobile session" problem. A process wakes or restarts, proves it can own session X, resumes from event cursor N, and emits one idempotent reattached event. The phone should only care that session X is live again, not whether the websocket or owner PID changed.
The acceptance test I would add is: permission prompt created, laptop sleeps before answer, phone sends answer while worker is gone, worker wakes, answer is either applied exactly once or returned as expired with a visible terminal state. No silent pending state.
I build cmdop, so biased — this is the same remote-session boundary we keep explicit for machine/agent control: the interactive client is not the durable authority. Public reference: https://docs.cmdop.com/concepts/remote-sessions
Supporting datapoint for the headless/server flavor of this request — it shows the
session loss is not tied to laptops, hibernation, or flaky links at all.
Setup:
claude remote-controlruns 24/7 as a systemd service on analways-on Ubuntu Server 26.04 box (native install, wired power, stable
connection — none of the usual "connection died" suspects). A nightly timer runs
claude updateand restarts the service when the CLI version changed, so theworker follows the near-daily patch releases.
Effect: every patch release kills every session. Each morning, all chats
from before ~03:40 show "Remote Control disconnected" in the mobile/desktop app,
and "Try again" does not recover them — while the transcripts in
~/.claude/projects/…/*.jsonlare fully intact and the same environment(
env_…) re-registers fine. Observed across at least 2.1.221 → .222 → .223(three consecutive mornings, 2026-08-04/05/06). On an always-connected server
the only trigger is the worker process restart — exactly the "session identity
is bound to an ephemeral process" root cause this issue describes.
Evidence that re-attach is attempted but refused server-side: at every
worker start, the CLI itself tries to re-register a previous session and the
backend rejects it:
Same line at 9 consecutive service starts since 2026-07-25, always for the same
(weeks-old) session id — so the worker persists some notion of "sessions to
re-attach" and retries them, but (a) the backend 404s the attempt, and (b) newer
sessions aren't even retried. The reconnect path exists in embryo; it just
doesn't work.
Workaround we settled on (mentioned in case it helps others running server
workers): we no longer restart the worker on every patch release — the new CLI
is downloaded nightly but only loaded on the next natural restart, with a forced
restart only when the running worker is ≥7 days old or major.minor jumps. That
keeps chats alive across nights, but it trades version staleness for session
continuity. A durable server-side session identity, as proposed here, would make
that trade-off unnecessary: environment id is stable, transcript is on disk,
session id is known — everything needed for adoption by a fresh worker process
already survives the restart today, except the binding itself.
Brief follow-up on the workaround above: we have since abandoned it and gone back to restarting the worker on every nightly update. Running a stale CLI for up to a week turned out to be the worse trade for us (releases are near-daily and regularly carry bug/leak fixes), so we now accept losing every session each night again.
Which is really the point of this issue in one sentence: the only two options a server deployment has today are stale worker or nightly session loss. Durable server-side session identity would remove that dilemma entirely.