A passive token & context meter bar for the OpenCode TUI — derived from the token-meter plugin of the DeepSeek Harness project.
| English | Bahasa Indonesia | 简体中文 |
|---|
While you chat, one line sits at the bottom of the session screen and shows live, per-session numbers:
in 1.2k │ out 0.4k │ rsn 0 │ cR 89.1k cW 2.1k │ hit 68% │ $0.04 │ ctx ██████░░░░ 43% · 128k │ 23.4 tok/s
in/out/rsn— cumulative input, output, and reasoning tokens for the sessioncR/cW— cumulative cache-read and cache-write tokenshit— cache hit rate, DeepSeek definition:cache.read / (cache.read + input)$— cumulative cost for the sessionctx— context pressure of the last request (progress bar + percent + model context limit); color shifts to warn/error as it fills- tok/s — live generation speed while the model streams (shown only while busy); heuristic of 4 characters per token, the same basis as
dsh-token-meter
The bar is passive: it only displays data, never steals a keystroke. Segments hide when their data is not available yet, and nothing renders on non-session routes (home screen).
- opencode
>= 1.18(TUI plugins —tui.json) - Node.js
>= 22only needed for development/typecheck
Copy the plugins/ folder and tui.json into your OpenCode config directory, then restart OpenCode:
| OS | Config dir |
|---|---|
| Linux / macOS | ~/.config/opencode/ |
| Windows | %USERPROFILE%\.config\opencode\ |
# example (Linux/macOS)
cd ~/.config/opencode
mkdir -p plugins
cp <clone>/plugins/token-meter.tsx plugins/
cp -r <clone>/plugins/token-meter plugins/
cp <clone>/tui.json ./tui.json registers the plugin:
{
"$schema": "https://opencode.ai/tui.json",
"plugin": ["./plugins/token-meter.tsx"]
}Restart opencode, open a session, send a message — the meter bar appears at the bottom of the screen.
bun install # or npm install
bun run typecheck # tsc -p tsconfig.json
bun run test # node plugins/token-meter/metrics.spec.tsThe code is split into a pure module (plugins/token-meter/metrics.ts, zero imports — runs directly under Node's type stripping) and the Solid JSX entry (plugins/token-meter.tsx) that wires it to the app_bottom TUI slot.
- Data source —
api.state.session.get()for the cumulative session aggregate,api.state.session.messages()for the newest assistant usage,api.state.providerfor the model context limit. - Context pressure — computed from the last assistant message that reports usage (
tokens.total ?? input + output + cache.read + cache.write), so it drops immediately after/compact; never the cumulative aggregate. - Refresh — re-renders on
message.updated,message.part.updated,session.updated,session.status,session.created, andtui.session.selectevents. - Design notes — see docs/design.md.
This project was vibe-coded: generated by the DeepSeek V4 Flash Free model running on OpenCode Zen, with human review and iterative verification (typecheck, smoke tests, and manual TUI checks).
It is derived from and inspired by
@deepseek-ai/dsh-token-meter
(MIT License, Copyright (c) 2026 DeepSeek — see NOTICE).
MIT © 2026 token-bar contributors