Skip to content

Architecture

llm-usage-metrics is organized around a small report-command architecture:

  1. report definitions describe command identity, shared option profile, and examples
  2. builders parse and normalize local usage data
  3. feature aggregators reshape that data into report-specific totals or series
  4. renderers emit terminal, JSON, Markdown, or share artifacts
  5. a shared report runtime handles output-format resolution, diagnostics, and stdout/stderr behavior
  • src/cli/report-definitions Canonical metadata for daily, weekly, monthly, compare, efficiency, optimize, trends, session, wrapped, doctor, and prune (config init is registered directly in create-cli.ts)
  • src/cli/report-runtime Shared prepare/run lifecycle for format validation, share handling, terminal overflow warnings, and stdout emission

This same metadata is reused for:

  • Commander command registration
  • generated CLI docs
  • root help examples

That keeps command/docs drift low without duplicating option descriptions outside Commander help.

buildUsageData(...) parses source events, applies pricing, aggregates by period/source/model, then renderUsageReport(...) formats the report.

buildEfficiencyData(...) reuses usage parsing, attributes events to a repository root, joins them with local Git outcomes, then renderEfficiencyReport(...) formats the result.

buildOptimizeData(...) reuses usage parsing and pricing, aggregates baseline token totals, computes candidate-model counterfactual costs, then renderOptimizeReport(...) formats the result.

buildTrendsData(...) reuses usage parsing, loads pricing only for cost mode, aggregates to daily totals, projects those totals into daily trend series, then renderTrendsReport(...) formats terminal charts or JSON.

buildCompareData(...) resolves the two date windows, builds one priced dataset spanning both, then aggregates each window separately and computes the deltas between them.

buildSessionData(...) reuses usage parsing and pricing, then groups priced events per conversation session — or per repository root with --by-repo — with a top-N row limit.

buildWrappedData(...) resolves the recap year in the report timezone, builds the priced dataset for that year’s date range, then aggregates a yearly recap.

doctor and prune are non-report commands with their own runners: doctor checks source discovery health and runtime configuration, and prune previews or deletes departed files from the event store.

src/persistence/event-store.ts owns a local SQLite ledger: schema, migrations, per-file ingest on parse, and stored-event revalidation. Schema changes run as migrations, and an unknown newer schema disables the store rather than rebuilding tables.

src/persistence/event-store-history.ts serves --history. It compares the current run’s discovered (source, file) pairs against stored files, replays departed files for the selected sources, and suppresses moved or copied files by content hash. History events join the pipeline before the provider/model/date filters, pricing, and aggregation, so report shapes stay unchanged. prune uses the same classification to delete departed-file rows and vacuum the ledger.

  • aggregateUsage(...) supports an includeModelBreakdown profile Usage keeps per-model breakdowns; efficiency, optimize, and trends skip them.
  • render/unicode-table.ts is driven by explicit row metadata (periodKey, rowKind) This keeps sorting and separators deterministic without coupling the generic table renderer to usage-row domain types.
  • src/cli: command creation, report builders, diagnostics emission
  • src/cli/report-definitions: command metadata and shared option profiles
  • src/cli/report-runtime: shared report lifecycle
  • src/config: TOML user-config loading and runtime override/env-var resolution
  • src/sources: adapter discovery and parsing
  • src/domain: canonical normalized contracts
  • src/pricing: LiteLLM pricing loader/cache/cost engine
  • src/persistence: SQLite event-store ledger, schema migrations, history suppression
  • src/aggregate: period/source usage aggregation
  • src/efficiency: repo attribution and Git outcome joins
  • src/optimize: counterfactual pricing aggregation
  • src/trends: daily trend-series aggregation
  • src/session: per-conversation and per-repository usage aggregation
  • src/wrapped: yearly recap aggregation
  • src/render: output formatters
  • src/utils: shared fs, JSONL, time, and logging helpers
  • deterministic ordering for periods, sources, candidates, and models
  • diagnostics on stderr, report body on stdout
  • JSON/Markdown stay data-only on stdout
  • provider identifiers are normalized at the domain boundary
  • incomplete pricing remains explicit in output (~, warnings, or incomplete flags)
  • Event Store — the SQLite usage-event ledger: ingest, fingerprints, history, and prune.
  • Parse Pipeline — how source files are discovered, filtered, parsed, and parallelized.
  • Pricing Pipeline — how LiteLLM pricing is fetched, cached, matched to model names, and turned into costs.
  • Config & Logging — how the TOML config resolves against flags and env vars, and how stderr logging is leveled.