Skip to content

Configuration

llm-usage-metrics uses a TOML config file for persistent defaults. CLI flags override it for one-off runs, and environment variables provide an override layer for scripts, CI, and debugging. For the design behind this (precedence, validation, the template, and log levels), see the Config & Logging deep dive.

Default path:

<config-root>/llm-usage-metrics/config.toml

Config root follows the platform:

  • XDG_CONFIG_HOME when set
  • %APPDATA% on Windows
  • ~/.config otherwise

Run llm-usage config init to write a commented template at the active config path. Set LLM_USAGE_CONFIG_PATH=/path/to/config.toml to point at a different config file. A missing config file is silent and uses built-in defaults. Malformed TOML is an error. Unknown keys are reported once on stderr and the run continues.

Run llm-usage config path to print the resolved config file path on stdout, one line, nothing else.

Unknown keys and values of the wrong type (for example enabled = "false" instead of enabled = false) are ignored with a warning; blank strings and empty lists mean “not set”. These warnings go to stderr, so config show output stays clean to redirect.

llm-usage config show prints what a report would use and where each value came from: flag, env var, config, or default. It covers the config file, each source’s directories or database files and whether they exist, the event store, configured machines, pricing, and the defaults reports apply. It accepts the flags that change those values (--source, --source-dir, the per-source path flags listed by --help-all, --timezone, --pricing-url, --pricing-offline, --pricing-overrides), so you can check a flag’s effect before running a report.

Sources
pi default missing ~/.pi/agent/sessions
missing ~/.omp/agent/sessions
codex flag found /work/codex
gemini env var missing /opt/gemini
claude config found /work/claude
Event store
enabled default yes
path config /work/store/events.db
file 4.1 MiB, schema v5, 12,408 events
Pricing
url default https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json
offline default no
refresh default every 24h 0m
cache ~/.cache/llm-usage-metrics/litellm-pricing-cache.json
fetched 2026-06-21 (3 h ago), fresh
prices from the cache
overrides none

A source marked env var was moved by its tool’s variable (CODEX_HOME, CLAUDE_CONFIG_DIR, XDG_DATA_HOME and the others on Sources). prices says what the next report prices with: the cache while it is fresh, otherwise a fetch from the URL; with --pricing-offline, a stale cache or the bundled snapshot. history is on whenever the event store is.

config show changes nothing and contacts nothing. It only stats source paths, opens the event store read-only, reads the pricing cache without fetching, and lists machines by name from the config without running ssh. To check whether a source’s files hold readable usage, or when a machine last synced, run doctor, which reads the files.

--json emits the same data with each value’s origin; the schema is report-config-show.v1.schema.json (llm-usage schema config-show).

TOML editors such as Taplo can validate the file through the #:schema directive. The schema is published at config-schema.json:

#:schema https://ayagmar.github.io/llm-usage-metrics/config-schema.json
timezone = "Africa/Casablanca"
logLevel = "info"
monthlyBudgetUsd = 200
sources = ["codex", "claude"]
parseMaxParallel = 8
parseWorkers = "auto"
parseWorkerMinBytes = 268435456
[sourceDirs]
codex = "/path/to/.codex/sessions"
claude = ["/path/to/.claude/projects", "/path/to/work/.claude/projects"]
opencode = "/path/to/opencode.db"
goose = "/path/to/goose/sessions.db"
[pricing]
offline = true
url = "https://example.com/model_prices_and_context_window.json"
overridesPath = "/path/to/pricing-overrides.json"
ignoreFailures = false
cacheTtlMs = 86400000
fetchTimeoutMs = 4000
[eventStore]
enabled = true
path = "/path/to/events.db"
[update]
skipCheck = false
cacheTtlMs = 3600000
fetchTimeoutMs = 1000

Higher layers win:

Layer Use case
CLI flags One-off command overrides
Environment variables CI, scripts, temporary runtime overrides
Config file Persistent personal defaults
Built-in defaults Zero-config behavior

A CLI --source-dir <id>=<path> overrides the config sourceDirs.<id> entry just like the dedicated --<id>-dir flag does. Config entries are defaults rather than explicit requests: a config source dir that cannot be read is reported as a warning instead of failing the run, and it never conflicts with a --provider or --model filter that excludes that source (both of which happen when the same path is passed on the command line). A config sources filter is a default too, so a config-only sources entry that --provider or --model excludes does not fail the run either.

Paths in the config file (sourceDirs.*, eventStore.path, pricing.overridesPath) may start with ~/, and relative paths resolve against the directory holding the config file, not the current directory.

Reports name the applied config file in their stderr summary line; --verbose prints the Active config: block with each applied value. Values shadowed by a flag or environment variable are not listed. Set logLevel = "warn" to suppress informational stderr by default, or pass --quiet to do the same for a single report command.

Config key CLI flag or env override What it controls
timezone --timezone Default report timezone
logLevel --quiet, --verbose Stderr logging level: silent, warn, info, or debug
monthlyBudgetUsd Config only Monthly budget the summary checks its projection against
sources --source Default source filter
sourceDirs.pi --pi-dir or --source-dir pi=... Pi sessions path
sourceDirs.codex --codex-dir or --source-dir codex=... Codex sessions path
sourceDirs.copilot --copilot-dir or --source-dir copilot=... GitHub Copilot OTEL path
sourceDirs.gemini --gemini-dir or --source-dir gemini=... Gemini CLI path
sourceDirs.droid --droid-dir or --source-dir droid=... Droid sessions path
sourceDirs.claude --claude-dir or --source-dir claude=... Claude projects path
sourceDirs.openclaw --openclaw-dir or --source-dir openclaw=... OpenClaw agents path
sourceDirs.opencode --opencode-db OpenCode SQLite DB
sourceDirs.goose --goose-db Goose SQLite DB
sourceDirs.amp --amp-dir or --source-dir amp=... Amp threads path
sourceDirs.qwen --qwen-dir or --source-dir qwen=... Qwen projects path
sourceDirs.kimi --kimi-dir or --source-dir kimi=... Kimi sessions path
sourceDirs.cline --cline-dir or --source-dir cline=... Cline tasks path
sourceDirs.roocode --roocode-dir or --source-dir roocode=... RooCode tasks path
sourceDirs.kilocode --kilocode-dir or --source-dir kilocode=... KiloCode tasks path
sourceDirs.antigravity --antigravity-dir or --source-dir antigravity=... Antigravity conversations path
sourceDirs.dsh --dsh-dir or --source-dir dsh=... DeepSeek Harness sessions path
pricing.offline --pricing-offline Use cached or bundled pricing without fetching
pricing.url --pricing-url LiteLLM pricing source URL
pricing.overridesPath --pricing-overrides JSON pricing overrides path
pricing.ignoreFailures --ignore-pricing-failures Continue without estimated costs when pricing cannot load
pricing.cacheTtlMs Config only Pricing cache TTL
pricing.fetchTimeoutMs Config only Pricing fetch timeout
eventStore.enabled LLM_USAGE_EVENT_STORE Enable SQLite event-store reuse
eventStore.path LLM_USAGE_EVENT_STORE_PATH SQLite event-store path
parseMaxParallel Config only Max parallel file parses
parseWorkers LLM_USAGE_PARSE_WORKERS Worker-thread parser count for large JSONL misses
parseWorkerMinBytes LLM_USAGE_PARSE_WORKER_MIN_BYTES Missed-file byte threshold before workers engage
update.skipCheck LLM_USAGE_SKIP_UPDATE_CHECK Skip startup update checks
update.cacheTtlMs Config only Update-check cache TTL
update.fetchTimeoutMs Config only Update-check fetch timeout
machines.<name>.ssh machine add <name> [ssh-target] ssh destination of another machine to sync usage from
machines.<name>.command machine add --command How llm-usage-metrics is launched on that machine
machines.<name>.enabled Config only false stops syncing it

A machine name is 1-32 lowercase letters, digits or dashes; local is reserved for this machine. llm-usage machine add syncs the machine once and only then appends its table to the config file, keeping your comments; machine remove deletes the table and the machine’s cached usage.

A sourceDirs value for a directory-backed source can be a list, which scans every listed directory as one source, like repeating its flag. sourceDirs.opencode and sourceDirs.goose take one database path.

There is no --no-pricing-offline flag. To force a one-off online pricing refresh while pricing.offline = true stays in the config, bypass the config for that run by pointing LLM_USAGE_CONFIG_PATH at a nonexistent file (a missing file loads an empty config) or edit the file:

Terminal window
LLM_USAGE_CONFIG_PATH=/nonexistent llm-usage monthly

Environment variables override the config file. Reports count them in the stderr summary line, and --verbose lists them in an Active environment overrides: block.

Variable Config key Default Notes
LLM_USAGE_CONFIG_PATH n/a platform config path Points at a config TOML file
LLM_USAGE_SKIP_UPDATE_CHECK update.skipCheck unset (false) Truthy values: 1, true, yes, on
LLM_USAGE_UPDATE_CACHE_SCOPE n/a global session isolates update-check cache by session
LLM_USAGE_UPDATE_CACHE_SESSION_KEY n/a unset Stable key for session-scoped update cache
LLM_USAGE_PARSE_WORKERS parseWorkers auto auto (up to 6 with the event store on, 8 without) or integer 0..64; 0 disables workers
LLM_USAGE_PARSE_WORKER_MIN_BYTES parseWorkerMinBytes 268435456 Clamps to 0..9007199254740991
LLM_USAGE_EVENT_STORE eventStore.enabled 1 (true) Set 0 to disable the store
LLM_USAGE_EVENT_STORE_PATH eventStore.path platform data events.db Use an isolated store for experiments or CI
LLM_USAGE_PROFILE_RUNTIME n/a unset (false) Emits runtime profiling diagnostics

Retained history (on by default) needs the event store; with the store disabled, reports run without it and an explicit --history fails. Deleting events.db also deletes retained departed-file history.

Example:

Terminal window
LLM_USAGE_PARSE_WORKERS=4 LLM_USAGE_EVENT_STORE=0 llm-usage monthly

Benchmarking-focused example:

Terminal window
LLM_USAGE_SKIP_UPDATE_CHECK=1 \
LLM_USAGE_EVENT_STORE=0 \
llm-usage monthly --provider openai --json