Frequent forced re-login when many concurrent sessions share ~/.claude (refresh-token rotation race?)
Summary
With many concurrent Claude Code CLI sessions sharing one ~/.claude/.credentials.json, the OAuth login is force-expired roughly weekly (sometimes more often), requiring /login again. Single- or low-concurrency machines on the same account are affected far less. We suspect a refresh-token rotation race between concurrent processes.
Environment
- Claude Code 2.1.228–2.1.240 (multiple long-running sessions across versions)
- Linux VPS (Ubuntu), 10–24 concurrent interactive CLI sessions in tmux under one OS user, shared
~/.claude - Second machine: macOS, normal usage, same subscription (Max)
- Auth: claude.ai subscription OAuth via
/login
Observed
~/.claude/.credentials.jsonaccess tokenexpiresAtis ~8h; the file is refreshed continuously by whichever process needs it.- At unpredictable intervals (≤1 week) all sessions on the machine drop to
Login expired · Please run /login; freshly spawned sessions start logged out. - The in-terminal 3-day expiry warning is easy to miss in headless/tmux operation.
Hypothesis
Multiple concurrent processes read the same credentials file and independently attempt token refresh. If refresh tokens are rotated server-side, two near-simultaneous refreshes can invalidate the chain (the loser presents an already-rotated refresh token), killing the login for the whole machine. There appears to be no cross-process lock/serialization around the refresh in the CLI (not documented, at least).
Ask
- Serialize token refresh across processes (file lock around read-refresh-write), or tolerate a concurrent-refresh grace window.
- Document the behavior/limits for multi-session setups.
- A machine-readable way to query login health/expiry (for external monitoring) would help headless setups a lot.
Happy to provide timestamps/logs on request (credentials contents obviously excluded).