Operations 34 min read

Manage Multiple Claude Code Accounts with claude-swap: Switch, Auto-Switch & Run Simultaneously

This guide covers claude-swap, an open-source CLI tool that stores credentials for multiple Claude Code accounts, enables instant switching, auto-switches when usage nears limits, runs simultaneous accounts in separate terminals, and provides a TUI panel and macOS menubar for visual management.

Tech Ocean
Tech Ocean
Tech Ocean
Manage Multiple Claude Code Accounts with claude-swap: Switch, Auto-Switch & Run Simultaneously

Installation

claude-swap is a Python tool (requires Python 3.12+) distributed as the claude-swap package on PyPI. The CLI command is cswap (alias claude-swap). Prerequisites: Claude Code already installed and logged in at least once. Recommended install via uv as a global tool: uv tool install claude-swap Alternatively, pipx install claude-swap. To run from source, clone the GitHub repository realiti4/claude-swap, run uv sync, then uv run cswap help. After installation, cswap help lists all subcommands; legacy flags --switch and --list still work. Upgrade with cswap upgrade (auto-detects uv/pipx on macOS/Linux, prints command on Windows) or directly via uv tool upgrade claude-swap / pipx upgrade claude-swap.

Adding Accounts

Log in to the first account in Claude Code normally, then run cswap add. This copies the current credentials and account info into a stored "archive" at slot 1. For a second account, run /login in Claude Code to switch, then cswap add again to store in slot 2.

Critical pitfall: Do not run /logout before adding another account. Claude Code stores a refresh token locally for automatic access-token renewal. Newer Claude Code versions may revoke that refresh token on logout, invalidating the archive. Simply overwriting with /login preserves the previous account's archive.

Accounts are distinguished by email + organization. The same email under two organizations (e.g., personal subscription vs. company team) becomes two separate accounts. Re-running cswap add for an existing account updates its archive rather than creating a new slot — useful when a login expires.

Optional flags: --slot N to choose a specific slot (prompts if occupied), --alias name to assign a memorable alias (e.g., cswap add --alias work).

Adding via Token (No Browser)

On headless servers or when importing tokens from another machine, use cswap add-token. It auto-detects token type:

# Long-lived token from `claude setup-token`
cswap add-token sk-ant-oat01-...
# API key
cswap add-token sk-ant-api03-...
# Read from stdin to avoid shell history
cswap add-token - --slot 3
# Custom email label
cswap add-token sk-ant-oat01-... --email [email protected]

Tokens lack email metadata; without --email, placeholders like [email protected] (OAuth) or [email protected] (API key) are used. This step does not call Anthropic APIs. API-key accounts behave like others for switching but have no subscription quota, show no usage, are not skipped as "exhausted" during best-available selection, and are unsupported in session mode (Section 5).

Viewing Usage & Manual Switching

cswap list

shows per-account usage: last 5 hours, last 7 days, and any model-specific weekly limits (e.g., Fable). If weekly usage exceeds the daily-paced baseline by >15 percentage points, an (ahead of pace) marker appears (suppressed on the first day after weekly reset). cswap status shows the current default login. cswap list --token-status adds OAuth token diagnostics and source paths for troubleshooting.

Usage numbers refresh every few minutes; active/near-switch accounts are polled more frequently, exhausted accounts ~every 10 minutes, with backoff on rate limits. Timestamps like "6m ago" indicate the next check hasn't arrived yet, not a hang. cswap switch replaces the default login (the credentials Claude Code reads), affecting all terminals and the VS Code extension instantly on Linux/Windows (file ~/.claude/.credentials.json is reloaded on change). On macOS, credentials live in Keychain; Claude Code caches them ~30 seconds, so a restart or reopening the VS Code tab is needed for immediate effect.

Switching examples:

# Cycle to next account
cswap switch
# Switch to slot 2
cswap switch 2
# By alias
cswap switch work
cswap switch [email protected]

Automatic selection strategies:

# Most remaining quota
cswap switch --strategy best
# Next in order, skipping exhausted
cswap switch --strategy next-available
# Include Fable weekly limit in calculation
cswap switch --strategy best --model Fable
--model

accepts names from cswap list (case-insensitive, comma-separated, all for all). After switching, ongoing conversations can continue; alternatively restart Claude Code and use claude --resume. The first message on the new account may consume extra quota as the conversation cache rebuilds.

Auto-Switch When Near Limits

cswap auto

runs a foreground loop (default 60-second interval). When the default account's 5-hour or 7-day window reaches 90% usage, it switches to the account with the most remaining quota, aiming to switch before hitting the hard limit. Usage data follows the same refresh cadence; only when near threshold and rising does it poll every minute.

The 90% default threshold (not 100%) accounts for: (1) macOS Keychain cache ~30s delay, (2) heavy sub-agent turns that might exceed the limit before the switch takes effect.

Anti-flapping guards:

Cooldown: At least 5 minutes between proactive switches (ignored if current account exhausted or unreadable).

Margin: Candidate must be below threshold and have at least 10 percentage points more remaining than current.

All-over-threshold: If every account exceeds threshold, switch to the one recovering soonest (must be ≥5 minutes earlier or have 2× remaining quota).

Adjustable via flags (one-shot) or persistent config:

# Switch at 80%
cswap auto --threshold 80
# Check every 2 minutes
cswap auto --interval 120
# 10-minute cooldown
cswap auto --cooldown 600
# Dry-run: print intended action only
cswap auto --dry-run

Persist with cswap config set autoswitch.threshold 80 (see Section 8). Additional options: --model Fable: Include that model's weekly limit in decisions; persist via cswap config set autoswitch.model Fable. --strategy consume-first: Actively use the account whose weekly quota resets soonest (avoids waste). Default best only switches when near limit. --include-api-key-accounts: Treat API-key accounts as last-resort fallbacks (default excluded).

Error handling is conservative:

Usage read failure: Reuse last reading, exponentially back off retries. After 3 consecutive failures for the current account, switch to one with readable usage.

Access token expiry: Renew using Claude Code's own locking mechanism; on failure, wait in place — no switch triggered.

All accounts exhausted: Slow polling, wake early before the next reset.

Refresh token invalid: Isolate the account (exclude from switching), alert continuously. Fix by re-logging in with that account and cswap add --slot N, or importing from a valid export (plain cswap import replaces invalid entries). Exported tokens may also be stale.

Switching during active Claude Code work is safe: cswap acquires the same two locks Claude Code uses for token renewal ( ~/.claude/.oauth_refresh.lock, ~/.claude.lock) plus ~/.claude.json.lock for config writes, preventing races.

For headless/periodic runs, use cron with --once (single evaluation, exits with code: 0=switched, 1=error, 2=no switch needed, 3=wanted to switch but no candidate). --json emits one JSON line per event for logging:

*/5 * * * * cswap auto --once --json >> ~/.cswap-auto.log 2>&1

Disable an account from auto-selection (e.g., work account) with cswap disable 2 (Section 6). Auto-switch is best for backing up genuinely separate accounts; stacking quotas via multiple accounts carries Terms-of-Service risk (Section 10).

Running Two Accounts Simultaneously

Session mode (marked experimental) lets one terminal use account A while another uses account B. cswap run 2 launches Claude Code with account 2 in an isolated config directory via CLAUDE_CONFIG_DIR; other terminals stay on the default login.

# Launch with account 2
cswap run 2
# Pass args to claude
cswap run 2 -- --resume
# Share chat history with default login
cswap run 2 --share-history

The isolated directory shares settings.json, keybindings.json, CLAUDE.md, skills, custom commands, and sub-agents via symlinks (macOS/Linux) or copies (Windows). User-level MCP server configs are copied each launch; inline env / headers (often containing secrets) are duplicated.

Chat history is separate by default. --share-history enables --resume across accounts and preserves existing history (Windows unsupported). --no-share removes all shared configs including copied MCP entries. Both flags are per-launch; persistent sharing requires repeating the flag.

Notable differences from normal operation:

If the specified account is already the default login, cswap run launches plain claude (duplicate credentials risk invalidation). Use --require-session to enforce a separate session (exits if not possible).

MCP OAuth logins are not copied; HTTP-type MCPs may need re-authorization via /mcp inside the session. Session-modified MCP configs are overwritten on next launch — edit the default login's config instead.

Session manages its own token renewal. In v0.26.0, renewed tokens are not written back to the archive. Switching the default login to that account afterward may push a stale (revoked) token. Workaround: /login with that account, then cswap add --slot N. Post-0.26.0 versions auto-write-back on session exit.

If a session is running and cswap switch also points the default login to the same account, cswap warns: the same refresh token exists in two places; server renewal invalidates one. If the session later fails, exit and re-run cswap run. (v0.26.0+ blocks such switches outright.)

During a session, that account's usage is read via the session's own credentials; cswap does not renew for it.

Directory-to-account mapping: cswap map 2 ~/work/client-app binds account 2 to that directory and subdirectories. cswap map 2 (no path) binds current directory. cswap run without a slot in a bound directory auto-uses the mapped account; unbound directories launch plain claude. cswap map lists bindings, cswap unmap removes (current directory if no path). Bindings are local, not exported, and cleaned up when the account is removed.

Organizing Accounts

Management commands:

# Alias slot 2 as 'work'
cswap alias 2 work
# Remove alias
cswap alias 2 --unset
# List aliases
cswap alias
# Delete account 2
cswap remove 2
# Move account 2 to slot 1 (swap if occupied)
cswap move 2 1
# Swap slots 1 and 3
cswap swap 1 3

Disable an account from rotation (e.g., work account): cswap disable 2. Unnumbered cswap switch, auto-switch, and best-available selection skip it; explicit cswap switch 2 still works. cswap enable 2 re-enables. Disabled accounts show (disabled) in list, TUI, and menubar, where they can also be toggled.

Unclaimed credentials: when switching, if the current login doesn't match any archive, cswap stashes it first. cswap unclaimed lists these entries with slot mapping and reason. cswap unclaimed --purge <id> deletes permanently; the account then requires /login + cswap add to restore.

TUI Panel & macOS Menubar

Run cswap (or cswap tui) without arguments for a full-screen terminal UI (only in interactive TTYs, not scripts/cron). cswap watch opens the live monitor directly. Works on macOS, Linux, Windows.

Top half: account overview (default login shows full usage card; others one line each). Bottom half: menu (arrow keys to navigate):

Switch Account: Full cards per account, Enter to switch. Press b to jump to best-available.

Live Monitor: Usage bars and reset times, auto-refresh. Press s to pick an account and switch, staying on monitor.

Auto-Switch: Runs same logic as cswap auto, shows candidate rankings and per-round decisions. Starts in observe-only; press l + confirm to enable real switching. Press t to adjust threshold (temp, not saved).

Add, disable/enable, delete accounts; toggle dark/light/terminal theme.

Shortcuts: s switch, w monitor, g auto-switch, f force refresh, Ctrl+T theme, q quit/back.

macOS Menubar App

Install with the menubar extra:

uv tool install 'claude-swap[menubar]'
# or
pipx install 'claude-swap[menubar]'
cswap menubar

Known issue on macOS 26 (Sequoia): Homebrew or python.org Python builds fail to show the menubar icon. Use uv's managed Python:

uv tool install --managed-python 'claude-swap[menubar]'
# Reinstall if already installed
uv tool install --managed-python --force 'claude-swap[menubar]'

pipx users must select a non-Homebrew, non-python.org Python interpreter.

Menubar shows per-account 5h/7d usage and extra-usage percentage (overage billing). Click to switch: by name, next, best-available, skip-exhausted. All panel actions (add, disable, delete, refresh) available. Settings → "Auto-switch accounts" enables background auto-switch (same logic, same config); default off. cswap menubar runs in foreground; closing the terminal stops it. For persistence, install a launchd service (no .app bundle needed):

# Install & start now, auto-start on login
cswap menubar --install-service
# Check status
cswap menubar --service-status
# Stop & remove
cswap menubar --uninstall-service

Service plist: ~/Library/LaunchAgents/com.cswap.menubar.plist. Logs: ~/Library/Logs/com.cswap.menubar.log and .err. Auto-restarts on crash. After cswap upgrade, re-run --install-service or kick the service:

launchctl kickstart -k gui/$(id -u)/com.cswap.menubar

Config, Export/Import & JSON Output

Configuration

cswap's own settings live in settings.json inside its archive directory (distinct from Claude Code's config; location shown in Section 9 table). Manage via cswap config:

# List effective settings
cswap config
cswap config get autoswitch.threshold
# Set (validates range)
cswap config set autoswitch.threshold 80
# Reset to default
cswap config unset autoswitch.threshold
# Show config file path
cswap config path

Configurable keys mirror cswap auto flags plus consecutive-read-failure threshold (default 3) and UI theme. cswap config --help lists each key's default; out-of-range set errors with allowed range. list / get support --json. CLI flags override config file; manual file edits work but cswap config is safer.

Export & Import

# Export all accounts
cswap export backup.cswap
# Export only account 2
cswap export backup.cswap --account 2
# Import (skip existing)
cswap import backup.cswap
# Import with overwrite
cswap import backup.cswap --force

Export file is plaintext JSON . By default includes only each account's own login credentials. Machine-bound secrets (MCP/Plugin OAuth tokens, device tokens) stay local. --full bundles the entire ~/.claude.json and full credentials — suitable for same-machine backup. Encrypt via pipe: cswap export - | gpg -c > backup.gpg.

If an imported account is currently the default login, cswap switch N (where N is its new slot) leaves it untouched unless --force is given.

JSON Output for Scripting

list

, status, switch accept --json: stdout is a single JSON object (schemaVersion included), stderr carries human messages. Exit code non-zero on error.

cswap list --json
cswap status --json
cswap switch --strategy best --json
switch --json

reports whether a switch occurred, from/to accounts, and reason. Account rows include timestamp of reading, last valid reading if current failed, disabled flag, alias. After ~1 day into the weekly window, extra projection fields appear (estimated exhaustion date, whether it will last until reset) — linear extrapolation, only in JSON. Fields only added, never removed; scripts should ignore unknown keys. cswap auto --json emits one JSON line per event.

Features in README but not yet in v0.26.0: cswap import-usage: Designate one machine to poll usage and distribute readings to others, avoiding duplicate API quota consumption.

JSON field loginExpiresAt per account for proactive re-login reminders; also includes read-failure reason and next retry time.

Session exit writes renewed tokens back to archive (fixes the v0.26.0 session-token staleness).

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Tech Ocean
Written by

Tech Ocean

Focused on AI programming, sharing ready-to-use development efficiency solutions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.