Skip to content

Trends

trends shows daily movement over time instead of a tabular aggregate.

Terminal window
llm-usage trends [options]
Terminal window
# Default: last 30 local calendar days of cost
llm-usage trends
# Last 7 days of token usage
llm-usage trends --metric tokens --days 7
# Combined date window
llm-usage trends --since 2026-02-01 --until 2026-02-28
# Per-source JSON output
llm-usage trends --by-source --json
# Write the combined series as an SVG
llm-usage trends --days 14 --share
  • --days <n>: trailing local calendar days to chart
  • --metric <name>: cost, tokens, or active-hours
  • --by-source: render one sparkline row per source
  • --share: write the combined series to trends-share.svg
  • shared filters apply: --source, --provider, --model, --since, --until, --timezone, source-path overrides, pricing flags, and --history

trends supports terminal output, --json, --markdown (one row per date plus a Total row), and --share. The share renderer needs the combined series, so --share cannot be combined with --by-source.

  • If you pass --days, the range is today - (days - 1) through local today.
  • If you pass neither --days nor explicit date flags, the command defaults to the last 30 local calendar days.
  • --days cannot be combined with --since or --until.
  • --until without --since expands back to the earliest observed day after filtering.
  • Reuses the same pricing pipeline as usage reports.
  • Incomplete pricing is carried into the trend output.
  • Approximate totals and peaks use the existing ~ convention.
  • Uses daily totalTokens.
  • Skips pricing loads entirely.
  • Pricing flags are accepted but have no effect in this mode.
  • Charts per-day active time: each day’s events are grouped by session, gaps between consecutive events are capped at 5 minutes, and the per-session results are summed.
  • A session crossing midnight splits at the day boundary — each day counts only the gaps between that day’s events.
  • Terminal and Markdown output format durations (2h 14m); JSON value, total, average, and peak.value are milliseconds, matching session activeMs.
  • Skips pricing loads entirely, like tokens.

--by-source renders one sparkline row per source instead of a single combined chart.

  • source order follows the adapter/source order
  • missing days are zero-filled
  • sources with no observed data in the selected range are omitted

When any bucket in the selected range has incomplete pricing:

  • the affected series summary is marked approximate with ~
  • JSON includes incomplete: true on affected buckets and summaries

If no observed bucket in the selected range has resolved cost, the terminal output adds a note suggesting --metric tokens or working pricing.

{
"schemaVersion": 1,
"report": "trends",
"data": {
"metric": "cost",
"dateRange": { "from": "2026-02-06", "to": "2026-03-06" },
"totalSeries": {
"source": "combined",
"buckets": [
{ "date": "2026-02-06", "value": 1.57, "observed": true },
{ "date": "2026-02-07", "value": 0, "observed": false }
],
"summary": {
"total": 87.4,
"average": 2.91,
"peak": { "date": "2026-02-28", "value": 5.12 },
"incomplete": true,
"observedDayCount": 12
}
}
}
}

Diagnostics are never included in the JSON body; they remain on stderr.