Skip to content

feat(usage): index Cursor sessions without inventing tokens - #579

Open
vc1492a wants to merge 4 commits into
dcouple:mainfrom
vc1492a:feat/cursor-usage-index
Open

feat(usage): index Cursor sessions without inventing tokens#579
vc1492a wants to merge 4 commits into
dcouple:mainfrom
vc1492a:feat/cursor-usage-index

Conversation

@vc1492a

@vc1492a vc1492a commented Sep 3, 2026

Copy link
Copy Markdown

Why

Cursor panes currently show 0 tokens / 0 messages in the usage dashboard, runpane panes cost, and leaderboard. Claude and Codex are indexed from durable JSONL; Cursor is not. Interactive cursor-agent can compute tokens in memory for --print JSON, but Pane launches a TTY session and ~/.cursor transcripts only persist {role, message} / turn_ended lines — there is no durable token meter to invent from.

Scope

  • Add cursor to the closed USAGE_PROVIDERS set with decodeUsageProvider (unknown rows drop; never remap to Claude).
  • Index ~/.cursor/projects/**/agent-transcripts/**/*.jsonl as unmetered events (tokens: null) counting assistant lines.
  • Bind Cursor sessions via chat UUID + meta.json cwd (never invert project slug).
  • Surface unmeteredMessageCount and honest costIncomplete (idle Cursor panes never fake $0.00; mixed panes keep Claude dollars + unmetered footnote).
  • Regenerate runpane contract / CLI / UI / leaderboard consumers. Leaderboard rankings stay on metered spend.

Tradeoffs

  • Honest incompleteness over invented numbers. Message counts are attributable; token/cost figures for Cursor are not.
  • One ledger through the existing usage pipeline instead of a parallel activity table or in-memory-only overlay, so panes cost and the dashboard stay consistent.
  • Idle Cursor panes stay costIncomplete rather than rendering a complete zero-dollar slice.

Blast Radius

  • Usage indexer, SQLite usage_events (metered column), aggregator, runpane contract, panes cost, usage UI, leaderboard types/service.
  • Existing Claude/Codex metering paths should be unchanged aside from removing provider remappers that previously collapsed non-Claude into Claude.

Verification

  • pnpm --filter main exec vitest run src/services/usage — 132 tests, exit 0
  • pnpm --filter main exec tsc --noEmit — exit 0
  • pnpm --filter frontend exec tsc --noEmit — exit 0
  • node scripts/generate-runpane-contract.js — exit 0
  • Live Pane.app UI / runpane panes cost against a real Cursor pane — not run (do not restart Pane.app in this session)

Made with Cursor

vc1492a and others added 4 commits September 2, 2026 22:23
Widen UsageProvider with a closed USAGE_PROVIDERS set and decodeUsageProvider
that drops unknown rows. Track unmeteredMessageCount and widen costIncomplete
so missing Cursor metering cannot render as a complete $0.00.

Co-authored-by: Cursor <cursoragent@cursor.com>
Parse assistant lines from ~/.cursor agent transcripts with tokens null,
bind sessions via chat UUID and meta.json cwd, and keep Claude remappers
from swallowing Cursor rows. Mixed panes keep metered dollars and mark
costIncomplete when unmetered messages are present.

Co-authored-by: Cursor <cursoragent@cursor.com>
Regenerate the runpane contract for cursor + unmeteredMessageCount, teach
panes cost and the usage dashboard to show incomplete Cursor cost without
fake dollars, and keep leaderboard rankings on metered spend only.

Co-authored-by: Cursor <cursoragent@cursor.com>
Align parse/seed/manager docs with unmetered assistant events and empty
Cursor seeds, drop the fake SAFETY on pane id lookup, and stop calling the
provider chart Anthropic vs OpenAI.

Co-authored-by: Cursor <cursoragent@cursor.com>
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