Skip to main content

Claude Codex Swap — multi-account and usage manager for Claude Code and OpenAI Codex

Project description

ccswap (Claude Codex Swap)

PyPI

Multi-account and usage manager for Claude Code and OpenAI Codex. Save multiple logins, check their quota windows, switch manually or automatically before you hit a rate limit, and manage both providers from one dashboard.

ccswap began as a fork of claude-swap (cswap) by Onur Cetinkol, and still carries the original MIT license and credit for that. Since then it's grown into its own project: no more tracking upstream, no cswap compatibility, its own package and release line, and adds Codex support. It's MIT-licensed too, so fork it, file issues, send PRs — whatever's useful to you.

Installation

Using uv (recommended)

uv tool install ccswap

Using pipx

pipx install ccswap

From source

git clone https://github.com/errhythm/cc-swap.git
cd cc-swap
uv sync
uv run ccswap help

Updating

ccswap upgrade          # uv/pipx installs on macOS/Linux: auto-detects and upgrades
# or run your installer directly:
uv tool upgrade ccswap
pipx upgrade ccswap

Usage

Add your first account

Log into Claude Code with your first account, then:

ccswap add

Add more accounts

Log in with another account, then:

ccswap add

Switch accounts

Rotate to the next account:

ccswap switch

Or switch to a specific account:

ccswap switch 2
ccswap switch user@example.com

Not sure which one? ccswap list is the dashboard — every account's 5-hour and 7-day usage and reset times at a glance:

ccswap list

Or ccswap auto-picks by remaining quota — ccswap switch --strategy best (most quota left) or --strategy next-available (skip rate-limited accounts).

Note: You usually don't need to restart — on Linux/Windows the new account is picked up automatically, and on macOS after the Keychain cache expires. To apply it instantly, restart Claude Code or reopen the VS Code extension tab. See Tips for the per-platform details.

Automatic switching

Let ccswap watch your usage and switch for you. When the active account's 5-hour or 7-day window reaches the threshold (default 90%), it switches to the account with the most quota left — before you hit the limit, and safe to run while Claude Code is working:

ccswap auto                     # foreground loop, polls every 60s
ccswap auto --threshold 80      # switch earlier
ccswap auto --once              # single check-and-switch, for cron/scripts
ccswap auto --dry-run           # log what it would do, never switch
How it behaves & advanced usage
  • Runs safely alongside Claude Code: switches take the same credential locks Claude Code uses, so a swap never collides with a token refresh.
  • A cooldown (default 5 min) and a hysteresis margin stop it flip-flopping near the threshold; when every account is exhausted it sleeps until the earliest reset.
  • Usage polling is adaptive — a couple of accounts per check, busy alternates watched more closely, exhausted ones left alone until they reset — so API traffic stays flat no matter how many accounts you manage.
  • It fails safe: if a usage check errors it keeps trusting the last-known numbers while retries back off, and an expired token on an idle machine makes it hold rather than fail over (Claude Code refreshes the token on your next message).
  • An account whose refresh token has died is quarantined and reported until you log in with it and re-run ccswap add --slot N. API-key accounts are never rotated onto unless you pass --include-api-key-accounts.

For cron/systemd timers, --once reports the outcome in its exit code (0 switched, 1 error, 2 nothing to do, 3 blocked — no viable target), and --json emits one JSON event per line:

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

Defaults like the threshold and cooldown are configurable with ccswap config set autoswitch.threshold 80 — flags override them (see Configuration).

Run multiple accounts at the same time (session mode)

Launch Claude Code as a specific account in the current terminal only — every other terminal and the VS Code extension stay on your default account, so two accounts can work in parallel.

ccswap run 2                     # launch Claude Code as account 2, here only
ccswap run user@example.com      # by email
ccswap run 2 -- --resume         # everything after '--' is forwarded to claude
ccswap run 2 --share-history     # share your chat history with this account too

Sessions use your normal ~/.claude setup (settings, CLAUDE.md, skills, etc.), but each account keeps its own chat history. Pass --share-history if you want your accounts to continue the same conversations — a session started under one account shows up in --resume under the others, and nothing already saved is lost. Not supported on Windows yet.

Interactive dashboard (TUI)

Run ccswap on its own (or ccswap tui) for the full-screen dashboard: live usage, switching, and auto-switching for Claude Code and Codex, all keyboard-driven. Use Provider: Claude Code… in the menu to change providers. Arrow-key and Vim-style menu navigation wraps at both ends. ccswap watch opens straight into the live monitor. Works on macOS, Linux, and Windows.

ccswap watch — live 5h/7d usage bars for every account, with reset times and the active account marked

Codex accounts

ccswap can also save and switch Codex CLI logins. Log into each account with codex login, then save it before logging into the next one:

codex login
ccswap codex add

# Log in to the next Codex account, then save it too.
codex login
ccswap codex add

ccswap codex list                 # accounts tagged by plan, e.g. [Codex Team]
ccswap codex usage                # 5h/7d windows with reset countdowns; diagnostic errors
ccswap codex switch 1
ccswap codex switch                 # rotate to the next saved account
ccswap codex auto --once            # switch when active quota reaches the threshold
ccswap codex remove 2

Codex switching preserves the rest of CODEX_HOME (configuration, skills, sessions, and history) and replaces only auth.json. Restart Codex after switching so its running process loads the selected login. For ChatGPT-backed file logins, the dashboard reads the same read-only Codex rate-limit endpoint used by Codex and shows its primary (5h) and secondary (7d) windows with live reset countdowns. Each account is labelled by its ChatGPT plan (Codex Team, Codex Pro, Codex Plus, …) — read from the login token, the closest local equivalent to Claude Code's org name, since Codex stores no workspace name on disk. API-key accounts have no ChatGPT subscription quota, so they remain status-only. ccswap codex auto uses the same threshold, cooldown, --once, --dry-run, and JSON event controls as Claude auto-switching; it prepares the account for the next Codex launch and reports when a restart is needed.

Codex must use its documented file credential store. If your ~/.codex/config.toml says cli_auth_credentials_store = "keyring", change it to "file", run codex login, then add the account. This deliberate restriction avoids writing a guessed OS-keyring entry.

Refresh expired tokens

If an account's token expires, log back into Claude Code with that account and re-run:

ccswap add

This will update the stored credentials without creating a duplicate.

Other commands

ccswap run 2                     # Run an account in this terminal only (session mode)
ccswap auto                      # Auto-switch when nearing rate limits (see above)
ccswap codex list                # List saved Codex CLI accounts
ccswap codex switch 2            # Switch the file-backed Codex login
ccswap config                    # Show or edit settings (see Configuration below)
ccswap list                      # Claude + Codex accounts with 5h/7d usage and reset times
ccswap list --provider codex     # Restrict to one provider (claude|codex|all)
ccswap status                    # Show current account
ccswap add --slot 3              # Add account to a specific slot (prompts before overwrite)
ccswap remove 2                  # Remove an account
ccswap tui                       # Interactive dashboard (also: bare `ccswap`)
ccswap watch                     # Dashboard, opened on the live watch page
ccswap upgrade                   # Upgrade ccswap to the latest version
ccswap purge                     # Remove all ccswap data

The legacy cswap command remains available as a compatibility alias; use ccswap for new scripts.

Tips

  • Do you need to restart after switching? For Claude Code, usually not. On Linux and Windows, credentials are stored in a file and Claude Code re-reads them whenever that file changes, so the new account takes effect on your next message — no restart needed. On macOS, credentials live in the Keychain, which Claude Code caches for about 30 seconds; a running session picks up the switch once that cache expires. Restart Claude Code (or close and reopen the VS Code extension tab) only if you want the change to apply instantly.
  • Codex always needs a restart. Unlike Claude Code, the Codex CLI reads auth.json once when it starts and keeps the login in memory — it never re-reads the file or caches it on a timer. A running Codex session therefore keeps using the old account no matter what you swap underneath it. ccswap codex switch and ccswap codex auto write the selected login and tailor the reminder to your machine: if a Codex process is running they tell you to quit and relaunch it (or start a new session / reload the IDE extension); if none is running they confirm the account is ready for the next launch. This is a limitation of the Codex CLI, not ccswap — there is no flag, signal, or config setting that makes a live Codex reload credentials, and ccswap deliberately does not kill your running Codex process for you.
  • Continuing sessions after switching: You can keep using the same Claude Code session after switching — run ccswap switch in any terminal and carry on. If you'd prefer a clean start, close and reopen Claude Code (or the VS Code extension tab) and use --resume to pick your previous session. Either way, the first message on the new account may use extra usage as its conversation cache rebuilds.

How it works

  • Backs up provider credentials when you add an account
  • Swaps Claude Code credentials or Codex's file-backed auth.json when you switch
  • Account credentials stored securely using platform-appropriate methods
  • Switches (manual and automatic) hold Claude Code's own credential locks while writing, so a swap never interleaves with a token refresh
  • Auto-switch freshens a target's token before activating it, and quarantines accounts whose refresh token has died (recover with ccswap add --slot N)
  • Codex usage checks refresh inactive saved logins when possible; running Codex sessions must be restarted after a Codex account switch

Data locations

Platform Credentials Config backups
Windows File-based (inside the backup directory, under credentials/) ~/.claude-swap-backup/
macOS macOS Keychain ~/.claude-swap-backup/
Linux / WSL File-based (inside the backup directory, under credentials/) ${XDG_DATA_HOME:-~/.local/share}/claude-swap/

Session-mode profiles (ccswap run) live under the backup directory in sessions/. Tool preferences (settings.json) and auto-switch state (autoswitch_state.json — cooldown and quarantined accounts; delete it to reset) live in the backup directory root.

On Linux/WSL, set XDG_DATA_HOME to override the default location.

Menu bar (macOS)

Optional macOS menu bar app — usage at a glance, click to switch

Needs the menubar extra (macOS only):

uv tool install 'ccswap[menubar]'   # or: pipx install 'ccswap[menubar]'
ccswap menubar

Shows every account's 5h / 7d / spend usage and switches with a click (specific / rotate / best / next-available), plus the TUI's add / remove / refresh actions. Enable Settings → Auto-switch accounts to run the same engine as ccswap auto in the background; it shares the autoswitch.* settings, so the menu bar and CLI stay in sync. Off until you turn it on.

Advanced

Configuration

Tool preferences live in settings.json in the backup root; ccswap config reads and edits it with validation, so you never have to find the file or guess valid ranges.

Commands & usage
ccswap config                              # list effective settings ("(default)" = not set)
ccswap config get autoswitch.threshold
ccswap config set autoswitch.threshold 80  # validated: rejects out-of-range values loudly
ccswap config unset autoswitch.threshold   # back to the default
ccswap config path                         # where settings.json lives

ccswap config --help lists every key with its valid range and default. Hand-editing the file still works — ccswap config is just a safer front door. list and get take --json for scripting.

Backup and migration

Move account data between machines or back it up:

ccswap export backup.cswap                    # All accounts to a file
ccswap export backup.cswap --account 2        # One account
ccswap export backup.cswap --full             # Include full local ~/.claude.json (same-PC backup)
ccswap import backup.cswap                    # Skips accounts that already exist
ccswap import backup.cswap --force            # Overwrite existing

The export file is plaintext JSON. If you need encryption, pipe through your tool of choice (e.g. ccswap export - | gpg -c > backup.gpg).

If an imported account is the one you're currently logged in as, activate the imported credentials with ccswap switch N --force (a plain switch to the current account is a safe no-op and won't touch the import).

JSON output for scripting

Add --json to list, status, or switch to emit a single machine-readable JSON object on stdout (human-readable notices go to stderr). Useful for scripting auto-swap and quota tracking.

ccswap list --json                   # BOTH providers, merged (default)
ccswap list --provider claude --json # Claude Code accounts only (bare payload)
ccswap list --provider codex --json  # Codex accounts only (bare payload)
ccswap status --json                 # current active account
ccswap switch --strategy best --json # switch, then report the result
ccswap switch 2 --json

ccswap list now covers both providers by default. In --json mode that means the output is keyed by provider (claude/codex); pass --provider claude (or codex) to get a single provider's bare payload — the same shape older scripts already parse.

Example output & schema notes

Merged (default) — ccswap list --json:

{
  "claude": {
    "schemaVersion": 1,
    "activeAccountNumber": 2,
    "accounts": [
      { "number": 2, "email": "you@example.com", "active": true, "usageStatus": "ok",
        "usage": { "fiveHour": { "pct": 25.0, "resetsAt": "2026-06-22T23:29:59Z" },
                   "sevenDay": { "pct": 16.0, "resetsAt": "2026-06-26T17:59:59Z" } } }
    ]
  },
  "codex": {
    "provider": "codex",
    "activeAccountNumber": 1,
    "accounts": [
      { "number": 1, "email": "you@example.com", "authMode": "chatgpt",
        "planType": "team", "label": "Codex Team", "active": true }
    ]
  }
}

Single provider — ccswap list --provider claude --json — returns just the inner Claude object above (schemaVersion, activeAccountNumber, accounts), unchanged from before. Migration: scripts that parsed the old top-level accounts from ccswap list --json should switch to ccswap list --provider claude --json.

Every Claude payload carries a schemaVersion (currently 1); on a handled error stdout is {"schemaVersion":1,"error":{...}} with a non-zero exit code. --switch/--switch-to report {"switched": true|false, "from": …, "to": …, "reason": …}.

Usage is served from a per-account cache: when the usage API is briefly unreachable, the last-known numbers are shown instead of nothing (the human view marks them with their age, e.g. · 2m ago). Rows with usage carry additive usageFetchedAt/usageAgeSeconds fields telling you how old the measurement is.

ccswap auto --json emits an event stream instead — one JSON object per line ({"schemaVersion":1,"event":"switch","ts":…, …} with kinds like poll, switch, no-switch, account-quarantined, all-exhausted, error). The contract is additive: new kinds and fields may appear, so scripts should ignore unknown ones.

Add an account from a raw token or API key

If you only have a long-lived setup-token (e.g., produced by claude setup-token) or a managed API key (sk-ant-api...) and you don't want to log in via the browser flow first — useful on headless servers or when receiving a token from another machine — register it directly. The token type is auto-detected:

ccswap add-token sk-ant-oat01-...             # OAuth setup-token
ccswap add-token sk-ant-api03-...             # managed API key
ccswap add-token sk-ant-oat01-... --slot 3
ccswap add-token - --slot 3                   # read token from stdin
ccswap add-token --email user@example.com     # optional label override

--email is optional; omitted values use setup-token-{slot}@token.local (or api-key-{slot}@token.local for API keys). No Anthropic API calls are made.

API-key accounts. An sk-ant-api... value registers a managed API-key account (the kind Claude Code uses after /login with a key) rather than an OAuth setup-token. It switches like any other account; since API keys have no subscription quota, they show no usage and the usage-aware switch strategies never skip them as rate-limited.

Uninstall

Remove all data:

ccswap purge

Then uninstall the tool:

uv tool uninstall ccswap
# or
pipx uninstall ccswap

Requirements

  • Python 3.12+
  • Claude Code and/or Codex CLI
  • A file-backed login for managed Codex accounts

License

MIT. This fork retains the original project's copyright and license notice; see LICENSE. Upstream: realiti4/claude-swap.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ccswap-0.21.0.tar.gz (591.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ccswap-0.21.0-py3-none-any.whl (202.4 kB view details)

Uploaded Python 3

File details

Details for the file ccswap-0.21.0.tar.gz.

File metadata

  • Download URL: ccswap-0.21.0.tar.gz
  • Upload date:
  • Size: 591.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ccswap-0.21.0.tar.gz
Algorithm Hash digest
SHA256 c7b11160fc210d1c081983794bf9663268146eb9bcd383d5adbdede5184eacc1
MD5 3cdedb6f53c5425371a0aac7181d6476
BLAKE2b-256 bb027b154fa3490a982c8b870fe1b610cbb30fd0cccc34ba77f23d7e04ef90e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for ccswap-0.21.0.tar.gz:

Publisher: publish.yml on errhythm/cc-swap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ccswap-0.21.0-py3-none-any.whl.

File metadata

  • Download URL: ccswap-0.21.0-py3-none-any.whl
  • Upload date:
  • Size: 202.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ccswap-0.21.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a82403898d823ae051704757112281a785d7c0fecd72fb70b59bfa03a8b48965
MD5 d463db6298a0b758fa353a829ff4d204
BLAKE2b-256 d5ad3eacd78bd6a431fe79b846b79e311f26bea2ea802076293a51918d789db5

See more details on using hashes here.

Provenance

The following attestation bundles were made for ccswap-0.21.0-py3-none-any.whl:

Publisher: publish.yml on errhythm/cc-swap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page