Skip to main content

ai-auth-switch

Switch auth profiles for AI coding agents while keeping the app's normal configuration, history, sessions, and cache layout unchanged.

Codex and Claude Code are supported. The design keeps each agent as the source of truth for everything except the active auth file:

  • ~/.codex/config.toml is not rewritten.
  • ~/.codex/history.jsonl, sessions/, skills/, and other Codex state stay in place.
  • Permanent profile changes switch only auth.json.
  • Profile-scoped runs isolate auth.json in a temporary CODEX_HOME while sharing the normal Codex configuration and state.
  • Saved profiles live outside Codex under ~/.local/share/ai-auth-switch/.
  • Hermes and OpenClaw Codex-dependent auth state is synchronized after Codex auth changes.
  • Claude Code profiles isolate .credentials.json while sharing the normal settings, history, sessions, skills, plugins, and cache layout.

Installation

Install or upgrade the latest stable release from PyPI:

python -m pip install --upgrade ai-auth-switch

Python 3.10 or newer is required.

To install the newest source directly from the official GitHub repository:

python -m pip install --upgrade "ai-auth-switch @ git+https://github.com/Lixtt/ai-auth-switch.git"

ais is the short command name for ai-auth-switch; both accept exactly the same arguments. Examples below use the long name for clarity.

For development, clone the official repository and use an editable install:

git clone https://github.com/Lixtt/ai-auth-switch.git
cd ai-auth-switch
python -m pip install -e .

Codex Usage

Save the currently active Codex login:

ai-auth-switch auth save codex

The profile name is inferred from the email inside the Codex OAuth token when available. If the token does not expose an email, the fallback is chatgpt-<account-id-prefix>.

Login a new Codex account and save it:

ai-auth-switch auth login codex

Optionally force a profile name:

ai-auth-switch auth login codex work

List and switch profiles:

ai-auth-switch auth list
ai-auth-switch auth list codex
ai-auth-switch auth list codex --usage
ai-auth-switch auth use codex someone@example.com
ai-auth-switch auth current codex

Add --usage to query every saved Codex account's current rate-limit windows in parallel. Each request uses that profile's own access token and explicit ChatGPT account ID, so limits cannot be accidentally attributed to another saved account. The normal list remains local and instant; usage lookup is opt-in because it requires network access and may report an expired login.

* someone@example.com [codex1] (plus, 5h 72% left, 168h 41% left)
  other@example.com [codex2] (team, 5h 18% left, 168h 83% left)

Results are cached for 60 seconds. Use --refresh-usage to bypass the cache, --usage-cache-ttl to tune it, --usage-timeout for slow networks, and --usage-workers to limit concurrency. A failure for one account is shown inline without hiding results for the other accounts. The command deliberately does not refresh expired OAuth tokens; run that profile through Codex or log in again so rotating credentials remain coordinated safely.

For status bars, monitoring, or account schedulers, add --json. The JSON contains profile identity, active/alias state, and structured usage windows when --usage is also present:

ai-auth-switch auth list codex --usage --json

After Codex auth is saved, logged in, or switched, ai-auth-switch also syncs Codex-dependent local tools:

  • Hermes is pointed at openai-codex and seeded with a Codex CLI access-token pool entry, so it follows the active Codex CLI account without handing turns to codex app-server. If hermes-gateway.service is active, it is restarted so Feishu and other messaging channels pick up the new auth immediately.
  • Current OpenClaw installs are synchronized through the SQLite auth store by writing openai:default from the active Codex CLI OAuth token. Older JSON auth-state installs still use the legacy openai-codex:default bridge.

You can run that step explicitly too:

ai-auth-switch auth sync codex

Hermes does not import or share the Codex CLI refresh token. The sync clears Hermes's old independent openai-codex OAuth state, installs the current Codex CLI access token into Hermes's openai-codex credential pool, and leaves Hermes's openai_runtime on auto. Current OpenClaw versions no longer import Codex CLI auth from ~/.codex at runtime, so the sync writes the active Codex OAuth tokens into OpenClaw's own SQLite auth store as openai:default and clears any failure cooldown for that profile. Older OpenClaw JSON auth-state installs still fall back to the legacy openai-codex:default bridge profile.

The old Hermes login flag is kept only for command compatibility and is now a no-op:

ai-auth-switch auth sync codex --hermes-login

Use ai-auth-switch auth sync codex normally. Before restarting active gateway services, the current process's standard proxy variables (http_proxy, https_proxy, and their uppercase variants) are imported into the systemd user manager, so Hermes/OpenClaw do not need a hard-coded proxy env file. To leave a running Hermes gateway untouched during an explicit sync, pass --no-hermes-restart.

If Codex reports that a refresh token was already used after switching profiles, that profile's stored refresh token has already been invalidated by the server. Log in to that Codex account again and save it back into the same profile name:

ai-auth-switch auth login codex <profile>

Recent versions sync Codex's atomically replaced auth.json back into the managed profile before switching away, which prevents reactivating a stale refresh token after Codex refreshes it.

On a fresh install, auth list can be empty even when Codex is already logged in. Import the active Codex auth first:

ai-auth-switch auth save codex

If you run as another Unix user, make sure CODEX_HOME points at the Codex config directory you actually use, or pass --codex-home /path/to/.codex.

Run Codex with isolated auth for the lifetime of one process. The default active auth is never changed:

ai-auth-switch run codex someone@example.com -- codex -C ~/workspace/project

Numbered command aliases are managed automatically for every saved Codex account. On the first sync, existing profiles are numbered in saved order; later accounts are appended. Removing an account compacts the sequence, and renaming an account keeps its number:

ai-auth-switch auth list codex
#   someone@example.com [codex1]
#   other@example.com [codex2]

The profile name is normally the authenticated email. If a credential file's actual account differs, auth list shows it explicitly as (actual auth: ...) instead of silently presenting a misleading codexN mapping.

Saving, logging in, switching, renaming, or removing profiles updates the alias records. For the default profile store, matching command links are also created under ~/.local/bin and stale links are removed. Run an explicit sync to backfill existing accounts or to choose a different command directory:

ai-auth-switch alias sync codex
ai-auth-switch alias sync codex --bin-dir /path/on/PATH

After installation, codex1 -C ~/workspace/project runs the Codex CLI under the corresponding profile without changing the account used by codex2 or by the default codex command. Numbered aliases can run concurrently, including multiple processes using the same saved account. A per-profile lock is held only for the wrapper's short credential installation and reconciliation steps, not for the lifetime of the Codex process.

Each run gets a private temporary CODEX_HOME containing only its selected auth.json. Existing entries from the normal Codex home—including config.toml, history.jsonl, sessions/, skills/, logs, caches, and plugins—are linked into that temporary home. An existing CODEX_SQLITE_HOME is preserved; when it is unset, SQLite state points back to the normal Codex home. If Codex refreshes and atomically replaces its isolated auth.json, the new credentials are written back to that saved profile when the process exits. Same-account processes reference the same saved profile file so they can observe a refresh-token rotation performed by another Codex process. If Codex atomically replaces a session's auth symlink, wrapper-side reconciliation back to the profile is serialized, skips unchanged stale credentials, and refuses a write-back whose actual account differs from the saved profile. Rejected credentials are preserved under the profile store's backups/codex/rejected/ directory for inspection.

Temporary homes use the machine-local per-user runtime directory by default (XDG_RUNTIME_DIR, with a /var/tmp fallback), so workers sharing the profile store do not contend on /mnt for per-process symlink creation and cleanup. Set AI_AUTH_SWITCH_RUNTIME_DIR to override the runtime parent when needed.

Names matching codex1, codex2, claude1, claude2, and so on are reserved for automatic management. Other alias names can still be created manually with ai-auth-switch alias set and ai-auth-switch alias install.

When --store-dir is passed, automatic command-link installation is skipped to avoid changing the user's global bin directory. Pass --bin-dir to alias sync, or set AI_AUTH_SWITCH_ALIAS_BIN_DIR, to opt into a specific directory. Editable installs prefer the checkout's shared bin/ai-auth-switch launcher, which keeps aliases portable when the home directory is mounted on multiple machines. Set AI_AUTH_SWITCH_ALIAS_TARGET or pass --target to choose another launcher explicitly.

Claude Code Usage

Claude Code OAuth profiles support the same save, list, switch, default, directory-binding, rename, remove, export, and import operations as Codex. On Linux, Claude Code stores OAuth credentials in ~/.claude/.credentials.json; the official CLAUDE_CONFIG_DIR override is also supported.

Import the currently stored Claude Code login:

ai-auth-switch auth save claude

The profile name is inferred from Claude Code's account metadata when an email is available. You can always provide an explicit name:

ai-auth-switch auth save claude work

Log in to another Claude account and save it without disturbing existing profiles:

ai-auth-switch auth login claude
ai-auth-switch auth login claude work -- --email someone@example.com

List, activate, and inspect profiles:

ai-auth-switch auth list claude
ai-auth-switch auth use claude someone@example.com
ai-auth-switch auth current claude

Numbered claude1, claude2, and so on aliases are installed and maintained automatically. Each alias runs with a private temporary CLAUDE_CONFIG_DIR, so multiple Claude accounts can run concurrently without changing the default Claude login:

claude1 -p "review this repository"
claude2 --continue
ai-auth-switch run claude someone@example.com -- claude -p "summarize the tests"

The temporary config shares normal Claude Code state but isolates .credentials.json and account metadata. Refreshed OAuth credentials are written back to the selected profile with an account-identity check, preventing an accidental /login from overwriting another saved account.

Claude Code gives environment credentials such as ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, and cloud-provider modes higher priority than saved OAuth credentials. claudeN and run claude remove those overrides in the child process so the selected OAuth profile wins. For permanent auth use switches, unset those variables in your shell. API-key, Bedrock, Vertex, Foundry, and apiKeyHelper profiles are not copied or managed.

Use a non-default config directory when needed:

ai-auth-switch --claude-config-dir /path/to/.claude auth list claude

File-based Claude OAuth profile management currently targets Linux. Claude Code uses the encrypted macOS Keychain on macOS, which is intentionally not copied by this tool; Windows isolated-run support has not yet been validated.

Directory Overrides

By default Codex auth is read from:

$CODEX_HOME/auth.json

or, when CODEX_HOME is unset:

~/.codex/auth.json

Override it explicitly:

ai-auth-switch --codex-home /path/to/.codex auth list codex

The profile store can be moved with:

AI_AUTH_SWITCH_HOME=/secure/path ai-auth-switch auth list codex

Claude Code's config directory can be selected with CLAUDE_CONFIG_DIR or the global --claude-config-dir option.

Default Profile and Directory Binding

run normally needs an explicit profile name. When you omit it, the profile is resolved from the provider's default profile first, then from the nearest directory binding:

ai-auth-switch run codex -- codex -C ~/workspace/project   # still explicit
ai-auth-switch run codex                                    # uses default/binding

Set, show, and clear the default profile per provider:

ai-auth-switch auth default codex someone@example.com
ai-auth-switch auth default codex
#   default profile -> someone@example.com
ai-auth-switch auth default codex --clear

Directory bindings select a profile automatically for every run inside a project tree. The binding is stored in .ai-auth-switch.json in the target directory and resolved from the nearest ancestor:

cd ~/workspace/project
ai-auth-switch auth bind codex someone@example.com
ai-auth-switch auth bind codex
#   bound profile -> someone@example.com (resolved from /home/me/workspace/project)
ai-auth-switch auth bind codex --clear

Use --dir to bind a directory other than the current one. Bindings take precedence over the default profile when both exist. If neither is set, run without a profile prints a message explaining both options.

Migrating Profiles Between Machines

Saved profiles (including their OAuth credentials) can be exported as JSON and imported on another machine. This is useful when the checkout and home are not shared:

# On the source machine.
ai-auth-switch auth export codex -o codex-profiles.json
ai-auth-switch auth export              # all providers, to stdout

The export file is written with private permissions (0600) and contains credentials; keep it secure and delete it after migrating. Import it on the target machine, or pipe it directly when the two machines can talk over SSH:

ai-auth-switch auth import codex-profiles.json
ai-auth-switch auth export | ai-auth-switch auth import -   # pipe, no file

Existing profiles with the same name are skipped to avoid clobbering local state; pass --force to overwrite them. Imported profiles automatically get their numbered aliases (codex1, codex2, claude1, claude2, ...) on the target machine.

Architecture

ai-auth-switch has three separate layers:

  • Auth management: save, list, activate, rename, remove, and inspect profiles.
  • Dependent sync: point Hermes and OpenClaw at the active Codex CLI auth.
  • Wrapper: run a command in a profile-scoped Codex or Claude config directory without changing the default active profile or blocking other accounts.

Provider support is intentionally small. A provider only needs to define where its active auth file lives, how to infer a profile name, and which login command should be run for interactive login.

Download files

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

Source Distribution

ai_auth_switch-0.4.0.tar.gz (64.0 kB view details)

Uploaded Source

Built Distribution

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

ai_auth_switch-0.4.0-py3-none-any.whl (47.4 kB view details)

Uploaded Python 3

File details

Details for the file ai_auth_switch-0.4.0.tar.gz.

File metadata

  • Download URL: ai_auth_switch-0.4.0.tar.gz
  • Upload date:
  • Size: 64.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for ai_auth_switch-0.4.0.tar.gz
Algorithm Hash digest
SHA256 e9848b4a7279fc46be8fc2f2c3b5f67d2a7bd4c2fe4f4fe00486900713576f11
MD5 8f0bd3b2728c2f4976725bcd3087b39d
BLAKE2b-256 56ecd129d054299ba64f9a076951daefc0ac0fd8cc9826215d8d9545875a6dc9

See more details on using hashes here.

File details

Details for the file ai_auth_switch-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: ai_auth_switch-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 47.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for ai_auth_switch-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fa980630dadc5d8cb4cda5f0e3b41edda165a35c5812934a030a0b0a7651771a
MD5 9d72e42a4fd48fc14c690ce5abd9880d
BLAKE2b-256 b395651fb3f5c672efc0da0e8ad6de08f8b9cde07b5bf02bb0d4b7e14740097f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.0

2 files

Supported by

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