| summary | Codex provider data sources: OpenAI web dashboard, Codex CLI RPC, credits, and local cost usage. | ||||
|---|---|---|---|---|---|
| read_when |
|
Codex has three automatic usage data paths (OAuth API, web dashboard, CLI RPC) plus a manual CLI PTY diagnostic parser and a local cost-usage scanner. The OAuth API is the default app source when credentials are available; web access is optional for dashboard extras.
- OAuth API (auth.json credentials).
- CLI RPC through
codex app-server. - If OpenAI web extras are enabled and a matching OpenAI web session is available (Automatic or Manual cookies),
dashboard extras load as a separate follow-up refresh and the source label becomes
primary + openai-web.
Usage source picker:
- Preferences → Providers → Codex → Usage source (Auto/OAuth/CLI).
- OpenAI web dashboard (when available).
- Codex CLI RPC through
codex app-server.
- Reads OAuth tokens from
~/.codex/auth.json(or$CODEX_HOME/auth.json). - CodexBar never publishes refreshed native tokens into
auth.json; when native credentials are stale, the explicit OAuth path delegates recovery to the Codex CLI, which owns that file. If the CLI is unavailable, the OAuth error is surfaced instead of mutating the shared file. - Calls
GET https://chatgpt.com/backend-api/wham/usage(default) withAuthorization: Bearer <token>. - The app reads reset-credit inventory once per refresh with a best-effort
GET https://chatgpt.com/backend-api/wham/rate-limit-reset-creditsusing the same account-scoped OAuth context; the CLI requests it only when optional credits are included. - The menu and provider settings list every still-available expiry, while the optional credits setting controls nearing-expiry notifications. CodexBar does not redeem or modify reset credits.
rate_limit.primary_window/secondary_windowmap to the session/weekly lanes.- Suspicious weekly resets keep the last trusted usage while confirmation is pending. A successful refresh for the same account and workspace clears stale connectivity errors even when the reading is withheld; failed, cancelled, or superseded refreshes do not clear them. Cached usage, credits, and other accounts remain unchanged.
- Credits-only updates preserve pending weekly-reset evidence in memory and account-snapshot storage, including when published credits are cleared. Candidate admission, expiry, boundary tolerances, and account guards remain unchanged; preserving evidence does not make an otherwise incompatible reset eligible for publication.
- Debug logs in
codex-weekly-reset-publicationinclude fixed reason codes for delayed-candidate creation, pruning, revalidation, and account-scoped storage requests. They distinguish source/confidence, timing, boundary, identity/plan compatibility, and credit-inventory failures without logging account or credit identifiers. Codes describe the first rejected prerequisite; they do not relax confirmation policy or prove the cause of a past stale reading.storeRequestedmeans the file-store call was made, not that a disk write succeeded. additional_rate_limits[](model-specific limits such as GPT-5.3-Codex-Spark) map to namedUsageSnapshot.extraRateWindowsentries. Spark uses stablecodex-spark/codex-spark-weeklyids andCodex Spark 5-hour/Codex Spark Weeklytitles. When the field is absent, the snapshot is unchanged.- Preferences → Providers → Codex → Visible usage items lets you hide individual Spark rows in menus, the Settings preview, and Overview. It does not change fetching, history, notifications, widgets, credits, or other extra limits.
- External Codex OAuth sources is a provider setting that must be enabled explicitly before CodexBar reads another application's OAuth file. It is off by default because this is a cross-application credential boundary.
- Without an explicit
$CODEX_HOME, native Codex auth wins first, followed by legacy~/.config/codex/auth.json, then OpenCode's~/.local/share/opencode/auth.json(or the equivalentXDG_DATA_HOMEpath). - An explicit
$CODEX_HOMEremains isolated; it never borrows credentials from those external locations. - External fallbacks accept OAuth token structures only; API-key entries are ignored. Usage probes never refresh or
publish OAuth token material into a shared
auth.jsonwithout a cross-writer publication contract. Stale native credentials can delegate to the CLI recovery path, while stale external credentials fail closed in every mode. Automatic mode also suppresses unscoped CLI fallback whenever a managed workspace is selected. Explicit managed-account workspace selection is stored in CodexBar's private managed-account metadata; it never edits the sourceauth.jsonor publishes anaccount_idchange back to another application's credential file. - If native credentials need renewal, use Reauthenticate for the affected account in Settings → Providers → Codex.
For CLI recovery, run
codex loginwith that account's existingCODEX_HOMEand select the intended workspace. The refresh error describes this manual recovery without promising automatic CLI fallback for managed workspaces. - Stacked account refreshes retain each managed account's selected workspace through usage publication and menu matching, even when its auth file names a different default workspace. Changing the selected workspace while a refresh is running discards the old workspace's result.
- System Account promotion fails closed when a managed selection differs from the auth file's default workspace. CodexBar keeps that selection managed rather than silently promoting the default or rewriting Codex-owned auth.
- Reusing OpenCode OAuth enables remote account quota, not OpenCode session token/cost ingestion. See OpenCode with Codex or OpenAI for the current history boundary.
- Managed Codex accounts remain the default multi-account path.
- Advanced users can add existing Codex homes to
~/.codexbar/config.jsonwithproviders[].codexProfileHomePaths. - Each configured path must be absolute or start with
~/, and point at a Codex home that containsauth.json. - CodexBar reads identity from the configured home, exposes it in the Codex account switcher, and scopes
remote Codex fetches with
CODEX_HOME. - Profile homes are not copied, reauthenticated, or removed by CodexBar.
Example:
{
"id": "codex",
"codexProfileHomePaths": [
"~/.codex-work",
"~/.codex-personal"
]
}Account settings, the System Account picker, and the menu switcher retain the workspace name when it is available. If the same email and workspace label would appear more than once (including missing names or the “Personal” fallback), CodexBar adds a stable eight-character hash of the workspace identity. The hash stays the same when selecting or promoting that workspace and never exposes the full provider identifier. This is display-only; stored account metadata and credential selection are unchanged. Separate profile homes for the same workspace also include a hashed source identity, so their labels stay distinct without exposing paths. Compact switcher buttons keep the discriminator visible when space is limited, using additional rows when needed.
- Subscription renewal or expiration dates load after the app publishes dashboard usage. CodexBar first tries the subscription API, then captures only the date and renewal flag from ChatGPT's own billing request in the same account-scoped web session, within an eight-second budget.
- Billing capture is best-effort: unavailable or malformed responses retain previously fetched dates, while a valid empty response clears them. Cancelled, replaced, disabled, or account-mismatched refreshes cannot attach dates. The CLI web source waits only within its remaining fetch deadline.
- Enable it in Preferences -> Providers -> Codex -> OpenAI web extras.
- It exists for dashboard-only extras such as code review remaining, usage breakdown, and credits history.
- It is intentionally opt-in because it loads
chatgpt.comin a hidden WebView and can materially increase battery or network usage. - OpenAI web battery saver is a separate toggle. When enabled, routine background/settings-driven refreshes are reduced, but explicit manual refreshes still run.
- OpenAI web battery saver currently defaults to off.
- Preferences → Providers → Codex → OpenAI cookies (Automatic or Manual).
- URL:
https://chatgpt.com/codex/settings/usage. - Uses an off-screen
WKWebViewwith a per-accountWKWebsiteDataStore.- Store key: deterministic UUID from the normalized email.
- WebKit store can hold multiple accounts concurrently.
- Each WebView acquisition keeps ownership across asynchronous page preparation. Explicit store eviction invalidates that store's pending preparations, so stale success, failure, or timeout retry cannot displace a replacement view. Evict-all invalidates all pending preparations; ordinary lease release does not invalidate concurrent temporary views.
- Leases retain their cleanup owner independently of the cache and release only once. Validated pages still support the brief reuse handoff; other releases schedule the existing deferred WebKit cleanup, including temporary views.
- Cookie import (Automatic mode, when WebKit store has no matching session or login required):
- Safari:
~/Library/Cookies/Cookies.binarycookies - Chrome/Chromium forks:
~/Library/Application Support/Google/Chrome/*/Cookies - Firefox:
~/Library/Application Support/Firefox/Profiles/*/cookies.sqlite
- Domains loaded:
chatgpt.com,openai.com. - No cookie-name filter; we import all matching domain cookies.
- Safari:
- Cached cookies: Keychain cache
com.steipete.codexbar.cache(accountcookie.codex, source + timestamp). Reused before re-importing from browsers. - Manual cookie header:
- Paste the
Cookie:header from achatgpt.comrequest in Preferences → Providers → Codex. - Used when OpenAI cookies are set to Manual.
- Paste the
- Account match:
- Signed-in email extracted from
client-bootstrapJSON in HTML (or__NEXT_DATA__). - If Codex email is known and does not match, the web path is rejected.
- Signed-in email extracted from
- Web scrape payload (via
OpenAIDashboardScrapeScript+OpenAIDashboardParser):- Rate limits (5h + weekly) parsed from body text.
- Credits remaining parsed from body text.
- Code review remaining (%).
- Usage breakdown chart (Recharts bar data + legend colors).
- Credits usage history table rows.
- Credits purchase URL (best-effort).
- Errors surfaced:
- Login required or Cloudflare interstitial.
- Launches local RPC server:
codex -s read-only -a never app-server. - JSON-RPC over stdin/stdout:
initialize(client name/version)account/readaccount/rateLimits/read
- RPC reads are bounded: initialization has a longer startup budget, and normal requests have a shorter per-method
timeout. On timeout, CodexBar closes the child
codex app-serverprocess's stdin and escalates from SIGTERM to SIGKILL after a bounded grace period, so the stdout reader unwinds and unresponsive children cannot linger. - Provides:
- Usage windows (primary + secondary) with reset timestamps.
- Credits snapshot (balance, hasCredits, unlimited).
- Account identity (email + plan type) when available.
- App-server errors are terminal for the CLI strategy, except when Codex includes a recoverable
wham/usageJSON body in the error text. - If macOS blocks or quarantines the
codexexecutable, CodexBar records the launch failure and skips background CLI launches for 30 minutes. Use a manual refresh after reinstalling or unblockingcodexto retry immediately. - CodexBar also discovers the Codex CLI bundled with current ChatGPT and legacy Codex desktop apps, even when
codexis absent from the shell PATH. - If managed Codex account login still reports a missing executable, turn on Show debug settings in
Settings > Advanced, then check Settings > Debug > CLI Paths. When no Codex binary appears there, confirm
codex --versionworks in Terminal, checkwhich -a codexfor stale duplicate installs, then runnpm install -g --include=optional @openai/codex@latestbefore retrying Add Account.
- Manual/debug parser only; automatic background refresh and
CodexBarCLI usage --source clido not launch bare Codex TUI. - Kept for explicit diagnostics/parser coverage because bare
codexTUI can start interactive auth and open browser tabs. - Parses rendered
/statusoutput:Credits:line5h limitline → percent + reset textWeekly limitline → percent + reset text
- Detects update prompts and surfaces a "CLI update needed" error.
- Latest Codex usage snapshot (from RPC, if available).
~/.codex/auth.json(JWT claims: email + plan).- OpenAI dashboard signed-in email (cached).
- Last imported browser cookie email (cached).
- Web dashboard fills credits only when OAuth/CLI do not provide them. Account-matched extra usage reconciles monthly caps and purchased balances separately: a newer confirmed zero clears an old balance, while an unread balance preserves the last successful reading. Extra usage shows monthly spend/limit and a distinct purchased balance when available; the optional credits setting controls visibility.
- CLI RPC:
account/rateLimits/read→ credits balance. - CLI PTY diagnostics can still parse
Credits:from saved/manual/statusoutput.
- Menu source selection:
- By default, a selected managed account keeps its own
CODEX_HOMEsession history. - Local session cost estimates is a Codex-only opt-in that instead scans this Mac's ambient
$CODEX_HOME(or~/.codex) independently of quota, OAuth, web-dashboard, and administrator access. - Regular menu cost refreshes publish local session estimates even when global cost tracking is off. This does not enable other providers' cost scans; results still require the same provider configuration and history/account scope.
- The local-only mode never makes a network request or uploads session content. It uses an existing local models.dev
cache when available, then the bundled
CostUsagePricingrates.
- By default, a selected managed account keeps its own
- Source files:
- Native Codex logs:
~/.codex/sessions/YYYY/MM/DD/*.jsonl~/.codex/archived_sessions/*.jsonl(flat; date inferred from filename when present)- Or
$CODEX_HOME/sessions/...+$CODEX_HOME/archived_sessions/...ifCODEX_HOMEis set.
- Supported pi-compatible sessions:
~/.pi/agent/sessions/**/*.jsonl~/.omp/agent/sessions/**/*.jsonl
- Native Codex logs:
- Scanner:
- Codex reserve telemetry uses the bundled GPT-5.6 Luna list-price estimate, including existing cached token rows. This estimates API-equivalent cost; it is not a charge for using a subscription reserve allowance.
- Bundled
gpt-6-astrapricing covers input, cache reads/writes, output, and the full-request long-context threshold above 272K input tokens. Astra Fast pricing is twice the applicable Standard rates when existing priority-request evidence selects that mode. Stored token rows are repriced without a history rebuild. Rates follow the OpenAI model card and pricing table. - Valid JSON whitespace between event fields is accepted during initial scans and appended-session refreshes. Older cached files are reparsed once through the normal scan budget; compatible stores retain their rows and checkpoints until each file is refreshed.
- Native Codex logs parse
event_msgtoken_count entries andturn_contextmodel markers; when both are present,turn_contextis authoritative for the model bucket. - A subagent's
subagent_history_start_ordinalis authoritative: earlier records are inherited context, even if they contain delivery markers or the file ends before child-owned history arrives. Later appends count only the child's own deltas. Older per-file parser revisions refresh through the normal scan budget while stored history and checkpoints remain available. - pi and OMP sessions count assistant-message usage rows and attribute
openai-codexassistant usage to Codex. - pi-compatible assistant usage is bucketed by assistant-turn timestamp, so mixed-model sessions can contribute to multiple days/models correctly.
- Matching assistant entry IDs within the same session are counted once across roots; distinct turns are retained.
- Native conversation rows reuse the corrected cached per-file totals and existing pricing tables. They are hidden when pi-compatible usage joins the aggregate because the native-only rows would not reconcile with the merged total.
- Cache:
- Native session store:
~/Library/Caches/CodexBar/cost-usage/cost-usage.sqlite - pi-compatible session cache:
~/Library/Caches/CodexBar/cost-usage/pi-sessions-v8.jsonis replaced atomically on macOS and Linux, retaining complete cached scan state across refreshes. - Catch-up status reads progress metadata without loading historical usage JSON or replay bodies. Cached token activity reads scoped daily aggregates without decoding individual usage events, retaining account, time zone, coverage, and incomplete-scan checks. Cached reports retain row-level pricing evidence and project/session details, but omit raw token snapshots, accumulator state, and replay bodies. File cursor metadata, including JSONL resume state, remains available for progress tracking. A native scan loads exact usage rows once, deferring raw token history and checkpoints until a file changes or a fork needs its ancestors. A single-use receipt binds those deferred reads and saves to the original connection, database identity and SQLite change observations, checking again under the writer lock. Filesystem/anchor and catch-up reconciliation still run at comparison time; a concurrent database change requests a rescan. Fresh database opens retain integrity validation.
- Saved day/model aggregates group each file's usage rows in one pass per aggregate build. Packed token totals, authoritative costs (including zero), and standard/priority estimation buckets retain their existing meanings.
- Fully read empty session fragments retain completion records even when another file contributes the same session. They contribute no usage and reparse from the start if they grow. Usage-bearing duplicates and incomplete fragments keep their existing accounting and retry rules. Existing 0.56.4 cost caches are adopted without rebuilding stored usage, retained reports, or partial-scan checkpoints.
- Priority trace scans resume after ordinary log pruning when enough distributed content anchors still match; changed source rows, replaced databases, or insufficient matching anchors require a fresh scan. Temporary trace-database failures retain the last validated report pricing and leave scan freshness unchanged for retry. Successful historical queries update their own pricing window independently of the live scan cursor, including results with no priority turns; validated pricing outside that window remains intact.
- Native session store:
- Window: configurable 1-365 day rolling history.
- Pending cost scans retain their discovery range when the same cache receives narrower or wider history requests ending on the same day. Reports still use the requested dates, and compatible existing caches retain stored usage and partial-scan progress on upgrade. A new ending day, changed roots/timezone, or a forced rescan keeps the usual discovery reset behavior.
- App cadence: regular timer-driven local-history refreshes have a 15-minute minimum (30 minutes in Low Power Mode). Manual disables the recurring refresh timer, not all scan activity: startup refreshes and pending Codex catch-up can still scan local history. Faster provider refreshes still update quota/status. The scanner's default 60-second debounce is a separate internal limit, bypassed by forced scans and catch-up passes; it is not the app's refresh cadence.
- Usage & Spend catch-up remains inactive after a no-progress or error pause until you choose Refresh in the dashboard toolbar or catch-up panel. Opening the dashboard or receiving background updates does not retry those terminal pauses. Low-power and thermal pauses can still recover automatically; this retry policy does not change cached history or token accounting.
- Automatic Codex catch-up scheduling in both usage and Spend Dashboard honors the app’s 30-minute Low Power Mode minimum after each pass. Explicit acceleration remains immediate, and physical low-power/thermal pauses retain their own retry policy. The setting applies when the next delay is computed; an already pending sleep is not replanned.
- Automatic catch-up reports thermal pressure when serious heat and Low Power Mode coexist. Both constraints keep the existing 60-second pause before rechecking resource state.
- A catch-up worker that loses its account or settings scope clears its abandoned Refreshing activity on exit. Legitimate pauses remain visible, and an older worker cannot clear a replacement worker's activity.
- When a warm cost refresh reaches its time limit, it saves the remaining file work and completed discovery. Compatible shorter/wider history requests resume that work across the retained scan range; publication still waits for exact inventory validation.
- Inline cost charts preserve a slot for every day in that window, using the selected cost-bucket time zone and the snapshot's date. Missing days are zero only after history coverage is established; unscanned days and entries without prices remain unknown. Long windows fit within the menu width without dropping dates.
- Hide personal information replaces project/source names with numbered labels and hides their paths in the cost-history submenu; Usage & Spend also masks project names. Costs, tokens, grouping, and stored history are unchanged, and disabling the setting restores the original labels. This is display masking, not data deletion or export sanitization.
- While a bounded refresh catches up with new session history, established totals remain visible only for the same account, history window, and bucket time zone. An incomplete first scan never borrows another account's totals.
- Pending local-history files receive a turn before fresh work, within the existing byte and duration limits. Unfinished files rotate behind waiting work, and the queue survives restarts without rebuilding compatible caches.
- Parent-session discovery also resumes within those limits after the requesting fork files leave both scan roots. Stale pending path associations are reconciled in the existing cache; surviving forks with missing parents still retain their unresolved usage instead of being counted as complete.
Settings → Usage & Spend performs a separate fixed 30-day scan for every visible Codex account. Each request freezes
the account source, exact Codex home, authentication fingerprint, and cache identity before scanning. A missing or
invalid home is omitted; it never falls back to ambient ~/.codex or to the global Codex token snapshot.
These account rows intentionally exclude pi and OMP sessions because their history is machine-local rather than owned by one Codex account. The normal Codex cost menu and CLI scan continue to include supported pi-compatible history. The dashboard labels its values as local estimates and keeps currencies separate.
- Web:
Sources/CodexBarCore/OpenAIWeb/* - CLI RPC + diagnostic PTY parser:
Sources/CodexBarCore/UsageFetcher.swift,Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift - Cost usage:
Sources/CodexBarCore/CostUsageFetcher.swift,Sources/CodexBarCore/PiSessionCostScanner.swift,Sources/CodexBarCore/PiSessionCostCache.swift,Sources/CodexBarCore/Vendored/CostUsage/*