github.com/denysvitali/llm-usage

Package main provides the CLI for llm-usage.


License
MIT
Install
go get github.com/denysvitali/llm-usage

Documentation

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.

Configure managed credentials

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.