Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,12 @@ Remove-Item "$env:LOCALAPPDATA\codex-auth\bin\codex-auth-auto.exe" -Force -Error

| Command | Description |
|---------|-------------|
| `codex-auth list [--debug]` | List all accounts |
| `codex-auth list [--debug] [--api|--skip-api]` | List all accounts. `--api` forces a live refresh, while `--skip-api` uses only stored local usage and team-name data. |
| `codex-auth login [--device-auth]` | Run `codex login` (optionally with `--device-auth`), then add the current account |
| `codex-auth switch [<email>]` | Switch active account interactively or by partial match |
| `codex-auth remove` | Remove accounts with interactive multi-select |
| `codex-auth switch [--api|--skip-api]` | Switch the active account interactively. `--api` forces a live refresh first; `--skip-api` stays local-only. |
| `codex-auth switch <query>` | Switch the active account directly by row number, alias, or fuzzy match using stored local data only. |
| `codex-auth remove [<query>...]` | Remove accounts interactively or by one or more selectors (row number, alias, or fuzzy match) using stored local data only. |
| `codex-auth remove --all` | Remove all stored accounts. |
| `codex-auth status` | Show auto-switch, service, and usage status |

### Import
Expand Down Expand Up @@ -128,34 +130,58 @@ Remove-Item "$env:LOCALAPPDATA\codex-auth\bin\codex-auth-auto.exe" -Force -Error
```shell
codex-auth list
codex-auth list --debug
codex-auth list --api # force usage/team-name API refresh, even if config api is disabled
codex-auth list --skip-api # use only stored registry data; skip usage/team-name API refresh
```

`--api` forces the foreground usage and team-name refresh path for this command only.
`--skip-api` keeps the current local snapshot exactly as stored in `registry.json`.
It does not call the usage API or `accounts/check`, so transient live-refresh failures such as `401` and `403` are not preserved in this mode.

### Switch Account

Interactive: shows email, 5h, weekly, and last activity.
Interactive `switch` shows email, 5h, weekly, and last activity.
Without `<query>`, it follows the configured refresh mode before opening the picker.
Use `--api` to force a foreground refresh first, or `--skip-api` to stay on stored local data only.

```shell
codex-auth switch
codex-auth switch --api
codex-auth switch --skip-api
```

![command switch](https://github.com/user-attachments/assets/48a86acf-2a6e-4206-a8c4-591989fdc0df)

Non-interactive: fuzzy match by email or alias.
`<query>` can be a displayed row number, an alias, or a fuzzy email/alias match.
The row number follows the interactive `switch` list, and the same number from `codex-auth list` also works because both commands use the same ordering.
`switch <query>` always resolves from stored local data and does not accept `--api` or `--skip-api`.

```shell
codex-auth switch john # match any account containing "john"
codex-auth switch john@gmail.com # match by full or partial email
codex-auth switch work # match by alias set during import
codex-auth switch 02 # switch by displayed row number
codex-auth switch john # fuzzy match by email or alias
codex-auth switch work # match by alias set during import
```

If the keyword matches multiple accounts, the command falls back to interactive selection. Press `q` to quit without switching.
If `<query>` matches multiple accounts, the command falls back to interactive selection.

### Remove Accounts

`remove` always uses stored local data and does not refresh from APIs before deleting.
Each selector supports the same query forms as `switch`: row number, alias, or fuzzy email/alias match.
The row number follows the interactive `switch` list, and the same number from `codex-auth list` also works because both commands use the same ordering.
You can pass multiple selectors in one command.
Selector-based `remove` does not accept `--api` or `--skip-api`.

```shell
codex-auth remove
codex-auth remove 01 03
codex-auth remove work personal
codex-auth remove 01 [email protected]
codex-auth remove --all
```

If any selector matches multiple accounts, `remove` asks for confirmation in interactive terminals before deleting.

### Login (Add Account)

Add the currently logged-in Codex account:
Expand Down
21 changes: 11 additions & 10 deletions docs/api-refresh.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ The `accounts/check` response is parsed by `chatgpt_account_id`. `name: null` an

- `api.usage = true`: foreground refresh uses the usage API.
- `api.usage = false`: foreground refresh reads only the newest local `~/.codex/sessions/**/rollout-*.jsonl`.
- when `api.usage = true`, `list`, interactive `switch`, and `remove` without a query or `--all` refresh all stored accounts before rendering, using stored auth snapshots under `accounts/` with a maximum concurrency of `3`
- when one of those per-account foreground usage requests returns a non-`200` HTTP status, the corresponding `list` / `switch` / `remove` row shows that response status in both usage columns until a later successful refresh replaces it
- when a stored account snapshot cannot make a ChatGPT usage request because it is missing the required ChatGPT auth fields, the corresponding `list` / `switch` / `remove` row shows `MissingAuth` in both usage columns until a later successful refresh replaces it
- when `api.usage = true`, `list` and interactive `switch` refresh all stored accounts before rendering, using stored auth snapshots under `accounts/` with a maximum concurrency of `3`
- when one of those per-account foreground usage requests returns a non-`200` HTTP status, the corresponding `list` / `switch` row shows that response status in both usage columns until a later successful refresh replaces it
- when a stored account snapshot cannot make a ChatGPT usage request because it is missing the required ChatGPT auth fields, the corresponding `list` / `switch` row shows `MissingAuth` in both usage columns until a later successful refresh replaces it
- when `api.usage = false`, foreground refresh still uses only the active local rollout data because local session files do not identify the other stored accounts
- `switch <query>` does not perform a foreground usage refresh before activation or before showing a local multi-match picker
- `remove <query>` and `remove --all` do not perform a foreground usage refresh before deletion
- `list --api` forces foreground usage refresh for this command even when `api.usage = false`; `list --skip-api` skips foreground usage refresh completely and renders only the stored registry data
- interactive `switch` follows the configured foreground usage mode by default; `switch <query>` always resolves selectors locally from stored data and does not accept `--api` or `--skip-api`
- `remove` always resolves selectors from stored local data and does not accept `--api` or `--skip-api`
- `switch` does not refresh usage again after the new account is activated
- the auto-switch daemon refreshes the current active account usage during each cycle when `auto_switch.enabled = true`
- the auto-switch daemon may also refresh a small number of non-active candidate accounts from stored snapshots so it can score switch candidates
Expand All @@ -58,10 +59,10 @@ The `accounts/check` response is parsed by `chatgpt_account_id`. `name: null` an
- A usable ChatGPT auth context with both `access_token` and `chatgpt_account_id` is required. If either value is missing, refresh is skipped before any request is sent.
- `login` refreshes immediately after the new active auth is ready.
- Single-file `import` refreshes immediately for the imported auth context.
- `list` refreshes synchronously before rendering and waits for `accounts/check` when the active user scope qualifies.
- interactive `switch` refreshes synchronously before showing the picker and waits for `accounts/check` when the current active user scope qualifies.
- `switch <query>` skips foreground account-name refresh and uses stored metadata only.
- `list` and interactive `switch` load the request auth context from the current active `auth.json`.
- `list --api` forces synchronous `accounts/check` refresh for this command even when `api.account = false`; `list --skip-api` skips it and uses stored metadata only.
- interactive `switch` follows the configured account-name refresh mode by default; `switch <query>` always stays local-only and does not accept `--api` or `--skip-api`.
- `remove` always stays local-only and does not accept `--api` or `--skip-api`.
- `list` and interactive `switch` load the request auth context from the current active `auth.json` when they do refresh.
- the auto-switch daemon still uses a grouped-scope scan during each cycle when `auto_switch.enabled = true`.
- daemon refreshes load the request auth context from stored account snapshots under `accounts/` and do not depend on the current `auth.json` belonging to the scope being refreshed.
- when multiple stored ChatGPT snapshots exist for one grouped scope, daemon refreshes pick the snapshot with the newest `last_refresh`.
Expand All @@ -76,7 +77,7 @@ Request failures and unparseable responses are non-fatal and leave stored `accou
Grouped account-name refresh always operates on one `chatgpt_user_id` scope at a time.

- `login` and single-file `import` start from the just-parsed auth info
- `list` and interactive `switch` start from the current active auth info
- `list` and interactive `switch` start from the current active auth info when foreground refresh is enabled
- the auto-switch daemon scans registry-backed grouped scopes and refreshes each qualifying scope independently

That scope includes:
Expand Down
Loading
Loading