I run three Claude Max plans on one Mac and want sessions live on all three. Claude Code offers /logout and /login. The community switchers all set CLAUDE_CONFIG_DIR to a second directory, which leaves you with two of everything: plugins, skills, settings, transcripts. Theo Browne on the alternative:

Warning to Claude Code account switchers: multi-account on the desktop app is NOT VIABLE. You have to hard log out and you will lose all your sessions. CLI doesn’t care at all, you can just /login in a different tab and all traffic gets routed correctly on existing runs.

— Theo Browne, June 10 2026

I wanted one of everything and three logins.

The Account Is One Keychain Entry

In the 2.1.278 binary, the Keychain item is Claude Code-credentials plus the first eight hex characters of sha256 of the config directory. No CLAUDE_CONFIG_DIR, no suffix. On Linux the login is .credentials.json inside the directory. A second account needs a second directory and nothing else.

Everything Shares Except History

I symlinked the new directory back to ~/.claude and ran a session.

  • Shared fine: projects (transcripts, --resume, memory), plugins, skills, commands, hooks, settings.json, CLAUDE.md, plans, file history.
  • Per account: .claude.json, which holds the login metadata and the paired browser.
  • Refused: history.jsonl. The reader rejects symlinks (not_regular) and hard links (multiply_linked). Prompt history stays per account.

One trap: /login inside a seat rewrites that seat’s Keychain item, so the seat now belongs to the other account.

The Usage Endpoint

/usage reads an OAuth endpoint, and its limits array holds a weekly bucket scoped to one model. My account once read 57% of the week and 87% of the Fable bucket. Either can end a seat’s week, so the picker ranks by whichever is tighter, then the five-hour window.

Don't poll it like a dashboard

A statusline polling once a minute got a 429 with a 258-second retry-after. ccseats caches per seat, asks at most every two minutes, and honours retry-after.

Idle seats have expired tokens. ccseats shows their cached numbers instead of refreshing, because racing Claude Code on a rotating refresh token can sign a seat out. An idle seat cannot use more quota, so the cache is an upper bound.

Chrome Checks Nothing

The Chrome bridge is a socket directory per OS user, not per account. Every window appears in every account’s /chrome list, and one account drove another’s window without complaint. Only a device id in each seat’s .claude.json keeps them apart. Name your windows before pairing.

Limits

  • Undocumented internals. The Keychain name, the endpoint and its payload can change in any release. The table flags a mismatch when it sees one.
  • Policy. I found no Anthropic text on multiple subscriptions. T3 Code closed its own auto-failover PR, saying it “needs stronger recovery semantics and a separate design.” The picker ships off.
  • Shared settings. A /model change in one seat changes all three.

Try It

ccseats is one zsh script. ccseats add work builds a seat, ccseats status prints the table, and ccseats statusline shows what is left of the session, the week and the model bucket.