codex-switch 0.1.13

Local CLI account switcher for Codex
# codex-switch

Local CLI account switcher for Codex.

## Install

```sh
cargo install codex-switch
```

For local development:

```sh
cargo install --path .
```

## Commands

```sh
codex-switch list
codex-switch login <name> [--replace] [--device-auth]
codex-switch import <name> [--file <path>]
codex-switch export <name-or-id> [--file <path>] [--force]
codex-switch switch <name-or-id>
codex-switch auto-switch
codex-switch run [--codex-bin <path>] -- [CODEX_ARGS]...
codex-switch update [--check] [--version <version>]
codex-switch usage [name-or-id]
codex-switch usage --all
codex-switch delete <name-or-id>
codex-switch rename <name-or-id> <new-name>
```

## Storage

Accounts are stored in `~/.codex-switch/accounts.json`.

Switching writes Codex auth data to:

1. `$CODEX_HOME/auth.json`, when `CODEX_HOME` is set
2. `~/.codex/auth.json`, otherwise

On Unix, both files are written with `0600` permissions.

## Switching

`switch` refuses to write Codex auth data while unmanaged active Codex processes are detected. Close regular Codex sessions before switching accounts. Sessions launched through `codex-switch run` are managed by the local proxy, so `switch` is allowed while those sessions are running.

`auto-switch` also refuses to switch while Codex is running. When Codex is not running, it checks stored ChatGPT OAuth accounts and switches to the account selected by the quota-aware policy. Accounts that are out of credits, rate-limited, usage-limited, or at 100% usage are not selectable. API key accounts are not usage-checkable and are skipped as replacement candidates.

`run` is the runtime auto-switching entrypoint. It checks accounts before startup, starts `codex app-server`, launches Codex as a remote TUI through a local websocket proxy, and passes arguments after `--` to `codex`. During the managed session, the proxy watches Codex app-server `account/rateLimits/updated` notifications and usage-limit errors. It also performs best-effort background auto-switch checks every 15-45 minutes. Hard usage-limit signals trigger an immediate recovery attempt. Non-hard rate-limit updates only schedule a background re-check when the current Codex auth account is near the shared 5% bottleneck headroom threshold, so normal updates do not block the TUI on usage API calls. If another shell runs `codex-switch switch <name-or-id>`, managed `run` sessions detect the current Codex auth account change and hot-load it when the selected account is ChatGPT OAuth.

`run` writes diagnostics to a per-process log file under `~/.codex-switch/logs/`. Before handing the terminal to Codex, startup diagnostics are also written to stderr using the default tracing format, including timestamp, level, target, and the log path, so startup hangs can be traced to initial auto-switch, app-server startup, proxy binding, or remote TUI spawn. After Codex TUI starts, codex-switch background diagnostics only go to the log file so they do not corrupt the TUI. Set `CODEX_SWITCH_LOG` to a level such as `off` or `debug`, or to a full tracing filter, to control this output.

```sh
codex-switch run
codex-switch run -- resume
codex-switch run -- resume --last
codex-switch run -- resume <session-id>
```

`run` supports Codex interactive commands that accept `--remote`: the default TUI, `resume`, and `fork`. ChatGPT OAuth accounts are required for runtime switching. API key accounts are not usage-checkable and cannot be applied to the running app-server. Switching to an API key account still updates `auth.json` for the next Codex start, but existing managed `run` sessions keep their current runtime auth. The runtime switch applies through Codex's app-server auth API; an in-flight request may continue with the auth it already started with, so the request that first reports a usage-limit error may still fail before the next turn uses the replacement account.

## Login

`login` uses ChatGPT/OpenAI browser OAuth by default. It starts a local callback server, opens the browser, and saves the account. It does not write Codex `auth.json`; run `codex-switch switch <name-or-id>` when you want to use the new account.

The browser callback server uses the same ports as Codex: `1455` by default, with `1457` as the fallback.

Use `codex-switch login <name> --device-auth` for device authorization. The CLI prints a verification URL and one-time code, then waits for authorization.

Use `codex-switch login <name> --replace` to re-login an existing stored ChatGPT OAuth account after its credentials stop refreshing. The target name must already exist. Replacement happens only after OAuth succeeds, preserves the stored account ID and timestamps, and does not write Codex `auth.json`; run `codex-switch switch <name-or-id>` to apply the refreshed credentials to Codex. API key accounts cannot be replaced by `login --replace`.

## Import

`import` reads an existing Codex `auth.json`. When `--file` is omitted, it imports from the current Codex auth file: `$CODEX_HOME/auth.json` when `CODEX_HOME` is set, otherwise `~/.codex/auth.json`.

`login` and `import` reject accounts that match an already stored auth identity. `login --replace` allows replacing the target account's own auth identity, but still rejects an identity that belongs to another stored account.

## Export

`export` writes a stored account as Codex-compatible `auth.json` JSON. By default it prints to stdout:

```sh
codex-switch export my-account
```

The exported JSON contains credentials. Treat stdout and exported files as secrets.

Use `--file` to write to a file. Existing files are not overwritten unless `--force` is passed.

```sh
codex-switch export my-account --file ./auth.json
codex-switch export my-account --file ./auth.json --force
```

Exporting does not change the current Codex auth file.

## Update

`update` checks GitHub Releases and replaces the current release binary with the matching platform asset:

```sh
codex-switch update --check
codex-switch update
codex-switch update --version 0.1.10
```

The updater verifies the GitHub release asset SHA-256 digest before replacing the executable. It does not run `sudo`; if the current executable path is not writable, rerun your install script or install the binary with elevated permissions. If codex-switch was installed with Cargo, use:

```sh
cargo install codex-switch --locked --force
```

## Usage

Usage reporting is supported for ChatGPT OAuth accounts. API key accounts are listed as unsupported for usage.

## Release

The GitHub Actions release workflow builds Linux musl binaries for `aarch64` and `x86_64`, plus a macOS arm64 binary. On pushes to `master`, it compares the current Cargo package version with the previous `Cargo.toml` version. When the version changes, it creates tag `v{version}`, creates a GitHub release, uploads the raw binaries, and publishes the crate to crates.io.

Publishing to crates.io requires a repository Actions secret named `CARGO_REGISTRY_TOKEN`.

```text
codex-switch-aarch64-unknown-linux-musl
codex-switch-x86_64-unknown-linux-musl
codex-switch-aarch64-apple-darwin
```

## Development

```sh
cargo fmt --check
cargo check --locked --all-targets --all-features
cargo test --locked --all-targets --all-features
cargo clippy --locked --all-targets --all-features -- -D warnings
```