Remote control bridge should auto-refresh OAuth token before expiry

Resolved 💬 3 comments Opened Mar 20, 2026 by syd3n Closed Apr 18, 2026

Summary

The remote control bridge silently dies when the OAuth token expires mid-session. The heartbeat fails with a 401 and the session becomes unrecoverable — but the bridge keeps polling as if nothing happened, giving no indication to the user that the session is dead.

Steps to reproduce

  1. Start a remote control bridge: claude remote-control --spawn same-dir --verbose
  2. Connect from a mobile device and use the session normally
  3. Wait ~5 hours
  4. Heartbeat fails with: Authentication failed (401): Token expired. Remote Control is only available with claude.ai subscriptions.
  5. Session is dead — bridge continues polling but no work comes in

Expected behavior

The bridge should proactively refresh the OAuth token before it expires, keeping the session alive indefinitely (or until the user disconnects).

Evidence that token refresh already works

The bridge does successfully refresh the token in other code paths. During shutdown, the stop-work call gets a 401, refreshes the token, and retries successfully:

[bridge:api] StopWork: 401 received, attempting token refresh
[bridge:api] StopWork: Token refreshed, retrying request
[bridge:api] POST .../work/.../stop -> 200

So the refresh capability exists — it is just not wired into the heartbeat loop.

Why this matters

The primary use case for remote control is controlling Claude Code from a phone while away from the laptop. If the token expires mid-session, there is no way to recover — the user cannot run /login from their phone since the bridge runs on the laptop. The session silently dies and the user loses access until they are physically back at the machine.

Suggested fix

  • Proactively refresh the OAuth token before TTL expiry (e.g., at 80% of TTL)
  • Or at minimum: catch 401 on heartbeat, refresh the token, and retry — same pattern already used in the stop-work path
  • If refresh fails, surface a clear error to the connected client rather than silently continuing to poll

Environment

  • macOS (Apple Silicon)
  • Claude Code CLI (latest as of Mar 2026)
  • Session duration before failure: ~5h 14m
  • Bridge continued polling for ~1.5h after token death before manual SIGINT

View original on GitHub ↗

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