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 machinery, validation, the template, and log levels — see the Config & Logging deep dive.
Config file
Section titled “Config file”Default path:
<config-root>/llm-usage-metrics/config.tomlConfig root follows the platform:
XDG_CONFIG_HOMEwhen set%APPDATA%on Windows~/.configotherwise
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. Run llm-usage config show to print the config file (with a (missing) marker when it does not exist) followed by the same Active config: block reports emit on stderr, listing every value the file overrides:
Config file: /home/user/.config/llm-usage-metrics/config.tomlActive config: /home/user/.config/llm-usage-metrics/config.toml timezone=Africa/Casablanca eventStore.enabled=trueUnknown-key warnings still go to stderr, so config show output stays clean to redirect. A --json variant is a possible follow-up once config output and the report envelope interaction is decided.
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.jsontimezone = "Africa/Casablanca"logLevel = "info"sources = ["codex", "claude"]parseMaxParallel = 8parseWorkers = "auto"parseWorkerMinBytes = 268435456
[sourceDirs]codex = "/path/to/.codex/sessions"claude = "/path/to/.claude/projects"opencode = "/path/to/opencode.db"goose = "/path/to/goose/sessions.db"
[pricing]offline = trueurl = "https://example.com/model_prices_and_context_window.json"overridesPath = "/path/to/pricing-overrides.json"ignoreFailures = falsecacheTtlMs = 86400000fetchTimeoutMs = 4000
[eventStore]enabled = truepath = "/path/to/events.db"
[update]skipCheck = falsecacheTtlMs = 3600000fetchTimeoutMs = 1000Precedence
Section titled “Precedence”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 |
Applied config values are printed on stderr as an Active config: block. 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 keys
Section titled “Config keys”| Config key | CLI flag or env override | What it controls |
|---|---|---|
timezone |
--timezone |
Default report timezone |
logLevel |
--quiet |
Stderr logging level: silent, warn, info, or debug |
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 |
pricing.offline |
--pricing-offline |
Use cached LiteLLM pricing only |
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 |
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:
LLM_USAGE_CONFIG_PATH=/nonexistent llm-usage monthlyEnvironment overrides
Section titled “Environment overrides”Environment variables override the config file and are printed as an Active environment overrides: block when set.
| 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 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 cache events.db |
Use an isolated store for experiments or CI |
LLM_USAGE_PROFILE_RUNTIME |
n/a | unset (false) |
Emits runtime profiling diagnostics |
--history requires the event store to stay enabled. Deleting events.db also deletes retained departed-file history.
Example:
LLM_USAGE_PARSE_WORKERS=4 LLM_USAGE_EVENT_STORE=0 llm-usage monthlyBenchmarking-focused example:
LLM_USAGE_SKIP_UPDATE_CHECK=1 \LLM_USAGE_EVENT_STORE=0 \llm-usage monthly --provider openai --json