Skip to content

feat: label popover cost as API-equivalent on Max/Pro/Team (#200) - #224

Closed
Borisserz wants to merge 1 commit into
chattymin:mainfrom
Borisserz:feat/label-api-equivalent-cost
Closed

Borisserz wants to merge 1 commit into
chattymin:mainfrom
Borisserz:feat/label-api-equivalent-cost

Conversation

@Borisserz

@Borisserz Borisserz commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • When the Claude credential reports a Max / Pro / Team plan, popover cost figures ($610.30) now read $610.30 (API-equiv.) so they are not mistaken for a bill. The number is unchanged — it is still ModelPricing × tokens.
  • API-key accounts, Free, and providers that already set reportsCost = false (Codex / Cursor / Copilot / …) keep today's presentation.
  • Out of scope (the two design questions on Plan-aware cost: label API-equivalent cost and show subscription leverage #200): Settings field for monthly plan price / leverage , and the menu-bar compact cost. Happy to follow up once those are decided.

Predicate lives on LimitStatus (where subscriptionType already lives) so generic today/week/month totals do not grow a providerID == branch.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • Other:

UI changes

Before After
Popover today / week / month / Claude row: $610.30 on Max/Pro/Team Same figures with (API-equiv.) (localized). API-key and Free unchanged. Menu bar $9.5 unchanged.

Checklist

  • swift build and swift test pass locally
  • PR title and description are written in English
  • UI changes are described above (before/after — images optional)
  • No copyrighted assets, secrets, or private tooling references are committed (see CONTRIBUTING)
  • Tests were added or updated for this change

Tests

  • LimitStatus.labelsCostAsAPIEquivalent — max/pro/team (incl. case fold) on; free/api/empty/nil off. A=false and B=true both locked.
  • TokenFormatter.cost(_:labeled:) — suffix appended; nil/empty suffix does not add a trailing space.
  • UsageStore.labelsCostAsAPIEquivalent — follows the injected Claude plan after refresh (Max/Team on, Free and no-limits off).
  • Source lock: popover consults the predicate + L.apiEquivalentCaption; menu-bar costCompact stays unlabeled.
  • Caption contains API and is parenthetical in every AppLanguage.allCases (ko/en/ja/es/fr/pt).

./scripts/test-gate.sh: 786 pass, 10 skipped, 0 failures. Logic-core line coverage 90.52%.

How to verify

On a Max/Pro/Team Claude login with official limits loaded, open the popover: today / week / month (and the Claude row) should show (API-equiv.) next to $. Switch the language in Settings — the qualifier localizes; the $ figure does not. Menu bar cost toggle should still be the compact $9.5 / $311 form.

Label-only slice of #200 (Settings price / leverage and menu-bar labeling left for a follow-up).

…#200)

Subscription plans already carry subscriptionType on LimitStatus; the
dollar figures are ModelPricing × tokens, not a bill. Qualify popover
rows only — menu bar and a Settings price field stay out of this PR.
@chattymin

Copy link
Copy Markdown
Owner

Thanks for implementing this, and for taking the conservative half of #200 — label only, no user-entered plan price, no hardcoded price table. That was the right slice to try first.

I'm not taking it, for two reasons.

The label lands on providers it isn't true for. The predicate reads the Claude subscription, but costText is applied to every provider row and to the combined header. Six providers report cost — Claude, Codex, Gemini, Grok, OpenCode and Hermes — so a user on Claude Max who also uses Grok would see "(API-equiv.)" on the Grok row, where the figure is a server-reported actual charge rather than an estimate. The qualifier would be saying the opposite of the truth there. If this ever comes back, the judgement has to be per-provider — is this provider's cost an estimate or a bill — rather than one global flag.

The part that motivated #200 isn't in it. The issue's argument was the leverage ratio — "$100/mo against $610 of API-equivalent tokens, 6.1×" — which is what makes the number instructive for someone learning token economics. Without it we pay the UI cost (a caption on every cost row, seven localization columns to maintain) and don't get the payoff. Meanwhile the bare number is the convention in this category and subscription users already read it as "what this would have cost on API".

I'm closing this and leaving #200 open — the underlying observation is fair, it just needs a different shape.

Thanks again, and sorry for the slow answer on this one.

@Borisserz

Copy link
Copy Markdown
Contributor Author

Follow-up for the two close reasons is in a new PR, not a reopen of this branch:

#249

Per-provider costIsEstimate (Grok/OpenCode/Hermes stay bills). Qualifier only on the leverage row. Optional Settings plan price. $Y is estimates only, so Max+Grok does not label Grok as API-equivalent.

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.

2 participants