4.4 KiB
Usage Command Design
Date: 2026-03-12
Goal: Add a built-in /usage command that reports model/account quota usage, starting with Codex running under ChatGPT OAuth, while keeping the retrieval path generic so other agents can plug in later.
Scope
- Add a new built-in slash command:
/usage. - The command is independent from
/statusand/doctor. - Usage retrieval is exposed as an optional agent capability, not hardcoded into the engine for a single vendor.
- First implementation targets the Codex agent when local ChatGPT OAuth credentials are available in
~/.codex/auth.json. - Unsupported agents should return a clear “not supported” style message rather than failing the whole command system.
Architecture
Command Layer
core/engine.go will register and dispatch /usage as a normal built-in command. The engine should not know how ChatGPT, Gemini, or any future provider exposes quota data. It only detects whether the current agent implements a usage-reporting interface and formats the response.
Agent Capability Layer
Add a new optional interface in core/interfaces.go, for example:
UsageReporter- a method such as
GetUsage(context.Context) (*UsageReport, error)
The report type should be generic enough to cover multiple providers:
- provider/agent name
- subject or account label
- plan type / tier if available
- one or more rate-limit buckets/windows
- optional credits/balance fields
- raw provider-specific metadata only if needed for debugging
This keeps future integrations local to each agent package.
Codex Implementation
agent/codex will implement the new interface by:
- Reading
~/.codex/auth.json - Extracting:
tokens.access_tokentokens.account_id
- Calling:
GET https://chatgpt.com/backend-api/wham/usage
- Passing headers:
Authorization: Bearer <access_token>ChatGPT-Account-Id: <account_id>User-Agent: codex-cli
- Mapping the JSON response into the generic usage report
If auth.json is missing, fields are absent, or the HTTP call fails, the agent should return a normal error so /usage can present a concise failure message.
Data Model
The generic report should support at least:
- identity:
- provider
- account_id
- user/email if available
- plan:
- plan_type
- standard rate limits:
- allowed
- limit_reached
- primary window
- secondary window
- review/code-review limits:
- same window shape when available
- credits:
- has_credits
- unlimited
- balance
Each window should preserve:
- used percent
- total window seconds
- reset-after seconds
- reset timestamp if supplied
This is enough for the current ChatGPT OAuth response and still general enough for other providers with multiple quota windows.
Output Format
The first output version should be plain text and compact. Suggested shape:
- title line with agent/provider
- plan line
- standard usage section
- code review usage section if present
- credits section if present
For each window:
- whether requests are currently allowed
- whether the limit is reached
- used percent
- reset timing
Prefer rendering both relative time and absolute time if easy to do consistently. If absolute rendering is added, it should use local time formatting already used by the project, or a simple RFC3339 fallback.
Error Handling
- Agent does not implement usage reporting:
- reply with a user-facing “current agent does not support
/usage”
- reply with a user-facing “current agent does not support
- Codex auth file missing:
- explain that ChatGPT OAuth login data was not found
- Token/account id missing:
- explain credentials are incomplete
- HTTP non-200:
- include status code in logs; show concise failure text to user
- JSON decode failure:
- report provider response parse failure
Do not expose bearer tokens or raw auth file contents in user-visible output or logs.
Testing
Minimum tests should cover:
- command dispatch recognizes
/usage - engine returns unsupported message when agent lacks the interface
- engine formats a successful generic usage report
- Codex usage fetch maps a representative
wham/usagepayload correctly - Codex usage fetch errors on missing auth file / missing token fields
Network-dependent tests should use injected transport or httptest, not live requests.
Non-Goals
- No merging into
/statusor/doctor - No card UI in the first version
- No polling or background caching in the first version
- No support for non-Codex agents in this change beyond the shared interface