Multi-account manager for OpenAI Codex CLI and OpenCode. Add, switch, list, and remove accounts with OAuth browser authentication. Seamlessly switch between both tools with shared credentials.
Zero dependencies - uses Node.js built-ins only.
npm install -g codex-quotaOr with bun:
bun add -g codex-quotaAfter installation, both codex-quota and cq commands are available.
# Add a new account (opens browser for OAuth)
codex-quota codex add personal
# Add a Claude credential (interactive)
codex-quota claude add work
# Check quota for all accounts
codex-quota
# Switch active Codex account
codex-quota codex switch personal
# Switch Claude credentials
codex-quota claude switch work
# Sync activeLabel to CLI auth files
codex-quota codex sync
codex-quota claude sync
# Preview sync without writing files
codex-quota codex sync --dry-run
codex-quota claude sync --dry-run
# List accounts
codex-quota codex list
codex-quota claude list
# Remove an account
codex-quota codex remove old-account
codex-quota claude remove old-accountRun codex-quota with no namespace to check combined Codex + Claude usage.
Check usage quota for Codex accounts.
codex-quota codex quota # All Codex accounts
codex-quota codex quota personal # Specific account
codex-quota codex quota --json # JSON outputCheck usage quota for Claude accounts.
codex-quota claude quota # All Claude accounts
codex-quota claude quota work # Specific credential
codex-quota claude quota --json # JSON outputAdd a new Codex account via OAuth browser authentication.
codex-quota codex add # Label derived from email
codex-quota codex add work # With explicit label
codex-quota codex add --no-browser # Print URL (for SSH/headless)Add a Claude credential interactively.
codex-quota claude add # Prompt for label + credentials
codex-quota claude add work # With explicit label
codex-quota claude add work --json # JSON outputSwitch the active account for Codex CLI, OpenCode, and pi.
codex-quota codex switch personalWhen you run codex switch:
- Codex CLI - Updates
~/.codex/auth.jsonwith the selected account tokens - OpenCode - If
~/.local/share/opencode/auth.jsonexists, updates theopenaiprovider entry - pi - If
~/.pi/agent/auth.jsonexists, updates theopenai-codexprovider entry
It also updates activeLabel in ~/.codex-accounts.json when available.
Switch Claude Code, OpenCode, and pi to a stored Claude credential.
codex-quota claude switch workThis updates activeLabel in ~/.claude-accounts.json when available. OAuth-based
credentials are required to update CLI auth files.
List all Codex accounts from all sources with status indicators.
codex-quota codex list
codex-quota codex list --jsonOutput shows:
*= active account (fromactiveLabel)~= CLI auth account when it diverges fromactiveLabel- Email, plan type, token expiry
- Source file for each account
If CLI auth diverges from the tracked activeLabel, list and quota print a warning and
suggest codex-quota codex sync to realign.
List Claude credentials from CLAUDE_ACCOUNTS or ~/.claude-accounts.json.
codex-quota claude list
codex-quota claude list --jsonOutput shows:
*= active account (fromactiveLabel)- Source file for each credential
For OAuth-based accounts, list and quota warn when stored tokens diverge from the
activeLabel account. Session-key-only accounts are skipped.
Remove a Codex account from storage.
codex-quota codex remove old-accountNote: Accounts from CODEX_ACCOUNTS env var cannot be removed via CLI.
Remove a Claude credential from storage.
codex-quota claude remove old-accountNote: Accounts from CLAUDE_ACCOUNTS env var cannot be removed via CLI.
Sync the activeLabel Codex account to CLI auth files.
codex-quota codex sync
codex-quota codex sync --dry-run
codex-quota codex sync --jsonThis updates:
~/.codex/auth.json~/.local/share/opencode/auth.json(if it exists)~/.pi/agent/auth.json(if it exists)
Sync the activeLabel Claude account to CLI auth files.
codex-quota claude sync
codex-quota claude sync --dry-run
codex-quota claude sync --jsonOnly OAuth-based Claude accounts can be synced. Session-key-only accounts are skipped with a warning.
| Option | Description |
|---|---|
--json |
Output in JSON format |
--dry-run |
Preview sync without writing files |
--no-browser |
Print auth URL instead of opening browser |
--no-color |
Disable colored output |
--version, -v |
Show version number |
--help, -h |
Show help |
Accounts are loaded from these locations (in order). Read/write indicates whether the CLI reads from or writes to each path.
| Source | Purpose | Read | Write |
|---|---|---|---|
CODEX_ACCOUNTS env var |
JSON array of accounts | Yes | No |
~/.codex-accounts.json |
Primary multi-account file (shared with OpenCode) | Yes | Yes (add, remove) |
~/.opencode/openai-codex-auth-accounts.json |
OpenCode accounts | Yes | No |
~/.codex/auth.json |
Codex CLI single-account (label codex-cli) |
Yes | Yes (switch) |
~/.local/share/opencode/auth.json |
OpenCode auth file (openai provider) |
No | Yes (switch if it exists) |
~/.pi/agent/auth.json |
pi auth file (openai-codex provider) |
No | Yes (switch if it exists) |
New accounts added via codex-quota codex add are saved to ~/.codex-accounts.json, which is
shared with OpenCode.
Claude sources (in order):
| Source | Purpose | Read | Write |
|---|---|---|---|
CLAUDE_ACCOUNTS env var |
JSON array of credentials | Yes | No |
~/.claude-accounts.json |
Claude multi-account file | Yes | Yes (add, remove) |
~/.claude/.credentials.json |
Claude Code credentials | Yes | Yes (switch, sync) |
~/.local/share/opencode/auth.json |
OpenCode auth file (anthropic provider) |
No | Yes (switch, sync if it exists) |
~/.pi/agent/auth.json |
pi auth file (anthropic provider) |
No | Yes (switch, sync if it exists) |
File: ~/.codex-accounts.json
{
"schemaVersion": 1,
"activeLabel": "personal",
"accounts": [
{
"label": "personal",
"accountId": "chatgpt-account-uuid",
"access": "access-token",
"refresh": "refresh-token",
"idToken": "id-token-or-null",
"expires": 1234567890000
}
]
}| Field | Type | Description |
|---|---|---|
schemaVersion |
number | Schema version marker (root field) |
activeLabel |
string|null | Active account label (root field) |
label |
string | Unique identifier for the account |
accountId |
string | ChatGPT account UUID |
access |
string | OAuth access token |
refresh |
string | OAuth refresh token |
idToken |
string|null | OAuth ID token (optional, for email extraction) |
expires |
number | Token expiry timestamp in milliseconds |
Root-level fields are preserved on write; unknown root fields are kept intact.
Claude multi-account files (~/.claude-accounts.json) use the same root fields
(schemaVersion, activeLabel) and store account entries that include a
sessionKey or OAuth tokens.
The codex add command uses OAuth 2.0 with PKCE for secure browser authentication:
- Generates PKCE code verifier and challenge
- Starts local callback server on
http://127.0.0.1:1455 - Opens browser to OpenAI authorization page
- User authenticates in browser
- Callback server receives authorization code
- Exchanges code for tokens using PKCE verifier
- Saves tokens to
~/.codex-accounts.json
In SSH sessions or headless environments (detected via SSH_CLIENT, SSH_TTY, or missing DISPLAY), the auth URL is printed instead of opening a browser:
codex-quota codex add --no-browser
# Prints: Open this URL in your browser: https://auth.openai.com/authorize?...Copy the URL to a browser on another machine, complete authentication, and the callback will be received by the local server.
Error: Port 1455 is in use. Close other codex-quota instances and retry.
Another process is using port 1455. Check for:
- Other
codex-quota codex addcommands running - OpenCode or Codex CLI auth processes
Find and kill the process:
lsof -i :1455
kill <pid>If browser doesn't open in SSH session:
- Use
--no-browserflag:codex-quota codex add --no-browser - Copy the printed URL to a browser on another machine
- Complete authentication in browser
- The callback is received by the server running over SSH
If token refresh fails:
Error: Failed to refresh token. Re-authenticate with 'codex-quota codex add'.
The refresh token may have expired. Add the account again:
codex-quota codex remove expired-account
codex-quota codex add new-labelAccounts from CODEX_ACCOUNTS env var cannot be removed via CLI:
Error: Cannot remove account from CODEX_ACCOUNTS env var. Modify the env var directly.
Edit your shell configuration to remove the account from the env var.
All commands support --json for scripting:
# Quota (combined)
codex-quota --json
# {"codex":[{"label":"personal","email":"user@example.com","usage":{...}}],"claude":[...]}
# List (Codex)
codex-quota codex list --json
# {"accounts":[{"label":"personal","isActive":true,"email":"...","source":"..."}]}
# Add (Codex, success)
codex-quota codex add work --json
# {"success":true,"label":"work","email":"user@example.com","accountId":"...","source":"~/.codex-accounts.json"}
# Switch (Codex)
codex-quota codex switch personal --json
# {"success":true,"label":"personal","email":"...","authPath":"~/.codex/auth.json"}
# Sync (Codex)
codex-quota codex sync --json
# {"success":true,"activeLabel":"work","updated":["~/.codex/auth.json",...],"skipped":[...]}
# Errors include structured data
codex-quota codex switch nonexistent --json
# {"success":false,"error":"Account not found","availableLabels":["personal","work"]}Use the claude namespace to check Claude usage alongside OpenAI quotas:
codex-quota claude quotaIf multiple Claude accounts are configured, each account is fetched and displayed separately.
To add a Claude credential interactively:
codex-quota claude addThis uses your local Claude session to call:
https://claude.ai/api/organizationshttps://claude.ai/api/organizations/{orgId}/usagehttps://claude.ai/api/organizations/{orgId}/overage_spend_limithttps://claude.ai/api/account
Authentication sources (in order):
CLAUDE_ACCOUNTSenv var (JSON array or{ accounts: [...] })~/.claude-accounts.json(multi-account format)- Browser cookies (Chromium/Chrome) to read
sessionKeyandlastActiveOrg ~/.claude/.credentials.jsonOAuthaccessToken
Multi-account format (Claude):
{
"accounts": [
{
"label": "personal",
"sessionKey": "sk-ant-oat...",
"cfClearance": "cf_clearance...",
"oauthToken": "claude-ai-access-token",
"orgId": "org_uuid_optional"
}
]
}Notes:
- Only
labelplus one ofsessionKeyoroauthTokenis required. cfClearance,orgId, andcookiesare optional.
Environment overrides:
CLAUDE_ACCOUNTSto supply multi-account JSON directlyCLAUDE_CREDENTIALS_PATHto point to a different credentials fileCLAUDE_COOKIE_DB_PATHto point to a specific Chromium/Chrome Cookies DB
Codex overrides:
CODEX_ACCOUNTSto supply multi-account JSON directly (read-only)CODEX_AUTH_PATHto point to a different Codex CLI auth fileXDG_DATA_HOMEto relocate OpenCode auth pathsPI_AUTH_PATHto point to a different pi auth file
Notes:
- On Linux, cookie access requires
sqlite3andsecret-tool(libsecret) to decrypt cookies. - For best results, keep
claude.ailogged in within your Chromium/Chrome profile.
- Run
bun testandbun run preflightbefore publishing. - Bump version with
bun pm version patch|minor|major. - Dry-run the package with
bun run release:pack. - Publish with
bun run release:publish(local publish, no provenance). - Ensure the git working tree is clean.
MIT