Skip to content

feat(codex): compute Codex credit usage (#408, #495) - #510

Merged
iamtoruk merged 2 commits into
mainfrom
feat/codex-credits
Jun 18, 2026
Merged

feat(codex): compute Codex credit usage (#408, #495)#510
iamtoruk merged 2 commits into
mainfrom
feat/codex-credits

Conversation

@iamtoruk

Copy link
Copy Markdown
Member

Addresses #495 (Codex pricing ≠ credit pricing) and lays the groundwork for #408 (credits as a usage currency). Do not merge yet — opening for review; UI display surface still to be decided.

Problem

CodeBurn prices Codex sessions at OpenAI API token rates (LiteLLM). ChatGPT/Codex subscription users actually consume credits, billed as credits-per-million-tokens at per-model rates that differ from API USD — so the reported dollar cost doesn't reflect credit consumption.

What this adds

  • src/codex-credits.ts: credit engine from the official rates (developers.openai.com/codex/pricing): GPT-5.5 125 / 12.5 / 750, GPT-5.4 62.5 / 6.25 / 375, GPT-5.4 mini 18.75 / 1.875 / 113 credits per 1M input / cached / output tokens. Tolerates -codex suffixes; returns null for unknown models.
  • Per-model credit usage in codeburn models JSON (credits field; null for non-Codex/unknown). models-report already folds reasoning into output and tracks non-cached input + cached-read separately — exactly what the credit rates expect, so the figure is exact.

Verified on real data

gpt-5.5   cost=$142.12   credits=3553.1
gpt-5.4   cost=$ 14.20   credits=355.1

The $/credit ratio (~$0.04) ≠ a naive conversion, confirming #495's point that the two pricings genuinely differ.

Tests

  • tests/codex-credits.test.ts (10): documented rates, suffix variants, reasoning-as-output, cached rate, clamping, unknown→null.
  • tests/models-report.test.ts: per-model credits + null for non-Codex/unknown + credits in JSON output.
  • Full suite green (1206).

Intentionally NOT in this PR (follow-up, your call on display)

  • Human surfaces: a Credits column in the models table, the TUI dashboard, and a menubar "credits used" view (alongside the existing "credits remaining"). Feature Request: Add Credits as Currency #408 is really a display-unit decision, so I left the rendering for you to direct.

iamtoruk added 2 commits June 18, 2026 14:44
Codex/ChatGPT subscription users consume credits, a unit separate from API
dollars: usage is billed as credits-per-million-tokens at per-model rates that
differ from the API USD pricing CodeBurn uses for cost. So the reported dollar
cost does not match what credits actually consume.

Add a credit engine sourced from the official Codex credit rates
(developers.openai.com/codex/pricing): GPT-5.5 125/12.5/750, GPT-5.4
62.5/6.25/375, GPT-5.4 mini 18.75/1.875/113 credits per 1M input/cached/output
tokens. Surface per-model credit usage in `codeburn models` JSON output
(credits field; null for non-Codex or unknown models). models-report already
folds reasoning into output and keeps non-cached input + cached-read separately,
which is exactly what the credit rates expect, so the figure is exact.

Engine + computation are unit-tested. UI display surfaces (the models table,
the TUI dashboard, the menubar "credits" view) are intentionally left for a
follow-up so the display choice can be decided.
Surface Codex credit usage in the menubar as a selectable metric, without
changing the default. Cost ($) stays the default in both the menubar and the
CLI; credits only appear when explicitly chosen.

- TS: buildMenubarPayloadForRange computes the period's Codex credits (via the
  tested aggregateModels, so reasoning/cached are handled) and exposes
  current.codexCredits in the menubar JSON.
- Swift: new DisplayMetric.credits, a "Credits (Codex)" option in the metric
  picker, decodes codexCredits, and renders it in the menu-bar title. Default
  metric remains .cost.
@iamtoruk
iamtoruk merged commit a3da2de into main Jun 18, 2026
3 checks passed
@iamtoruk
iamtoruk deleted the feat/codex-credits branch June 18, 2026 15:03
iamtoruk added a commit that referenced this pull request Jun 21, 2026
* fix(menubar): surface CLI stdout/stderr on decode failure (#515)

A failed decode of the CLI menubar-json output threw an opaque
DataClientError.decode(error) that surfaced only "not valid JSON", hiding
whether stdout was empty or carried a non-JSON prefix (e.g. a stray Node
banner on stdout, the root cause in #515). Wrap it in a CLIDecodeFailure that
carries a bounded stdout snippet, the stdout byte count, and stderr, so
String(describing:) is self-diagnosing in logs and the UI.

* test(menubar): add missing codexCredits arg so the Swift test target compiles

Two tests built CurrentBlock without the codexCredits parameter added in #510,
so the Swift test target failed to compile (CI does not run the Swift tests, so
it went unnoticed). Add codexCredits: nil to both.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant