Fixing Claude Code OAuth token revoked when switching accounts
Claude Code caches OAuth tokens in at least four places: environment variables, macOS Keychain, dotfiles, and XDG config directories. When you switch from one Anthropic account to another — say, moving to a different Max plan email — the old token stays cached and you get a "token revoked" error on every launch. The CLI never prompts you to re-authenticate because it thinks it already has a valid token.
The fix is a full credential purge. Here's every location you need to hit:
1. Remove hardcoded tokens from your shell config
sed -i '' '/CLAUDE_CODE_OAUTH_TOKEN/d' ~/.zshrc
If you exported the token directly in .zshrc or .bashrc at any point, that stale value loads before Claude Code even starts. Delete the line.
2. Unset lingering env vars in the current session
unset CLAUDE_CODE_OAUTH_TOKEN
unset ANTHROPIC_API_KEY
source ~/.zshrc
The shell session still holds the old value in memory even after editing the file.
3. Clear macOS Keychain
security delete-generic-password -s "Claude Code" 2>/dev/null
Claude Code stores credentials in the system keychain. This survives shell restarts and even npm updates.
4. Delete all cached credential directories
rm -rf ~/.claude
rm -f ~/.claude.json
rm -rf ~/.config/claude-code/
rm -rf ~/.config/@anthropic-ai/
Four separate locations. Miss one and the stale token comes back.
5. Clear tmux environment (if applicable)
Tmux maintains its own environment that survives terminal restarts. If you use tmux: tmux set-environment -gu CLAUDE_CODE_OAUTH_TOKEN or just tmux kill-server before reopening.
6. Restart terminal completely
Close the terminal app entirely and reopen. source ~/.zshrc is not enough — some env vars get inherited from the parent process.
7. Update Claude Code
npm update -g @anthropic-ai/claude-code
8. Login fresh
claude
When the OAuth page opens, use an incognito browser window. This prevents your browser's cached Google/Anthropic session from auto-selecting the wrong account. Pick the correct Max plan email explicitly.
If you use multiple accounts permanently, isolate their configs to prevent the Keychain collision entirely:
alias claude2='CLAUDE_CONFIG_DIR=~/.claude-account2 claude'
Now claude uses your primary account and claude2 uses the second. Separate config dirs, separate Keychain entries, no overwrites.
The root cause: OAuth token caching is distributed across shell config, OS keychain, and multiple XDG directories. There's no single claude logout that clears all of them. When switching accounts, you need to scorched-earth the credential layer and start clean.