Skip to content

Repository files navigation

pi-ocgo-usage

npm license: MIT

Footer demo

A Pi coding agent extension that displays OpenCode Go subscription usage in the footer when using an opencode-go/* model.

⚠️ This extension requires an OpenCode Go session cookie to function. The cookie is a full user session (not an API key) and grants access to your entire OpenCode account. Treat it with the same care as your password. See Configuration below for how to obtain and store it.

Why

OpenCode Go is a prepaid subscription — rolling (5h), weekly, and monthly windows, each with its own quota. When a window is exhausted you get rate-limited mid-work, which is exactly the worst moment to discover it. Yet there is no official usage API yet: the only place to see your numbers is the opencode.ai dashboard, and you have to open a browser to check.

This extension puts the numbers where you already are — the Pi footer:

  • Always visible while you work with an opencode-go/* model, no browser tab needed
  • Warns before you hit the wall: color shifts to warning at ≥80% and error at ≥90% or when rate-limited
  • Shows data freshness: 14:32 (last successful fetch, local time) tells you how fresh the numbers are, so a stale footer never misleads you
  • Pre-wired for the official API (PR #16513): the apikey path is implemented and usable today via OPENCODE_GO_MODE=apikey; once opencode ships the endpoint, auto mode flips to it with the cookie/SSR path as fallback (tracked by the PR workflow)

Features

  • Auto Footer Display — Automatically shows usage in the footer when using any opencode-go/* model
  • Three Windows — Rolling (5h), weekly, and monthly usage percentages with reset countdowns
  • Color Thresholdsmuted / warning (≥80%) / error (≥90% or rate-limited)
  • Non-Blocking — All refreshes are fire-and-forget: event handlers return instantly and the fetch runs in the background, so usage checks never delay message flow. Even a stuck request is aborted in the background by OPENCODE_GO_TIMEOUT_MS
  • Configurable Refresh TTL — Refresh cadence follows the OPENCODE_GO_CACHE_TTL config (default 300s, clamp 60–3600); a failed fetch enters a 60s cooldown instead of hammering the server on every turn
  • Graceful Degradation — On HTTP error, footer shows <err:code>; on missing config, footer shows <err:noconfig>
  • Future-proof — The official API (PR #16513) path is implemented and usable via OPENCODE_GO_MODE=apikey; auto mode flips to it once the endpoint ships

Install

From GitHub (recommended for testing)

pi install https://github.com/v587d/pi-ocgo-usage.git

This clones the repo (which ships a pre-built dist/) and registers the extension in your ~/.pi/agent/settings.json.

From npm (after first release)

pi install npm:pi-ocgo-usage

From a local checkout (development)

git clone https://github.com/v587d/pi-ocgo-usage.git
cd pi-ocgo-usage
bun install
bun run build
pi install ./

Note: pi install uses --ignore-scripts, so prepare and postinstall hooks won't run. The repo ships a pre-built dist/ for GitHub installs; for local development, run bun run build after install.

Configuration

Required: provide your OpenCode Go session cookie + workspace ID

  1. Open https://opencode.ai/workspace/<your-workspace-id>/go in a browser (sign in if prompted). The URL is your workspace ID — copy the part starting with wrk_.

  2. Open DevTools → Application → Cookies → https://opencode.ai Copy the full value of the auth cookie. It looks like Fe26.2*<base64>*<sig>*<exp>*<hmac>.

  3. Set environment variables (preferred for personal use):

    export OPENCODE_GO_COOKIE="auth=Fe26.2*...; oc_locale=zh"
    export OPENCODE_GO_WORKSPACE_ID="wrk_01XXXXXXXXXXXXXXXXXXXXXXXX"

    Or write to ~/.pi/agent/pi-ocgo-usage.json:

    {
      "cookie": "auth=Fe26.2*...; oc_locale=zh",
      "workspaceID": "wrk_01XXXXXXXXXXXXXXXXXXXXXXXX"
    }
    chmod 600 ~/.pi/agent/pi-ocgo-usage.json

Optional overrides

Env var Default Description
OPENCODE_GO_BASE_URL https://opencode.ai API base URL
OPENCODE_GO_CACHE_TTL 300 Footer refresh TTL in seconds, 60–3600
OPENCODE_GO_MODE auto auto / cookie / apikey
OPENCODE_GO_TIMEOUT_MS 10000 HTTP timeout

⚠️ Cookie expiration: the auth cookie is signed by Cloudflare Iron Session and is valid for 1 year from issue. When it expires (or is revoked), the /workspace/<wrk>/go page 302-redirects to the login page, which parses as an empty page — the footer then shows no windows rather than an error. Re-login to opencode.ai and update the cookie via /oc-go-config set.

Slash commands

The extension registers the /oc-go-config command — run it inside a Pi chat to configure or test the extension without touching your shell:

Command What it does
/oc-go-config (no args) Show current config summary + usage help
/oc-go-config status Same as no args (explicit)
/oc-go-config set Interactive wizard: paste workspace_id + cookie → persists to ~/.pi/agent/pi-ocgo-usage.json (mode 0600) after confirmation. Pasting works with any of: full header (auth=…; oc_locale=zh), just the auth value (Fe26.2*…), or value + locale — it is normalized automatically
/oc-go-config test One-shot live fetch with current config; renders exactly what the footer would show (use this to verify cookie/workspace)
/oc-go-config clear Delete the persisted config file (cookie + workspace ID)

Usage

When using any opencode-go/* model, the footer shows:

OC.go: 5h 23% (3h 25m) · wk 30% (4d 6h) · mo 12% (12d 4h)
  • Each window: <label> <percent>% (<time remaining>)
  • Color: muted → warning (≥80%) → error (≥90% or rate-limited)
  • On successful fetch: appended as · 14:32 — local time of the last successful refresh, so you can see how stale the data is
  • If any window is missing (e.g., new account): that segment is omitted

Footer is cleared when switching to a non-OpenCode-Go model or on session shutdown.

How It Works

The extension reverse-engineered the opencode.ai console and found that the /_server RPC endpoint (which the dashboard uses for its own API-key calls) always rejects cookie-authenticated requests with HTTP 500 — so it is not usable. Instead, the extension scrapes the SSR-rendered usage page:

GET /workspace/<wrk>/go
Cookie: auth=Fe26.2*...; oc_locale=zh

The page renders each usage window as a data-slot="usage-item" block; the extension parses the percent and the human-readable reset phrase (e.g. Resets in 2 hours 29 minutes) and normalizes them into the internal NormalizedUsage shape:

{
  "useBalance": true,
  "updatedAt": 1786335000000,
  "rolling": { "percent": 80, "resetInSec": 3840,  "status": "ok" },
  "weekly":  { "percent": 32, "resetInSec": 586800,"status": "ok" },
  "monthly": { "percent": 66, "resetInSec": 939600,"status": "ok" }
}

updatedAt (epoch ms) is stamped by fetchUsage on every successful fetch and rendered as the footer's · HH:MM freshness indicator (local timezone). useBalance (whether over-limit usage falls back to your Zen balance) is still parsed but no longer rendered.

Non-blocking refresh (fire-and-forget)

Usage fetches never sit in the message path. On session_start, model_select (switch to an opencode-go/* model) and turn_end, the extension fires a background refresh and returns immediately — the footer updates when the data arrives. This holds even on failure: a stuck request is aborted in the background by OPENCODE_GO_TIMEOUT_MS, and message delivery is unaffected.

  • Refresh cadence is driven by OPENCODE_GO_CACHE_TTL (default 300s); a fresh cache just re-renders the footer without any network call
  • A failed fetch enters a 60s cooldown (footer keeps the last <err:code>) instead of retrying every turn
  • Switching away from an opencode-go/* model or session shutdown clears the footer and discards any in-flight result; a stale extension context can never throw

(v0.1–v0.2 used pi-usage-lib's createUsageExtension wiring, whose handlers awaited the network fetch inline — this could delay the message pipeline by up to timeoutMs per cold fetch. Since v0.3 the cache is self-implemented in src/usage-cache.ts and the events are fully non-blocking.)

Official API auto-switch (anomalyco/opencode#16513)

The official GET /zen/go/v1/usage endpoint (Bearer auth via ctx.modelRegistry.getApiKeyForProvider("opencode-go")) is pre-wired: you can try it today with OPENCODE_GO_MODE=apikey (it 404s until the PR merges). In auto mode the cookie/SSR path is used; flipping auto to apikey-first is a one-line change shipped in the release that follows the PR merge — the tracking workflow below opens an issue the moment the PR merges to prompt it. No client-side changes are required on your end; watch the PR (or the tracking workflow) for the switch.

Tracking the official API PR

Two ways to stay informed — use both:

  1. GitHub notification (instant, manual): sign in to GitHub, open anomalyco/opencode#16513 and click Subscribe (🔔, right sidebar). You get an email on every event, including the merge.
  2. Repo auto-tracker (zero effort): this repository ships a scheduled workflow (.github/workflows/pr-tracker.yml) that polls the PR every 6 hours and:
    • commits a status snapshot to docs/pr-16513-status.md (state, merge commit, last checked),
    • opens an issue in this repo the moment the PR merges — if you watch this repo (or get notifications for your own repos), that's your automated ping to update/release the extension with the apikey path enabled.

See docs/RESEARCH.md for full reverse-engineering details and docs/SPEC.md for the implementation contract.

Troubleshooting

Symptom Meaning / fix
Footer empty, no windows Cookie invalid/expired → 302 to login page (parses as empty). Re-login & /oc-go-config set
<err:http500> Server-side error on /workspace/<wrk>/go (transient backend issue). Retry later; run /oc-go-config test for the raw message
<err:noconfig> Missing cookie + workspace ID. Run /oc-go-config set or set the env vars above
<err:timeout> Backend slow; raise OPENCODE_GO_TIMEOUT_MS

Security

  • The auth cookie is a full OpenCode user session. Anyone with it can access every workspace, subscription, and billing detail in your account. Treat it like a password:

    • Never share it in chat / issues / screenshots
    • Never commit ~/.pi/agent/pi-ocgo-usage.json to git
    • The extension sets chmod 600 on the config file automatically
    • If you accidentally leak the cookie, sign out of opencode.ai immediately (this invalidates it)
  • The extension never:

    • Logs the cookie value
    • Persists it to session entries
    • Emits it via pi.events
    • Includes it in error messages shown to the user

Development

bun install
bun run dev        # watch mode
bun run test       # run unit tests
bun run check      # typecheck + lint
bun run build      # tsc → dist/

License

MIT — see LICENSE.

About

A Pi coding agent extension that displays OpenCode Go subscription usage in the footer when using an opencode-go/* model.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages