Honest limitations

The tradeoffs that come with per-session account placement

  • A move restarts the process. A session changes account only by respawning under another store: the supervisor stops claude, at the committed turn boundary when a hook triggered the move or as soon as its own seat watch reads the seat at a bar, and resumes the same conversation, so the transcript survives but the process does not, a turn in flight is cut (its completed steps are in the transcript, the step in progress is not), every background Bash task, Monitor, and Workflow run the session started ends (the resume prompt asks Claude to relaunch what the task still needs), anything typed in that split second is lost, and the first turn on the new account rebuilds its prompt cache (caches are never shared across organizations, and a same-organization move can miss too). A bar-triggered move compacts the conversation on the account it leaves first, which takes up to a few minutes and trades the full history for a summary (a compaction that does not land leaves the full context); a move after a refusal cannot compact and re-uploads the full context. See the measured profile.
  • Cached targets. A move reads cached figures; the periodic check samples up to three accounts per tick, live seats first, each at most once per sample interval, so a figure is about one interval old: with the default policy.usagePollTtlMs, 15 minutes for an empty account or one with no session or borrower on this host, down to 90 seconds for a live one near a bar. Use from another host or from claude.ai therefore shows on an idle account up to 15 minutes late. A figure can be older by one tick per three pooled accounts, older when its samples keep failing, frozen while Claude Code cannot refresh an expired stored access token, and frozen for an account flagged for reauthentication until you run auth.
  • Sample interval on a seat with no tee. A pi session and a borrowed seat (tokenmaxxing seat) push no tee, so the seat's figure comes from these samples alone. A session that uses its whole session bar within 15 minutes of a sample that read its account empty crosses the bar before the next sample. When the server refuses a turn of a Claude Code session, the StopFailure hook runs the move decision. A pi session runs no hook, so the server refuses its turns until the next sample reads the account at the bar.
  • Early reset on an exhausted account. An account at or over an aggregate bar is sampled every 15 minutes, because a scheduled reset already reads as 0. An early server-side reset, such as a manual one, shows only in a sample, so the account stays screened for up to 15 minutes after it.
  • Depleted-pause hiccup. Only a fully depleted pool stops the session for the countdown; anything typed in that split second is lost.
  • Interrupted turn. When a supervised turn dies on an enforced limit, the relaunch on the fresh account resumes the transcript and asks Claude to continue from where the previous turn left off; the interrupted turn itself is not replayed.
  • Input in flight at a move. The supervisor polls for the respawn marker every 150 ms, so in a terminal session a message sent between the end of the turn that triggered the move and the kill reaches the process about to be stopped, as does any message Claude Code had queued during that turn; the relaunch does not replay either. Send the next message after the resume prompt's reply. A stream-json session's input is queued by the supervisor across the restart and replayed after the resume prompt.
  • Unsupervised sessions are not moved. A claude started outside the supervisor (an editor integration, a script calling the binary by path, claude -p) runs on whatever login its environment names, by default Claude Code's own store, and tokenmaxxing never writes that store: such a session is never moved and its usage is not attributed to a pooled account. When a hard limit lands there, the StopFailure hook names the way out: it prints the shim command, ~/.config/tokenmaxxing/bin/claude --resume <session-id>, as a system message, so you can hand the session to the supervisor for a fresh account. A session that a supervised session spawns inherits its store and runs on the same account.
  • A live status samples under the pool lock. status without --cached samples every account whose tee is stale (the direct usage read) while holding the pool lock, so a hook decision or a launch that arrives meanwhile waits for it to finish; status --cached reads nothing but the state files. An account whose stored access token has expired adds a claude refresh child, about 3 seconds in the observed case, before its read.
  • A lent Claude account stays put. A consumer that borrows with seat <pid> runs no supervisor, so it never moves: at a bar it keeps running on its account until the server refuses it. Its figure comes from the check tick, which samples accounts with a live record first. On macOS a store's credential is a keychain item named after the store directory, so the printed directory works for a process on the same host and not inside a Linux container. See Lending a Claude store.
  • One shared identity file. ~/.claude.json keeps a single oauthAccount, which Claude Code rewrites after whichever session refreshed last, so the email /status shows can belong to another session's account. The credential a session uses is the one in its store regardless.
  • Plaintext credentials on Linux. Claude Code itself stores Linux credentials as a 0600 plaintext file; a store follows the same model.
  • API-key credit is an estimate. The credit left on a key is the balance you entered minus the cost Claude Code estimates on the client for the supervised sessions on this host. Spend by other hosts, by other tools, and by claude processes outside the supervisor is invisible, and so is the compaction that runs before a move off a key. Anthropic offers no API that reads a key's balance, so re-enter it with tokenmaxxing key credit <label> <usd> from time to time. The only refusal tokenmaxxing recognizes is the billing_error a turn ends on when the balance is too low; a workspace spend limit arrives as unknown and a 429 spend cap as rate_limit, and neither moves a session off the key.
  • API-key mode is Claude only. The Codex pool, pi sessions, and seat borrowers never run on a key.
  • A key session leaves a key at a turn boundary. A session on a key returns to a usable subscription account only when a turn ends (or at session start), so a long turn or a harness session that runs background work between prompts keeps spending on the key until its turn ends.
  • The status-only grok pool does not switch. grok status shows the weekly subscription credit window. The pool has no supervisor or move; see Status-only pools.
  • One pool per host. Pooling the same accounts on several machines works because each host logs each account in separately and so holds its own grant; grants of one account do not interfere with each other. What breaks is one grant in two places: on Claude a refresh rotation revokes the previous access token immediately, so a copied store fails with 401 on the other side and its stale refresh token comes back invalid_grant (needs-reauth); for Codex a refresh from a stale copied store is fatal to that login (OpenAI invalidates the whole grant family on refresh-token reuse, forcing auth on every host). Never copy a store between machines; log in on each.