Summary
Cursor sessions show up as "today's usage" even when Cursor hasn't been launched in weeks. On my machine, CodeBurn 0.9.8 reported 317 Cursor calls / $7.57 for 2026-05-13, while every file under ~/Library/Application Support/Cursor/ had an mtime of 2026-04-23 or earlier and Cursor.app was not running.
Repro
- Have a long-lived Cursor
globalStorage/state.vscdb (mine is ~1 GB).
- Don't open Cursor for several weeks.
- Run
codeburn today --provider cursor.
Expected: empty / no data for today.
Actual: hundreds of "today" calls, costed at Sonnet rates.
Root cause
In src/providers/cursor.ts (verified against dist/cli.js in the published 0.9.8 build):
BUBBLE_QUERY_SINCE_HEAD deliberately keeps rows with a missing createdAt:
AND (json_extract(value, '$.createdAt') > ? OR json_extract(value, '$.createdAt') IS NULL)
- In
parseBubbles, when created_at is null, the JS falls back to Date.now():
const timestamp = createdAt || new Date().toISOString();
So every undated historical bubble is stamped with the current wall-clock time and bucketed into today.
Suggested fix
Drop rows with no usable timestamp instead of dating them to now — either:
- Remove the
IS NULL branch from the SQL filter, or
- In
parseBubbles, continue when createdAt is missing/invalid.
If older bubbles legitimately have an alternative timestamp field (e.g. on the parent composer), use that as a fallback before falling through to Date.now().
Environment
- macOS 24.6.0 (Darwin)
- Node 22.19.0 (also reproduced on the bottled node 26.0.0 via Homebrew install)
- codeburn 0.9.8 (Homebrew)
Summary
Cursor sessions show up as "today's usage" even when Cursor hasn't been launched in weeks. On my machine, CodeBurn 0.9.8 reported 317 Cursor calls / $7.57 for 2026-05-13, while every file under
~/Library/Application Support/Cursor/had an mtime of 2026-04-23 or earlier andCursor.appwas not running.Repro
globalStorage/state.vscdb(mine is ~1 GB).codeburn today --provider cursor.Expected: empty / no data for today.
Actual: hundreds of "today" calls, costed at Sonnet rates.
Root cause
In
src/providers/cursor.ts(verified againstdist/cli.jsin the published 0.9.8 build):BUBBLE_QUERY_SINCE_HEADdeliberately keeps rows with a missingcreatedAt:parseBubbles, whencreated_atis null, the JS falls back toDate.now():So every undated historical bubble is stamped with the current wall-clock time and bucketed into today.
Suggested fix
Drop rows with no usable timestamp instead of dating them to now — either:
IS NULLbranch from the SQL filter, orparseBubbles,continuewhencreatedAtis missing/invalid.If older bubbles legitimately have an alternative timestamp field (e.g. on the parent composer), use that as a fallback before falling through to
Date.now().Environment