pi-usage-meters
Pi extension: /usage shows subscription quota meters for Claude, Codex, Copilot, Kimi, Grok, GLM, and MiniMax plans.
Package details
Install pi-usage-meters from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-usage-meters- Package
pi-usage-meters- Version
0.6.1- Published
- Nov 4, 2026
- Downloads
- 478/mo · 294/wk
- Author
- quigleybits
- License
- MIT
- Types
- extension
- Size
- 61.6 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-usage-meters
A pi coding agent extension that adds a /usage command showing subscription quota for every provider you're connected to — one compact, colour-coded block instead of a dashboard per provider. Claude, Codex, Kimi, Grok, and GitHub Copilot authenticate via pi's OAuth; the GLM and MiniMax plans use the API keys pi already holds (ZAI_API_KEY / ZAI_CODING_CN_API_KEY, MINIMAX_API_KEY / MINIMAX_CN_API_KEY). Pay-as-you-go accounts without a plan (DeepSeek, MiniMax sk-api- keys) are out of scope by design: this meters plans. A credit balance that belongs to a metered plan, such as Codex credits, shows in that plan's block.

Each provider block is colour-coded on your terminal's existing background, bars fill left-to-right with usage, and the pie glyph (○ ◔ ◑ ◕ ●) fills as the quota window elapses toward reset. The entry renders in the transcript but never enters LLM context.
Install
pi install npm:pi-usage-meters
Try without installing:
pi -e npm:pi-usage-meters
Then run /usage in any pi session. Results are cached in memory for 60 seconds; use /usage --refresh to bypass the cache. No extension-specific configuration is needed — OAuth credentials come from pi's own auth store (/login) and refresh automatically. The GLM meter resolves either zai / ZAI_API_KEY or zai-coding-cn / ZAI_CODING_CN_API_KEY from the same auth registry; if both are configured, the existing global zai provider takes precedence.
Only providers you are connected to get a block. Everything else collapses into one dim footer line — not connected: Codex · Kimi, Claude: login expired (/login anthropic), Kimi: no credits left — plan used up or expired, Codex: timed out — so an account you do not have never shows up as an error. /usage --all lists the per-provider login hints as blocks instead. Footer lines are plain words; the HTTP status or error code behind each one is kept in the entry's hidden debug field (visible in the session file), never on screen.
Providers & endpoints
| Provider | Plan label source | Quota endpoint |
|---|---|---|
Claude (anthropic) |
api.anthropic.com/api/oauth/profile |
api.anthropic.com/api/oauth/usage |
Codex (openai-codex) |
plan from usage payload | chatgpt.com/backend-api/wham/usage + .../rate-limit-reset-credits |
Kimi (kimi-coding) |
membership level from usage payload | api.kimi.com/coding/v1/usages |
Grok (xai) |
cli-chat-proxy.grok.com/v1/settings |
cli-chat-proxy.grok.com/v1/billing?format=credits (one weekly SuperGrok pool; product rows indent under it when they sum to that pool; monthly fallback) + redeemed-reset detection |
Copilot (github-copilot) |
copilot_plan / access_type_sku from the user payload |
api.github.com/copilot_internal/user (monthly premium requests from quota_snapshots; Copilot Free renders its chat/completions allowances); GitHub Enterprise logins use api.<your-host> |
GLM (zai, zai-coding-cn) |
plan level from usage payload | Global: api.z.ai/api/monitor/usage/quota/limit; China: open.bigmodel.cn/api/monitor/usage/quota/limit (coding-plan windows: 5h session plus weekly or monthly, classified from the payload's unit/number; an explicit 7-day window renders as Week) |
MiniMax (minimax, minimax-cn) |
token plan | Global: api.minimax.io/v1/token_plan/remains; China: api.minimaxi.com/v1/token_plan/remains (5h session + weekly window per model family, same contract as the official MiniMax CLI); pay-as-you-go sk-api- keys are skipped, so a China-region plan key still meters; the block reads not connected only when no plan key exists |
Privacy & security
- OAuth access tokens come from pi's auth store only (
ctx.modelRegistry.getProviderAuth). The GLM meter resolveszaiandzai-coding-cnAPI keys the same way and sends each key only to its matching issuer (api.z.aioropen.bigmodel.cn) — never to another provider's endpoint. The same holds for MiniMax (api.minimax.io/api.minimaxi.com, the hosts pi already sends those keys to). - The Grok reset-detection feature persists a small state file at
~/.pi/agent/usage-meters-state.json(override:PI_USAGE_METERS_STATE). It contains only the last-seen Grok weekly period boundaries, pool percentage and a timestamp, plus, after a detected reset, that reset's date and its two percents for the rest of the week — no tokens, no secrets, no other providers. It is written atomically, deletable at any time, and never leaves the machine. - Codex's non-secret account ID is decoded from the OAuth JWT.
- One documented exception to "credentials come from
getProviderAuthonly" — Copilot. GitHub's quota endpoint authenticates the GitHub OAuth token, but pi hands extensions only the exchanged Copilot session token. So, only aftergetProviderAuth("github-copilot")confirms a live OAuth login (pi validates and refreshes it there), the Copilot meter reads pi's stored credential through pi's publicreadStoredCredential()API — this package never parses the credential file itself — and sends that token only toapi.github.com(or your GitHub Enterprise API host). Nothing else in this package reads the credential store. - Credentials are used solely in the
Authorizationheader on the provider's own HTTPS quota endpoints. OAuth providers and global Z.AI useBearer; Z.AI Coding CN uses the raw API-key value required by its endpoint. Credentials are never logged, rendered, or written into session entries. Remote error bodies are not persisted — at most a short identifier-like error code (for exampleresource_exhausted) is kept in the entry's hiddendebugfield alongside the HTTP status. Fetches refuse redirects (redirect: "error"), so a credential can never follow a redirect to another host. - API responses are size-limited; untrusted strings are length-limited and stripped of terminal controls, ANSI, and bidirectional-text controls both before storage and again at render time.
- Each provider fetch is isolated. Every request is capped at 8 s, and the whole provider, login lookup included, at 10 s: one failure or stall never blanks the others.
Privacy note: /usage stores plan labels, quota percentages, reset times, and any displayed spend figures in the current pi session. Exporting or sharing that session includes this output. Do not share the session if those account details are sensitive.
Notes & caveats
- These quota endpoints are undocumented and may change without notice; each provider fetch is isolated and fails soft.
- A request that stalls is cut off after 8 s — one budget per provider, optional follow-up calls included — and a provider whose login lookup stalls is cut off after 10 s. Both read
timed outin the footer line; the other meters still render. A failed login refresh readslogin expiredonly when the provider rejects the login; a network drop, a 5xx or a 429 during the refresh readsnetwork error,provider error — try again laterorrate limited — try again shortly. Other failures readrate limited — try again shortly,no credits left — plan used up or expired(HTTP 402, or 429 with an exhausted/quota code — Kimi answers this way once a plan's credits are gone),access denied,endpoint changed — update the extension,provider error — try again later,network error. A connected account with no quota windows (no active plan) shows asno plan data. - Claude: profile tier
claude_max_20xis labelledUltraandclaude_max_5xis labelledMax, from the plan tier only. API readings alone do not establish Ultra verification or whether a 5h limit is enforced. On Ultra, a reported 5h reading carries the noteAPI meter; may not be an enforced limit; on every plan, a missing or nullfive_hourfield adds no Session row. Neither the note nor an absent row means unlimited or verified. If onelimitsentry haskind: "session"and a booleanis_active, Ultra shows that literal value asAPI session flag is_active: true|false. This flag is telemetry from an undocumented endpoint. It does not show whether a limit is enforced or whether the account is verified. The meter checks everylimitsentry for session flags. If the response contains several, the meter shows the total count and does not treat any one as authoritative. It lists up to ten literal values and ends the list with…when there are more. On any plan, a window with no numeric reading showswindow reported, reading unavailableinstead of 0%. The same rule holds for every provider: a missing reading is never drawn as 0% or 100%. - MiniMax's
*_usage_countfields historically meant remaining; when the payload carries*_remaining_percentthe meter uses it to pick the right reading (mirroring the official MiniMax CLI), and a weekly boost (weekly_boost_permille) is applied the same way. Models flagged "not in plan" are skipped; the sharedgeneralbucket is the primary meter and a window the server flags as exhausted (status2) renders as 100% used even if its percent is stale. The API reports auth failures in-band (HTTP 200 withstatus_code1004 or 2049), which the meter maps toAPI key rejected. - Copilot:
quota_snapshots.premium_interactionsdrives the meter (percent_remaining→ used, withentitlement/remainingcounts and any overage); unlimited snapshots (chat and completions on paid plans) are skipped. Copilot Free rendersmonthly_quotasagainstlimited_user_quotas. A lapsed subscription (subscription_ended) carries no snapshots and shows asno plan data. Whenpercent_remainingis missing, the meter uses theentitlement/remainingcounts; a snapshot with no reading shows as unavailable. The month pie assumes a 30-day window ending onquota_reset_date. - Codex: the usage payload's
credits.balanceis the flexible-usage balance, shown asCredits N remaining.unlimitedshowsunlimited. A missing balance,has_credits: false, or a non-numeric balance adds no row and is not treated as zero. This is separate from banked resets. The banked-reset lookup sendsOpenAI-Beta: codex-1andoriginator: Codex Desktop, matching the existing Codex client endpoint contract. Review this compatibility choice if OpenAI publishes an official replacement. - xAI reports SuperGrok usage as one weekly credit pool (
creditUsagePercent). Product rows are a split of that pool when their percents add up to it, and then indent under the week line.GrokBotandGrokBuildrender asBot.Apirenders asGrok API. That row is the pool's API slice. It is not the X developer credit balance, and it is not a console.x.ai prepaid balance. Chat and Imagine labels stay unchanged. Legacy monthly credit totals provide a fallback when xAI omits the weekly payload or its percent. Grok Bot usage on a SuperGrok plan is theBotrow of this pool, so/login xaicovers it and no second login is needed. - Grok usage-reset credits are served only to the grok.com web app (a cookie-authenticated Connect RPC,
prod_mc_billing.ConsumerUiSvc/GetRemainingResets); the OAuth-reachable billing API never reports them. The meter therefore detects redeemed resets by inference: within one weekly period the pool percentage only climbs, so a drop of 5+ points while the period is unchanged is reported asReset used 21 Aug (35% → 5%). The line stays for the rest of that week, and a new week clears it. This needs a small state file (see Privacy). It is inference — an xAI-side recomputation could in theory produce the same signature. If xAI ever exposes explicit counts (resetsRemaining), they are rendered asResets N availableand take precedence in spirit.scripts/probe-grok-billing.mjs(repo only, not shipped) dumps the sanitized payload for re-checking. - The state file path defaults to
~/.pi/agent/usage-meters-state.jsonand can be overridden with thePI_USAGE_METERS_STATEenvironment variable. Delete the file at any time; the meter simply re-seeds a baseline on the next/usage(no reset line is reported for the first observation). - The pie glyph uses
○ ◔ ◑ ◕ ●from the Unicode Geometric Shapes block so a single font renders all states uniformly. - Requires a pi version with OAuth login support for the providers you use (
/login anthropic,/login openai-codex,/login kimi-coding,/login xai,/login github-copilot). The Copilot meter needs pi ≥ 0.80.8, which added thereadStoredCredentialexport.
Development
Runtime code has no installed dependencies: pi's extension loader supplies the @earendil-works/pi-tui and @earendil-works/pi-coding-agent imports from its own bundle. extensions/index.js is the small pi adapter (it also hands readStoredCredential to the loader); provider, formatting, caching, and security logic lives in extensions/core.js, which stays testable outside pi.
npm test
npm run check
pi -e ./extensions/index.js
License
MIT