[BUG] macOS Remote Control server: claude.ai keychain login gets wiped blank every 2-7 days (refresh-token race), no headless recovery

Status Open
Reported on v2.1.284
Maintainer reply None cached
Activity 1 comment · opened Oct 3, 2026

Preflight Checklist

  • [x] I have searched existing issues. Closest: #76905 (closed by the inactivity bot, same keychain race), #90697 and #88054 (open, Remote Control auth). This adds a reproducible Remote Control server data set on current versions.
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code available to me (2.1.284)

What's wrong?

On an always-on Mac mini running claude remote-control in server mode, the claude.ai subscription login in the macOS Keychain item Claude Code-credentials is periodically written blank: claudeAiOauth.accessToken and refreshToken become empty strings and expiresAt becomes 0, while the subscription metadata in the same item stays intact. From that moment the server can't serve the phone. The Claude iOS app either can't reach the device or doesn't list it, and nothing recovers until someone physically at the machine runs claude auth login --claudeai.

Four occurrences in 16 days:

| Login wiped (CT) | CLI | What was running |
|---|---|---|
| 2026-09-15 10:38 | 2.1.263 | server + phone-spawned sessions |
| 2026-09-18 ~01:06 / 09:42 | 2.1.263 | server logged Failed to refresh session cse_... token: Remote Control is only available with claude.ai subscriptions; the first phone session of the day then died with OAuth session expired and could not be refreshed, after which the keychain item was blank |
| 2026-09-28 13:41 | 2.1.276 | server only, after 7 days up |
| 2026-09-30 05:49 | 2.1.284 | server only, 37 hours after a fresh login; no session transcript has activity at that time |

Upgrading (2.1.263 → 2.1.276 → 2.1.284) did not change it.

What should happen?

A long-running Remote Control server, the sessions it spawns, and any other Claude Code process on the same account should refresh the rotating OAuth token without invalidating each other. If a refresh does fail, the existing credential should not be overwritten with empty tokens, and there should be some way to re-authenticate a headless Remote Control host remotely. Today the only fix needs the machine's own keyboard, which defeats the purpose of Remote Control when you're travelling.

Setup

  • macOS 26 (Darwin 27.0.0), Apple Silicon Mac mini, always on (sleep disabled)
  • Claude Code 2.1.284, npm global install
  • Max subscription, claude.ai OAuth login in the login Keychain
  • claude remote-control --name "<host>" --permission-mode auto --capacity 24, started by a launchd user agent (KeepAlive) inside a detached screen session
  • Same account and same keychain item also used on that machine by the Claude desktop app's Code tab, and by sessions spawned from the iOS app (claude --print --sdk-url ... children of the server)

Related observations

  • Zombie server: once the login is wiped, the remote-control process does not exit. It stays up looking healthy to launchd, so KeepAlive never helps. It also ignores SIGHUP, so screen -X quit and launchctl kickstart -k don't stop it; only pkill does.
  • The documented workaround is not usable: claude setup-token / CLAUDE_CODE_OAUTH_TOKEN makes claude auth status report logged in, but claude remote-control refuses it ("Remote Control requires a full-scope login token. Long-lived tokens ... are limited to inference-only"). So there is no headless-safe credential for Remote Control.
  • claude auth status is unreliable inside a desktop-app session (host auth env vars are injected), so diagnosing this from a Claude session on the same machine gives misleading answers. Reading the keychain item's token lengths is the only reliable check.

Workaround I'm using

A launchd watchdog checks every 5 minutes for blank keychain tokens (or the "only available with claude.ai" message on the server's screen). When it finds one, it kills the server and sends a Slack alert. Re-login is then done by a script that runs claude auth login --claudeai in a detached screen, sends the sign-in URL to my phone, and pastes the returned code. It works, but it shouldn't be needed.

Steps to reproduce

  1. Log in with a claude.ai Max account on macOS (keychain storage).
  2. Run claude remote-control in server mode under launchd and leave it up.
  3. Use it from the iOS app on and off for a few days, while also using the desktop app on the same machine.
  4. Within 2 to 7 days, security find-generic-password -s "Claude Code-credentials" -w shows claudeAiOauth with empty access and refresh tokens, and the device is unreachable from the phone.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗