Repository navigation
[BUG] Remote Control: automatic reconnection doesn't work -- connection drops silently with no recovery #34255
Description
Activity
- addedplatform:macosIssue specifically occurs on macOSIssue specifically occurs on macOSplatform:iosIssue specifically occurs on iOSIssue specifically occurs on iOS
on Mar 14, 2026 +1 on @BluCreator issue. Same version of Claude Code / model / iTerm2 and same behavior.
Terminal window shows 'Remote Control reconnecting'. Running /remote-control does not correct the failed connection.
Continuing the session from the iTerm2 does not result in reconnecting the session.
Reacted by Christian Meinerding, Jordi Mola, Ferran Bonàs, Newozz, Pierre BOURDU, Olivier Miserez, Josh, Samuel Ainsworth, zzmartin, Nam Nguyen and 3 more+1 on @BluCreator issue. Same version of Claude Code / model / iTerm2 and same behavior.
Terminal window shows 'Remote Control reconnecting'. Running /remote-control does not correct the failed connection.
Continuing the session from the iTerm2 does not result in reconnecting the session.
I have the same issue
Reacted by Ferran Bonàs, Newozz, Jak S, Samuel Ainsworth, Nam Nguyen, AGENCIA RSE., Aaron, Chintella-Esq and lordvyceConfirming we're seeing this too on Linux (Oracle Cloud, RHEL/aarch64). Two independent sessions disconnect at identical timestamps, confirming server-side. Client stops reconnecting after the 3rd drop (1002 protocol error). No viable workaround — the loop-restart approach doesn't help since it generates a new session each time, requiring manual reconnect on the phone anyway.
Reacted by Newozz, Xiyu Zhai, Samuel Ainsworth, zzmartin, Nam Nguyen, AGENCIA RSE., Aaron, Chintella-Esq and lordvyceReproducing this on WSL2 + iOS — v2.1.76
Environment
- OS: WSL2 Ubuntu (Linux 6.6.87.2-microsoft-standard-WSL2)
- Claude Code: v2.1.76
- Client: iOS Claude app (connecting via Remote Control)
- Usage: Start session in WSL2 terminal, enable
/remote-control, connect from phone
Symptoms
-
Silent disconnect while status shows "Active": The statusline shows "Remote Control active" but the phone is actually disconnected. No error, no status change — completely silent.
-
"Connecting..." hangs indefinitely: After a disconnect, the auto-reconnect kicks in and shows "Remote Control connecting..." but never transitions back to "active". It stays stuck in this state until manual intervention.
-
Only workaround: Type
/remote-control→ select Disconnect → type/remote-controlagain → Connect. This requires physical access to the PC terminal, which defeats the purpose of remote control.
Frequency
- Happens every 20-60 minutes during active use
- Also happens during idle periods (phone screen off / app backgrounded on iOS)
- The "active but actually dead" case is the worst — you don't know it's broken until you try to send a message from the phone and get no response
Impact
This makes Remote Control unusable for its intended purpose (continuing work from mobile away from desk). Every disconnect requires physically going back to the PC to restart the connection.
Suggested improvements
- Auto-reconnect that actually works — when the relay connection drops, the CLI should aggressively retry (exponential backoff) without requiring user intervention via
/remote-controltoggle - Accurate status indicator — if the relay hasn't received a heartbeat in N seconds, show "disconnected" not "active"
- Programmatic reconnect — allow reconnecting without the interactive menu (e.g., a non-interactive flag or API), so users can script a watchdog
Reacted by WatPalders, Hsieh-Ting Lin (林協霆), Ferran Bonàs, Newozz, Mark Dannemiller, Georgi Mateev, Nam Nguyen, Chintella-Esq and lordvyceSystemd keep-alive watchdog workaround for Linux users
Hitting this consistently on Linux (v2.1.81): after a period of idle, the
service loses its connection to Anthropic's bridge and never recovers. The
mobile app shows the session as active but messages are never processed.How we detect the stuck state:
Instead of counting log lines (unreliable — normal operation also generates ~1
line/sec), we check whether the process has an active ESTAB TCP connection to
Anthropic's servers on port 443. No connection = stuck.Watchdog script (~/.local/bin/claude-remote-watchdog.sh):
#!/bin/bash
SERVICES=("claude-remote.service" "claude-remote-ha.service")for SERVICE in "${SERVICES[@]}"; do
PID=$(systemctl --user show "$SERVICE" --property=MainPID --value
2>/dev/null)
STATE_FILE="/tmp/claude-watchdog-${SERVICE}.fail"if [ -z "$PID" ] || [ "$PID" = "0" ]; then rm -f "$STATE_FILE" continue fi CONNECTIONS=$(ss -tnp | grep "pid=$PID," | grep "ESTAB" | grep ":443" | wc-l)
if [ "$CONNECTIONS" -eq 0 ]; then if [ -f "$STATE_FILE" ]; then echo "$(date): $SERVICE has had no connection for 2 checks (~10min) — restarting"
rm -f "$STATE_FILE"
systemctl --user restart "$SERVICE"
else
echo "$(date): $SERVICE no connection — waiting for next check"
touch "$STATE_FILE"
fi
else
rm -f "$STATE_FILE"
fi
donesystemd timer (runs every 5 minutes):
[Timer]
OnBootSec=5min
OnUnitActiveSec=5minImportant caveats:
- We use a 2-check grace period (~10 min) before restarting, to allow the
process to reconnect naturally after a transient NAT/idle timeout — avoiding
unnecessary session loss - Restarting still creates a new session and loses conversation history — so
this is a last resort, not a real fix - Even without the watchdog, returning to a session after many hours of idle
often results in a broken/empty session on the mobile side — so the real issue
is the bridge session not surviving long idle periods end-to-end
A proper fix in the reconnection logic (or bridge session persistence) would be
much preferred over any client-side workaround.Reacted by Newozz, Almog Cohen, Jackson Chen, Xiyu Zhai, AGENCIA RSE. and Chintella-Esq- We use a 2-check grace period (~10 min) before restarting, to allow the
I'm seeing the same exact issue on multiple machines. No network disruption.
Environment Info
- Platform: darwin
- Terminal: iTerm.app
- Version: 2.1.81
- Plan: Max 200
This is not the documented 10-minute network timeout. The local machine remains online, and the CLI process is still running. The disconnect appears to be triggered by something else — possibly an idle timeout, a transient server-side drop, or a cellular/WiFi handoff on the mobile side — but the root cause is unknown because no diagnostic information is surfaced.
Observed Behavior
- Remote Control session is established and functioning normally.
- At some point (trigger unknown), the mobile client shows a yellow "reconnecting" message.
- The reconnection never completes. The session is unresponsive indefinitely.
- The only recovery is to physically return to the terminal and manually cycle the connection: run /remote-control → Disconnect → restart with /remote-control [session-name].
Reacted by Newozz, Almog Cohen and Chintella-EsqConfirming this also occurs on Linux (Ubuntu 22.04 on Azure VM). Same symptoms: silent disconnection after extended session, no auto-recovery, manual disconnect/reconnect cycle fixes it.
Reacted by Andrew Rich, Arun VS and Chintella-Esqsame issue by the time I'm ready to use my remote connection in iOS it's bad/stale; rendering the feature not very useful
Reacted by Chintella-EsqIt appears that this phenomenon is widespread and requires urgent improvement.
Reacted by Jinjing LI, Alex Kevakian, fisherpro, kfir, Tony, jumpmanjay, John Sutor, krizslash, Xiyu Zhai, Mark Dannemiller and 4 moreReacted by Chintella-EsqReacted by Jinjing LI, Tony, Mark Dannemiller and Chintella-EsqExactly the same happens on Windows 10 running in Windows Teminal/Powershell 7 and Android on the mobile side.
Reacted by Chintella-Esqsame issue mac os VM with tmux session
Reacted by gldi8r and Xiyu ZhaiSame issue. Windows 11, Windows Terminal, Claude Code 2.1.81, Android app. Session shows "Remote Control reconnecting" and never recovers. Manual disconnect/reconnect from terminal always fixes it, but that defeats the purpose of remote control.
51 remaining items
i also facing the same issues
Confirming this is still happening in Claude for windows
this is still happening on recently updated version of claude code desktop for windows
Reacted by Dan HarborneThe mechanism: a 3-drops-per-hour circuit breaker turns a transient drop into a permanent one
This report says reconnection "doesn't work" and that a manual
/remote-controlcycle always fixes it. Reading v2.1.233, that is exactly right, and there is a specific reason for it: reconnection is not failing at the protocol level, it is being refused by a circuit breaker.function v5p() { let e = [], t = Number.NEGATIVE_INFINITY; return { charge(r, n) { e = e.filter((i) => r - i < QgS); // QgS = 24h if (n && e.length >= m5p) return "daily_exhausted"; // m5p = 72 if (ar(e, (i) => r - i < f5p && (!n || i >= t)) >= p5p) // f5p = 1h, p5p = 3 return "hourly_exhausted"; e.push(r); return "charged"; }, noteHealthyBeat(r) { let n = e.at(-1); if (n !== undefined && r - n >= eyS) t = r; // eyS = 10 min } }; }
Budgets: 3 reconnects per rolling hour, 72 per 24 hours. A drop only stops counting against you once a healthy beat lands at least 10 minutes after the previous drop. Separately, a single reconnect campaign is
{ attempts: 14 }, and when it runs out the user-facing reasons are:"could not reach the Remote Control server for about 30 minutes""the connection to the Remote Control server kept dropping after each reconnect""the connection to the Remote Control server dropped more than 72 times in 24 hours"
Why it never recovers
Combined with the idle-TTL bug in #32982, the sequence is:
- Session goes idle → the server expires it ([BUG] Remote Control sessions die after ~20 min idle — server TTL ignores keepalives #32982: the 30s keepalive only runs while a turn is running, and the client reports
idle_secondsderived purely from turn activity). - Client notices and reconnects. The session is still idle, so it expires again inside the same window.
- Third drop inside the hour →
hourly_exhausted→ Claude Code stops trying, permanently. - Because the drops arrive faster than the 10-minute healing interval, the budget never refills. Nothing recovers on its own, ever.
That is why the manual cycle "always works": it does not repair a broken protocol path, it clears a budget the automatic path has exhausted. The original report's intuition — "the reconnection logic itself isn't broken at the protocol level" — is correct, and this is the missing piece.
Why this is the part that actually hurts
The failure is silent and permanent and it lands precisely when you are away from the machine — the state Remote Control exists for. From a phone the three failure modes are indistinguishable: a spinner. And the remedy requires physical access to the terminal the feature was supposed to make unnecessary.
A circuit breaker sized for a flapping connection is the wrong shape for a starved one.
Suggested fixes
- Repeated drops with the same cause (idle TTL) should not consume the budget three times. Charge per distinct cause, or exempt server-side TTL expiry entirely.
- When the budget is exhausted, do not stop — fall back to a long slow retry (every 10–15 min, indefinitely) while the local process is alive. There is no cost to retrying against a session the user has not ended.
- Surface exhaustion to the remote client. Today the CLI knows the connection is dead while the phone shows a spinner. The remote surface should say "disconnected — reconnect" and offer a button, which is what [FEATURE] Remote Control: manual Reconnect / Disconnect controls on the session row (Desktop and mobile apps) #84987 asks for from the UI side.
- Have the automatic path perform the same teardown/re-establish that the manual
/remote-controlcycle does, as the original report suggests — including resetting the budget, since a user-initiated reconnect is proof the user still wants the session.
A note for anyone who arrived here blaming tmux
I checked v2.1.233 for tmux-attachment awareness and there is none: no
list-clients,session_attached, orclient_attachedanywhere in the binary; the onlyfocusOutsymbols come from a bundled web UI library; and the heartbeat is a plainsetTimeoutchain that runs regardless of whether a terminal is rendering. tmux shows up in these reports because tmux is how people leave a session idle, not because it causes anything. On my machine the correlation was perfect and entirely spurious — sibling sessions in the same tmux server, under the same detach events, ran multi-hour autonomous tasks and never dropped, because they were never idle.Details of the idle half are in #32982.
Same failure on Windows, from the Claude Desktop app rather than the CLI. Adding data because the app side has a second, independent timer that is not covered in the reports above.
Setup
- Windows 11, Claude Desktop app 1.32352.0 (bundled Claude Code 2.1.229)
- "Enable remote control by default" is ON. Confirmed in logs: over the 12/08 to 18/08 window, 66 sessions started, 66 got
Enabling remote control, 0 failures. Remote control registration itself is 100% reliable. - Claude iOS app, Code tab
What happens
Every session goes offline after exactly 900 s of inactivity, and cannot be revived from the phone. Tapping a disconnected session returns:
The remote control session is offline. Reconnect or run /remote-control to start a new session.
Which requires physical access to the machine, defeating the point of the feature.
The app-side timer
%APPDATA%\Claude\logs\main.log:2026-08-18 08:03:11 [info] [remote-control] bridge_state: connected 2026-08-18 08:03:20 [info] [WarmLifecycle:session] Starting idle timeout for local_cef69fb2: 900s 2026-08-18 08:34:53 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_b25a1207 2026-08-18 08:34:53 [info] [CCD] Pausing session local_b25a1207 (idle_timeout)A screenshot of the mobile list taken at 08:37 shows that session as Disconnected, three minutes after the pause. So on Desktop the disconnect is not only the server TTL described in #32982, it is also a local
WarmLifecycletimer that pauses the session process at 900 s. No user-facing setting exposes it.Timer re-fires in a loop
One session logged
Idle timeout reachedevery 15 minutes for hours after it was already paused:2026-08-18 00:25:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903c 2026-08-18 00:40:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903c 2026-08-18 00:55:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903c 2026-08-18 01:10:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903c 2026-08-18 01:25:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903c 2026-08-18 01:40:45 [WarmLifecycle:session] Idle timeout reached, disconnecting local_e7d3903cThe timer rearms and refires against an already-paused session instead of being cleared, which looks like a leak rather than intended behaviour.
Refresh token expiring repeatedly
Three times in three days, the bridge parked itself and never recovered without a re-login:
2026-08-15 09:01:29 [error] OAuth token refresh failed: status=400, {"error": "invalid_grant", "error_description": "Refresh token expired"} 2026-08-16 23:34:49 [error] OAuth token refresh failed: status=400, {"error": "invalid_grant", "error_description": "Refresh token expired"} 2026-08-17 09:03:10 [error] OAuth token refresh failed: status=400, {"error": "invalid_grant", "error_description": "Refresh token expired"} 2026-08-17 09:03:10 [warn] [sessions-bridge] OAuth stale-session (session_stale_relogin); parking bridge until re-loginThis account is a Max plan shared across three devices, so refresh token rotation between devices is a plausible cause. Matches what #69543 reports about
bridge-state.jsongoing stale on Windows.What would fix this from a user standpoint
- A remote "wake" action: let the phone restart a paused local session, since the process manager is still running on the machine.
- Make the 900 s
WarmLifecycletimeout configurable, or skip it entirely while remote control is connected. - Clear the idle timer once a session is paused, rather than rearming it every 15 minutes.
Confirming this is still happening on Claude Code for Mac OS X
If you need something that holds up while this gets fixed, one option, shell.online, MIT, single binary. Disclosure, I work on Pilot Protocol, which develops it.
shell clauderuns claude in a detached local PTY and prints a browser link, the process keeps running whether or not anything is connected, so a dropped phone connection is just reloading the tab. No pairing, no server-side session registry, and it works on any plan since it wraps the CLI. I tested the detach and reconnect mechanics on macOS and Linux today. Limits, the link is a bearer credential, anyone holding it can view and type, and the relay is Cloudflare, not E2E.Reacted by Andrew RichI'm experiencing the same issue.
My Mac stayed awake and connected to the network all night without sleeping,
but when I checked the Claude iOS app in the morning, some of my sessions
showed as "disconnected." Auto-reconnect did not happen — the only way to
restore the connection was to run/remote-controlagain on the Mac itself.This is a serious problem for me because I'm currently traveling without
physical access to my Mac. If this happens while I'm away, there's no way
to recover the session from my phone at all, and I'm completely stuck until
I get back to my Mac.I havn't even been using the RC, and got the error... ● Remote Control disconnected — Transport recovery exhausted (code 4093) — run /remote-control to reconnect
This has been happening for months now. Really wish there was a fix. Currently my biggest gripe with Claude is that we don't have seamless integration across devices.
Also seeing this on Windows (Claude Code v2.1.252, npm-global install), not just iOS/macOS adding for cross-platform visibility.
Ruled out on my end:
claude auth statusis clean (logged in, correct account, active Pro subscription)- Windows Firewall rules for claude.exe are all outbound-allow, nothing blocking
- Desktop app is confirmed logged into the same account as the CLI; fully quit via system tray and reopened no change
- Checked settings.json for the
remoteControlAtStartup/ccRemoteControlDefaultEnabledcollision mentioned in Remote Control: ccRemoteControlDefaultEnabled + remoteControlAtStartup collide — desktop session disables itself on first message (trigger for #77915) #80826 not present here
What I'm seeing: a fresh
claude --remote-control --backgroundsession shows/rc activelocally (the CLI-to-relay handshake succeeds), and I also hit an explicitRemote Control host unreachable (computer_unreachable)error on a separate attempt. Either way, Desktop's Code tab never reflects any session old or brand new as connected.So on this setup the break looks like it's specifically in relay→Desktop sync rather than CLI→relay connectivity.
Any help with this ? i really want to have all my sessions back on the desktop app
Still reproduces on 2.1.278 (Windows). Nothing in the changelog through 2.1.278 touches the auto-reconnect path.
The health signal already exists.
~/.claude/sessions/<pid>.jsoncarriesbridgeSessionIdnext tostatusandupdatedAt, An external watcher can already tell which sessions are meant to be remote-controlled. (Careful withupdatedAtthough — it's a last-activity stamp, not a heartbeat: It can't be used as a liveness check.)What's missing is a recovery entry point.
--remote-control [name]only applies at launch and/remote-controlis a TUI command, so neither a hook nor an external script can re-establish the bridge for a running session. That leaves killing and relaunching, which loses live session state (armed background shells, session-scoped permission grants) even though the transcript itself resumes fine.A runtime equivalent of the launch flag — anything callable that re-runs the connect path on the current session — would make the external workaround unnecessary.
Temp workaround while this is open — it automates the manual
/remote-controlreconnect from the machine itself, so a dropped bridge comes back without havign to be at the machine. Tested on Claude Desktop for macOS2.2553.1. Scope: Code chats started in the desktop app (Code tab) on that machine.The app's built-in DevTools console exposes the internal call the manual flow uses — no debug port needed (the app refuses
--remote-debugging-portanyway):echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json, then restart Claude.- Cmd-Opt-I → main window → Console (type
allow pasting+ Enter once if it blocks the paste). - Paste a small script that, every few minutes, runs this for each grouped chat:
await LS.warmSession(id); // LS = window["claude.web"].LocalSessions await LS.toggleRemoteControl(id, true);
The tell that matches this bug: a bare
toggleRemoteControl(id, true)on an idle session is refused with"Remote Control requires an active session". CallingwarmSession(id)first makes it succeed, and it re-registers the bridge with no message posted and no turn spent (session stays idle,remoteControlState→on). So the auto-reconnect likely just needs to warm + re-enable on drop.Unofficial / internal APIs, and it dies on a full app restart (re-paste). Full script + README: https://github.com/fazaamal/claude-desktop-remote-control-keepalive
Reacted by fazaamal and Dave Lamb
Preflight Checklist
What's Wrong?
Problem
Remote Control (/remote-control) silently drops the connection to the Claude iOS app (Code tab) during long sessions. Once dropped, the mobile client becomes completely unresponsive -- messages don't go through and there's no indication on either side that the connection is dead.
The core issue is that the built-in reconnection doesn't work. The connection drops and never recovers on its own. The only fix is to physically walk to the terminal and manually:
Run /remote-control
Select "Disconnect this session" from the interactive TUI menu
Run /remote-control [session-name] again
Notably, this manual disconnect/reconnect cycle always works -- the connection comes back healthy every time after cycling it. This suggests the reconnection logic itself isn't broken at the protocol level; something in the automatic recovery path is failing to trigger what a manual disconnect/reconnect does successfully. The fix may be as straightforward as having the auto-reconnect perform the same teardown/re-establish cycle that the manual flow does.
This defeats the entire purpose of remote control. If you're away from your desk -- which is the whole point of the feature -- you're locked out until you can physically get back to the machine.
The real fix
Remote Control's automatic reconnection needs to actually work. When the connection drops, Claude Code should detect the failure and re-establish the connection automatically, with no manual intervention required. This is the expected behavior for any persistent remote connection (SSH keep-alive, WebSocket reconnect, etc.).
The connection should be resilient to:
Network interruptions (WiFi switching, cellular handoffs)
iOS app backgrounding and foregrounding
Idle timeouts
Transient server-side disconnects
Why CLI flags alone wouldn't solve this
Adding flags like --restart or --reconnect would be nice for scripting, but they don't actually address the problem: you can't type commands when you're not at the computer. That's the whole reason you're using remote control in the first place. The fix has to be automatic.
Workarounds considered (none viable)
Custom slash commands / skills: Can't trigger built-in CLI commands like /remote-control from within a conversation or custom command.
tmux + scripted keystrokes: Theoretically possible (run Claude Code inside tmux, have a cron send keystrokes to disconnect/reconnect), but extremely brittle -- depends on exact TUI menu state, cursor position, timing. Not a real solution.
Cron-based reconnect: Would require non-interactive CLI flags that don't exist (/remote-control --disconnect, /remote-control --reconnect). Even if they did, it's a band-aid for what should be built-in behavior.
Nice-to-haves (secondary to the main fix)
If automatic reconnection is hard to ship immediately, these would at least unblock workarounds:
Non-interactive CLI flags: /remote-control --restart to cycle the connection from a script, enabling cron-based keep-alive
Connection health signal: A heartbeat or status indicator so external tools can detect a dead connection and attempt recovery
Mobile-side indication: Show the user on the iOS app that the connection dropped, instead of silently failing
Use case
I run long Claude Code sessions (hours to a full day) and manage them remotely from my iPhone via the Code tab. This is an incredibly powerful workflow when it works -- I can manage development, run automations, check on projects, all from my phone. But the silent connection drops make it unreliable for anything beyond a few minutes, which undermines the feature entirely.
Environment
Claude Code (CLI)
macOS (Apple Silicon)
Remote client: Claude iOS app, Code tab
Connection typically drops after 15-60 minutes of use
What Should Happen?
Remote Control's automatic reconnection needs to actually work. When the connection drops, Claude Code should detect the failure and re-establish the connection automatically, with no manual intervention required. This is the expected behavior for any persistent remote connection (SSH keep-alive, WebSocket reconnect, etc.).
The connection should be resilient to:
Network interruptions (WiFi switching, cellular handoffs)
iOS app backgrounding and foregrounding
Idle timeouts
Transient server-side disconnects
Error Messages/Logs
Steps to Reproduce
Leave a /remote-control session running and watch it fail to reconnect after a few hours.
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.76
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
No response