Summary
On macOS, Claude Code stores its OAuth credentials in the login keychain (generic password, service Claude Code-credentials), not in ~/.claude/.credentials.json. This switcher only ever reads/writes that file, so on a default macOS install it cannot work:
- listing / syncing fails with
ENOENT: ... open '~/.claude/.credentials.json'
- even if a switch "succeeds", it writes a file that Claude Code never reads, so the active account never actually changes.
The README lists macOS as supported, but the keychain case isn't handled.
Reproduction
Fresh macOS install of Claude Code (credentials in keychain, no .credentials.json on disk):
npx claude-code-multi-accounts install
cc-switch
# Switch failed: ENOENT: no such file or directory, open '/Users/<me>/.claude/.credentials.json'
Confirm credentials are in the keychain:
security find-generic-password -s "Claude Code-credentials" -w
# -> {"claudeAiOauth":{...},"mcpOAuth":{...}}
Cause
bin/lib/store/io.cjs hardcodes the file path and uses fs for all credential I/O:
function getDefaultCredentialsPath() {
return path.join(os.homedir(), '.claude', '.credentials.json');
}
// readJson / writeJson / backupFile all assume a real file on disk
There's no keychain code path, so on macOS the credentials are invisible to the tool.
Suggested fix
When process.platform === 'darwin' and the credentials file is absent, bridge credential I/O to the keychain via the security CLI:
- read:
security find-generic-password -s "Claude Code-credentials" -w
- write:
security add-generic-password -U -s "Claude Code-credentials" -a <account> -w <json>
(-U updates the existing item; <account> is the existing item's acct)
- backup: dump the current keychain value to the backup dir before overwriting (the file
backupFile step has no effect when there's no file).
The stored value already has the exact shape the tool expects ({ claudeAiOauth, mcpOAuth } → credentials.claudeAiOauth), so only the I/O layer needs to change; the rest of the switch logic works unchanged.
I patched io.cjs locally along these lines and the full flow (sync / list / switch, with pre-switch keychain backup) now works on macOS, preserving both claudeAiOauth and mcpOAuth. Happy to send a PR if useful.
Environment
- macOS (Darwin), Node.js v25.9.0
- Credentials in login keychain (
Claude Code-credentials), no ~/.claude/.credentials.json
- Internal
STORE_VERSION 0.2.9
Summary
On macOS, Claude Code stores its OAuth credentials in the login keychain (generic password, service
Claude Code-credentials), not in~/.claude/.credentials.json. This switcher only ever reads/writes that file, so on a default macOS install it cannot work:ENOENT: ... open '~/.claude/.credentials.json'The README lists macOS as supported, but the keychain case isn't handled.
Reproduction
Fresh macOS install of Claude Code (credentials in keychain, no
.credentials.jsonon disk):npx claude-code-multi-accounts install cc-switch # Switch failed: ENOENT: no such file or directory, open '/Users/<me>/.claude/.credentials.json'Confirm credentials are in the keychain:
Cause
bin/lib/store/io.cjshardcodes the file path and usesfsfor all credential I/O:There's no keychain code path, so on macOS the credentials are invisible to the tool.
Suggested fix
When
process.platform === 'darwin'and the credentials file is absent, bridge credential I/O to the keychain via thesecurityCLI:security find-generic-password -s "Claude Code-credentials" -wsecurity add-generic-password -U -s "Claude Code-credentials" -a <account> -w <json>(
-Uupdates the existing item;<account>is the existing item'sacct)backupFilestep has no effect when there's no file).The stored value already has the exact shape the tool expects (
{ claudeAiOauth, mcpOAuth }→credentials.claudeAiOauth), so only the I/O layer needs to change; the rest of the switch logic works unchanged.I patched
io.cjslocally along these lines and the full flow (sync / list / switch, with pre-switch keychain backup) now works on macOS, preserving bothclaudeAiOauthandmcpOAuth. Happy to send a PR if useful.Environment
Claude Code-credentials), no~/.claude/.credentials.jsonSTORE_VERSION0.2.9