feat(cursor): spend view toggle for included vs billed usage - #996
feat(cursor): spend view toggle for included vs billed usage#996maxmilian wants to merge 3 commits into
Conversation
|
Nice work — architecture and default look right ( Follow-up I'd take:
Not blocking on (3); (1)–(2) are the ones I'd land before or right after merge. |
|
Thanks for the review! Pushed
On (3): agreed that |
Cursor's export marks each row as plan-included or billed (on-demand) via the Cost column. Parse that into CursorBillingKind and add a per-device Spend View setting (All / Included / API) that filters which rows the spend tiles and Usage Trend aggregate; All Usage keeps today's combined behavior. The bounded meters (Total/Auto/API %) stay as Cursor's API reports them. Rows from exports without a Cost column can't be split, so they only count under All Usage. Setting lives in the Cursor Customize detail and forces a refresh on change. Closes robinebers#609 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019dpF8491eHK8reiuJ8vMxB
The 'Spend View' section already titles the card, so the row label only needs 'Show'. Pin it with .fixedSize(horizontal: true) so the trailing Spacer can't squeeze it onto a second line (addresses review follow-up 1-2).
"API Usage" was already taken by the bounded meter Cursor reports, so a picker option of the same name read as if it filtered that meter rather than the spend tiles. The case is renamed alongside the label so the code has one word for the billed side instead of two (addresses review follow-up 3).
4ac3e81 to
53176f5
Compare
|
Folded (3) in and rebased onto current On (3) specifically: I asked back on 07-18 whether you wanted the rename now or left as a follow-up. Rather than hold the PR waiting on an answer, I've made the call and kept it trivially reversible — it's its own commit (
Deliberately left alone: the bounded
|
TL;DR
Adds a Cursor Spend View toggle (All / Included / API Usage) so the spend tiles and Usage Trend can show plan-included usage, billed on-demand usage, or the combined picture — implementing #609.
Closes #609.
What was happening
Cost), but OpenUsage dropped theCostcolumn and summed every row together.What this changes
CursorUsageCSVreads theCostcolumn into a newCursorBillingKind(included/billed/unknown). The column is optional: exports without it still parse, with rows left.unknown.CursorSpendViewSetting(all/included/api), aUserDefaultsBackedenum likeTimeFormatSetting, persisted per device, defaultall(unchanged behavior).CursorUsageMapper.appendSpendLinestakes the view and filters rows before aggregating; a view with no matching rows reads "No data" rather than a fabricated $0. Filtered rows drop out of tiles, trend, and the model breakdown alike.CursorProviderreads the setting at each refresh (so a flip applies on the next snapshot) and logs when a Cost-less export can't satisfy a non-All view.CursorSpendViewSection), following theAPIKeysSectionpattern; changing it forces a refresh.docs/providers/cursor.mdgains a Spend View subsection.Heads-up
unknownrows (Cost-less exports) count only under All Usage; assigning them to a side would fake the split.Tests
CursorSpendViewSettingfiltering: All = $7 / 700 tok, Included = $1 / 100 tok, API = $2 / 200 tok on a mixed day; empty-after-filter → "No data".Costcolumn parsing:Included/included→ included,\$1.23/1.23→ billed, empty/absent column → unknown.main.Screenshots
Cursor Customize detail → new Spend View card with the three-way picker:
🤖 Generated with Claude Code
https://claude.ai/code/session_019dpF8491eHK8reiuJ8vMxB