Atomic account switching for AI agent CLIs — Claude Code, Codex, Gemini, opencode.
aswitch lets you keep multiple accounts for the same AI agent (two Claude Pro
seats, a personal and a work Codex, several opencode provider sets) side by
side and flip between them in one command — atomically, with rollback on any
failure. It plugs into the agent's own credential store (macOS Keychain,
Linux libsecret, or a file like ~/.codex/auth.json); the agent itself keeps
working as usual, you just point it at a different identity.
$ aswitch ls
Saved accounts: 4
[1] claude-code/work
Email: [email protected]
Quota: remaining=67%, reset=04-28 14:50
Monthly Usage: req 9k | in 101.1k | out 8.3M
Weekly Usage : req 1.7k | in 15.2k | out 2M
Next Refresh : 04-28 10:14
Active : yes
[2] codex/work
Email: [email protected]
Quota: remaining=0%, reset=04-29 08:49
Monthly Usage: req 7k | in 684.5M | out 5.6M
Weekly Usage : req 3.4k | in 320.5M | out 3.3M
Next Refresh : 04-28 10:14
Active : -
[3] codex/personal
Email: [email protected]
Quota: remaining=14%, reset=04-29 18:35
Monthly Usage: req 7k | in 684.5M | out 5.6M
Weekly Usage : req 3.4k | in 320.5M | out 3.3M
Next Refresh : 04-28 10:14
Active : yes
[4] gemini/default
Email: [email protected]
Quota: -
Monthly Usage: req 11 | in 271.6k | out 885
Weekly Usage : req 11 | in 271.6k | out 885
Next Refresh : 04-28 10:14
Active : yes
$ aswitch use codex/personal --scope global
Switched to codex/personal
Restart the corresponding client for the new account to take effect.
$ aswitch ls --view status
registry version: 1
last switch: 2026-04-26 20:33
PLUGIN STATUS SOURCE ACTIVE COUNT LAST_USED
claude-code ok user work 1 2026-04-26 06:55
codex ok user personal 2 2026-04-26 20:33
gemini ok user default 1 2026-04-24 20:55
opencode ok user - 0 -
$ aswitch ls --view current
PLUGIN ALIAS EMAIL ORG PLAN SCOPE
claude-code work [email protected] Alice's Org - global
codex personal [email protected] - - global
gemini default [email protected] - - global
opencode - - - - -
| Pain | What aswitch does |
|---|---|
| Two Claude Pro seats, one machine | Saves each seat's Keychain entry as a named account; one command flips the live credential. |
| Codex login keeps clobbering the previous account | Backups are kept in ~/.aswitch/, switch is a transaction, any failure rolls back. |
| Project A wants the work account, Project B the personal one | --scope project writes a .aswitch.toml, picked up automatically when you cd in. |
| "Did I burn through my quota this month?" | aswitch ls (default view) reads the agent's own JSONL logs and shows monthly / weekly usage per account. |
| New agent CLI launched yesterday | Drop a TOML manifest in ~/.aswitch/plugins/ — no recompile. |
What aswitch deliberately doesn't do: no daemon, no auto-switching, no quota alerts, no proxying the agent's network traffic, no Windows. It is a focused, on-demand switcher.
brew tap amoswzw/tap
brew install aswitchcargo install --git https://github.com/amoswzw/aswitch aswitch-cligit clone https://github.com/amoswzw/aswitch.git
cd aswitch
cargo build --release -p aswitch-cli
./target/release/aswitch --versionOn first run aswitch creates ~/.aswitch/ and unpacks the four bundled plugin
manifests into ~/.aswitch/plugins/.
# 1. Capture an account (after you've logged in to the agent normally)
aswitch save claude-code/work
# 2. Or run the agent's native login and save in one step
aswitch login codex/personal
# 3. List what you have
aswitch ls
# 4. Enable shell integration once per shell (zsh/bash)
eval "$(aswitch init)"
# 5. Switch in this shell
aswitch use codex/personal
# 6. Or open the TUI and pick with arrow keys
aswitchaswitch use chooses where the switch is recorded. Precedence is
shell > project > global.
| Scope | What it changes | Affects |
|---|---|---|
shell (default) |
An env-var stub injected by aswitch init |
Just this shell |
project |
Writes .aswitch.toml in the current directory tree |
Anyone working under that tree |
global |
The agent's own native credential location | Every shell, every project |
aswitch use codex/work # shell only
aswitch use codex/work --scope project # this repo
aswitch use codex/work --scope global # the whole machine
aswitch use --off # turn the shell scope off
aswitch use --off --scope project # remove .aswitch.toml bindingaswitch # opens the TUI when stdin is a tty
aswitch tui # explicit| Key | Action |
|---|---|
j / k or arrows |
Move |
Enter |
Switch the selected account globally |
Tab / 1 / 2 |
Move between panels |
w |
Cycle the usage time window |
s |
Cycle the usage source (local logs / provider API / both) |
R |
Refresh usage data |
? |
Help |
q |
Quit |
Bundled with the binary; updates ship in amoswzw/aswitch-plugin.
| Plugin | Credential store | Login command | Notes |
|---|---|---|---|
claude-code |
macOS Keychain (file fallback on Linux) | claude login |
Backs up ~/.claude/.claude.json alongside |
codex |
~/.codex/auth.json |
codex login |
Identity from the JWT in tokens.id_token |
gemini |
macOS Keychain / libsecret | gemini |
Aux files: ~/.gemini/.env, settings.json |
opencode |
~/.local/share/opencode/auth.json |
opencode auth login |
Treats the multi-provider auth.json as one snapshot |
Adding a new agent only takes a plugin.toml — see the
manifest schema.
macOS 12+ (arm64 / x64) and Linux (glibc 2.31+, arm64 / x64). Windows is not supported and not planned.
Every switch runs as a transaction:
- Take the file lock on
~/.aswitch/.lock. - Read the currently active credential and any aux files; back them up.
- Read the target account's saved snapshot.
- Atomically write the snapshot to the live location (
securityfor Keychain,tmp + renamefor files). - Update
~/.aswitch/registry.json.
If any step fails the rollback stack runs in reverse, restoring the live location to the pre-switch state. The exit code distinguishes fully rolled back (10) from rollback partially failed (11), so automation never has to guess the state.
~/.aswitch/
├── plugins/ # bundled and user manifests
├── accounts/<plugin>/<alias> # per-account credential + aux + cached identity
├── usage_cache/ # snapshots from `aswitch ls` (TTL'd)
├── registry.json # active accounts and metadata
└── logs/aswitch.log # rotating log
aswitch-core— switching engine, identity extraction, login capture, usage collection, cache.aswitch-cli— theaswitchbinary and TUI.assets/bundled-plugins/— TOML manifests baked into the binary.
The full feature reference lives in USAGE.md.
amoswzw/aswitch-plugin— official plugin manifests and authoring docs.amoswzw/homebrew-tap— Homebrew formula.
MIT — see LICENSE.