Output Formats
The CLI keeps report data on stdout and diagnostics on stderr. Redirecting JSON or Markdown therefore produces a clean data file while discovery and pricing notes remain visible in the terminal.
Choose a format
Section titled “Choose a format”| Report | Terminal | JSON | Markdown | Share report |
|---|---|---|---|---|
| Summary | Yes | Yes | Yes | Yes |
| Hourly | Yes | Yes | Yes | No |
| Daily / weekly / monthly | Yes | Yes | Yes | Yes |
| Projects | Yes | Yes | Yes | No |
| Compare | Yes | Yes | Yes | Yes |
| Session | Yes | Yes | Yes | No |
| Trends | Yes | Yes | Yes | Yes |
| Blocks | Yes | Yes | Yes | No |
| Value | Yes | Yes | Yes | No |
| Efficiency | Yes | Yes | Yes | Yes |
| Optimize | Yes | Yes | Yes | Yes |
| Wrapped | Yes | Yes | Yes | Yes |
| Pricing | Yes | Yes | Yes | No |
| Doctor / prune | Yes | Yes | No | No |
Events exports JSONL, CSV, or OTLP traces or metrics using --format; it does not use the report-format flags. Status line prints one line of text. schema prints a JSON Schema document. The config subcommands print text, and config show also takes --json.
Terminal
Section titled “Terminal”llm-usage dailyThe default renderer uses a boxed title and a Unicode table. NO_COLOR=1 removes ANSI color without changing the content.
Usage tables fit the terminal width. When the full table is too wide, the renderer steps down in this order until it fits: abbreviate token counts (616M, 24.3K; cost stays exact), hide Reasoning and Cache Write, hide Models, then hide Input and Output. At any step, a model name longer than the space left for the Models column (at least 20 characters) gets a middle … instead of wrapping. Period, Source, Cache Read, Total, and Cost always stay (Cost unless --no-cost). A note on stderr lists what was left out. Piped output has no terminal width and keeps every column.
llm-usage daily --compact--compact starts from the abbreviated table without Reasoning and Cache Write, even when the terminal is wide or the output is piped. It works with terminal and Markdown output, not JSON. If even the narrowest table is wider than the terminal, as on a phone, each row is listed on its own instead: a title line with the period and source, then one label value line each for Input, Output, Cache Read, Total, and Cost (abbreviated; Models, Reasoning, and Cache Write are left out). The other terminal reports (summary, projects, session, tools, context, compare, blocks, value, efficiency, optimize, pricing, wrapped) switch to the same list when their table does not fit, and a report title too wide for its box prints without one. --per-model-columns tables keep the table and warn on stderr instead, since their metric lines only make sense next to the model names.
llm-usage daily --no-costllm-usage monthly --share --no-cost--no-cost leaves cost out of hourly, daily, weekly, monthly, projects, blocks, and value for a screenshot or a shared report that should not show spend: tables drop their cost columns, and the share report holds no cost at all. It works with terminal, Markdown, and --share, not JSON. On hourly, daily, weekly, monthly, and blocks it also skips loading prices, so it never fetches them; projects and value still load prices because they rank projects by cost.
llm-usage daily --all --json > usage.jsonUse JSON for scripts and pipelines. Without date bounds, daily and weekly cover only their default windows (the last 7 days and the last 8 weeks), so scripts that need full history should pass --all or explicit --since/--until dates. Every report wraps its payload in a versioned envelope:
{ "schemaVersion": 1, "report": "usage", "data": []}report identifies the report family (summary, usage, projects, compare, session, tools, context, trends, blocks, value, efficiency, optimize, wrapped, pricing, doctor, prune, or config-show for config show; hourly, daily, weekly, and monthly all use usage) and data carries the report-specific payload documented on each report page. schemaVersion increments only on breaking JSON changes; additive fields inside data are safe and do not bump it. Diagnostics never enter the JSON body. The envelope arrived in 0.8.0; Upgrading to 0.8 maps the old field names to the new ones.
Every payload has a published JSON Schema (draft 2020-12) validated in CI against real CLI output:
| Report | Schema |
|---|---|
| shared definitions | report-common.v1.schema.json |
| summary | report-summary.v1.schema.json |
| usage | report-usage.v1.schema.json |
| projects | report-projects.v1.schema.json |
| compare | report-compare.v1.schema.json |
| session | report-session.v1.schema.json |
| tools | report-tools.v1.schema.json |
| context | report-context.v1.schema.json |
| trends | report-trends.v1.schema.json |
| blocks | report-blocks.v1.schema.json |
| value | report-value.v1.schema.json |
| efficiency | report-efficiency.v1.schema.json |
| optimize | report-optimize.v1.schema.json |
| wrapped | report-wrapped.v1.schema.json |
| pricing | report-pricing.v1.schema.json |
| share (in the HTML) | report-share.v1.schema.json |
| doctor | report-doctor.v1.schema.json |
| prune | report-prune.v1.schema.json |
| config show | report-config-show.v1.schema.json |
The installed CLI also carries these schemas, so pipelines can validate against the exact contract of their installed version without the network:
llm-usage schema usage > report-usage.schema.jsonllm-usage schema --listschema accepts every report name plus share, events-line, machine-export, config (the config file) and config-show (the config show report), and prints the schema document itself (not wrapped in the report envelope). Report, events-line and machine-export schemas embed the shared definitions under $defs, so the printed file compiles on its own in any JSON Schema 2020-12 validator.
Machine export
Section titled “Machine export”llm-usage machine export > usage.ndjsonmachine export prints the events this machine’s reports count, so another machine can combine them into its own reports. It refreshes the local event store the way a report does and needs it enabled. The output is NDJSON with one object per line, each validated by machine-export.v1.schema.json:
- a
headerline with the bundleformat, itsversion(1), the exporting CLI version and host name, andparserVersions, the parser version each source was read with (missing from exports before it was added). Version 1 headers can gain fields, so readers should ignore header fields they do not know - a
fileline per counted file, with itssource,filePath, an opaquerevisionand itsevents(the same objects asevents --format jsonl, but unpriced:costUsdis present only when the source recorded the cost). Files of claude, codex and pi also carrysessionEvents, their tool calls and messages as the event store keeps them, without text. Older exports leave it out and older readers ignore it, so version 1 stays readable both ways - an
endline listing every counted file as[source, filePath, revision], plus the totaleventCountof usage events
A bundle without its end line is incomplete. --known <path> (or - for stdin) takes {"version":1,"files":[[source, filePath, revision], ...]}, usually the files of a previous end line, and leaves out the events of files listed at the same revision. A file that a reader holds but the end line no longer lists is no longer counted.
Markdown
Section titled “Markdown”llm-usage daily --markdown > usage.mdMarkdown works for summary, usage (hourly to monthly), projects, compare, session, tools, context, trends, blocks, value, efficiency, optimize, wrapped, and pricing reports. It does not work for doctor, prune, config show, or events.
Usage and session output keep the same ordering and row limits as the terminal renderer. --per-model-columns and --compact also work with Markdown usage reports.
Share reports
Section titled “Share reports”--share writes one self-contained HTML report to the current directory and still prints the normal report to stdout. It works with summary, daily, weekly, monthly, compare, trends, efficiency, optimize, and wrapped. The page charts and filters the command’s usage by hour, source, model, project, and machine, loads nothing from the network, and opens in your browser unless you pass --no-open. --redact replaces project and machine names, and local or path-shaped model names, in the file.
llm-usage monthly --share --no-openInteractive report lists the file each command writes and what the page offers, and explains names, costs, and file size.
Per-model columns
Section titled “Per-model columns”llm-usage monthly --per-model-columnsllm-usage monthly --markdown --per-model-columnsThis usage-report option expands token and cost values per model into aligned multiline cells. Models are ranked by total tokens inside each row.
Keep diagnostics separate
Section titled “Keep diagnostics separate”llm-usage daily --all --json > usage.json 2> usage.logusage.json contains report data. usage.log contains a one-line discovery and pricing summary, any warnings, and notes such as --history totals. Pass --quiet to keep only warnings, or --verbose to add per-source counts, routine skipped rows, and the config and env blocks.