DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Month Tokens — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
M

dsh-month-tokens

Month Tokens

Sidebar counter for one calendar month of provider-reported token usage: this DSH home plus opencode, from local data only, resetting at 00:00 on the 1st.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:greyhackintoch-dev/dsh-month-tokens#082b4ff03372c7b50d316b44847fecea66b0ffa4
READMECompatibilityVersions

Compatibility and provenance

Month Tokens is published as dsh-month-tokens and currently resolves to version 0.5.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/24/2026

Versions

0.5.0stable
9/24/2026

Related plugins

Loading related plugins…

Latest
0.5.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 1
Weekly downloads
0
Last push
9/24/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in models-usage.

Usage@linxin666/dsh-usageUsage statistics plugin for the dsh web GUI: per-provider balance and coding-plan quota detection plus a live token usage ledger, with a compact price glance card above the sidebar's Settings rowWhale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editinCommandcode Provider@mars-sea/dsh-commandcode-providerUnofficial DeepSeek Harness LLM provider plugin for Command Code, ported from pi-commandcode-provider (MIT). Registers the 'commandcode' provider route with a Models-page card and live model catalog.Plugin Subscriptionsdsh-plugin-subscriptionsUse ChatGPT (Codex), Claude, Grok (X Premium), GitHub Copilot, and Google Antigravity subscriptions as DeepSeek Harness LLM providers, with OAuth login from the web Settings page

README

dsh-month-tokens

A DeepSeek Harness plugin that puts one calendar month of token usage in the sidebar, directly above Settings. It counts this DSH home and opencode, reads only local data, and resets at 00:00 on the 1st.

┌──────────────────────────────┐
│  ▮▮  本月消耗Token    3.61亿  │   ← this plugin
│  ⚙   Settings                 │
└──────────────────────────────┘

Click the row for the breakdown.

Install

dsh plugin --profile web add github:greyhackintoch-dev/dsh-month-tokens

No build step, so there is no allowBuilds approval to answer. Restart dsh web afterwards.

Install through the agent instead

Prefer not to touch a terminal? Paste this into any DSH session:

Install the dsh-month-tokens plugin by running:

dsh plugin --profile web add github:greyhackintoch-dev/dsh-month-tokens

Then confirm dsh-month-tokens appears in ~/.dsh/profiles/web/package.json
under dsh.profile.bundles, and remind me to restart dsh web for it to take
effect.

The command writes outside the agent's workspace sandbox, so expect a single approval prompt. dsh plugin reconciles the package into dsh.profile.bundles by itself — the bundle declares dsh.bundle, so its cordis.patch.yml is applied with no further configuration.

Requires a browser-shell DSH (web profile)

The browser half runs in a page with a real origin. Two consequences:

The official DSH Desktop app is not supported. dsh plugin refuses its reserved profile outright:

$ dsh plugin --profile desktop add github:greyhackintoch-dev/dsh-month-tokens
error: profile "desktop" is managed exclusively by the Electron application

Installing it there by other means would not help either. The browser half streams over a plain HTTP route (GET /token-ledger/stream), while the Electron shell loads the frontend from file:// and carries every bit of DSH's own client I/O through window.__DSH_TRANSPORT__ instead. Under file:// a relative URL has no host to resolve against — the shell's own code detects this, since location.origin is the string "null" — and nothing exposes the loopback port to the renderer, so there is no absolute URL to fall back to.

Third-party desktop wrappers that embed the standard web profile do work. If the client is a BrowserWindow pointed at the local web GUI, it is an ordinary browser context, and the command above is all that is needed.

What makes it different

Most usage plugins show you a number. This one also tells you how much of the month it could not attribute, and refuses to invent the difference.

DSH ships no projection that buckets usage by day — every shipped unit is either cumulative (tokenUsage) or a snapshot of the present (contextPressure, contextBreakdown, sessionStats). A cumulative per-session figure cannot be reconstructed into "how much of this happened after the 1st". So each session is decided by the first rule that applies, and the rule used is reported:

RuleConditionResultAccuracy
ledgeran optional per-day ledger covers the monthsum the days with this month's prefixexact
borncreated at or after the 1stits whole totalexact
idlecreated earlier, last user prompt before the 1st0exact
splitcreated earlier and prompted this month0, and counted in unattributedunknown

A long-running session that spans the boundary lands in split, and that is exactly the case where a naive counter silently reports too little. When any session lands there, local.exact is false, local.unattributed says how many, and the panel says so in the warning colour.

To resolve the remaining cases exactly, add a per-day activity projection. The community dsh-context plugin contributes one named contextActivity; when it is mounted, the ledger rule takes over automatically and no session is left ambiguous. Measured on a real 79-session home it covered 78 sessions exactly, the exception being a session checkpointed before that plugin existed. This plugin has no dependency on it — it is an optional upgrade, and everything works without it.

What it counts

SourceWhere it comes fromLatency
This DSH homeper-session tokenUsage projectionslive — pushed on every settled turn
opencodeits own SQLite database, read-onlya poll, up to ~1 minute behind

Both are local. The plugin makes no HTTP request of any kind: opencode's calls never pass through DSH, so reading its database is the only way to see them.

opencode

opencode writes one row per assistant message into ~/.local/share/opencode/opencode.db, whose data JSON carries tokens: { input, output, reasoning, cache: { read, write }, total }. The columns line up with this ledger's vocabulary almost exactly:

Ledger bucketopencode field
uncachedInputTokenstokens.input — uncached; cache reads are separate
cacheReadTokenstokens.cache.read
cacheWriteTokenstokens.cache.write
outputTokenstokens.output + tokens.reasoning

reasoning is the one translation: opencode reports it apart from output, while DSH folds it in, so the two are summed to keep the rows comparable.

Rows are filtered by providerID (deepseek by default) and by time_created >= 本月 1 日. The database is opened read-only and closed on every poll — it is a third-party schema under active WAL writes, so holding a handle buys nothing and risks a stale snapshot.

Requirements: Node 22.5+ for node:sqlite. On an older runtime the plugin still runs; it reports that opencode cannot be read instead of quietly counting zero.

Three limits worth knowing:

  1. Not real-time. opencode records usage when a message completes, so the best available cadence is a 60-second poll. The DSH number is genuinely live.
  2. Private schema. message.data is an opencode implementation detail that any release can change. A schema that still queries but yields no token fields is reported as drift, never as a smaller month.
  3. Provider, not key. providerID: 'deepseek' names the provider, not the credential. Same key in both tools → correct. Swap in a different DeepSeek key in opencode and the two are silently merged.

Override the location or the provider list in the plugin's entry:

- insert:
    - id: token-ledger
      name: 'dsh-month-tokens'
      config:
        opencodeDbPath: /custom/path/opencode.db
        opencodeProviders: [deepseek]

DSH_TOKEN_LEDGER_OPENCODE_DB overrides the path when no config is given.

Routes

RouteBody
GET /token-ledger/streamSSE; one ledger event per movement, plus : keep-alive every 25s
GET /token-ledger/summarythe same payload as one JSON document
{
  "revision": 6,
  "period":  { "kind": "month", "key": "2026-09", "start": 1788192000000, "end": 1790294400000 },
  "month":   361262338,
  "totals":  { "uncachedInputTokens": 3944544, "outputTokens": 2456933, "cacheReadTokens": 269710720, "cacheWriteTokens": 0 },
  "local":   { "total": 346169232, "month": 346169232, "monthSource": "mixed", "exact": true, "unattributed": 0 },
  "tools": {
    "opencode": { "state": "ok", "messages": 98, "fetchedAt": 1790231906819,
      "totals": { "uncachedInputTokens": 1700628, "outputTokens": 77406, "cacheReadTokens": 13315072, "cacheWriteTokens": 0 } }
  },
  "sessions": { "counted": 79, "live": 2, "skippedSeeded": 0, "scannedAt": 1790229233573 }
}

month is the headline. totals is the all-time DSH bucket breakdown, shown in the panel under a 本机历史累计(仅 DSH) caption. monthSource is ledger, born, idle, mixed, or none; tools.opencode.state is loading, ok, absent, drift, unavailable, or error.

curl -s http://127.0.0.1:3080/token-ledger/summary | python3 -m json.tool

Why the period needs no stored counter

The window is derived from the clock on every read:

start = 本月 1 日 00:00(本地时间)
end   = 明天 00:00

There is no accumulated total and no reset job, so a process that slept through midnight on the 1st still reports the new month the moment it next looks, and no reset can be missed. A timer also fires at the boundary so an open panel turns over immediately rather than waiting for the next turn or rescan.

Development

npm test        # node test/host.test.mjs && node test/client.test.mjs

The suite is dependency-free, offline, and hermetic: it points the plugin at a path that cannot exist, so it can never read your real opencode database.

To mount a working copy instead of the installed package, insert it by absolute path — dsh converts absolute paths inside insert rows to file URLs, and the client-module scanner walks up from the entry file to the nearest package.json:

- insert:
    - id: token-ledger
      name: /absolute/path/to/dsh-month-tokens/lib/index.js

Use either the bundle or the path insert, never both — the token-ledger id would collide and the duplicate route registration would fail loudly.

Restart dsh web after editing the host half. Profiles with patchReload: live recompose on a patch edit, but the host module is a plain ESM import and stays in the module cache. The browser half is read from disk, so a page refresh is enough for it.

How it is put together

  • lib/index.js — the host half. Folds DSH's projections, reads opencode, and serves the two routes. No dependencies beyond Node builtins.
  • client/client.js — the browser half, hand-bundled for the DSH client module loader (window.__ModuleLoader__.load({ id, factory })). It requires only the platform seed words react and react-dom, registers one entry into the sidebar.footer.action list slot, opens one EventSource, and renders whole values the host computed. No domain folding happens in the browser.

Counts render in Chinese myriad units — 999, 2.95万, 2.77亿 — with the exact integer on hover.

Cost

  • Cold scan on boot and every 60s: one sessionPersistence.list() (a directory walk plus a stat per session) and one in-memory cachedSnapshot per cold session. No session log is ever read.
  • One read-only COUNT/SUM over opencode's message table per minute.
  • An idle rescan does not republish, so a quiet ledger never re-renders an open panel. fetchedAt is deliberately excluded from the change comparison — including it would bump the revision once a minute forever.

Security

The two routes answer without the dsh web launch-token exchange, because the webserver's named-route table is not behind that guard. That is acceptable here: the webserver binds to 127.0.0.1 by default, the payload is aggregate counts rather than session content, and no access-control-allow-origin header is sent, so a cross-origin page cannot read the body. If you deliberately expose the GUI with networkExposure: 0.0.0.0, these two routes become reachable by anyone who can reach the port.

The plugin reads exactly two things off disk: DSH's own session projections, and opencode's message table. It never reads opencode's auth.json, never opens that database for writing, and never puts a credential or a message body into a payload or a log line — only counts.

License

MIT