Jump to: Pre-configured providers · Custom providers · API keys · Setup notes
Most providers work automatically. Automatic means OpenCode Quota reuses the login you saved with OpenCode's /connect, read through OpenCode 2's plugin API. Open a Needs setup link only if you use that provider.
- Several logins for one provider? Each gets its own rows, and
(active)marks the one OpenCode uses. - A provider can appear in both audience tables when the vendor sells both.
Personal
| Provider | Auth/setup | Data from | Reports |
|---|---|---|---|
| Anthropic (Claude) | Needs setup | Local CLI/OAuth | Quota |
| Chutes AI | Automatic | Remote API | Quota |
| Cursor | Needs setup | Local estimate | Budget and spend |
| GitHub Copilot | Automatic | Remote API | Budget and usage |
| Google AGY | Needs setup | Remote API | Quota |
| Kilo Gateway | Automatic | Remote API | Quota and balance |
| NanoGPT | Automatic | Remote API | Quota and balance |
| Ollama Cloud | Automatic | Remote API | Quota and balance |
| OpenAI | Automatic | Remote API | Quota |
| OpenCode Go | Automatic | Remote API | Quota |
| OpenCode Zen | Automatic | Remote API | Budget and balance |
| OpenRouter | Automatic | Remote API | Budget and spend |
| Synthetic | Automatic | Remote API | Quota |
| xAI | Automatic | Remote API | Quota |
Business / Enterprise
| Provider | Auth/setup | Data from | Reports |
|---|---|---|---|
| Anthropic (Claude) | Needs setup | Local CLI/OAuth | Quota |
| Chutes AI | Automatic | Remote API | Quota |
| Cursor | Needs setup | Local estimate | Budget and spend |
| Gemini CLI | Needs setup | Remote API | Quota |
| GitHub Copilot | Needs setup | Remote API | Budget and usage |
| Google AGY | Needs setup | Remote API | Quota |
| NanoGPT | Automatic | Remote API | Quota and balance |
| OpenAI | Automatic | Remote API | Quota |
| OpenCode Zen | Automatic | Remote API | Budget and balance |
| OpenRouter | Automatic | Remote API | Budget and spend |
| Synthetic | Automatic | Remote API | Quota |
| xAI | Automatic | Remote API | Quota |
These tables show which plans a vendor sells. Except for Copilot organization/enterprise billing, each integration reports one signed-in account, seat, API key, or workspace.
Personal
| Provider | Auth/setup | Data from | Reports |
|---|---|---|---|
| Alibaba Coding Plan | Automatic | Local estimate | Quota |
| Alibaba Personal Token Plan | Needs setup | Official CLI | Quota |
| DeepSeek | Automatic | Remote API | Balance and status |
| Kimi Code | Automatic | Remote API | Quota |
| Kimi Code (CN) | Automatic | Remote API | Quota |
| MiniMax Token Plan | Automatic | Remote API | Quota |
| MiniMax Token Plan (CN) | Automatic | Remote API | Quota |
| Xiaomi MiMo | Needs setup | Dashboard API | Quota and balance |
| Z.ai Coding Plan | Automatic | Remote API | Quota |
| Zhipu Coding Plan | Automatic | Remote API | Quota |
Business / Team
| Provider | Auth/setup | Data from | Reports |
|---|---|---|---|
| Kimi Code | Automatic | Remote API | Quota |
| Kimi Code (CN) | Automatic | Remote API | Quota |
| MiniMax Token Plan | Automatic | Remote API | Quota |
| MiniMax Token Plan (CN) | Automatic | Remote API | Quota |
| Zhipu Coding Plan | Automatic | Remote API | Quota |
These show only your own member API key's usage, not the whole organization's.
Quotacovers quota and rate-limit windows; JSON tells them apart.- OpenCode Zen, NanoGPT, Xiaomi MiMo, Kilo Gateway, DeepSeek, and Cursor keep quota, rate limit, budget, usage, spend, credits, and balance as separate rows. A balance is not remaining allowance, and spend is not a budget percentage.
- Money uses uppercase currency codes such as
USD 12.50orCNY 8.25. OpenCode Quota never converts, combines, or picks a preferred currency. accountingDetail: "detailed"adds supplementary balance, status, and spend rows. See Show accounting detail.- Which rows can show a Runs out estimate: see Estimate when fixed quota runs out.
Custom providers can report quota, rate limit, usage, spend, budget, balance, or status. Run the guided setup:
npx @slkiser/opencode-quota@latest provider addIt asks how the provider works, previews the exact global config change, and asks before writing. It never asks for a response body, credential, or secret value.
- Remote API: real quota data from a supported endpoint (formats below).
- Local estimate: counts matching completed OpenCode requests in 1–16 windows, with optional spend estimates.
utc-dayresets at UTC midnight;rollingusesdurationMinutes(up to 366 days). Every window needsrequestLimit;usdBudgetis optional. - Credentials: the variable named by
apiKeyEnv, then trusted globalprovider.<providerId>.options.apiKey, then an API-key login saved in OpenCode 2 (opencode.db) for that provider id. Project secrets are never read. - With
enabledProviders: "auto", definitions run automatically. A manual list must includequota-providersplus every built-in provider you still want. - A custom model provider still needs its normal OpenCode provider/model config.
/connect→ Other stores its credential, not its model setup. - OpenRouter is built in. A custom OpenRouter definition only helps if you need a different endpoint or label.
- Alibaba Personal Token Plan uses the reserved
alibaba-token-planID and stays a separate official-CLI provider; it is not a local-estimate tuning target.
See Configuration for a complete example and the other rules (pricing, state files, what is not allowed).
Recipes: Vercel AI Gateway, Moonshot, Poe
Add the providers you use to quotaProviders in quota-toast.jsonc, then set the key variable (or use an API-key login saved in OpenCode):
- Provider docs: Vercel AI Gateway credits, Moonshot balance, Poe usage API.
- Poe: a Poe sign-in made through OpenCode's OAuth can't be used here. Create a key at poe.com/api/keys and set
POE_API_KEY. - These recipes follow the providers' docs and weren't tested with a real key; open an issue if one doesn't work.
Remote API response rules
mode: "remote-api" accepts three formats:
quota-v1reads the standard OpenCode Quota envelope.json-v1maps fields from a strict JSON response through a declarative adapter.openrouter-key-v1reads OpenRouter's key response.
A quota-v1 response looks like this:
{
"version": "quota-v1",
"entries": [
{ "kind": "percent", "name": "Requests", "resultType": "quota", "percentRemaining": 42, "label": "Daily:", "right": "58/100" },
{ "kind": "value", "name": "Spend", "resultType": "spend", "value": "$12.50" }
]
}For json-v1, the guided command builds the adapter one field at a time: literal property segments, compatible metric sources, and optional units and timestamps. This saved-config example maps remaining, limit, and status from one response object:
{
"mappings": [
{
"resultType": "quota",
"name": "Requests",
"label": "Daily:",
"unit": "requests",
"unitPosition": "suffix",
"metric": { "type": "remaining-limit", "remaining": { "path": ["remaining"] }, "limit": { "path": ["limit"] } }
},
{ "resultType": "status", "name": "Status", "metric": { "type": "status", "value": { "path": ["status"] } } }
]
}Adapter rules:
- Rows: optional
rowsPathand 1–16mappings. WithoutrowsPath, an object is one row and an array holds the rows. Selected arrays hold 1–100 rows, responses allow at most 32 container levels, and at most 1,600 row/mapping candidates are checked. - Paths: 1–8 literal own-property segments of 1–64 Unicode code points. Dots and brackets mean nothing special; array indexes and the segments
__proto__,prototype, andconstructorare rejected. - Size: adapter input is limited to 8 container levels, 128 objects, 384 object properties, and 640 array elements. Names and labels are 1–80 code points, units 1–32, and status/display output (including a provider-prefixed entry name) at most 160.
- Metrics:
percentage,used-limit,remaining-limit,spend-budget,remaining-budget,value, andstatus. Calculations are fixed; no formulas or fallback parsing. - Numbers: exactly one
pathorliteral, finite, with absolute magnitude at most1e15. A response may also write a number as text if it is a plain decimal like"95.50"or"-3"(spaces around it are ignored); other text such as"95.50 USD"or"1e3"is rejected. Zero is not the same as missing ornull. Path sources may usedivideBywith100,1000, or1000000. - Timestamps:
iso-8601,unix-seconds, orunix-milliseconds. ISO needs a time zone, allows 1–3 fractional digits and offsets through±14:00, and must fall within years 1970–9999. Output is canonical UTC ISO. - Errors: a bad mapping candidate gets a fixed, redacted diagnostic while other valid candidates stay visible. At most 16 detailed errors plus one summary are kept. More than 100 successful entries rejects the response.
Metric compatibility and fixed output:
metric.type |
Allowed resultType |
Percent or value output |
|---|---|---|
percentage |
quota, rate_limit, budget |
remaining: percentage; used: 100 - percentage |
used-limit |
quota, rate_limit |
(limit - used) / limit * 100; right side is used/limit |
remaining-limit |
quota, rate_limit |
remaining / limit * 100; right side is remaining/limit |
spend-budget |
budget |
(budget - spend) / budget * 100; right is spend/budget |
remaining-budget |
budget |
remaining / budget * 100; right is remaining/budget |
value |
Determined by valueType |
The selected numeric value |
status |
status |
The selected bounded text value |
For metric.type: "value":
valueType |
Allowed resultType |
Negative values |
|---|---|---|
used |
quota, rate_limit, usage |
Rejected |
limit |
quota, rate_limit |
Rejected |
remaining |
quota, rate_limit |
Allowed |
balance |
balance |
Allowed |
spend |
spend |
Rejected |
budget |
budget |
Rejected |
Pair denominators (limit and pair-form budget) must be greater than zero. Remaining values cannot exceed their denominator; used and spend may exceed it, so the calculated remaining percentage may be negative. A direct remaining percentage may be negative but cannot exceed 100; a direct used percentage must be non-negative and may exceed 100. Values are never clamped.
unit and unitPosition must appear together. Units are forbidden for percentage and status; prefix units render like $2/$10, while suffix units render like 2/10 tokens.
Never put secrets in adapter display configuration. Static name, label, and unit fields and every literal can appear in the provider-add preview, written configuration, cache identity, rendered quota rows, or exports.
OpenCode Quota sends a fixed authenticated GET. The URL must use HTTPS, except for loopback testing. Redirects and URLs containing credentials, queries, or fragments are rejected. Responses must be JSON and are limited to 256 KiB. Standard envelopes and selected json-v1 row arrays are limited to 100 rows.
These providers read an API key from, in order: an environment variable, then trusted user/global OpenCode config (provider.<id>.options.apiKey), then an API-key login saved in OpenCode 2 (opencode.db).
- Project-local
opencode.json/opencode.jsoncis never read for secrets. - An OpenCode login used as a fallback must be an API-key login, not an OAuth sign-in.
provider.<id>.options.apiKeycan also be written in OpenCode 2's native form,providers.<id>.settings.apiKey. Like OpenCode 2, a nativeproviders.<id>entry replaces theprovider.<id>entry with the same id.
| Provider | Environment variables (first match wins) | Notes |
|---|---|---|
| Alibaba Coding Plan | ALIBABA_CODING_PLAN_API_KEY, ALIBABA_API_KEY |
|
| Chutes AI | CHUTES_API_KEY |
|
| DeepSeek | DEEPSEEK_API_KEY |
See DeepSeek. |
| Kilo Gateway | KILO_API_KEY |
See Kilo Gateway. |
| Kimi Code / Kimi Code (CN) | See Kimi Code | Each region has its own keys. |
| MiniMax Token Plan | MINIMAX_CODING_PLAN_API_KEY, MINIMAX_API_KEY |
International endpoint. Runtime/config ids like minimax and minimax-coding-plan use this provider. |
| MiniMax Token Plan (CN) | MINIMAX_CHINA_CODING_PLAN_API_KEY |
Config under minimax-china-coding-plan, minimax-cn-coding-plan, minimax-cn, or minimax-china. Runtime id minimax-cn-coding-plan uses this provider. |
| NanoGPT | NANOGPT_API_KEY, NANO_GPT_API_KEY |
|
| Ollama Cloud | OLLAMA_API_KEY |
See Ollama Cloud. |
| OpenCode Go | OPENCODE_API_KEY |
Has its own order; see OpenCode Go. |
| OpenRouter | OPENROUTER_API_KEY |
See OpenRouter. |
| Synthetic | SYNTHETIC_API_KEY |
|
| Z.ai Coding Plan | ZAI_API_KEY, ZAI_CODING_PLAN_API_KEY |
A malformed fallback login shows as an auth error. |
| Zhipu Coding Plan | ZHIPU_API_KEY, ZHIPU_CODING_PLAN_API_KEY |
A malformed fallback login shows as an auth error. |
If something below does not work, see Provider fixes.
Personal quota works automatically from your OpenCode Copilot login. GitHub.com uses api.github.com; a GHE.com login uses the enterpriseUrl saved with that login and calls api.<enterprise-host>.
If Quota shows <plan> | usage needs billing token, GitHub reported your plan but no usage for your login. This is normal for Business and Enterprise seats (usage comes from the organization's pool), and it does not mean you are out of credits. Add the token below to see real numbers.
Organization and enterprise billing need a separate token with billing access. Create copilot-quota-token.json in the OpenCode config folder shown by opencode debug paths. Example for a personal Copilot Max plan:
{
"token": "github_pat_REPLACE_ME",
"tier": "max",
"username": "your-github-login"
}- Tiers:
free,student,pro,pro+,max,business, andenterprise. - A configured token always wins. It never falls back to, or borrows the host from, your OpenCode login.
Organization and enterprise setup
| Billing scope | Required config | Token permission |
|---|---|---|
| Personal | tier and optional username |
Fine-grained PAT with Plan: read, GitHub App user token, or supported classic token |
| Organization | tier: "business", organization, optional username |
Organization administration: read; user, installation, or authorized classic token |
| Enterprise | tier: "enterprise", enterprise, optional filters |
Classic PAT held by an enterprise admin or billing manager |
Organization example (for an enterprise, use "tier": "enterprise", add "enterprise": "your-enterprise", and organization becomes an optional filter):
{
"token": "github_pat_REPLACE_ME",
"tier": "business",
"organization": "your-org",
"username": "optional-user-filter",
"enterpriseUrl": "your-company.ghe.com"
}- Omit
enterpriseUrlfor GitHub.com. For GHE.com, use only the hostname or a host-only HTTPS URL such ashttps://your-company.ghe.com. Paths, queries, fragments, ports, userinfo, wildcards,api.prefixes, IP/localhost values, HTTP URLs, and non-.ghe.comdomains are rejected before any request. - GitHub does not allow fine-grained PATs or GitHub App tokens for enterprise billing reports.
What Copilot reports
- OpenCode login: GitHub's undocumented internal
premium_interactionssnapshot, normally labeled Copilot Premium Interactions (not assumed to match public AI Credit billing). GitHub supplies the entitlement, remaining amount, optional percentage, unlimited state, and reset. For in-range snapshots, used is derived from entitlement minus remaining; a percentage is calculated only when GitHub omits one. Token-based placeholder responses show the plan only. - Token-based billing over limit: once token-based billing usage passes the entitlement, GitHub reports a negative remaining amount plus a GitHub-reported
credits_usedAI-credit usage total. OpenCode shows that reported total; if it is missing or invalid, usage falls back to entitlement minus remaining and is marked locally derived. The remaining percentage stays provider-reported and does not exceed 100% when over limit. - Personal token: GitHub's public billing report for the current UTC calendar month. It is usage only, for example
Used 100 | Included 80 | Billed 20 ($0.20), with no allowance, remaining percentage, or reset. A missing percentage is expected. - Organization and enterprise tokens: the same used/included/billed fields for that payer. If GitHub returns an additional-usage budget, it shows as a separate Copilot Additional Usage row comparing billed spend with that budget.
Older annual Pro and Pro+ plans
Only if an existing annual Pro or Pro+ plan stayed on request-based billing after June 1, 2026:
{
"token": "github_pat_REPLACE_ME",
"tier": "pro+",
"billingModel": "legacy_premium_requests",
"username": "your-github-login"
}Totals come from the configured tier. The remaining percentage and next-month reset are calculated locally, not returned by GitHub.
GitHub references: AI Credit billing reports, billing budgets, GHE.com REST hostnames, individual AI Credit allowances, organization and enterprise pools, and legacy annual plans.
OpenCode's Anthropic login is enough; Claude Code is optional. To also use Claude Code as the quota source and credential fallback, install it and sign in:
claude auth login
claude auth status- OpenCode Quota runs
claudefrom OpenCode'sPATH, or else the first working one of~/.claude/local/claude,~/.local/bin/claude,/opt/homebrew/bin/claude, and/usr/local/bin/claude(not on Windows). If Claude lives elsewhere, or on Windows whenclaudeis not on OpenCode'sPATH, setanthropicBinaryPath./quota_statusshows the one it ran asbinary_path. - When Claude Code does not expose quota windows itself, quota comes from Anthropic's OAuth usage endpoint, using the first usable token: OpenCode's own
anthropiclogin, then Claude Code's credentials./quota_statusshows which one asoauth_credential_source. - Claude Usage Credits: a separate monthly group when that response includes enabled Usage Credits with numeric utilization. Missing or invalid credit data never changes the regular 5-hour and weekly rows.
- Fable: a separate weekly row when Anthropic returns that model-scoped window. It is never guessed from your plan name. See Claude Fable models on your plan.
Use companion plugin cursor-opencode-provider. Add its OpenCode 2 entry before @slkiser/opencode-quota in opencode.json:
{
"plugin": ["cursor-opencode-provider/plugin/opencode2", "@slkiser/opencode-quota"],
}Restart OpenCode, run /connect, choose Cursor, then sign in with Cursor account (browser login) or paste an API key from cursor.com/settings. A CURSOR_API_KEY environment variable also works. OpenCode 1 plugins such as @playwo/opencode-cursor-oauth and @rama_nigg/open-cursor do not run on OpenCode 2; replace them with this entry.
Cursor estimates the current billing cycle from your local OpenCode history:
- With all models known and an allowance (
cursorPlanorcursorIncludedApiUsd), it shows an API budget percentage with used, limit, and remaining USD. - Without an allowance, it shows API spend.
- If any Cursor model is unknown, it shows only Known API spend plus a partial-data issue, never a percentage or a total.
- Auto+Composer spend is a supplementary row shown in detailed output when there is room.
- Set
cursorBillingCycleStartDayto your billing day; otherwise the cycle is the local calendar month.
This is separate from Alibaba Coding Plan. Install and sign in to Alibaba Cloud Model Studio's official CLI yourself:
npm install -g bailian-cli
bl auth login --console- OpenCode Quota runs only
bl usage token-plan --output json. It never installsbl, opens a login, reads console cookies, or runs a custom command. - On macOS and Linux,
blmust be in an absolute folder on thePATH(the OpenCode service's inside OpenCode, your shell's in the terminal). Relative entries are ignored, and so is anything inside the project folder, including ablthat links into it. Your home folder is not a project, so~/.local/binand nvm folders work. - On Windows, use WSL. Native
bl.exeand.cmdshims are not supported in this release. - Team plans, China-only
alibaba-token-plan-cnruntimes, and cookie-based console scraping are not supported. - After switching the CLI's console account, restart OpenCode or wait for the next live check.
- With a manual provider list, include
alibaba-token-planinenabledProviders.
OpenCode Quota's Google integrations use independent community companion plugins. They are not endorsed by Google.
Use companion plugin @anthonyhaussman/opencode-agy-auth. OpenCode 2 needs its OpenCode 2 build, currently the alpha: @anthonyhaussman/opencode-agy-auth@alpha. Add it before @slkiser/opencode-quota in opencode.json, then sign in once and choose Antigravity CLI (OAuth):
opencode auth login google-agy- It shows the companion's grouped weekly and five-hour windows for each account. AGY logins copied from OpenCode 1 keep working.
- With a manual provider list, include
google-agyinenabledProviders. - If the login has no project id, set
OPENCODE_AGY_PROJECT_ID, orproviders.google-agy.settings.projectIdin your user/globalopencode.json(the OpenCode 1 formprovider.google-agy.options.projectIdalso works).
Gemini CLI works only with Gemini Code Assist Standard or Enterprise (organization) accounts. Google ended personal Gemini Code Assist accounts (individual, AI Pro, and AI Ultra) on 2026-06-18; see Google's notice. Personal Google users should use Google AGY.
Use companion plugin opencode-gemini-auth 2.x, which supports OpenCode 2. Add it before @slkiser/opencode-quota in opencode.json, then sign in once and choose OAuth with Google (Gemini CLI):
opencode auth login googleIf you use manual provider selection, include google-gemini-cli in enabledProviders.
Shows your on-demand account balance from GET https://api.deepseek.com/user/balance. DeepSeek has no quota reset window, so there is no quota percentage.
- Each valid Total balance is its own currency row. Detailed output can add Granted balance and Topped-up balance. Currencies are never added up or converted.
- With no valid total balance, it shows the API's availability status. A malformed number becomes a partial-data issue, not zero.
- Key:
DEEPSEEK_API_KEY, orprovider.deepseek.options.apiKeyin trusted user/global config (for example"{env:DEEPSEEK_API_KEY}"). See API keys. - With a manual provider list, include
deepseekinenabledProviders.
- Daily quota and Monthly quota percentages, with used, limit, and remaining requests when available.
- The balance is its own row: USD when available, otherwise a valid NANO balance. USD and NANO are never combined.
- Subscription and balance requests work independently, so one failing leaves the other rows visible with a partial-data issue.
Create an API key in your Kilo personal profile, then set KILO_API_KEY (or use trusted user/global provider.kilo.options.apiKey, or a kilo API-key login saved in OpenCode 2). The provider id is kilo; with a manual provider list, include kilo in enabledProviders.
It checks the kiloPass.getState endpoint first, then shows:
- Active Kilo Pass with credits: one Credits percentage with used, limit, and remaining USD, plus the reset when available.
- Active pass with zero credits: one Remaining credits USD value, with the reset.
- No active pass: one Total balance USD row, with no invented usage, percentage, or reset.
- Base, usage, bonus, remaining, overage, and reset source values stay in
/quota_statusand JSONrawDetails.
Each regional plan has its own key and host. A key is sent only to its own host, and a failed request is never retried on the other one.
- Kimi Code (Global) uses
api.kimi.ai. Key order:KIMI_GLOBAL_API_KEY→ trusted user/globalprovider.kimi-code-plan-global.options.apiKey→kimi-code-plan-globalAPI-key login saved in OpenCode 2. - Kimi Code (CN) uses
api.kimi.com. Key order:KIMI_CN_API_KEY→KIMI_API_KEY→KIMI_CODE_API_KEY→ trusted user/global config underkimi-code-plan-cn,kimi-for-coding,kimi-code, orkimi→ an API-key login saved in OpenCode 2 under those same ids. The legacy idskimi-for-coding,kimi-code, andkimibelong to the CN plan.
Reads the signed-in dashboard API: one Monthly quota with used/limit tokens, plus optional Total balance (primary), Cash balance, and Gift balance (detailed output). A valid currency code is kept; with none, amounts are credits.
Use exactly one trusted credential source. The environment variable wins:
export MIMO_USAGE_COOKIE='api-platform_serviceToken=...; userId=...'Or create the user/global file opencode-quota/mimo.json (usually ~/.config/opencode/opencode-quota/mimo.json), never in a repository:
{
"cookie": "api-platform_serviceToken=...; userId=..."
}To copy the cookie:
- Sign in at
platform.xiaomimimo.com. - Open the browser Developer Tools, then Network.
- Refresh the dashboard and select the
/api/v1/balancerequest. - Copy its Request Headers → Cookie value into the variable or file above.
- The value may start with
Cookie:. Line breaks are rejected.api-platform_serviceTokenanduserIdare required,api-platform_phandapi-platform_slhare kept, and every other cookie is removed before requests. - An invalid variable or a higher-priority
mimo.jsonblocks lower-priority sources instead of falling back. - Provider ids:
xiaomi,xiaomi-token-plan-cn,xiaomi-token-plan-ams, andxiaomi-token-plan-sgp. With a manual provider list, usexiaomi. - Plan name and code only label the display. An expired plan is not shown as active, and
currentPeriodEndis not a quota reset. - The three dashboard requests are independent, so other rows still appear if one fails. Per-API-key costs are not supported yet.
Create an Ollama API key, then set OLLAMA_API_KEY (or use trusted user/global provider.ollama-cloud.options.apiKey, or an ollama-cloud API-key login saved in OpenCode 2).
- Calls
https://ollama.com/api/balance. Credit plans show a Monthly row (included credits left, with the period's reset time); legacy plans show Session and Weekly rows with their reset times. - Purchased shows unexpired purchased credits in USD when there are some, or when Ollama returns nothing else.
- The API gives no per-model rows.
- The old
OLLAMA_USAGE_COOKIE,ollama-cloud.json, andollama-usage/config.yamlcookie setup is no longer supported.
- OpenAI: ChatGPT quota needs a Codex login:
/connect→ OpenAI → Codex browser (legacy) or Codex device code (legacy). OpenAI rejects Sign in with ChatGPT logins on ChatGPT's usage endpoint (HTTP 401no_matching_rule), so they show "ChatGPT quota unavailable for Sign in with ChatGPT", and stored API keys show "ChatGPT quota unavailable for API key", both without a ChatGPT request./quota_statusshows the active login's method asauth_method(chatgpt-token-sharingis Sign in with ChatGPT). - xAI: reads OpenCode's xAI login and shows its single Weekly window. The credits endpoint sets the quota; a best-effort subscription lookup labels the plan as xAI Lite, xAI SuperGrok, or xAI Heavy. If the plan is unknown, the quota still shows under the xAI SuperGrok label.
Reads your OpenCode API key and calls OpenRouter's current-key endpoint. Limited keys show used budget and remaining percentage; unlimited keys show spend. No reset time is invented. /quota_status has an openrouter: section with the key source and the live check result.
If you are signed in to the OpenCode Console in OpenCode 2, Go first asks the Console (/api/go/status). If you are not signed in, the sign-in fails, or that call fails, it uses the official https://opencode.ai/zen/go/v1/usage API with your API key.
API key order:
OPENCODE_API_KEY- Trusted user/global OpenCode config:
provider.opencode-go.options.apiKey - Trusted user/global fallback:
provider.opencode.options.apiKey - An
opencode-goAPI-key login saved in OpenCode 2 (opencode.db).opencode auth login opencode-gocreates it. - A legacy
opencodeAPI-key login as the final fallback.
- Without an API key: a sign-in OpenCode cannot return shows as an error, and a failed Console call (including HTTP 403) shows no Go quota.
- If the Console reports no Go subscription (for example HTTP 404), no Go rows appear.
- A window with API status
rate-limitedis shown as used up (0% left) with its reset time. Other windows stay visible. opencodeGoWindowspicks which of Five-hour, Weekly, and Monthly appear everywhere.tuiSidebarPanel.opencodeGoPreferredWindow(rolling,weekly, ormonthly) picks the row shown while the sidebar is collapsed; if unset or unavailable, the lowest remaining window is used.- Old workspace/cookie setups cannot be converted to an API key. See OpenCode Go findings.
Zen uses your OpenCode Console sign-in from OpenCode 2; no cookie or workspace ID is needed.
- Run
opencode auth login opencode, sign in to the Console in your browser, and pick the organization to track. - To track another organization, sign in again and pick it. With several saved sign-ins,
opencode auth switch opencodepicks the active one. - Check it with
/quota_statusin OpenCode, oropencode-quota statusin a terminal.
- Inside OpenCode, an expired token is refreshed; the terminal command does not refresh it.
- An OpenCode API key alone is not a Console sign-in. Without a sign-in, auto mode skips Zen; include
opencodeinenabledProvidersto see a sign-in hint instead. - Zen reads unofficial Console routes (
/api/billing/status,/api/billing/account,/api/billing/auto-recharge,/api/policies/members/{account id}, and/api/usage/cost-by-day), so OpenCode may change them. - Monthly budget: a percentage with used, limit, and remaining USD. It queries the member detail route for the signed-in account and only trusts it when the returned
userIDmatches the sign-in's account id. A budget rule counts only when both itspolicyIDandruleIDmatch into the response's policies with a verified rule shape (kind: "budget",period: "month", alignedscope/per). Among the applicable rules it shows the one with the smallest remaining USD, so a personaleachcap wins over the workspacecombinedcap whenever it leaves less. Budget scopes differ:eachis a per-member budget,combinedis shared accounting across the rule's audience — not necessarily the whole organization. A member with no personal budget gets the workspace budget this way. A $0 limit counts as a real blocking budget. A rule whoseselectorrestricts models (models,vendors, orinputPriceAtLeast;includeUnknownPricealone does not) is only usable when it proves to cover every model, and non-zeroper: "model"budgets have no per-model spend here — both are skipped instead of guessed. A member budget resets at 00:00 UTC on the 1st of the next month. If any budget candidate is skipped (model-restricted, non-zeroper: "model", unmatched rule, missing amounts), Zen uses no member budget at all (the skipped one could be the binding cap, so the selected one is not trusted), and/quota_statusshowsmember_budget_note. Without a usable member budget (no budget candidates, a skipped one, or a missing, forbidden, or unusable member route), Zen falls back to the Console credit limit (/api/billing/account) plus this month's usage costs (/api/usage/cost-by-day).opencodeMonthlyLimitinquota-toast.jsonoverrides the budget from either source. - Balance: always required. It is supplementary when a budget percentage exists, and primary otherwise (next to a Monthly spend row when this month's usage is known).
- Auto-reload: a supplementary enabled/disabled row. Its amount and trigger stay in diagnostics.
- If a non-balance route fails, Zen still shows the balance, hides only the rows that need the failed data, and lists the failed route as an error.
accountingDetail: "detailed"shows the supplementary balance and auto-reload rows. The oldopencodeZenDisplaysetting is gone; see What can change automatically.- The old
opencode-quota/opencode.jsonfile andOPENCODE_WORKSPACE_ID/OPENCODE_AUTH_COOKIEvariables are no longer read. See OpenCode Zen findings.
{ "quotaProviders": [ { // Vercel AI Gateway: team credit balance and total spend, in USD. "id": "vercel-credits", "providerId": "vercel", "label": "Vercel AI Gateway", "mode": "remote-api", "url": "https://ai-gateway.vercel.sh/v1/credits", "format": "json-v1", "apiKeyEnv": "AI_GATEWAY_API_KEY", "adapter": { "mappings": [ { "resultType": "balance", "name": "Balance", "label": "Balance:", "unit": "USD", "unitPosition": "suffix", "metric": { "type": "value", "valueType": "balance", "value": { "path": ["balance"] } } }, { "resultType": "spend", "name": "Spend", "label": "Spend:", "unit": "USD", "unitPosition": "suffix", "metric": { "type": "value", "valueType": "spend", "value": { "path": ["total_used"] } } } ] } }, { // Moonshot / Kimi API platform (not Kimi Code, which is built in): available balance, in USD. "id": "moonshot-balance", "providerId": "moonshotai", "label": "Moonshot", "mode": "remote-api", "url": "https://api.moonshot.ai/v1/users/me/balance", "format": "json-v1", "apiKeyEnv": "MOONSHOT_API_KEY", "adapter": { "mappings": [ { "resultType": "balance", "name": "Balance", "label": "Balance:", "unit": "USD", "unitPosition": "suffix", "metric": { "type": "value", "valueType": "balance", "value": { "path": ["data", "available_balance"] } } } ] } }, { // Poe: point balance (points, not money). "id": "poe-points", "providerId": "poe", "label": "Poe", "mode": "remote-api", "url": "https://api.poe.com/usage/current_balance", "format": "json-v1", "apiKeyEnv": "POE_API_KEY", "adapter": { "mappings": [ { "resultType": "balance", "name": "Points", "label": "Points:", "unit": "points", "unitPosition": "suffix", "metric": { "type": "value", "valueType": "balance", "value": { "path": ["current_point_balance"] } } } ] } } ] }