Usage Report
opencode plugin: /usage command showing subscription quota windows for configured providers
1
1,235
754 in 7 days
41.4
Multi-signal model
1 day ago
2026-10-04
Install and configure
opencode.jsonWrites to this project's opencode.json — applies to this repository only.
opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-usage-report@0.6.1"]
}Writes to ~/.config/opencode/opencode.json — applies to every project.
~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-usage-report@0.6.1"]
}If you want to modify the plugin locally, install it into the project and reference the local path.
shell
pnpm add -D opencode-usage-reportOpenCode loads npm dependencies through its embedded runtime on startup and caches them locally — no manual global install needed.
An opencode plugin that shows how much of your inference
subscriptions you have left. It adds a /usage command and a usage_report
tool covering both the context window of the current session and the
quota windows (5-hour, weekly, monthly) of your provider plans —
Kimi Code (kimi-code-plan-global on kimi.ai and kimi-code-plan-cn on
kimi.com), OpenCode Go (opencode-go), GitHub Copilot
(github-copilot) and ChatGPT (openai). Results are cached on disk, fall
back to a local estimate when an API is unreachable, and raise background
low-quota toasts in the TUI.
Features
/usagecommand andusage_reporttool for on-demand quota reports, with JSON output and single-provider filtering.- Context usage panel (new in 0.4.0) — the exact prompt-token total against the model's context window, a cell grid that fills by category, the auto-compaction point with live headroom, and session cost.
- TUI sidebar panel with live progress bars,
NN%usage and reset countdowns for every quota window. - On-disk caching with a configurable TTL, plus an explicit refresh that bypasses it.
- Local fallback estimate when a provider API is unreachable and no cache exists.
- Low-quota warnings on startup and on
session.idle. - Privacy-first: API keys are never logged, cached, or rendered.
Install
The plugin exposes two entrypoints and opencode loads them from two different config files. Install both for the full experience:
| Config | Entrypoint | Provides |
|---|---|---|
opencode.json |
server plugin | usage_report tool, low-quota warnings, prompt capture |
tui.json |
TUI plugin | /usage command, sidebar panel |
The quickest path is opencode's own installer, which detects both entrypoints and writes both configs for you:
opencode plugin opencode-usage-report # project scope (./.opencode)
opencode plugin -g opencode-usage-report # global scope
Or add the plugin manually to each file and restart opencode:
// opencode.json — server plugin
{
"plugin": ["opencode-usage-report"],
}
// tui.json — TUI plugin
{
"plugin": ["opencode-usage-report"],
}
Use the bare package name in both files. opencode reads the package
exportsmap itself and resolvesexports["./tui"]for the TUI andexports["./server"](ormain) for the server. A subpath spec such asopencode-usage-report/tuiis not valid and will silently load nothing.opencode plugin opencode-usage-reportprintsDetected server + tui targetswhen the resolution works.
OpenCode 2.x (0.6.0). Both entrypoints now default-export a dual definition. The server entrypoint exports
{ id, setup, server }— V2 callssetup, V1 callsserver. The TUI entrypoint exports{ id, setup, tui }— V2 callssetup(itskeymap.layerruns from a headlessapp-slot component), V1 callstui. OpenCode 2's TUI loader rejects a default export without asetupfunction (Invalid V2 TUI plugin module); before 0.6.0 the TUI module exported only the V1tuishape and failed to load on 2.x. OpenCode 1.18.29+ and 2.x both load either entrypoint.
Options can be passed in the tuple form, independently per entrypoint:
{
"plugin": [["opencode-usage-report", { "thresholdPercent": 75 }]],
}
Local development
Point the configs at the source instead of the published package. Config is read once at startup and is not hot-reloaded, so restart opencode after every edit:
// opencode.json
{ "plugin": ["file:///abs/path/to/opencode-usage-report/src/index.ts"] }
// tui.json
{ "plugin": ["file:///abs/path/to/opencode-usage-report/src/tui.tsx"] }
Commands
/usage— open the report dialog: the context panel for the current session on top, and every configured provider's quota windows below. This is a local TUI command, so it costs no model tokens. Requires the TUI plugin. Providers whose credential cannot be resolved are skipped in this view./usagedialog keys —escclose,rrefresh now,tabcycle provider scope (all → each provider),jtoggle the raw JSON view.usage_reporttool — the same report for agents and headless runs. Takesprovider(exact id:kimi-code-plan-global,kimi-code-plan-cn,opencode-go,github-copilotoropenai; an unknown id returns an error listing the known ids),json(rawProviderReport[]) andrefresh(bypass the on-disk cache).
Changed in 0.4.0.
/usageused to be an LLM-mediated prompt template that routed through the model, and it accepted--json/--refresh/ a provider id as slash arguments. The TUI command now owns the name, so/usagereaches no model and those capabilities moved to the dialog keys and theusage_reporttool arguments. Running/usage --jsonis no longer supported.
Context usage panel
The top of the /usage dialog reports how full the model's context window is
for the current session:
Context
Kimi K2 (High) · 42,318 / 200,000 tokens (21.2%)
████████████████████████████ ████████████████████████████████ ████████████ ░░░░░░░░░░░░░░
████████████████████████████ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░
● User messages 8,204 4.1% ● System & tools 8,144 4.1%
● Agent responses 11,650 5.8% ● Free space 157,682 78.8%
● Reasoning 2,140 1.1%
● Tool calls 12,180 6.1%
Auto-compacts at 180,000 · 137,682 headroom $0.42 spent
What is exact. The headline total, the percentage, free space, the
compaction point, the cost and the number of pruned tool outputs all come from
numbers the provider and opencode report. The total is the prompt size —
input + cache.read + cache.write — which is what actually occupies the context
window. opencode's own sidebar Context block sums five fields including the
completion, so it reads slightly higher than this panel by design.
What is estimated. The per-category rows. opencode records no token count
per message or part, so each category is estimated with the same characters / 4
heuristic opencode itself uses, then normalized so the rows agree with the exact
total.
System & tools. opencode assembles the system prompt and tool definitions on
every request and never persists them. The server plugin measures the real
system string through the experimental.chat.system.transform hook and stores
only its size, so the row can be split into system prompt and
tools & framing. That hook is undocumented, so it is treated as best-effort:
if it stops firing, the sidecar goes stale, or anything fails to validate, the
panel falls back to the derived residual and labels the row (derived). The
plugin never breaks a request over it.
Compaction headroom. Auto-compacts at N mirrors opencode's own overflow
check, including the configured compaction.reserved buffer. This is the point
at which opencode automatically summarizes the session — a number opencode
exposes nowhere else.
Options
Shared by both entrypoints:
| Option | Type | Default | Meaning |
|---|---|---|---|
thresholdPercent |
number |
80 |
Warn when a window is at/above this percent used. |
cacheTtlSeconds |
number |
120 |
How long a cached API result is considered fresh. |
providers |
string[] | null |
null |
Providers to report; null = every registered adapter. |
fallback |
boolean |
true |
Use a local estimate when the API fails and no cache exists. |
TUI only:
| Option | Type | Default | Meaning |
|---|---|---|---|
refreshIntervalSeconds |
number |
60 |
Sidebar/dialog refresh cadence, clamped to 5–3600. |
barWidth |
number |
14 |
Progress-bar width in cells, clamped to 4–40. |
fallback is fixed at true for the TUI entrypoint. Malformed option values
are ignored and the defaults are kept.
Warnings
On startup and again on session.idle (both throttled to at most once every
10 minutes, sharing one timer), the plugin checks the cached reports. Any window
at or above thresholdPercent, or whose status is rate-limited / frozen,
produces a TUI toast. A warning fires once per window until that window resets;
it re-arms after usage drops below thresholdPercent - 10. Toast failures
(headless/server mode) are swallowed.
Data sources & privacy
- Credential resolution order. First
OPENCODE_USAGE_<ID>_KEY(optionally paired withOPENCODE_USAGE_<ID>_ACCOUNT_ID, e.g.OPENCODE_USAGE_OPENAI_ACCOUNT_ID, to supply the ChatGPT account id), then~/.local/share/opencode/auth.json: atype: "api"entry's.key, or atype: "oauth"entry's.access(falling back to.refreshfor GitHub Copilot, which stores its token there). For ChatGPT the oauth entry's.accountIdis read automatically.$OPENCODE_DATA_HOMEoverrides the data directory. - APIs.
https://api.kimi.ai/coding/v1/usages(global plan),https://api.kimi.com/coding/v1/usages(China plan),https://opencode.ai/zen/go/v1/usage(requires a customUser-Agent),https://api.github.com/copilot_internal/user(GitHub Copilot) andhttps://chatgpt.com/backend-api/wham/usage(ChatGPT). - Auth. Run
opencode auth loginand pick GitHub Copilot or OpenAI ChatGPT. ChatGPT additionally needs the account id that login writes toauth.json; the plugin reads it automatically. - Cache and state live in
<data-home>/usage-report/: the TTL cache, the session id, the warn state, andcontext/<sessionID>.json— the system-prompt size sidecar, which holds counts only and never prompt text. - Local fallback reads
opencode.dbread-only. - API keys are never logged, cached, or rendered. Adapter errors are
sanitized (key substrings replaced with
<redacted>) before they reach any output, and the live smoke script never prints credentials.
Troubleshooting
/usage does not appear in the command list.
Both configs are required — the command comes from the TUI plugin, not the
server plugin. Check that tui.json lists "opencode-usage-report" (bare name)
and restart opencode; config is not hot-reloaded. To confirm the package exposes
what opencode expects, run opencode plugin opencode-usage-report — it should
print Detected server + tui targets.
The sidebar is empty and no providers are reported.
Every window belongs to a provider whose credential could not be resolved, so it
is skipped. Run opencode auth login, or set
OPENCODE_USAGE_<ID>_KEY for the provider in question.
An old version keeps loading after you upgrade.
opencode caches installed plugin packages under
~/.cache/opencode/packages/<name>@latest/ and re-resolves versions on install,
not on every start. Re-run opencode plugin opencode-usage-report, or delete
that cache directory, to force a refresh. This is the usual cause of "I
published a new version but opencode still runs the old one".
Quota numbers look stale or marked (stale) / (est).
(stale) means a cached result was served past its TTL without a successful
refresh; (est) means the API was unreachable and a local estimate was used.
Press r in the dialog (or ctrl+shift+u in the sidebar) to force a refetch.
Extending
New providers are trivial:
- Implement
ProviderAdapter(src/types.ts) — anid,displayName, andfetch(cred, opts)returning{ windows, extras? }. - Register it in
src/providers/index.ts(adaptersarray). - Add fixture-driven tests under
test/.
Reference endpoints for future adapters (not built in v1):
- Gemini:
cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota(requires Google OAuth). - Claude:
api.anthropic.com/api/oauth/usage(requiresanthropic-beta: oauth-2025-04-20, the claude-code User-Agent, and~/.claude/.credentials.json).
Development
npm run lint # oxlint
npm run lint:fix # oxlint --fix
npm run format # oxfmt (write in place)
npm run format:check # oxfmt --check
npm test # vitest, no network
npm run typecheck # tsc --noEmit
npm run check # lint + format:check + typecheck + test
npm run smoke -- --yes-live # manual live check (real keys; opt-in)
Releasing
Releases are staged, not published directly. Pushing a v* tag triggers
.github/workflows/publish.yml, which verifies that the tag matches
package.json, runs npm ci, and uploads the tarball with
npm stage publish --provenance --access public using npm Trusted Publishing
(OIDC — no NPM_TOKEN secret). Nothing goes live until a maintainer approves
the staged release with 2FA:
git tag v0.4.1 && git push origin main v0.4.1
npm stage list # find the stage id
npm stage approve <stage-id> # 2FA prompt; or approve in the npm UI
prepublishOnly runs lint, format check, typecheck and tests before the upload,
so a failing check blocks the stage.
Changelog
- 0.6.1 — Kimi Code adapter tracks the 2026-09 quota-model API change:
usage windows now come from the
usages.limit_5h/limit_7d/limit_month_totalratios (with alimit_month_codebreakdown), and Extra Usage is read from the camelCaseboosterWallet(fixed-pointBOOSTERbalance). The pre-2026-09usage/limits[]/totalQuota/booster_walletshapes remain as fallbacks. - 0.4.1 — internal: shared provider HTTP plumbing (
src/providers/http.ts) replaces the copy-pasted fetch/retry/error code; context estimates simplified; reset times render asWed, Sep 16. - 0.4.0 — context usage panel (
/usagenow shows context breakdown, grid, compaction headroom and cost);/usagebecame a local TUI command that costs no model tokens; sidebar rendering extracted tosrc/quota-lines.ts. - 0.3.0 — GitHub Copilot and ChatGPT (OpenAI) adapters.
- 0.2.0 — Kimi Code split into the kimi.ai (
kimi-code-plan-global) and kimi.com (kimi-code-plan-cn) plans.
License
MIT © Kaan Chinar
Security policy: SECURITY.md
Similar plugins
Tui Quota Usage
opencode-tui-quota-usage
OpenCode quota usage sidebar tracker for OpenCode V2 CLI/TUI
Providers Balances
opencode-providers-balances
OpenCode TUI plugin that shows provider account balances in the session sidebar. Providers are configured entirely in opencode.jsonc.
Codex Usage
opencode-plugin-codex-usage
OpenCode TUI plugin that shows live Codex usage limits in the session sidebar.