Skip to content
133 changes: 133 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ Most of these also run as a **direct CLI** with no agent or model involvement, s
| Backups | `~/.opencode/backups/` or `~/.opencode/projects/<project-key>/backups/` |
| Logs | `~/.opencode/logs/codex-plugin/` |
| TUI quota cache | OpenCode state dir plus `oc-codex-multi-auth-tui-quota.json`, else `$OPENCODE_STATE_DIR/oc-codex-multi-auth-tui-quota.json` or `~/.local/state/opencode/oc-codex-multi-auth-tui-quota.json` |
| TUI pool quota cache | `oc-codex-multi-auth-tui-quota-overview.json`, in the same directory, written only when `quotaStatus.mode` is `overview` |

Per-project storage is enabled by default. The plugin walks up from the current directory to find a project root, then stores account pools under the project-specific key. If no project root is found, it falls back to global storage.

Expand All @@ -318,6 +319,132 @@ Primary config files:
- `~/.config/opencode/tui.json`
- `~/.opencode/openai-codex-auth-config.json`

### Quota percentage display

Every quota percentage a person reads is worded as the headroom still left,
which is how Codex itself reports a quota:

```text
5h limit: 88% left # codex-limits, quota details dialog
5h 88% # TUI prompt status line
```

Set `quotaDisplay` to `"used"` to report consumption instead:

```json
{
"quotaDisplay": "used"
}
```

```text
5h limit: 12% used
5h 12%
```

Add it to `~/.opencode/openai-codex-auth-config.json`, or set
`CODEX_AUTH_QUOTA_DISPLAY=used`, then quit and restart OpenCode. The setting
covers the TUI prompt status line and quota details dialog, `codex-limits`,
the standalone `limits` CLI, the interactive account check, and the macOS
quota notifications below.

It changes wording only. Quota exhaustion, rotation blocks, notification
thresholds, and the status line's warning/danger colouring all stay keyed on
the percentage remaining, so a nearly spent account still colours red while
reading `95%`. The `usedPercent` and `leftPercent` fields in `--json` /
`format="json"` output are unaffected.

### Pool-wide quota status

The prompt status line describes the account that served the last request. On
a pool of several accounts that account changes as rotation moves, so the line
changes identity under you and no single glance shows where the pool stands.

Set `quotaStatus.mode` to `"overview"` to describe the whole pool on one
constant line instead, which only changes when a quota does:

```json
{
"quotaStatus": {
"mode": "overview",
"layout": "accounts",
"accountNames": "number",
"order": "number",
"multipliers": false,
"allotment": false,
"resetTimes": "low",
"resetCredits": false,
"recovery": false,
"rows": 1,
"showFor": "always"
}
}
```

```text
24%: #1 13%, #2 0% 3d, #3 12% # defaults
24%: 3 accounts # "layout": "count"
24%: #1 5x 13%, #2 20x 0% 3d, #3 1x 12% # "multipliers": true
24%: #1 5x 13%, #2 20x 0% 3d 1r, #3 1x 12% # + "resetCredits": true
24%: 3 accounts, +12% in 3d # "layout": "count", "recovery": true
24% of 26x: #1 13%, #2 0% 3d, #3 12% # "allotment": true
24%: #1 13% 2d, #2 0% 3d, #3 12% 5d # "resetTimes": "always"
24%: 13%, 0% 3d, 12% # "accountNames": "none"
24%: damian 13%, work 0% 3d, spare 12% # "accountNames": "label"
24%: #2 0% 3d, #1 13%, #3 12% # "order": "most-used"
24%: 13% 2d, 0% 3d 4d 5d # "layout": "aggregate"
```

Each switch is independent, so any combination works. `#N` is the account
number `codex-list` and `codex-switch` use. An account is shown by whichever
of its windows has the least headroom, since that is the one that stops a
request; a reset time (`3d`) is added for an account at or below 25% by
default, for every account under `"resetTimes": "always"`, and for none under
`"never"`. `1r` counts banked rate-limit resets that account can redeem now.

`order` takes `number`, `most-used`, `least-used`, `renewing-earliest`, or
`renewing-latest`. `layout: "aggregate"` prints a shared percentage once and
keeps only what differs after it, which matters most on a pool where several
accounts are spent.

The leading figure is the pool total, and it is a **weighted** mean: a Pro seat
spent to 50% has given up twenty times the capacity a Business Standard seat
does at 50%, so an unweighted average would describe a pool nobody has. The
per-plan ratios are listed in [docs/plan-allotments.md](docs/plan-allotments.md),
and `"allotment": true` shows what they add up to.

`mode` also accepts a list, and the line then alternates between those screens
every `rotateMs` (default 5000). The third screen, `resets`, appears only once
every account is spent and lists the banked reset credits worth redeeming,
latest reset first - redeeming one on an account that renews by itself tomorrow
throws it away:

```json
{
"quotaStatus": { "mode": ["overview", "resets"] }
}
```

```text
Free resets: 6d 1r damian@nowaker.net, 4d 2r work@example.com
```

`"rows"` (1-4, default 1) is a ceiling rather than a height: a rendering that
fits on one row still takes one, so `"rows": 2` costs nothing on a wide terminal
and buys the whole line back on a narrow one, where the agent/model label beside
it has already wrapped to two rows anyway. `"showFor": "codex-models"` hides the
line unless the session is running a model this plugin routes.

Percentages follow `quotaDisplay`, so the first line above reads
`76%: #1 87%, #2 100% 3d, #3 88%` under `"used"`. The whole setting is
presentation only: rotation, quota blocks and the line's warning/danger
colouring stay keyed on the headroom remaining.

Add the object to `~/.opencode/openai-codex-auth-config.json`. It is read from
that file only - a display preference belongs to a person, not to a shell - and
the status line re-reads it while sessions are open, so an edit takes effect
within a couple of seconds without a restart.

### Desktop quota notifications

Quota notifications are an optional macOS-only feature. Separately, the quota
Expand All @@ -339,6 +466,10 @@ Account identities are omitted for readability and lock-screen privacy:
Weekly: 72% | resets 22:30 on Aug 30
```

The percentage follows `quotaDisplay`, so the same two lines read `90%` and
`28%` under `"used"`. `thresholds` are always remaining-percent values
regardless.

```json
{
"quotaNotifications": {
Expand Down Expand Up @@ -441,6 +572,8 @@ Selected runtime/environment overrides:
| `CODEX_TUI_GLYPHS=ascii\|unicode\|auto` | Force terminal glyph style |
| `CODEX_TUI_MASK_EMAIL=0/1` | Mask account emails across account-display surfaces (list/status/limits/health/dashboard/menus + TUI quota status) |
| `CODEX_TUI_MASK_EMAIL_DETAILS=0/1` | Also hide account email in quota details when prompt masking is enabled |
| `CODEX_AUTH_QUOTA_DISPLAY=free\|used` | Word quota percentages as headroom left (default, matching Codex) or as consumption |

| `CODEX_AUTH_PER_PROJECT_ACCOUNTS=0/1` | Disable/enable per-project account pools |
| `CODEX_AUTH_CREDENTIAL_SNAPSHOTS=0/1` | Disable/enable pre-write snapshots of the credential store (default on) |
| `CODEX_AUTH_CREDENTIAL_SNAPSHOTS_MAX_COUNT=<n>` | How many credential snapshots to keep (`0` keeps all of them) |
Expand Down
1 change: 1 addition & 0 deletions docs/DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ docs/
├── getting-started.md # install + first-run guide
├── tools-and-cli.md # 24 codex-* tools + standalone CLI
├── configuration.md # full config reference
├── plan-allotments.md # ChatGPT plan -> allotment multiplier map
├── troubleshooting.md # operational debugging guide
├── faq.md # short common answers
├── privacy.md # data handling notes
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This documentation set is split by purpose so the main README can stay focused o
- [Tools and CLI](tools-and-cli.md): complete catalog of 24 `codex-*` tools and standalone bin commands
- [Architecture Overview](architecture.md): public map of the installer, OpenCode plugin entry, TUI plugin, tool registry, request pipeline, rotation, and storage model
- [Configuration Reference](configuration.md): config keys, environment variables, fallback behavior, and file locations
- [Plan Allotments](plan-allotments.md): what each ChatGPT plan is worth relative to a 1x seat, and how the pool-wide quota total is weighted
- [Troubleshooting](troubleshooting.md): common failure modes and recovery steps
- [FAQ](faq.md): short answers for common questions
- [Privacy & Data Handling](privacy.md): what is stored locally, what is sent upstream, and how to delete it
Expand Down
Loading