quotch
quotch ("quota + check") prints subscription-plan usage for AI coding agents — fast, cross-platform, and JSON-native.
It reads the usage limits your agents actually enforce. For Claude Code that means the authoritative numbers from Anthropic's OAuth usage endpoint — the same figures the service bills against — not a log-file estimate that drifts from reality. Credentials are read-only: quotch reads each agent's own credential store and never writes or refreshes tokens. One provider failing never affects the others. Humans get colored bars; AI agents get a frozen JSON contract.
Providers
| Provider | Status | Windows |
|---|---|---|
| Claude Code | ✅ shipped | 5h session, 7d weekly (all models), 7d per-model |
| GitHub Copilot | ✅ shipped | monthly premium interactions (request counts) |
| Codex | ✅ shipped | 5h + weekly (Plus/Pro) or monthly (Go) |
| Antigravity | ✅ shipped | 5h + weekly per model group (via agy / Google) |
Install
From crates.io:
From git or a local checkout:
Prebuilt binaries are attached to each GitHub Release: static musl on Linux, macOS (arm64 + x64), and Windows — produced by the release workflow on version tags.
Usage
Humans
$ quotch
claude · max 5h ████░░░░░░░░░░░░░░░░ 19% resets 3h 26m
7d ████░░░░░░░░░░░░░░░░ 21% resets 5d 22h
7d:fable ███████░░░░░░░░░░░░░ 35% resets 5d 22h
On a TTY the bar and percentage are colored by utilization: green < 70, yellow < 90, red ≥ 90. Non-ok snapshots render as a single line:
claude (stale 2m) ... # header suffix when serving cached data after a failed fetch
codex ⚠ not logged in (run: codex) # auth_missing — log in with the provider's own CLI
codex ✗ network: timed out # error — the message comes from the provider
AI agents
Always use --json. The envelope is a frozen v1 contract:
Full JSON Schema: docs/schema.json. Agent-facing usage notes: skill/SKILL.md.
Frozen-schema guarantee. v is 1. Evolution is additive only: new fields, new status values, and new window keys may appear, but existing fields never change meaning or type. Consumers must ignore unknown fields and never assume a fixed set of window keys.
status:ok|stale(live fetch failed, cached data shown — checkfetched_atfor age) |auth_missing|error(seeerror). (not_detectedis reserved and not currently emitted — undetected providers are omitted from the array.)used_pctis always present (0–100, may exceed 100 on overage).used/limitare populated only for request/credit-count providers.- Window
key:5hrolling session,7dweekly all-models,7d:<model>weekly per-model,5h:<group>/7d:<group>per-model-group (Antigravity),monthly/monthly:<key>calendar month (Copilot premium requests), plus unknown keys.
Exit codes. Always 0 — per-provider problems are data in status, never process failures. Parse stdout; do not branch on exit code. 2 is returned only for CLI usage errors.
For AI agents
quotch ships an agent skill inside the binary. Install it so an agent knows when and how to check quota:
SKILL.md tells an agent to prefer quotch --json, how to read the envelope, when to warn before token-heavy work (highest used_pct is the binding constraint; ≥ 90 means warn and cite resets_at), and useful jq one-liners. The skill is embedded in the binary, so reinstall after upgrading quotch to pick up the latest version.
Architecture
src/
main.rs arg parsing, warm-cache fast path, concurrent per-account fetches, output
model.rs Account, Snapshot, Window, Status — the internal + wire types
registry.rs all() — the list of active providers
cache.rs atomic on-disk cache, 60s TTL
render/ json.rs (frozen v1 envelope) + line.rs (human bars)
providers/ mod.rs (Provider trait) + claude.rs, codex.rs, copilot.rs, antigravity.rs
Each provider reads credentials inline today; a shared creds.rs helper may be
extracted once multi-account discovery lands.
Every provider implements one trait:
An Account is a credential source, not a person — its id is offline-derivable (default, a label, or a hash of a path). The cache is keyed provider:account, so multiple accounts of one provider never collide. Discovery is offline and cheap; only stale/missing pairs hit the network, each on its own thread, so a slow or broken provider can't stall the others.
Adding a provider
- Implement
Providerinsrc/providers/<name>.rs. - Return one
Accountper credential source fromdiscover()(offline, no network). - In
fetch(), call the provider's usage endpoint and map its native response into one or moreWindows. - Register it in
registry.rs::all().
Roadmap
- multi-account per provider (Codex
--authfiles, multiple Google/GitHub logins) - Codex offline fallback (read cached quota from
~/.codex/sessions/when the token is expired) - statusline / tmux renderers
- usage history and burn-rate
License
MIT