OpenCode Go Usage
A DeepSeek Harness plugin: a composer-dock pill for sessions running on the OpenCode Go provider, and a dialog behind it showing your real plan usage — the same 5-hour, weekly and monthly meters the OpenCode Console renders.
Install
dsh plugin --profile <name> add github:prasenkakade21/dsh-opencode-go-usage
The desktop application manages its own profile, so there use the Plugins page's Add flow instead of the CLI. After it loads, click the pill and Connect to approve the device code.
What it shows
▮▮▮ 3.17% / $0.08 ← account month, then this session's cost
3.17%— your monthly Go meter, read from the Console (two decimals).$0.08— this session's token cost at OpenCode Go prices.
Clicking it opens the account dialog:
┌──────────────────────────────────────────┐
│ ▮ OpenCode Go $0.08 │
│ ──────────────────────────────────────── │
│ This session · 0.08% of the monthly limit │
│ ──────────────────────────────────────── │
│ 5-hour 2.10% resets in 3h 12m │
│ ▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ Week 6.34% resets in 4d 0h │
│ ▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ Month 3.17% resets in 26d 4h │
│ ▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ ──────────────────────────────────────── │
│ go plan · renews 26d 4h [Sign out] │
└──────────────────────────────────────────┘
The first line is this session as one sentence — its share of the model's monthly allowance, with no dollars and no model name. (The dollars stay in the title and the footer.) The three account windows follow it, and the dialog ends with an Edit display in Plugins button that jumps straight to the settings.
The Display switches live in exactly one place: this plugin's page in Settings → Plugins → OpenCode Go Usage, beside the bundle's own configuration — one click from the Plugins list, like the built-ins. They are round on/off switches for the bottom bar — Monthly percentage, Session cost, Usage ring, 5-hour percentage and Weekly percentage — stored in the browser and broadcast to every open view, so flipping one repaints the pill immediately with no reload. Turning everything off leaves the pill as its glyph alone, keeping the dialog reachable.
Where the numbers come from
| Number | Source |
|---|---|
| 5-hour / weekly / monthly meters | GET https://opencode.ai/console/api/go/status — the Console's own Go subscription meters |
| This session's cost | the tokenUsage + modelSelection Session projections, priced by the book in client.js |
The Console keeps usage behind a sign-in, so the Host half runs a device-code flow: the dialog
shows a short code, you approve it in the browser, and the session is stored at
$DSH_HOME/opencode-go-usage/state.json with 0600 permissions. Tokens never reach the page — the
browser only receives percentages and reset times. Access tokens refresh silently two minutes before
they expire.
The route (/api/opencode-go-usage/...) is a plain node:http handler registered on a longer prefix
than the connection carrier's /api, so it is answered directly rather than through the fetch
bridge. It exposes no token, only the normalized meters.
Accuracy
- The meters are exact — they are the Console's numbers, not a reconstruction. Anything done in the opencode CLI or on another machine is already included, because the Console counts the account.
- The session figure is an estimate. It prices the session's token buckets at Go list prices, so it approximates what that session contributed to the meters. DeepSeek V4.1 Flash and V4 Pro bill double during 01:00–04:00 and 06:00–10:00 UTC on weekdays; the session has no per-request timestamps, so the whole session is priced at the rate in force now.
- One model per session. A session that switched models is priced against its current one.
- Input tiers are not modelled (Grok, GPT Luna, Claude Haiku, Qwen3.7 Plus, MiniMax M3 raise prices above a per-request prompt size).
- Prices drift. When OpenCode changes a price, edit
PRICESinclient.js.
Files
| File | Role |
|---|---|
index.js |
Host half: device sign-in, token refresh, Console status, the /api route |
client.js |
Client half: the dock pill, the dialog, the Plugins-page Display section, the session pricing, locale, styles |
cordis.patch.yml |
Inserts the opencode-go-usage Host row |
locale/en.json, locale/zh.json |
Plugin Manager title/description |
icon.svg |
Original icon |
The device-code flow, the Console URLs and the refresh shape are adapted from
dsh-opencodego-status by Assidefok (MIT).
Configuration
The bundle row accepts one setting:
- id: opencode-go-usage
name: '@local/opencode-go-usage'
config:
refreshSeconds: 60 # 15 – 3600; how long one Console reading is reused
Development
node test/smoke.mjs runs both halves headlessly: the Console payload normalization, the
device-flow helpers, the session pricing and peak windows, the rendered pill and dialog in connected,
not-connected and host-down states, and the route's 404 answer.
Host code is ESM-cached at app start, so a change to index.js needs an app restart; client.js is
served from this directory and reloads with the page.
Known limits
- The Console endpoint is not a documented public API. If OpenCode changes it, the dialog degrades to an error with a retry rather than breaking the dock.
- The route is served on the loopback HTTP listener without the carrier's cookie fence (a longer prefix wins). It returns percentages only, never a token.
No comments yet. Be the first to write one.