Bundle
dsh-usage-estimator
Sidebar usage monitor for opencode.go and commandcode credits — usage bars plus per-model estimated request counts from the official pricing docs
- Source
- lbwfff
- License
- MIT
- Updated
- Updated 2 days ago
Readme
<div align="center">
# 📊 dsh-usage-estimator
**Sidebar usage monitor for [opencode.go](https://opencode.ai/docs/zh-cn/go/) & [commandcode](https://commandcode.ai/docs/plans/goat)** — a dual-face plugin for **DeepSeek Harness Web**
Live usage bars · Per-model request budget estimates · 中文 / English UI
[](LICENSE)
[](https://github.com/topics/dsh-plugin)
**🌐 [Read this in 中文](./README.zh.md)**
---
</div>
The **host half** serves a `/quota` route on DSH's own HTTP server — no separate
process, no port, no CORS. The **browser half** polls that route and renders
usage bars into the sidebar footer (`sidebar.footer.action` slot).
The UI follows your DSH language setting (Simplified Chinese or English).
Product vocabulary stays untranslated on purpose: the time-window labels
`5-Hour` / `Weekly` / `Monthly` and the provider names `OpenCode Go` /
`Command Code`.
## 🖼️ Screenshots
<div align="center">
**Sidebar usage bars**
<img src="assets/sidebar-usage.png" width="420" alt="Sidebar usage bars">
**Estimated request counts modal** — the feature most other quota plugins lack
<img src="assets/estimated-request-counts.png" width="480" alt="Estimated request counts">
</div>
## ✨ Features
- 📈 **Live usage bars** — rolling / weekly / monthly quota for both providers,
with time-until-reset.
- 🧮 **Estimated request counts** — one merged table comparing OpenCode Go vs
Command Code GOAT per-model request budgets (per 5h / week / month). Models
present in only one plan show a slash (`/`) in the other plan's columns.
- 🌐 **Fully localized** — follows your DSH language setting (中文 / English).
- 🔒 **Privacy-conscious** — cookie reading is optional and clearly documented.
- 📦 **Zero-setup request tables** — scraped from the official pricing docs,
no auth needed.
### Why these two plans?
OpenCode Go and Command Code GOAT are the two **most affordable coding plans** —
the ones most people actually run their daily coding on. That's why the plugin
tracks their live usage and request budgets out of the box.
On a different plan or provider? The quota collector and the request-count
tables are plain readable scripts, and the plugin's config lets you point it at
your own workspace id and credit caps — adapt it to your own setup with DSH.
Data sources (cached ~6 h):
| Source | URL |
|---|---|
| 🌐 OpenCode Go | <https://opencode.ai/docs/zh-cn/go/> |
| 🌐 Command Code GOAT | <https://commandcode.ai/docs/plans/goat> |
## 📦 Install
**Prerequisite:** `dsh plugin` forwards to pnpm, so you need it on your PATH:
```bash
npm i -g pnpm # or: corepack enable
```
Then install the plugin:
```bash
dsh plugin --profile web add github:lbwfff/dsh-usage-estimator
```
> [!NOTE]
> The first git install may ask you to allow pnpm's build scripts — add the
> exact key pnpm prints under `allowBuilds` in
> `~/.dsh/profiles/web/pnpm-workspace.yaml`, then re-run.
Then **restart dsh web**. The plugin registers itself into the profile's bundle
layers automatically (`dsh.bundle` + `cordis.patch.yml`).
## ⚙️ Configuration
The plugin reads its settings from the profile patch
(`~/.dsh/profiles/web/cordis.patch.yml`) under the entry's `config`:
```yaml
- insert:
- id: dsh-usage-estimator
name: dsh-usage-estimator
config:
# your opencode.go workspace id (required for the OpenCode Go bars)
opencodeWorkspaceId: wrk_xxxxxxxxxxxxxxxxxxxxxxxx
# your commandcode monthly credit cap (used to compute the monthly %)
commandcodeMonthlyCap: 70
# read browser cookies to authenticate against the official APIs
cookieEnabled: true
# path to a commandcode.ai HAR you exported yourself (fallback source)
# harPath: /path/to/commandcode.ai.har
```
| Field | Default | Meaning |
|---|---|---|
| `opencodeWorkspaceId` | `""` | opencode.go workspace id (`wrk_...`). Empty disables the OpenCode Go bars. |
| `commandcodeMonthlyCap` | `0` | monthly credit cap for commandcode. Without it the monthly % falls back to the API-reported cap or is shown as unavailable. |
| `cookieEnabled` | `true` | read browser cookies to authenticate against the official APIs. Set `false` to disable cookie reading entirely (request-count tables keep working). |
| `harPath` | `~/.dsh-usage-estimator/commandcode.ai.har` | user-exported HAR used when the live API is unreachable. |
### 🔑 Finding your OpenCode Go workspace id
`opencodeWorkspaceId` is the one field you **must** set yourself — it's a
per-account value we can't ship in the plugin. To find yours:
1. Log in to [opencode.ai](https://opencode.ai) in your browser.
2. Open your workspace's usage page — the URL looks like
`https://opencode.ai/workspace/wrk_xxxxxxxxxxxxxxxxxxxxxxxx/go`.
3. Copy the `wrk_...` segment and paste it into `opencodeWorkspaceId`.
Everything else is optional: with just the workspace id set (and
`cookieEnabled` left on), the plugin shows both providers' live usage bars and
the full request-count table. If you leave it empty, the OpenCode Go bars show
a clear "not configured" message and the rest keeps working.
## 🔒 Privacy
Read this before enabling cookie mode.
- ✅ **`cookieEnabled: true` (default)** — the collector reads your browser
cookies (Edge, then Chrome/Firefox/Safari as fallbacks) for `opencode.ai`
and `commandcode.ai`, and sends them **only** to those official domains to
fetch your quota. Cookies never leave your machine to anywhere else, and
nothing is logged or transmitted to any third party.
- 🚫 **`cookieEnabled: false`** — no cookie is read at all. You lose the live
usage bars but keep the request-count tables (which need no auth).
- 💾 **HAR fallback** — if you export a `commandcode.ai` HAR yourself (DevTools
→ Network → save), the collector can read usage from it when the live API
is down. The HAR stays on your machine; never commit it to a repo.
- 🗂️ The collector stores only a local cache of the public request-count
tables (`~/.cache/dsh-usage-estimator/`), refreshed every 6 hours.
## 🏗️ Architecture
```
scripts/quota.py ──────────────(execFile)──> host half (lib/index.js)
├─ usage bars (opencode.go + commandcode credits) │
└─ requestCounts (2 pricing-doc tables merged, 6h cache) ▼
registers exact route "/quota" on ctx.webServer
DSH web server (same origin)
│
▼ fetch("/quota") every 10 min
browser half (lib/client.js)
│
▼ ctx.slots.inject("sidebar.footer.action")
sidebar footer widget (+ Requests modal)
```
- **Host half** (`lib/index.js`): a Cordis plugin that registers a `/quota`
exact route on the web profile's existing `webServer` service. Each request
shells out to `scripts/quota.py` via `execFile`, caches the snapshot for
120s, and returns it as JSON. Your cordis `config` is forwarded to the
script as `QM_*` environment variables. Registers on startup, unregisters on
shutdown — no standalone process.
- **Browser half** (`lib/client.js`): a `window.__ModuleLoader__.load()` bundle
mounting a React component into `sidebar.footer.action`, polling `/quota`
every 10 minutes (manual refresh forces a re-fetch via `?force=1`). The
Requests modal uses the platform `Modal` primitive
(`@deepseek-ai/dsh-client-ui-primitives`) and the DSH locale plugin for its
Chinese/English UI.
## 🧩 Files
| File | Role |
|---|---|
| `lib/index.js` | Host entry — `apply(ctx, config)` registers the `/quota` route on `webServer` |
| `lib/client.js` | Browser bundle — React component + slot injection + polling + Requests modal |
| `scripts/quota.py` | Data collector — reads `QM_*` env vars, outputs the JSON snapshot |
| `scripts/requests_count_lib.py` | Shared request-table scraper + name normalization + merged table |
| `requirements.txt` | Python deps (only `browser_cookie3`, for the live usage bars) |
| `lib/types/*.d.ts` | Type declarations |
| `assets/` | README screenshots |
| `test-host.js` | Smoke test: boots real Cordis + WebServer, hits `/quota`, prints JSON |
| `package.json` | `dsh.bundle` + `dsh.client` declarations + `exports["./client"]` |
## ✅ Requirements
- Python 3 with `browser_cookie3` (only needed when `cookieEnabled: true`):
```bash
pip install -r requirements.txt
```
- The request-count tables need no extra Python deps (standard library only).
- **Cookie reading supports Edge, Chrome, Firefox and Safari** (in that order
of preference). The collector reads the browser cookies for
`opencode.ai` / `commandcode.ai` from whichever of these browsers has you
logged in — so if you sign in with Chrome instead of Edge, it works too.
Only the login state of these browsers is used; nothing else is read.
## 🧪 Test
```bash
node test-host.js
# [test] webServer listening on 64573
# [test] status: 200
# [test] go.ok: ... | cc.ok: ... | cc.source: ...
# [test] requestCounts.opencode.ok: true | rows: 22
# [test] requestCounts.cc_goat.ok: true | rows: 30
# [test] requestCounts.merged rows: 34
# [test] privacy scan: OK
# [test] PASS
```
## 📝 Notes
- **Data refresh**: host caches quota.py output for 120s; browser polls every
10 min; manual refresh sends `?force=1` to bypass the cache.
- **Request tables**: quota.py refreshes them from the docs every 6 h
(`~/.cache/dsh-usage-estimator/requests-count-cache.json`).
- **Collapsed sidebar**: the widget shrinks to a status dot (the Requests modal
is still reachable after expanding).
- **No personal data shipped**: the workspace id, credit caps, cookie opt-in
and HAR path all come from your cordis config. Export your own HAR if you
want the offline fallback — don't commit it.
Install
dsh plugin --profile web add github:lbwfff/dsh-usage-estimator#5aca37480cd2942707f4ecf77a9044c7af39349d
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-usage-estimator from the hub