Codex CLI
Local-file provider for the OpenAI Codex CLI. Reads session logs, auth state, and config to show today's activity, plan info, and rate-limit windows.
At a glance
- Provider ID —
codex - Detection —
~/.codexdirectory on disk - Auth — token stored in
~/.codex/auth.jsonby the Codex CLI; no env var needed - Type — coding agent
- Tracks:
- Latest session: tokens, model, client
- Daily session counts
- Model and client breakdowns
- Rate-limit windows (primary and secondary)
- Credit balance
- Plan and version
- Patch stats
Setup
Auto-detection
OpenUsage registers the provider as soon as ~/.codex/ exists. Run the Codex CLI at least once to create it.
Manual configuration
{
"accounts": [
{
"id": "codex",
"provider": "codex",
"extra": {
"config_dir": "~/.codex",
"sessions_dir": "~/.codex/sessions"
}
}
]
}
Override config_dir and sessions_dir only if the CLI uses non-default paths.
Data sources & how each metric is computed
Codex has two data paths:
- Local files — JSONL session transcripts and auth/config metadata under
~/.codex/. Always available after a single Codex run. - Live ChatGPT usage endpoint — an authenticated POST to ChatGPT's backend, only attempted when
~/.codex/auth.jsoncontains a non-empty access token. Provides plan, credits, and rate-limit windows.
The base URL for the live endpoint is, in order: acct.BaseURL → extra.chatgpt_base_url → the value parsed from ~/.codex/config.toml (chatgpt_base_url) → https://chatgpt.com/backend-api. The path is /wham/usage for chatgpt.com/backend-api and /api/codex/usage otherwise.
Latest session
- Source: the most recently modified
~/.codex/sessions/**/*.jsonl. The provider parses the trailing turn'sInfo.TotalTokenUsagefor tokens, plusmodelandclientfrom the same payload. - Transform: tokens stored as
latest_session_tokens, model/client stored underRaw["latest_session_model"]andRaw["latest_session_client"].
Daily / model / client breakdowns
- Source: the same JSONL files, scanned per poll (with mtime + size caching to skip unchanged files).
- Transform: each turn becomes a usage record. Records are aggregated by model, by client, and by day. Outputs:
sessions_today— distinct sessions with at least one turn whose timestamp falls in today (local time).- Per-model rows with input/output/cached token totals.
- Per-client rows with the same totals plus session count.
Rate-limit windows (rate_limit_primary, rate_limit_secondary)
- Source:
rate_limit.primaryandrate_limit.secondaryfrom the live usage endpoint. Each carriesused_percent,window_minutes,resets_at(Unix seconds). - Transform:
Used = used_percent,Limit = 100.Resets[…]is set fromresets_at.Windowis<minutes>m. Each window is also exposed via a direct alias for the dashboard widget:plan_auto_percent_usedaliasesrate_limit_primary,plan_api_percent_usedaliasesrate_limit_secondary. A separateplan_percent_usedmetric reflects the greater of the two.
Credit balance
- Source:
credits.balance(orcredits.has_creditsboolean) from the same live response. - Transform: stored as a metric
Remainingin USD.unlimited=trueis reflected as a special attribute.
Plan, version, account email
- Source:
plan_type,emailfrom live response; CLI version from~/.codex/version.json; account ID fromauth.json(tokens.account_idor top-levelaccount_id). - Transform: each stored as a snapshot attribute.
Patch stats
- Source: scanning JSONL turns for tool-call entries that look like file edits.
- Transform: aggregated counts of patches/files-changed.
Auth status
- Source: combination of HTTP status code on the live call and the presence of
auth.json. - Transform:
401/403from the live endpoint setserrLiveUsageAuth; the provider then keeps the local-data-only path intact and surfaces the error as a diagnostic.
What's NOT tracked
- Per-token spend in dollars from local sessions. Codex sessions don't carry pricing — only token counts. The credit balance is the only $ figure, and it comes from the live endpoint.
- Hook-driven real-time events without the integration. Install the
codexintegration (see Daemon integrations) for per-turn events.
:::note Cost values hidden by default on Plus / Pro / Team / Enterprise
On a ChatGPT subscription plan (Plus, Pro, Team, Enterprise) the dollar number is misleading — usage is governed by rate-limit windows, not by per-call pricing. OpenUsage hides cost columns by default whenever the live plan_type reports a subscription tier; rate-limit windows, sessions, and tokens stay visible. Override with dashboard.hide_costs or the c keystroke.
:::
How fresh is the data?
- Polling: every 30 s by default. JSONL files are re-parsed when their mtime/size changes; otherwise served from cache.
- Hook (when integration is installed): real-time per turn.
API endpoints used
- Optional live usage endpoint:
GET https://chatgpt.com/backend-api/wham/usage(default), orGET <base>/api/codex/usagefor non-ChatGPT bases.- Headers:
Authorization: Bearer <auth.json access_token>andChatGPT-Account-Id: <account_id>when available.
Files read
~/.codex/sessions/**/*.jsonl— session transcripts~/.codex/auth.json— auth token (tokens.access_token,tokens.account_id)~/.codex/config.toml— CLI configuration (chatgpt_base_urlif set)~/.codex/version.json— installed version
Caveats
- Credit balance only appears when the live endpoint is reachable; offline sessions still show local activity.
- Rate-limit windows are reported by the API and may differ from documented limits during quota changes.
- The provider has hooks-style integration with the daemon: see Daemon integrations.
Troubleshooting
- Tile is empty — run
codexonce to populate~/.codex/sessions/. - No credit balance —
~/.codex/auth.jsonis missing or expired. Re-authenticate with the Codex CLI. - Sessions missing — confirm
sessions_dirmatches the path Codex writes to.
Related
- OpenAI — direct API rate limits for the underlying models
- Claude Code — sibling local-file coding-agent provider