Codex Reverse Engineering

How We Figured Out the Codex Usage Dashboard

This page captures the reasoning behind codex_nerve.py: where the account credentials come from, which endpoint exposes usage windows, which headers matter, and why local session counting is only an optional supplement.

Open the full Codex auth deep dive

Inputs

What We Already Had

The local Codex CLI stores authentication metadata in ~/.codex/auth.json and session transcripts in ~/.codex/sessions.

Goal

What We Wanted

A lightweight terminal view of account usage: 5-hour and weekly utilization, reset countdowns, plan information, and a rough local session count.

Output

What We Built

codex_nerve.py polls the usage endpoint, draws a curses dashboard, and optionally scans local session files for recent activity.

Refresh

How Tokens Stay Current

~/.codex/auth.json includes both an access_token and a refresh_token, so a stale copied token can be recovered without logging in again.

Discovery Path

  1. Start from a working Codex installation. If Codex already works on the machine, the safest path is to reuse the locally stored auth context rather than trying to manually reconstruct credentials.
  2. Extract the account-scoped identifiers. The two critical values are the bearer token and the ChatGPT account id, both available in ~/.codex/auth.json.
  3. Replicate the account usage request. The dashboard calls https://chatgpt.com/backend-api/wham/usage with the same two headers the CLI uses for account-level views.
  4. Treat session counts as a local hint, not an API truth. The usage payload exposes limit windows and plan state, but not a canonical account-wide “session count,” so ~/.codex/sessions is scanned separately.

The Minimal Request Shape

The dashboard’s network layer is intentionally small. The essential request is:

GET https://chatgpt.com/backend-api/wham/usage
Authorization: Bearer <access_token>
ChatGPT-Account-Id: <account_id>
Accept: application/json

That response provides the usage windows used by the TUI, including primary and secondary rate-limit windows, reset times, plan metadata, and code-review window information.

How We Inferred the Refresh Flow

The installed Codex binary contains clear OAuth strings for token recovery, including refresh_token, grant_type, application/x-www-form-urlencoded, the ChatGPT client id app_EMoamEEZ73f0CkXaXp7hrann, and log messages like “Access token expired, refreshing.”

Separately, the local token claims show iss=https://auth.openai.com and the offline_access scope, which strongly suggests standard OAuth refresh semantics. I verified the token endpoint from the OpenAI OIDC discovery document: https://auth0.openai.com/oauth/token.

POST https://auth0.openai.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
refresh_token=<refresh_token from ~/.codex/auth.json>
client_id=app_EMoamEEZ73f0CkXaXp7hrann
The dashboard uses this flow only as a recovery step after an auth failure. The standalone helper script codex_refresh_auth.py lets you inspect or run the same refresh explicitly.

Read the step-by-step auth investigation

Why Local Session Counting Is Separate

The dashboard scans *.jsonl files under a configured sessions_dir and groups them into “last 5 hours,” “last 7 days,” and “all time.” This is helpful for local machine awareness, but it is not the same thing as server-side account usage.

A local sessions directory can be missing, incomplete, or tied to just one machine. The API data is the source of truth for rate limits; the session scan is supplemental.

Bootstrapping the Config Safely

The helper script writes credentials into Codex/.local/accounts.ini, which is gitignored. That keeps the live token file out of normal source control while still giving the dashboard a stable default path.

./Codex/codex_bootstrap_accounts.sh
python3 Codex/codex_refresh_auth.py --print-only
python3 Codex/codex_nerve.py

Project Links