llm-usage
llm-usage is a Go CLI for checking subscription and quota usage across
multiple LLM providers. It is designed for both humans at a terminal and
small integrations such as Waybar, scripts, and a local HTTP server.
What it does
- Queries Claude, Codex, Grok, Kimi, and MiniMax through one interface.
- Discovers existing Codex and Grok CLI sessions without asking you to copy
tokens into another configuration file.
- Supports named accounts for providers that use llm-usage-managed
credentials.
- Renders Lip Gloss terminal output, JSON, and Waybar-compatible JSON.
- Provides setup, diagnostics, shell completion, continuous refresh, and a
local web server.
- Exposes reusable public provider packages for Go applications.
Providers and authentication
| ID |
Provider |
Authentication |
Usage |
claude |
Claude (Anthropic) |
Claude CLI session, or managed OAuth credentials |
Implemented |
codex |
Codex (OpenAI) |
Codex CLI session in ~/.codex/auth.json |
Implemented |
grok |
Grok (xAI) |
Grok CLI session in ~/.grok/auth.json |
Implemented |
kimi |
Kimi |
Managed API key |
Implemented |
minimax |
MiniMax |
Managed cookie and group ID |
Implemented |
Codex and Grok are automatically included when their local CLI sessions are
available. They do not need a setup add step. Claude credentials can be
read from the Claude CLI or migrated into llm-usage-managed storage.
Install
From source:
go install github.com/denysvitali/llm-usage@latest
Or download a platform binary from the
releases page.
Quick start
If you already use Codex or Grok locally, this is enough:
llm-usage
Select providers explicitly when you want a predictable result:
llm-usage --provider=codex,grok
llm-usage --provider=claude,kimi --timeout=10s
Useful checks:
llm-usage provider list
llm-usage doctor
llm-usage --help
The command returns a non-zero status when every selected provider fails.
Waybar output always returns zero so a temporary provider error does not stop
the bar module.
CLI reference
Query usage
# Human-readable terminal output
llm-usage
# One provider or a comma-separated selection
llm-usage --provider=codex
llm-usage --provider=claude,kimi
# Select a managed account
llm-usage --provider=kimi --account=work
# Query every account for a provider
llm-usage --provider=kimi --all-accounts
# Machine-readable output
llm-usage --json
llm-usage --waybar
llm-usage --raw
# Include provider response details when debugging an integration
llm-usage --provider=codex --debug
# Bound slow provider requests
llm-usage --timeout=15s
# Tune or disable the response cache (see Rate limits)
llm-usage --cache-ttl=5m --stale-if-error
llm-usage --cache-ttl=0
The provider selector accepts all or these IDs: claude, codex, grok,
kimi, and minimax.
--json emits normalized provider reports. --waybar emits a single JSON line
for Waybar custom modules. --raw emits the upstream provider API responses as
a JSON map keyed by provider ID (or provider/account for non-default
accounts). --raw, --json, and --waybar are mutually exclusive.
Launch the interactive setup wizard:
llm-usage setup
Non-interactive account management commands:
llm-usage setup add claude
llm-usage setup add kimi --account=work
llm-usage setup add minimax --account=personal
llm-usage setup list
llm-usage setup list kimi
llm-usage setup rename kimi work home
llm-usage setup remove kimi home --yes
llm-usage setup migrate-claude
setup migrate-claude imports credentials from the Claude CLI when needed.
Codex and Grok should be authenticated with their own CLIs instead.
Configuration and diagnostics
llm-usage config init
llm-usage config path
llm-usage config validate
llm-usage config explain
llm-usage config --file ./llm-usage.yaml validate
llm-usage doctor
The default configuration directory is $XDG_CONFIG_HOME/llm-usage, or
~/.config/llm-usage when XDG_CONFIG_HOME is unset. Use
--credentials-file to load a combined credentials file, which is useful for
CI and secret managers:
llm-usage --credentials-file ./credentials.json --provider=kimi
Values in that file may reference environment variables with $VAR or
${VAR}. Do not commit the file.
The root query command uses this configuration when it exists. Explicit CLI
flags override configured values. If no configuration exists, provider
selection falls back to managed credentials and locally authenticated CLI
sessions.
Watch and serve
Refresh the terminal view continuously:
llm-usage watch
llm-usage watch --provider=codex,grok --interval=2m
Start the local web UI and JSON API:
llm-usage serve
llm-usage serve --host=127.0.0.1 --port=9090
The default server address is http://localhost:8080. Use --web-dir when
the web assets are stored outside the repository.
The server refreshes usage from the providers at most once per --cache-ttl
(one minute by default) and shares that result across every connected
dashboard, so open tabs and refresh clicks do not each cost a provider
request. --stale-if-error is on by default here: a browser sees the last good
read instead of an error when a provider is briefly unavailable.
The dashboard leads with the tightest limit across every account, and each
meter carries a tick showing how far into that window you are — fill past the
tick means you are spending faster than the window refills. It adapts down to
roughly 240px wide, so it works pinned to a narrow strip beside an editor.
| Key |
Action |
r |
Refresh now |
s |
Sort by urgency or name |
d |
Comfortable or dense layout |
t |
Theme: auto, dark, light |
Preferences persist per browser. To pin a mode instead — handy when launching
the dashboard into a fixed panel — append ?theme=dark, ?density=dense, or
?sort=name to the URL.
Shell completion
llm-usage completion zsh > "${fpath[1]}/_llm-usage"
llm-usage completion bash > /etc/bash_completion.d/llm-usage
llm-usage completion fish > ~/.config/fish/completions/llm-usage.fish
llm-usage completion powershell > llm-usage.ps1
Waybar
Use separate modules when you want each provider to have its own icon, color,
and status. The Waybar output contains text, tooltip, and a CSS class.
{
"modules-center": ["clock", "custom/codex-usage", "custom/grok-usage"],
"custom/codex-usage": {
"exec": "llm-usage --provider=codex --waybar",
"return-type": "json",
"interval": 300,
"escape": false,
"tooltip": true,
"format": "{}"
},
"custom/grok-usage": {
"exec": "llm-usage --provider=grok --waybar",
"return-type": "json",
"interval": 300,
"escape": false,
"tooltip": true,
"format": "{}"
}
}
Codex displays its 5-hour and 7-day windows in order. Grok displays its
weekly window. Use llm-usage --waybar without --provider for one combined
module instead.
Rate limits
Provider usage endpoints are themselves rate limited, so llm-usage is built to
ask for as little as it can get away with.
Successful responses are cached for one minute (--cache-ttl, or
defaults.cache.ttl in the config file). Repeated invocations inside that
window — a bar module, a shell prompt, several dashboards — are answered from
disk without touching the provider, and the terminal output notes how old the
reading is. --cache-ttl=0 disables caching entirely. --stale-if-error
additionally permits expired values when a live request fails.
When Claude answers 429 Too Many Requests, llm-usage records the cooldown it
asks for (Retry-After, or the anthropic-ratelimit-*-reset header, or one
minute when neither is present) and stops contacting that account until the
cooldown expires — retrying sooner only extends the lockout. During the
cooldown the last good reading is shown, marked with the time of the next
attempt. The cooldown is stored on disk, so it survives across invocations, and
it is honored even when caching is disabled.
The cooldown machinery is provider-neutral: any provider client that reports a
provider.RateLimitError gets the same treatment. Claude is the one wired up
today; the others still surface a 429 as a plain error and are protected only
by the response cache.
JSON output
--json emits normalized provider reports. Each report contains a provider
ID, zero or more usage windows, optional provider-specific extra data, and a
normalized error when the provider is unavailable.
{
"providers": [
{
"provider": "codex",
"windows": [
{"label": "5-Hour", "utilization": 8, "resets_at": "..."},
{"label": "7-Day", "utilization": 17, "resets_at": "..."}
]
}
]
}
Provider failures are represented in the response instead of being mixed into
the normal usage text. This makes the output safe to consume from scripts.
Go library
The normalized types live in the public provider package. Provider-specific
clients are available under providers/<name> and accept caller-owned context,
credentials, and HTTP clients where applicable.
package main
import (
"context"
"fmt"
"github.com/denysvitali/llm-usage/providers/grok"
)
func main() {
client, err := grok.NewClient(grok.ClientOptions{AccessToken: "token"})
if err != nil {
panic(err)
}
usage, err := client.GetUsage(context.Background())
if err != nil {
panic(err)
}
fmt.Println(usage.Windows)
}
The public registry in providers exposes provider capabilities and the
application-facing loading contract. Credential discovery remains internal to
the CLI so reusable clients do not depend on local config files.
Development
Requirements: Go 1.23 or newer.
git clone https://github.com/denysvitali/llm-usage.git
cd llm-usage
make fmt
make test
make lint
make build
Run the complete local verification target with:
make all
Build artifacts such as llm-usage, coverage reports, credentials, and local
CLI session files should remain uncommitted.
License
MIT. See LICENSE.