Skip to content

feat(accounts): automatic Claude account failover on the 5-hour limit - #1250

Open
fabianthegiant wants to merge 1 commit into
eneskirca:mainfrom
fabianthegiant:feat/claude-account-failover
Open

fabianthegiant wants to merge 1 commit into
eneskirca:mainfrom
fabianthegiant:feat/claude-account-failover

Conversation

@fabianthegiant

Copy link
Copy Markdown

When a Claude account hits its 5-hour session limit, every session on it stops until the window resets, even if a second logged-in account is free. This adds an opt-in failover: pick a primary and a secondary account in Settings → Accounts. While the primary is in its 5-hour limit, its idle local Claude sessions move to the secondary and continue the same conversation. Once the primary is free again, exactly those sessions move back.

Every move is the existing "Switch Claude account" choreography (runClaudeAccountSwitch: quit, copy the transcript, rebind, recycle + --resume), so no new switching path exists.

Behaviour

  • Only a fresh ok usage read decides (failoverLimitState). Error, held last-good numbers or a missing session window means unknown, and nothing moves.
  • Nothing moves in the edge cases: the primary in its weekly limit, the secondary limited or unreadable, busy (working/blocked) sessions, SSH nodes or SSH projects, relay tabs. A model-scoped weekly cap does not count as a weekly limit.
  • Moved nodes carry a persisted data.claudeFailover mark, so the way back survives a restart and only those nodes return. A manual switch clears the mark: the beforeRecycle patch always carries the key, which is undefined on a manual switch.
  • Cost: a 60 s Canvas tick calls usage.fetch(primary), which the usage service mostly answers from its 5-min cache. There is one forced refresh once the session reset time has passed (at most every 2 min). The secondary is read only when a move is due.
  • Off by default. The setting is settings.claudeFailover in machine-local settings.json, re-validated on read (resolveFailover), so a malformed value reads as off.

Surfaces

  • Desktop: full.
  • Server Edition: works in a browser tab, because both shells serve usage.fetch and claudeAccounts.copySession. It runs only while a tab is open, and only a visible tab acts, so two tabs do not both switch one session. Headless installs have no tab, so they do not fail over.
  • Kanban: nothing to add (nodes are moved, not cards).
  • Mobile: N/A.

Why renderer-side

The switch choreography (the CLI exit, the restart closure, the beforeRecycle merge) lives in the renderer. A core-side watcher would need a second, headless switch path. I chose to reuse the existing one, at the cost of needing an open window or tab. Moving it to core, so a headless server fails over without a tab, is the obvious follow-up.

How it was checked

  • npm run typecheck, npm run build and the full npm test pass locally (1626 files passed, 9 skipped).
  • New unit tests in src/renderer/canvas/claude-failover.test.ts cover settings validation, limit classification and the move/return planning, including every no-move edge case.

Not verified: a live run with two real accounts actually hitting the 5-hour limit (detection, the move and the move back in a running app), the Server Edition tab-visibility gating in a real browser, and macOS/Windows.

Known limits

  • Detection lag: cache plus tick means up to ~6 min before a reached limit is noticed.
  • Active project only: the watcher sees only the active project's canvas. Sessions in other projects move when that project is opened.
  • New sessions: they still open on the picked or default account, not on the secondary.

Docs: docs/claude-account-failover.md (user-facing) and a bullet under Managed Claude accounts in CLAUDE.md.

🤖 Generated with Claude Code

Settings → Accounts gains "Automatic Claude failover": a primary and a
secondary local Claude account. While the primary is in its 5-hour session
limit, idle local Claude sessions on it move to the secondary through the
existing "Switch Claude account" choreography (quit, copy transcript, rebind,
recycle + resume), and move back once the primary is free again.

Only a fresh usage read decides. A weekly-limited primary, a limited or
unreadable secondary, busy sessions, SSH nodes and relay tabs never move.
Moved nodes carry a persisted `claudeFailover` mark so only they return, and
a manual switch clears it. Off by default; works on the desktop and in a
Server Edition browser tab (only a visible tab acts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fabianthegiant

Copy link
Copy Markdown
Author

We heavily use claude team plan and only have 5h limit. For claude to run indefinitely I want to use 3 Team plans in parallel. For that I've expanded your already existing account switching feature and added limit detaction and automatic switching of accounts. I released it under the branch feat/claude-account-failover. If you think that is usefull please merge that into main would greatly appriciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant