I have two Claude accounts and I keep signing in and out of Claude Code. Can this fix that?
That is the whole point. Claude Account Switcher keeps a saved copy of each login and puts the one you pick back in place — from its window, or from the icon up top without leaving what you are doing: the tray on Linux, the menu bar on macOS.
One switch covers both places you use Claude Code: the CLI and the VSCode extension read the same login files, so the editor comes along with the terminal.
What does it actually touch on my machine?
Your login, in the two pieces Claude Code keeps it in — and of the second one only the handful of keys that say who you are.
What gets copied
~/.claude/.credentials.jsonthe OAuth token, whole — on macOS the login keychain, underClaude Code-credentials~/.claude.jsononly the account keys —oauthAccount,userID, …
Where it lands
~/.config/claude-switch/profiles/<id>/one folder per saved account~/.config/claude-switch/backups/a snapshot on every switch
~/Library/Application Support/claude-switch/ instead.The rest of ~/.claude.json — your projects, history and preferences — is left
exactly as it is, and every write is atomic, so an interrupted switch cannot leave you
with half a config.
On macOS the app writes wherever it finds the login: if the keychain already holds an entry it uses that, otherwise it falls back to the file. Either way the CLI reads the right account, whichever of the two routes your installed version takes.
One detail worth knowing: right before each switch the live credentials are copied back into the profile you are leaving. Claude Code rotates tokens while you work, and without that step you would be saving a token that has already moved on.
How do I see that an account is running out?
Every account carries two meters: the 5-hour session and the week. The filled part is what that window has spent; the marker on the bar is a threshold you can drag.
The numbers come from GET https://api.anthropic.com/api/oauth/usage, the same
endpoint Claude Code reads for its own /usage, called with that account's
token.
It is not a public API. Its shape can change without notice, so every field
is treated as optional: if one is missing the bar shows — and nothing
downstream fires.
The accounts that are not active are read with their stored token, and the app
keeps that token alive itself rather than waiting for Claude Code to do it — so the
meters no longer go blank on an account nobody has run claude under
lately.
How often does it ask? That endpoint is not yours to hammer.
It is not, and an earlier version found the edge the hard way: one request per account per minute earned exactly the refusals that rate predicts.
The budget it now paces itself by is not our measurement. It comes from realiti4/claude-swap, which probed the endpoint deliberately and wrote down the method and the dates: roughly 28–30 requests an hour per account, over a trailing 60-minute window rather than a bucket that refills. So each account carries its own schedule.
- 3 min
- the floor, and as long as a reading counts as fresh
- 5 min
- the active account, once nothing is moving
- 10 min
- another saved account — or one already spent, which is asked slowly but never abandoned: a grant can free it early
- 1 min
- the active account within 15 points of its threshold and actually moving — the case the whole thing exists for
- 6 → 30 min
- after a refusal, backing off while they keep coming
The cache lives on disk, cooldowns included, so a restart does not put every account back in the queue at once — a burst is the thing that saturates the hour. A refusal is about the account behind that one token, so the others keep being read; and rather than blanking its meters, the app keeps showing the last numbers it knows.
Which is why cards say how old their numbers are once they pass five minutes — “numbers from 3h ago” — and so does the tray menu, where a frozen number is easiest to mistake for a live one. Kept numbers that look freshly loaded are how a spent account appears to have room left.
Can it switch by itself when one account runs dry?
That is what those thresholds are for. Drag one to say how full a window has to be before the account counts as spent — 100% by default, so out of the box nothing happens until you actually hit the limit.
With auto-switch on, every reading of the active account is also a decision: as soon as either counter reaches its own threshold the app moves to the next account in list order. Which means it is checked as often as the schedule above says — down to the minute when it is close and still climbing.
- A candidate already past its own thresholds is skipped.
- If nobody is available, the app says so and stays where it is.
- An account whose usage cannot be read is treated as usable. Better to try the switch than to sit still on a network error.
- Nothing acts on a reading older than 15 minutes. Showing an old number is fine — the card says how old it is — but a five-hour window that has since reset still reads as full in the cache, and rotating accounts on that is a switch nobody asked for.
You can watch it happen without opening the window: the menu behind the icon up top lists every account with both of its percentages. Within 5 points of a threshold a ⚠ appears next to the name, and the icon itself picks up a warning badge.
Can it just open on whichever account has the most left?
Start on the freest account, in Settings, off by default. Once per launch it puts you on the account with the most week left — and “most” is a ratio, not a percentage:
room per day = (100 − week used) / days until the week resets
So 20 points to make six days last is a tighter week than 70 points for one day, and the second account wins. Below a day the divisor stops falling: a window resetting in ten minutes is not a reason to start on an account with nothing left in it right now.
It is deliberately quiet about the cases it declines. An account whose usage cannot be read is not a candidate — a comparison against a blank is not one — and a login the app has never saved is left alone until you save it. When it does move, the window says which account it landed on and why.
How do I add the second account in the first place?
Claude Code owns the login flow, so the app works around it rather than through it — three steps, all in the Add account dialog:
And if you are already signed in the first time you open the app, you do not need any of that: a “Login not saved” banner offers to capture the account you are on with a single press. Save current login, at the bottom of the window, is the same thing later on — for when you signed in outside the app and want the saved copy brought up to date this second.
Do the saved tokens go stale while they sit there?
They used to. Claude Code owns the login flow, but not the renewal: the refresh token it stores was issued to its own public client, so the same grant works from here and produces exactly the credentials the CLI would have written.
A pass every 20 seconds reads a few expiry dates off disk and sends nothing at all unless something is due — a stored account 30 minutes before it expires, the live login only within 5 minutes of it, the same window Claude Code would refresh in.
Renewing the live login does not need Claude Code closed. The write goes through the very lock the CLI takes for its own, and the file is re-read inside that lock: if a session renewed first, this app stands down rather than overwriting.
A lock whose timestamp has stopped moving for 15 seconds is treated as abandoned and cleared — which is also the cure for Claude Code's own “another Claude Code process is refreshing it or exited mid-refresh”, left behind by a session that died mid-write.
A refresh token that has been revoked or already spent cannot be renewed by anyone. The
app says so once, and that account needs a fresh claude login.
Does it switch Claude Desktop too?
No — and that is a decision, not an oversight.
The switch covers the CLI and the VSCode extension, which share the two pieces above.
Claude Desktop is an Electron app that authenticates like a browser: its session is a
sessionKey cookie inside the Chromium profile in ~/.config/Claude/.
Nothing in common with what this app moves, so it simply stays on whatever account
you signed it into.
It could be extended to cover it — the session is only a couple of hundred kilobytes of that profile — but it would mean closing Claude Desktop on every switch and chasing its updates. Not worth it, for now.
Anything I should know before handing it my logins?
Two things, plainly:
- Switch with Claude Code closed. The credentials go in under the
CLI's own lock, but
~/.claude.jsonis not covered by it, and a running session can rewrite the account keys there and undo the switch. Renewing a token is the exception — that one is safe while Claude Code runs. - Tokens are stored in the clear, with
0600permissions — the same way Claude Code stores them itself. On macOS the live tokens sit in the keychain, but the copies in the app's own profiles are still0600files. This is not a keyring, and it does not pretend to be one.
Can it just be there when I log in?
Settings has four switches: auto-switch, start on the freest account, launch at login, and start in the bar — no window on startup, just the icon up top.
Closing the window leaves the app running behind that icon, and you quit it from its menu. Launching it again does not start a second copy: the new process hands over to the one already there, which brings its window back. On macOS, so does clicking the Dock icon.
The interface speaks English and Italian, follows your system by default, and changes language on the spot without a restart.
And that update at the top — does it install itself?
Only when you press the button. Every six hours, and once at launch, the app asks GitHub for the newest release — one unauthenticated request, nothing sent but a user agent. A newer tag puts a red dot on the gear in the title bar and the offer at the top of Settings, with what is out, what is running, and a link to the notes.
Pressing it downloads the package into your Downloads folder, checks its size against what
the release says, and hands it to the system package manager under
pkexec — polkit puts up its own password dialog and takes the password
itself. This app never sees it, and dismissing that dialog is reported as cancelled, not
as a failure.
What no package manager takes is still handed over: a .dmg is mounted, an
AppImage is shown in its folder rather than opened — opening one would only start a
second copy of the app.
Tags are compared as three numbers, and anything else — a
-beta.1, a nightly — never counts as newer: guessing where it
sorts is how an app talks someone into a downgrade. And installing does not replace the
copy already running. Quit from the menu up top and start it again to be on the new one.