axusage
v3.8.4
Published
Monitor API usage across Claude, ChatGPT, GitHub Copilot, and Gemini from a single CLI
Maintainers
Readme
axusage
Monitor API usage across Claude, ChatGPT, GitHub Copilot, and Gemini from a single CLI.
Quick Start
# Install globally
npm install -g axusage
# One-time authentication per provider
claude
codex
gemini
gh auth login
# Optional: print service-specific auth instructions
axusage --auth-setup copilot
# Check auth status
axusage --auth-status
# Fetch usage for all services
axusageRequirements
claudeCLI (Claude auth) -npm install -g @anthropic-ai/claude-codecodexCLI (ChatGPT auth) -npm install -g @openai/codexgeminiCLI (Gemini auth) -npm install -g @google/gemini-clighCLI (GitHub Copilot auth) -https://cli.github.com/orbrew install gh
Custom Paths
If CLIs are not on your PATH, override binary paths:
export AXUSAGE_CLAUDE_PATH=/path/to/claude
export AXUSAGE_CODEX_PATH=/path/to/codex
export AXUSAGE_GEMINI_PATH=/path/to/gemini
export AXUSAGE_GH_PATH=/path/to/gh
# Optional: dependency check timeout (milliseconds, default: 5000)
export AXUSAGE_CLI_TIMEOUT_MS=5000AXUSAGE_GH_PATH is also used as a Copilot fallback when resolving a token
via gh auth token.
Authentication
Authentication is managed by provider CLIs for all services.
- Claude:
claude - ChatGPT:
codex - Gemini:
gemini - GitHub Copilot:
gh auth login
Use:
axusage --auth-setup <service>to print the correct command for a given service.
Check auth status with:
axusage --auth-status
axusage --auth-status claude--auth-status checks whether each service is authenticated and reports the
detected auth method. It does not validate API token freshness.
Usage
# Query all services
axusage
# Query a single service
axusage --service claude
axusage -s codex
axusage -s copilot
# Output formats
axusage --format text
axusage --format tsv
axusage --format json
axusage --format prometheus
# Auth utilities
axusage --auth-setup claude
axusage --auth-status
# Disable color output
axusage --no-colorExit Codes
0: Success1: One or more failures (including partial failures)
Credential Sources
Credential source config is read from:
- Config file path shown in
axusage --help AXUSAGE_SOURCESenvironment variable (JSON), which overrides file config
Multi-Instance Configuration
To monitor multiple accounts for the same service, use an array of instance configs:
{
"claude": [
{ "source": "vault", "name": "work", "displayName": "Claude (Work)" },
{
"source": "vault",
"name": "personal",
"displayName": "Claude (Personal)"
}
]
}Each instance resolves credentials independently. Named credentials require vault to be configured (AXVAULT env). Single-instance configs can use string shorthand ("auto", "local", "vault") or object form.
Examples
Extract service and utilization (TSV + awk)
axusage --format tsv | tail -n +2 | awk -F'\t' '{print $1, $5"%"}'Count windows by service (TSV + cut/sort/uniq)
axusage --format tsv | tail -n +2 | cut -f1 | sort | uniq -cFilter by utilization threshold (TSV + awk)
axusage --format tsv | tail -n +2 | awk -F'\t' '$5 > 50 {print $1, $4, $5"%"}'Extract utilization as JSON (JSON + jq)
axusage --format json \
| jq -r '(.results? // .) | (if type=="array" then . else [.] end) | .[] | .windows[] | [.name, (.utilization|tostring)] | @tsv'Output
Human-readable output includes:
- Utilization percentage per window
- Usage rate vs expected rate
- Reset times
- Color coding: on track / over budget / significantly over
JSON output provides structured data for automation. Prometheus output emits text metrics suitable for scraping.
Serve Mode
axusage serve starts an HTTP server exposing usage data at /metrics (Prometheus) and /usage (JSON). An initial fetch runs at startup to pre-populate the cache (enabling /health to return a meaningful status from the first connection). After that, no background polling runs: subsequent requests within the cache window are served instantly, and the first request after the cache expires triggers a refresh (blocking on /usage, non-blocking on /metrics).
Usage
# Start with defaults (port 3848, max cache age 5 minutes)
axusage serve
# Custom configuration
axusage serve --port 9090 --interval 60 --service claude
# With environment variables
AXUSAGE_PORT=9090 AXUSAGE_INTERVAL=60 axusage serve
# With debug logging
AXUSAGE_LOG_LEVEL=debug axusage serveOptions
| Flag | Env Var | Default | Description |
| ---------------------- | --------------------- | ----------- | ----------------------------------------------------- |
| --port <port> | AXUSAGE_PORT | 3848 | Port to listen on |
| --host <host> | AXUSAGE_HOST | 127.0.0.1 | Host to bind to |
| --interval <seconds> | AXUSAGE_INTERVAL | 300 | Max cache age in seconds |
| --log-level <level> | AXUSAGE_LOG_LEVEL | info | Fastify/Pino log level |
| --service <service> | AXUSAGE_SERVICE | all | Service to monitor |
| — | AXUSAGE_TRUST_PROXY | false | Trust proxy headers (set true behind reverse proxy) |
Invalid serve-mode configuration now fails fast. For example, non-numeric ports, zero/negative intervals, or unsupported log levels exit with an error instead of silently falling back to defaults.
Endpoints
GET /metrics— Prometheus text exposition (text/plain; version=0.0.4). Serves cached data immediately; triggers a background refresh when stale. Returns 503 with JSON{ "statusCode": 503, "error": "Service Unavailable", "message": "No data yet" }when no usage data is available.GET /usage— JSON array of usage objects (one per service instance; multi-instance configs produce multiple entries per service type). Waits for a fresh snapshot when stale. Returns 503 with JSON{ "statusCode": 503, "error": "Service Unavailable", "message": "No data yet" }if no data is available. Date fields (e.g.resetsAt) are serialized as ISO 8601 strings.GET /health— JSON health status with version, last refresh time, tracked services, and errors. Always responds immediately from cached state without triggering a refresh.
Rate limiting is applied globally (100 req/min per client); /health and /metrics are exempt. Unmatched routes (404s) use a separate burst limit of 3 requests per 500ms to prevent URL probing. Security headers are set via @fastify/helmet.
Serve mode uses Fastify's structured logger and graceful shutdown handling. Request/response validation and serialization are enforced with Zod-backed route schemas.
Container Deployment
# Build image
podman build -t axusage .
# Run (configure credential sources via AXUSAGE_SOURCES)
podman run -p 3848:3848 --user 1000:1000 \
-e AXUSAGE_SOURCES='{"claude":{"source":"vault","name":"claude-oauth"}}' \
-e AXVAULT_URL=http://axvault:3847 \
-e AXVAULT_API_KEY=axv_sk_... \
axusageDocker Compose
cp .env.example .env
# Edit .env with credential sources and vault config
docker compose up -d --buildPublishing
Container publishing is part of CI/CD:
- Pushes to
mainrun theReleaseworkflow. - If
semantic-releasecreates a new version tag, CI builds and publishes a multi-arch image toregistry.j4k.dev/axusage:<version>.
For manual publishing:
./scripts/publish-image.sh --dry-run
./scripts/publish-image.sh --version 1.0.0Troubleshooting
"Required dependency '... not found'"
Install the missing CLI or set the corresponding override env var (for example, AXUSAGE_GH_PATH).
Authentication errors (401 / unauthorized / no saved authentication)
- Run
axusage --auth-statusto see which services are not authenticated. - Re-authenticate in the provider CLI (
claude,codex,gemini,gh auth login). - Retry
axusage.
Partial failures
axusage exits with code 1 if any service fails, even when other services succeed. Check warnings in stderr for the failed service(s).
Agent Rule
Add to your CLAUDE.md or AGENTS.md:
# Rule: `axusage` Usage
Run `npx -y axusage --help` to learn available options.
Use `axusage` when you need a quick, scriptable snapshot of API usage across Claude, ChatGPT, GitHub Copilot, and Gemini. It standardizes output (text, JSON, Prometheus) so you can alert, dashboard, or pipe it into other Unix tools.Development
For local development in this repository, pnpm run start triggers a clean rebuild before executing the CLI. Use node bin/axusage only when dist/ is already up to date. End users installing globally should run the axusage binary directly.
