Objective
Add a cursor source adapter for local usage CSV caches so Cursor usage can be parsed without introducing auth or sync behavior into this repository.
Source shape to support
- directory-backed cache source containing
usage.csv and usage.<account>.csv
- at least two known CSV header layouts must be supported
- rows carry explicit cost
- timestamps may be full ISO datetimes or date-only values
- model strings may need conservative provider inference
Implementation plan
-
Adapter file
- add
src/sources/cursor/cursor-source-adapter.ts
- implement
SourceAdapter with id = 'cursor'
- keep this source parse-only; do not add login, API sync, or cache-population behavior here
-
Discovery
- treat this as a directory-backed source reachable through generic
--source-dir cursor=...
- discover the cache files deterministically and ignore unrelated files
- account-scoped files should remain distinct inputs rather than being merged before parsing
-
Parsing
- support both known CSV header layouts instead of assuming one fixed column order
- preserve explicit cost through
createUsageEvent({ costUsd, costMode: 'explicit' })
- infer provider conservatively from the model string; do not overclaim fixed-provider capabilities for this source
- keep cache write tokens derived from the delta between “input with cache write” and “input without cache write” when the file shape exposes both
- for date-only rows, assign a stable in-day timestamp (rather than a boundary timestamp that can drift across local-day bucketing)
- skip blank / malformed rows without aborting the whole file
- if diagnostics are worthwhile, implement
parseFileWithDiagnostics() so malformed-row counts are visible
-
Wiring
- register
cursor in src/sources/create-default-adapters.ts
- make sure supported-source IDs and help output reflect the new source
- do not add a bespoke
--cursor-dir flag unless implementation proves generic --source-dir is insufficient
-
Tests and docs
- add
tests/sources/cursor-source-adapter.test.ts
- update shared registry/help tests that assert supported source IDs/counts
- document the supported cache file shapes and
--source-dir cursor=... usage in README.md
Code paths to touch
src/sources/cursor/cursor-source-adapter.ts
src/sources/create-default-adapters.ts
src/sources/parsing-utils.ts
src/domain/usage-event.ts
tests/sources/cursor-source-adapter.test.ts
tests/sources/create-default-adapters.test.ts
tests/cli/create-cli.test.ts
README.md
Verification
- parser fixtures cover:
- both CSV header layouts
usage.csv and usage.<account>.csv
- blank/malformed rows skipped cleanly
- date-only timestamp handling is stable for report bucketing
- explicit cost is preserved
- provider inference stays conservative
llm-usage daily --source cursor --source-dir cursor=<fixture-dir> works
- no auth/sync commands, credentials, or network code are introduced
- full validation passes:
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run format:check
Objective
Add a
cursorsource adapter for local usage CSV caches so Cursor usage can be parsed without introducing auth or sync behavior into this repository.Source shape to support
usage.csvandusage.<account>.csvImplementation plan
Adapter file
src/sources/cursor/cursor-source-adapter.tsSourceAdapterwithid = 'cursor'Discovery
--source-dir cursor=...Parsing
createUsageEvent({ costUsd, costMode: 'explicit' })parseFileWithDiagnostics()so malformed-row counts are visibleWiring
cursorinsrc/sources/create-default-adapters.ts--cursor-dirflag unless implementation proves generic--source-diris insufficientTests and docs
tests/sources/cursor-source-adapter.test.ts--source-dir cursor=...usage inREADME.mdCode paths to touch
src/sources/cursor/cursor-source-adapter.tssrc/sources/create-default-adapters.tssrc/sources/parsing-utils.tssrc/domain/usage-event.tstests/sources/cursor-source-adapter.test.tstests/sources/create-default-adapters.test.tstests/cli/create-cli.test.tsREADME.mdVerification
usage.csvandusage.<account>.csvllm-usage daily --source cursor --source-dir cursor=<fixture-dir>workspnpm run lintpnpm run typecheckpnpm run testpnpm run format:check