Canonical and compatibility paths for account, settings, cache, and logs.
Default root:
~/.codex/multi-auth
Override root:
CODEX_MULTI_AUTH_DIR=<path>
| File | Default path |
|---|---|
| Unified settings | ~/.codex/multi-auth/settings.json |
| Unified settings backup | ~/.codex/multi-auth/settings.json.bak |
| Accounts | ~/.codex/multi-auth/openai-codex-accounts.json |
| Accounts backup | ~/.codex/multi-auth/openai-codex-accounts.json.bak |
| Accounts WAL | ~/.codex/multi-auth/openai-codex-accounts.json.wal |
| Flagged accounts | ~/.codex/multi-auth/openai-codex-flagged-accounts.json |
| Flagged accounts backup | ~/.codex/multi-auth/openai-codex-flagged-accounts.json.bak |
| Quota cache | ~/.codex/multi-auth/quota-cache.json |
| Runtime observability | ~/.codex/multi-auth/runtime-observability.json |
| First-run setup marker | ~/.codex/multi-auth/first-run-setup.json |
| Alternate / legacy plugin config | ~/.codex/multi-auth/config.json |
| Usage directory | ~/.codex/multi-auth/usage/ |
| Usage ledger | ~/.codex/multi-auth/usage/usage-ledger.jsonl |
| Usage ledger archives | ~/.codex/multi-auth/usage/usage-ledger.<timestamp>.jsonl |
| Account policies | ~/.codex/multi-auth/account-policies.json |
| Routing profiles | ~/.codex/multi-auth/routing-profiles.json |
| Budget guards | ~/.codex/multi-auth/budget-guards.json |
| Local bridge client tokens | ~/.codex/multi-auth/local-client-tokens.json |
| Cross-process refresh leases | ~/.codex/multi-auth/refresh-leases/ |
| Runtime app helper status | ~/.codex/multi-auth/runtime-rotation-app-helper.json |
| Persistent app bind directory | ~/.codex/multi-auth/app-bind/ |
| Named pool backups | ~/.codex/multi-auth/backups/ |
| Per-project account pools | ~/.codex/multi-auth/projects/<project-key>/openai-codex-accounts.json |
| Logs | ~/.codex/multi-auth/logs/codex-plugin/ |
| Cache | ~/.codex/multi-auth/cache/ |
| Settings / config save locks | ~/.codex/multi-auth/*.lock (transient) |
| Reset-intent markers | ~/.codex/multi-auth/*.reset-intent (excluded from recovery candidates) |
| Codex CLI accounts | ~/.codex/accounts.json |
| Codex CLI auth | ~/.codex/auth.json |
| Codex CLI config | ~/.codex/config.toml |
first-run-setup.json lives under the multi-auth root
(getCodexMultiAuthDir() / ~/.codex/multi-auth by default). On the first
manager CLI invocation after install, the package records a one-shot marker and
best-effort self-heals packaged app bind + launcher routing when runtime
rotation is enabled. Concurrent first invocations claim the marker with an
exclusive create so setup runs at most once. Failures are debug-logged and never
block the user command.
The marker carries a version. A marker written before the Codex auth-store
step existed (version: 1) is migrated in place on the next manager CLI
invocation: only that step is replayed, and app bind / launcher install are
deliberately not rerun so shortcuts the user removed stay removed. The migration
takes no exclusive claim because both the config.toml rewrite and the marker
write are idempotent and atomic. An unreadable or truncated marker is treated as
pre-v2 and migrated the same way, rather than re-triggering full setup.
A failed auth-store step deliberately leaves the marker pre-v2 so the next
invocation retries it — otherwise one transient Windows EPERM/EBUSY on a
locked config.toml would strand the CLI on keychain mode permanently. This
applies to the initial setup too: if that step fails there, the marker records
the older version and the next run replays only that step. A skipped result
does advance the version, since it is the normal outcome both for a config
already pinned to "file" and for an explicit
CODEX_MULTI_AUTH_ENFORCE_CLI_FILE_AUTH_STORE=0 opt-out.
Deleting the marker can re-trigger first-run setup on the next CLI run.
Ownership note:
~/.codex/multi-auth/*is managed by this project.~/.codex/accounts.json,~/.codex/auth.json, and~/.codex/config.tomlare managed by official Codex CLI.- The
codex-multi-auth-codexwrapper preserves that official CLI file-backed auth layout by forwarding non-auth commands with-c cli_auth_credentials_store="file", unless the caller already setcli_auth_credentials_storeexplicitly. - That
-coverride only covers processes the wrapper launches. Third-party front-ends (menu-bar apps such as CodexBar, editor extensions) exec the official binary directly and read~/.codex/config.tomlinstead, so a config left oncli_auth_credentials_store = "keychain"keeps raising macOS login-keychain "Always Allow" prompts. The persisted top-level value is therefore reconciled to"file"at three points: first-run setup, wrapper startup before forwarding, anddoctor --fix. - Only the top-level assignment is rewritten. A
cli_auth_credentials_storeinside a[profiles.*]table is left as authored, and a top-level key is inserted above the first table instead. The rewrite preserves the file's existing line endings (a CRLFconfig.tomlstays CRLF) and accepts either TOML string form, so'file'is recognized as already-correct and left alone. - Set
CODEX_MULTI_AUTH_FORCE_FILE_AUTH_STORE=0to opt out of both the wrapper-injected-coverride and the wrapper-startup config reconcile, leaving the downstream CLI auth store untouched. - Set
CODEX_MULTI_AUTH_ENFORCE_CLI_FILE_AUTH_STORE=0to opt out of everyconfig.tomlrewrite (first-run, account switch/login sync, anddoctor --fix) while leaving the per-invocation-coverride in place. - Neither the keychain nor the
securityCLI is ever read or written: reading a keychain item would itself raise the prompt this behavior exists to eliminate. Credentials saved by an earlier officialcodex loginstay where they are, are no longer read once the store is pinned to"file", and can be removed manually via Keychain Access. - Runtime rotation may create a temporary shadow
CODEX_HOMEunder the operating-system temp directory while a forwarded Codex command is running. The wrapper syncs refreshed official state files back to the original Codex home before cleanup. - Interactive TUI sessions are the exception: they run against the canonical
CODEX_HOMEand receive the rotation provider through-coverrides instead, so session history and SQLite state are read and written in place rather than copied into a shadow and synced back.config.tomlitself is never rewritten on this path. - Because interactive sessions share the canonical home, two of them can run concurrently against the same state — the same as running the official CLI twice. No lock is taken: neither session copies or syncs state, so there is nothing to clobber, and serializing them would be a regression against stock behavior. Concurrent-session state retention is covered by a regression test in
test/codex-bin-wrapper.test.ts. - When
CODEX_HOMEis set to a non-default directory, multi-auth resolves strictly to$CODEX_HOME/multi-authand does not scan~/.codex/multi-authfor existing pools. - V3 account storage may also carry
pinnedAccountIndexandaffinityGenerationfor CLI pin / session-affinity invalidation.
Compatibility note:
- This file-store forwarding keeps auth state readable from disk outside interactive terminals, so wrapper forwarding and non-TTY auth flows stay deterministic after the Ink migration.
Windows note: The wrapper keeps the official Codex CLI file-store layout unchanged, so Windows
EPERM/EBUSYretry handling still lives with the downstream CLI writes rather than this wrapper layer. Opting out withCODEX_MULTI_AUTH_FORCE_FILE_AUTH_STORE=0stops injecting the file-store override for future wrapper launches, but it does not rewrite or expose previously written CLI auth files beyond the standard~/.codex/auth.jsonand~/.codex/accounts.jsonlocations. The wrapper-startupconfig.tomlreconcile writes through the same atomic rename withEPERM/EBUSYretries; if it still fails (locked or read-only config), the failure is swallowed and forwarding proceeds, because the per-invocation-coverride already protects that run.
Backup metadata:
getBackupMetadata()reports deterministic snapshot lists for the canonical account pool (primary, WAL,.bak,.bak.1,.bak.2, and discovered manual backups) and flagged-account state (primary,.bak,.bak.1,.bak.2, and discovered manual backups). Cache-like artifacts and.reset-intentmarkers are excluded from recovery candidates.settings.json.bakstores the last valid unified settings snapshot before each write and is used as a recovery fallback whensettings.jsonis unreadable.- Flagged-account backup recovery is suppressed whenever the flagged reset marker is still present, so partial clears cannot revive previously cleared flagged entries.
Upgrade note:
- Restore workflows now distinguish between unreadable state and intentionally cleared state.
settings.json.bakis only used whensettings.jsonexists but cannot be read, while flagged-account backups stay suppressed whenever the reset marker survives a partial clear. - Operators validating a restore or clear flow should use
codex-multi-auth verify-flagged,codex-multi-auth fix --dry-run, andcodex-multi-auth doctor --fixto confirm what will be recovered, what stays cleared, and whether manual repair is still needed. - Maintainers validating the on-disk upgrade behavior can run
npm run buildplusnpm test -- --run test/unified-settings.test.ts test/storage-recovery-paths.test.ts test/storage-flagged.test.tsbefore shipping backup or restore changes.
When project-scoped behavior is enabled:
~/.codex/multi-auth/projects/<project-key>/openai-codex-accounts.json
<project-key> is derived as:
- sanitized project folder basename (max 40 chars)
-- first 12 chars of
sha256(normalized project path)
On Windows, normalization lowercases drive/path segments before hashing.
Implementation reference: lib/storage/paths.ts (getProjectStorageKey).
Worktree behavior:
- Standard repositories: identity is the project root path.
- Linked Git worktrees: identity is the shared repository root, so all worktrees for the same repo share one account pool.
- Non-Git directories: identity falls back to the detected project path.
Older installations may still have compatibility-read paths during migration. These are migration-only and not canonical for new setup.
Examples:
~/DevTools/config/codex/- older pre-
~/.codex/multi-authcustom roots
Runtime rotation adds local state only when enabled or when a helper has recently run.
| Path | Purpose |
|---|---|
~/.codex/multi-auth/runtime-observability.json |
request counters, last selected runtime account metadata, and cooldown context for status/report commands |
~/.codex/multi-auth/runtime-rotation-app-helper.json |
wrapper-launched codex app helper state, idle timeout, request count, and last-account metadata |
~/.codex/multi-auth/app-bind/runtime-rotation-app-bind.json |
persistent packaged-app bind state |
~/.codex/multi-auth/app-bind/codex-config-backup.json |
backup metadata for restoring the real Codex config.toml |
~/.codex/multi-auth/app-bind/runtime-rotation-app-bind-status.json |
persistent app router status |
~/.codex/multi-auth/app-bind/runtime-rotation-app-router.log |
persistent app router log |
~/.codex/multi-auth/first-run-setup.json |
one-shot first CLI run marker for Codex auth-store enforcement / app bind / launcher self-heal (versioned; v1 markers migrate in place) |
The app bind writes a provider entry to the real ~/.codex/config.toml only after taking a backup. codex-multi-auth rotation disable and codex-multi-auth rotation unbind-app restore the backup and remove the router startup entry.
| Path | Purpose |
|---|---|
~/.codex/multi-auth/usage/ |
Directory for the local usage ledger and rotated archives |
~/.codex/multi-auth/usage/usage-ledger.jsonl |
Append-only local usage metadata ledger |
~/.codex/multi-auth/usage/usage-ledger.<timestamp>.jsonl |
Archived ledgers produced by codex-multi-auth usage rotate |
~/.codex/multi-auth/account-policies.json |
Hashed-account policy metadata for tags, weights, pause, drain, and notes (codex-multi-auth account ...) |
~/.codex/multi-auth/routing-profiles.json |
Project-aware profile preferences keyed with getProjectStorageKey |
~/.codex/multi-auth/budget-guards.json |
Local budget limits evaluated from usage summaries (codex-multi-auth budget ...) |
~/.codex/multi-auth/local-client-tokens.json |
Local bridge token hashes and prefixes only (codex-multi-auth bridge token ...) |
The local bridge is loopback-only and exposes /health, /v1/models, and
/v1/responses. Plain client tokens are shown only by codex-multi-auth bridge token create or codex-multi-auth bridge token rotate; the token store persists hashes.
Policy pause/drain entries in account-policies.json are enforced at selection
time by evaluateRuntimePolicy (blocked accounts are excluded from hybrid
rotation).
Experimental named backup exports are written under the local plugin-owned backup namespace beside the active accounts file:
- global root:
~/.codex/multi-auth/backups/<name>.json - project root:
~/.codex/multi-auth/projects/<project-key>/backups/<name>.json
Rules:
.jsonis appended when omitted- backup names may only contain letters, numbers,
_, and- - path separators and
..are rejected .rotate.,.tmp, and.walnames are rejected- existing files are not overwritten unless a lower-level force path is used explicitly
Experimental sync targets the companion oc-chatgpt-multi-auth storage layout:
- global target:
~/.opencode/openai-codex-accounts.json - project target:
~/.opencode/projects/<project-key>/openai-codex-accounts.json - target backups:
~/.opencode/backups/or project-localbackups/beside the target account file
codex-multi-auth status
codex-multi-auth list
codex-multi-auth verify --paths