feat(cost): a SPEND card that prices seats, beside a TOKEN COST card - #44
Merged
Conversation
The Overview led with SPEND over a figure that is not spend - it is
the window's tokens priced at API list rates. That figure keeps its
card under the name it deserved, TOKEN COST, with the rate, delta and
unpriced qualifiers unchanged.
The SPEND card now answers the question its name asks: what the seats
behind the usage actually cost per month. Figures come from
[cost.subscriptions], or failing that from the plan the tool's own
transcripts name - Codex writes rate_limits.plan_type on the same
records the token counts come from, so this reads no account state.
A detected plan prices at its published list rate via the fallback
table CostConfig::monthly already carried, and is marked as an
estimate; a tool with usage but no figure floors the total; knowing
nothing, the card shows a dash and the config key rather than a guess.
The Cost view's subscription table picks up detected plans through the
same one line, still suffixed est. Detected plans persist in the
ledger - version 5, because a steady-state scan reads no bytes and
anything gathered during a read has to survive between scans, the same
argument that put session metadata in version 4. The first scan after
upgrading re-reads transcripts once.
Verified against a real corpus: a fresh scan writes
plans:{codex:team} and the card prices it at $30/mo, flagged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 1, 2026
# Conflicts: # CHANGELOG.md # docs/guide/dashboard.md # src/ui/mod.rs
kleyt0n
added a commit
that referenced
this pull request
Aug 11, 2026
Two conflicts, both from main having merged #44 (spend-vs-token-cost) after this branch already carried it. src/ui/mod.rs — main's copy of `the_token_cost_card_qualifies_its_dollars` landed as a duplicate of the one already here (commit cf88d91 gave this branch's copy the same cache rates), and git split the duplicate across the metering tests. Dropped the duplicate, kept main's fuller doc comment on the surviving copy, and kept `metering: Default::default()` on the fixture main does not know the field for. CHANGELOG.md — this branch had flattened main's entries to ASCII (`—` → `-`, `≥` → `>=`), truncated their prose and added a UTF-8 BOM. Main's text is canonical for the shared entries, so the section is rebuilt from it plus the three entries only this branch adds: the card row, the metering view and `[usage.repo_aliases]`. BOM removed. cargo fmt / clippy -D warnings clean; 287 tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Overview led with SPEND over a figure that is not spend — it is the window's tokens priced at API list rates. Two cards now ask two different questions about the same tokens:
Where SPEND's figures come from
[cost.subscriptions]— configured seat prices, shown plainly. Always wins.rate_limits.plan_typebeside its token counts, so this reads no account state. A detected plan is priced at its published list rate via the fallback tableCostConfig::monthlyalready carried (previously unreachable — the plan argument was alwaysNone) and marked≈an estimate.≥a floor; knowing nothing, the card shows–and names the config key. Never a guess.The Cost view's subscription table picks up detected plans through the same line, still suffixed
est.Ledger v5
Detected plans persist in the ledger (
plans: tool → plan), version 4 → 5 — the same argument that put session metadata in v4: steady-state scans read no bytes, so anything gathered during a read must survive between scans. First scan after upgrading re-reads transcripts once.Verification
"plans":{"codex":"team"}and the card shows≥≈$30.00/mo · 1 plan(s) detected · ▲ 1 tool(s) unpriced(Claude Code here has usage but no plan/config — correctly floored).rate_limits, plan ingested into the ledger, plan survives save/reload (last one wins), and the card's three states (dash/never-guess,≈detected estimate,≥floor with configured seat).--demoseeds two plans so the card demos populated. Docs updated everywhere the "does not guess your plan" claim lived (README, dashboard.md, costs.md, configuration.md, surface.example.toml) plus CHANGELOG.cargo fmt,clippy -D warnings, all 249 tests pass.Interactions
Independent of the other open PRs (#41, #42, #43); it will conflict trivially with #43 on the qualifier line under what is now the TOKEN COST card — whichever lands second rebases one line.
🤖 Generated with Claude Code