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.
- 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.
| 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.
From source:
go install github.com/denysvitali/llm-usage@latestOr download a platform binary from the releases page.
If you already use Codex or Grok locally, this is enough:
llm-usageSelect providers explicitly when you want a predictable result:
llm-usage --provider=codex,grok
llm-usage --provider=claude,kimi --timeout=10sUseful checks:
llm-usage provider list
llm-usage doctor
llm-usage --helpThe 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.
# 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=0The 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 setupNon-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-claudesetup migrate-claude imports credentials from the Claude CLI when needed.
Codex and Grok should be authenticated with their own CLIs instead.
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 doctorThe 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=kimiValues 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.
Refresh the terminal view continuously:
llm-usage watch
llm-usage watch --provider=codex,grok --interval=2mStart the local web UI and JSON API:
llm-usage serve
llm-usage serve --host=127.0.0.1 --port=9090The 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.
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.ps1Use 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.
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 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.
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.
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 buildRun the complete local verification target with:
make allBuild artifacts such as llm-usage, coverage reports, credentials, and local
CLI session files should remain uncommitted.
MIT. See LICENSE.