dsh-plugin-token-usage
QwenPaw-style cross-session token usage statistics for DSH.
The plugin aggregates the provider-reported token usage of every model call
across all persisted sessions (including subagent sessions) into
(date, provider, model) buckets and serves them through a single /usage
command.
- Zero runtime dependencies — only the Cordis
ctxAPI and Node 22's built-innode:zlib(zstd) are used. - Durable source of truth — it reads the session logs under
~/.dsh/sessions, so it works on history that predates the plugin and needs no separate bookkeeping at write time. - No double counting — a committed
assistant/message.usagewins; a step that never produced a message (failure) falls back to its last streamingusagechunk, flushed atturn/end. A persisted per-file watermark ({hiSeq, framesIngested}) makes the incremental scan idempotent across restarts and crash-recovery re-encodes.
Command
/usage # last 30 days (configurable defaultDays)
/usage 7d # last 7 days
/usage 7d qwen3.8 # last 7 days, model filter (substring on provider/model)
/usage qwen3.6 # default range, model filter
Example output:
📊 Token Usage 2026-07-17 → 2026-08-16
Total: 906.9M tokens · 4954 calls
input 473.3M · output 3.4M · cache read 430.1M
By model:
sglang/Qwen3.8-27B — 719.4M tokens · 3320 calls
in 337.7M · out 2.8M · cacheR 378.9M
sglang/Qwen3.6-27B — 187.4M tokens · 1634 calls
in 135.6M · out 669900 · cacheR 51.2M
By day:
2026-08-13 42.6M tokens · 481 calls
2026-08-14 195.7M tokens · 1587 calls
2026-08-15 380.5M tokens · 1513 calls
2026-08-16 288.1M tokens · 1373 calls
Token units: 1.2M for >= 1,000,000 (million), 1.5B for >= 1,000,000,000
(billion), plain integer below (one decimal, trailing .0 dropped).
Config
| key | default | description |
|---|---|---|
defaultDays |
30 |
lookback window for a bare /usage. |
backfillIntervalSec |
30 |
seconds between incremental backfill passes (keeps the state file warm). |
sessionsRoot |
~/.dsh/sessions |
DSH session-log root (empty = auto from DSH_HOME). |
stateFile |
~/.dsh/token-usage.json |
aggregated state + watermark. |
flushDelayMs |
5000 |
debounce for the state write. |
enableCommand |
true |
register /usage. |
verbose |
false |
log backfill progress. |
Mounting
The plugin is an out-of-tree module mounted through a profile patch (same
pattern as the telegram / thinking-mode plugins). Add an insert row to
~/.dsh/profiles/web/cordis.patch.yml:
- insert:
- id: token-usage
name: '/home/lovedheart/Documents/dsh-plugin-token-usage/lib/index.js'
config:
defaultDays: 30
backfillIntervalSec: 30
enableCommand: true
verbose: true
commands is an optional dependency (consumed via an optional child
fiber), so the plugin also loads in command-less assemblies — it just stores
without registering the interactive command.
Layout
src/frames.js— zstd frame scanner (mirrors DSH'sscanZstdFrames).src/store.js— bucket aggregation, dedup, persistence,summarize.src/backfill.js— incremental session-log walk +listSessionFiles.src/render.js—fmtTokens,renderUsageReport,parseUsageArgs.src/index.js— plugin entry (name/inject/Config/apply).lib/— build output (npm run preparecopiessrc/*.js).test/—node --testunit + harness tests.
Development
npm install # installs the cordis peer for the harness test
npm test # node --test test/*.test.mjs
npm run prepare # sync lib/ from src/
No comments yet. Be the first to write one.