Why Claude sessions keep dying on limits and "login expired," what the investigation actually found, and the decisions that make it stop.
2026-08-31 · status: Proposed — pending Fede's picks · three-agent investigation (14-day forensics, mechanism audit, official docs); nothing has been changed anywhere
The rotation almost never fails at switching — it fails because there is nothing left to switch to, and it can't tell. Eight Claude engines and ~263 sessions a day share one machine-wide login. The rotator has fresh usage numbers for only the account it's already on (the other eleven read "stale"), and the limits that actually killed sessions — the Opus weekly cap, "out of usage credits" — are ones it doesn't measure at all. Result: 1,860 of 1,862 rotation decisions in four days were "nowhere to go," a 31-minute morning outage where it logged "account unusable" 204 times without switching, and you typing /login by hand 13 times in 26 hours.
The keychain theory is dead. Both keychains are set to never lock, the mini never sleeps, and the account bank moved to its own always-unlocked vault on Aug 12. The handful of real "keychain" errors were a write-permission ACL bug (3 scheduled fires) and background jobs having no GUI session (4 events, one evening, pre-migration code) — none was a lock. Moving credentials to env/files is still the right direction, but for a different reason: it's what makes per-terminal accounts possible.
What the 14-day record shows
Exhaustion, not mechanics: ~590 account switches succeeded with only 4 mechanical failures — but the fleet was parked "ALL CAPPED" 28 times (once for 5 hours, once for 4).
Blind meters: sessions died on limits while the rotator's own meter read healthy (weekly 25–30%) — the Opus-specific weekly cap and usage-credit exhaustion are invisible to it.
Half the pool is dark or broken: 6 of 12 accounts are manual-only by your Aug 27 ruling; 2 more have silently dead logins since Aug 27 (revoked refresh tokens) — effective auto-pool: 6 accounts for the entire fleet.
The backup token lane is mis-wired: six fresh year-long tokens (minted Aug 27–28) sit unused because the token rotator reads the old folder holding two dead ones; the global env pin was removed Aug 30 because it glued everything to one account.
Policy leaks: the auto-rotator once switched to gera@ (manual-only), and the lease system allowed 8 simultaneous claims on gera@ from one machine — the mutex doesn't mutex.
RESOLVED (Aug 31 follow-up) — the MiniClaws Mac is Gera's Mac mini. AWS audit logs show its pool reads authenticated as Gera's admin user, from the same home network as his laptop. His fleet currently holds 7 concurrent claims on his own account and is also leasing Fede's personal account (as is his laptop) — while Fede's own fleet sat parked "ALL CAPPED" this morning. The two founders' fleets are silently competing for the same accounts.
RESOLVED (Aug 31 follow-up) — why the rotator is blind: two causes, both verified. (1) The usage-refresh job was never scheduled anywhere — no background job on the mini ever runs it; fresh numbers exist only for the account currently in use. (2) The shared pool's write ownership is currently held by Gera's mini, and Fede's machine correctly refuses to refresh login tokens it doesn't own — so 10 of 11 banked accounts on Fede's mini read "stale" and stay that way.
Your laptop never went down — separate machine, separate login. That contrast is the whole redesign: separate logins don't fail together.
The look-alikes were myths this window: zero confirmed GitHub-401-from-locked-keychain or stale-cookie-403 incidents in 14 days. It's all account/token exhaustion.
Decision made — Aug 31, late morning
Fede called it: return to the original, pre-pool setup. "I had no issues with that." Executed the same morning, after tracing the history:
Aug 9 — Fede's machine backs up its own logins to private per-account entries in AWS. Local rotation, no sharing. Works fine.
Aug 24, 11:05–11:12am — Gera builds the shared pool, reads Fede's per-account entries, migrates them into it, and deletes the originals. Seven minutes.
Aug 27 — first collisions: two service accounts die of "revoked login" (two machines refreshing the same account invalidate each other); the "nowhere to switch" spinning starts that evening.
Aug 28 — Gera's mini publishes Fede's six accounts into the shared pool document.
Aug 30, 9:13pm — Fede's machine gets the pool-aware switcher, which stops it refreshing its own stored logins (pool ownership sits with Gera's mini). The 13-manual-logins night begins hours later.
What was done: Fede's six accounts removed from the shared pool (it now holds only Gera's six); zero claims remain on Fede's accounts; Fede's machine restored to the last pre-pool switcher, which freely keeps his own six logins fresh again — the original working behavior. The pool lives on for Gera's fleet, untouched.
Still open: Fede signs out other devices on claude.ai for his personal account (kills the copies on Gera's machines — until then they can still burn his weekly limit); Gera drops Fede's accounts from his machines; the exposed email key still needs scrubbing + rotation (R4).
The original decisions (R1–R3 overtaken by the rollback; kept for the record)
Answers save and are shared. Recommended option marked.
R1 · The cheap repairs (bundle)
Unblind the rotator (scheduled usage refresh for all accounts, so "no candidate" means it, not "can't see"); point the token rotator at the folder with the six fresh tokens; make "out of usage credits" / Opus-cap errors count as switch triggers even when the meter reads healthy; re-login the two dead accounts; fix the two policy leaks (manual-only never auto-picked; one lease per account actually enforced).
R2 · The structure: who runs on what
R3 · The six-account ring (your Aug 27 lock)
R4 · Hygiene found along the way
Item (2) is now answered: the MiniClaws lessee is Gera's Mac mini (verified via AWS audit logs — his admin credentials, his home network). So the remaining actions are: (1) scrub the plaintext SendGrid email key from the local session transcript and rotate the key; (2) agree with Gera which accounts his fleet may lease — today it leases Fede's personal account — and enforce one-lease-per-account for real.
Notes
Appendix — the record behind the claims
Full handoff with file paths and mechanism map: ~/.claude/handoffs/account-rotation-rethink-2026-08-31.md. Raw investigator reports live in session 004's task outputs.
Rotation log, 4 days: 1,942 events → 1,936 "no candidate", 1 rotate. Daemon log, 14 days: ~590 switches OK, 4 failed (all Aug 27, background-session errors), 28 ALL-CAPPED parks, ~3,800 no-op "recovery" ticks; Aug 31 morning: 204 "unusable" ticks in 31 min, then a 291-minute park.
Died-while-meter-said-healthy: Opus weekly cap at meter 14%/30% (Aug 30, two build agents); out-of-credits at 72% and 25% (Aug 30, two sessions).
Keychains: login + bank both "no-timeout"; sleep disabled; exit-195 = ACL write error on 3 scheduled fires; the scheduled-fire log has been dead since Aug 28.
Officially supported per-process auth: a year-long token from claude setup-token in CLAUDE_CODE_OAUTH_TOKEN, or an API key, or a refreshing helper script; limits are per account, pooled across devices.
Aug 31 follow-up (all verified read-only): usage refresh was never scheduled (no background job runs it — zero refresh events in the rotation log); pool write ownership held by Gera's mini, which locks Fede's machine out of refreshing its 10 banked accounts; live lease table shows Gera's mini + laptop holding leases on his account and on Fede's personal account; AWS audit log ties MiniClaws to Gera's admin user on his home network; Fede's fleet parked "ALL CAPPED, wake in ~5h" at 09:31 this morning with his account at 80% weekly.