Skip to content

feat(source): add Claude Code adapter #57

@ayagmar

Description

@ayagmar

Objective

Add a claude source adapter for local Claude Code session files so Claude usage flows through the existing reporting pipeline like the current pi, codex, gemini, droid, and opencode adapters.

Source shape to support

  • directory-backed source under ~/.claude/projects/**/*.jsonl
  • JSONL session transcripts containing assistant rows with usage payloads
  • duplicate usage rows can appear for the same assistant/request pair and should not double count
  • timestamps may be missing or malformed on individual rows

Implementation plan

  1. Adapter file

    • add src/sources/claude/claude-source-adapter.ts
    • implement SourceAdapter
    • expose id = 'claude'
    • expose capabilities = { fixedProviderRoots: ['anthropic'] }
  2. Discovery

    • follow the directory-backed pattern already used by PiSourceAdapter / CodexSourceAdapter
    • use discoverJsonlFiles() for deterministic recursive discovery
    • validate explicit directory overrides the same way current adapters do (non-empty, exists/readable when explicitly required)
  3. Parsing

    • use readJsonlObjects() with line prefiltering so only relevant assistant/usage rows are parsed
    • emit usage events only for assistant rows with real usage signal
    • normalize timestamps through normalizeTimestampCandidate() before createUsageEvent
    • preserve repo attribution metadata when present (cwd, repo_root, repoRoot, project_root, projectRoot-style fields)
    • deduplicate repeated usage rows within a file using a stable composite key when the transcript exposes both request and message identity
    • prefer parseFileWithDiagnostics() so invalid timestamps / malformed rows can contribute skipped-row diagnostics instead of silently disappearing
  4. Wiring

    • register the adapter in src/sources/create-default-adapters.ts
    • make sure getDefaultSourceIds() now includes claude
    • keep this source directory-backed and reachable through generic --source-dir claude=...
    • update any stable-order expectations in adapter registry tests/help output tests
  5. Tests and docs

    • add tests/sources/claude-source-adapter.test.ts
    • extend tests/sources/create-default-adapters.test.ts for registry order, supported IDs, and --source-dir coverage
    • update tests/cli/create-cli.test.ts expectations that currently hard-code the supported-source count/help text
    • update README.md and generated docs/help output if source examples or supported IDs change

Code paths to touch

  • src/sources/claude/claude-source-adapter.ts
  • src/sources/create-default-adapters.ts
  • src/sources/source-adapter.ts
  • src/sources/parsing-utils.ts
  • src/utils/discover-jsonl-files.ts
  • src/utils/read-jsonl-objects.ts
  • src/domain/usage-event.ts
  • tests/sources/claude-source-adapter.test.ts
  • tests/sources/create-default-adapters.test.ts
  • tests/cli/create-cli.test.ts
  • README.md

Verification

  • parser fixtures cover:
    • valid assistant usage rows
    • duplicate request/message rows not double counted
    • malformed JSONL lines or irrelevant rows skipped cleanly
    • invalid/missing timestamps surfaced via diagnostics
    • repo-root extraction when available
  • llm-usage daily --source claude --source-dir claude=<fixture-dir> works
  • provider filtering can prune/select this source correctly via fixedProviderRoots: ['anthropic']
  • full validation passes:
    • pnpm run lint
    • pnpm run typecheck
    • pnpm run test
    • pnpm run format:check

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions