dsh-token-usage
August 17, 2026 · View on GitHub
A token-usage display plugin for the DeepSeek Harness Web GUI.
It shows token consumption in dsh web, in two surfaces:
- Per-session pill: on the right side of the session header — current session input/output tokens and context occupancy; click for the breakdown (provider usage, context composition, context pressure, session stats).
- Global consumption panel: opened from the "Token stats" button at the bottom of the sidebar — daily totals with a last-30-days bar chart, per-model breakdown (input/output/cache/total/share), and a per-day drilldown table. Data comes from the session logs, aggregated on the fly; the panel auto-refreshes every 60s while open.
No configuration needed.
This plugin does not modify any files: the per-session pill only reads the session projections Harness pushes in real time; the global panel only read-scans the session logs under $DSH_HOME\sessions (no writes, no deletions, no changes to any log).
Screenshots
| Global consumption panel (daily · per-model · per-day drilldown) | Session-header token pill |
|---|---|
![]() | ![]() |
One-click install (GitHub)
dsh plugin --profile web add github:AFAP/dsh-token-usage
Then restart dsh web to activate.
After install the plugin lives at
$DSH_HOME\profiles\web\node_modules\dsh-token-usage(pnpm clones it from GitHub), independent of the source repo location.Update:
dsh plugin --profile web update dsh-token-usageUninstall:
dsh plugin --profile web remove dsh-token-usage
Manual install from a source directory (equivalent, for verification)
dsh plugin --profile web add "D:\path\to\dsh-token-usage"
Verify it loaded
Open any session → the token pill appears in the header; the "Token stats" button appears at the bottom of the sidebar.
Architecture & data flow
Per-session pill (pure client)
The data path is entirely provided by built-in DeepSeek Harness components:
@deepseek-ai/dsh-token-meter(built into the base layer) folds each request's token usage into session projections:tokenUsage,contextPressure,contextBreakdown;@deepseek-ai/dsh-session-stats(built into the web layer) providessessionStats.dsh-host-apiproxybroadcasts every projection change as asession/projectionframe; history tails also carry the projection baseline for reopened sessions.- The browser's
dsh-client-runtimewrites intoProjectionValueStore, exposed to UI components through theuseProjection(key)hook of the slot standard kit. - The plugin registers
TokenUsageBadgeintoconversation.session.header.utilities.
Global panel (host-side log scan + client render)
dsh-token-usage (node half, lib/index.js — zero external deps, Node builtins + ./stats.js only)
GET /api/token-stats ──▶ scans $DSH_HOME/sessions/**/session.jsonl.zstd
(concatenated zstd frames, decompressed frame by frame, JSONL events parsed)
├─ assistant/message events → data.usage (provider-reported tokens)
├─ request/header / request/context → current model
└─ aggregated by "local day × model" → JSON
│
▼ (browser fetch, same-origin)
GlobalStatsPanel (client half) ── summary cards + 30-day bar chart + per-model table + per-day drilldown
- Log format:
dsh-session-persistence-jsonl's multi-frame zstd container (one independent frame per appended batch); this plugin ports the official frame-boundary scanner (magic/descriptor/block/checksum), decompresses each frame withzstdDecompressSync(built into Node 22.22+), and skips torn trailing frames left by a crash. - Per-request memoization by file mtime/size: only changed session logs are re-read, so refreshes are near-instant.
/api/token-statsis registered as an exact route on the webserver (it wins over the connection plugin's/apiprefix) and applies its own browser-trust fence (loopback / trustedHosts + same-origin checks, mirroring the/apifence indsh-client-connection), rejecting DNS rebinding and cross-site requests.- The host half is deliberately dependency-free: DSH_HOME is resolved from the environment (
$DSH_HOME→~/.dsh) and no@deepseek-ai/*package is imported, so it loads correctly no matter how it is installed (git / registry / file: / link:).
Directory layout
dsh-token-usage/ # repo root = npm package root
├── package.json # dsh.bundle.patch (config patch layer) + dsh.client (browser declaration)
├── cordis.patch.yml # composition row: inject webRuntime + trustedHosts config
├── LICENSE # MIT
├── screenshot/ # screenshots (panel.jpg global panel / pill.jpg session pill)
└── lib/
├── index.js # host half: /api/token-stats route + zstd frame scan + aggregation cache
├── stats.js # pure aggregation logic (no deps, independently testable)
└── client.js # browser bundle: per-session pill + global panel
Usage
- Per-session pill:
in {input} · out {output} · ctx {occupancy%}(compact 1.2k / 3.4M format); click for the four-section breakdown (provider usage / context composition / context pressure / session stats). - Global panel (sidebar bottom → Token stats):
- Summary cards: total / today / last 7 days / requests / sessions;
- Last-30-days daily bar chart (today highlighted, hover shows values); click a day's bar → expands that day's 24-hour usage below;
- By-model summary (collapsed by default, click to expand): model | input | output | cache | total | share — the collapsed header shows the aggregate of all models;
- Per-day drilldown: day | total | input | output | requests | model detail, click a day row to expand that day's models;
- Auto-refreshes every 60s while open, manual refresh too; Esc / clicking the backdrop closes it.
- Instant open: aggregated data is cached locally, so the panel opens instantly and stays fast across repeated opens and dsh restarts.
- UI language follows the interface: Simplified Chinese / English dictionaries are both built in.
License
MIT

