A self-contained pi coding-agent extension that
tracks the agent's own token and cost usage and renders it as a /usage overlay
dashboard.
No core modifications, no auth-broker access, no external services. The plugin hooks the
provider-response lifecycle itself and persists every request as a session custom entry,
so the ledger survives /reload, compaction, and restarts.
- Total tokens (input / output / cache-read / cache-write, plus reasoning tokens when the provider reports them)
- Total cost in USD — computed by pi itself from the catalog model pricing (no price table is invented by this plugin)
- Per-model breakdown (request count, tokens, cost)
- Per-provider breakdown
- Time windows:
24h/7d/ all - Daily sparkline (last 14 days)
- Works headless: outside the TUI,
/usagefalls back to a one-line notification summary
No install step needed — point the extension loader at the compiled entry (or the
TypeScript source directly; pi loads .ts extensions natively):
pi -e ./pi-usage/dist/index.js
# or, from source:
pi -e ./pi-usage/src/index.ts(-e/--extension is repeatable.)
Copy the plugin into a trusted extension location and reload:
~/.pi/agent/extensions/(global).pi/extensions/(project-local)
mkdir -p ~/.pi/agent/extensions/pi-usage-ledger
cp -r pi-usage/dist ~/.pi/agent/extensions/pi-usage-ledger/package.json declares the extension under pi.extensions (./dist/index.js), so the
directory is a valid pi package. To install from npm or git, see
packages.md.
Run /usage. An overlay dashboard opens (TUI mode):
| Key | Action |
|---|---|
1 / 2 / 3 |
Switch window: 24h / 7d / all |
← / → |
Cycle window |
esc / ctrl+c / enter |
Close |
The extension event after_provider_response does not carry token or cost data — its
payload is only the HTTP status and response headers. The authoritative per-request usage
arrives on the finished assistant message: the agent loop emits message_end with an
AgentMessage snapshot whose usage field (from @earendil-works/pi-ai) carries the full
token breakdown (input, output, cacheRead, cacheWrite, totalTokens, reasoning)
and usage.cost (input/output/cacheRead/cacheWrite/total in USD) — pi
computes cost from catalog model pricing. This plugin hooks pi.on("message_end").
Each qualified request is appended as a session custom entry:
pi.appendEntry("pi-usage.record", record);Custom entries (CustomEntry) are excluded from LLM context and are kept across reloads and
compaction. The /usage command rebuilds the full ledger from the session branch:
for (const entry of ctx.sessionManager.getBranch()) {
if (entry.type === "custom" && entry.customType === "pi-usage.record") { … }
}{
v: 1, // schema version
ts: number, // request start (Unix ms)
provider: string, // e.g. "anthropic", "openai", "openrouter"
model: string, // e.g. "anthropic/claude-sonnet-4-5"
stopReason?: string, // e.g. "stop" | "length" | "toolUse"
usage: { input, output, cacheRead, cacheWrite, totalTokens, reasoningTokens? },
cost: { input, output, cacheRead, cacheWrite, total } // USD
}- Every finished assistant message with
stopReason !== "error"and reportedtotalTokens > 0is recorded — including truncated (length) and aborted responses that consumed tokens. - Requests with zero reported usage (error placeholders, providers without usage reporting) are not recorded: the plugin never fabricates token or cost numbers.
- Cost shows
$0.00 (pricing n/a)when tokens were reported but pi had no pricing for the model; the plugin does not invent a price table. - The ledger is per session: each session file accumulates its own records (subagent sessions run their own extension runners against their own session files).
npm install # devDeps: @earendil-works/pi-coding-agent, @earendil-works/pi-tui
npm run build # tsc → dist/index.js + dist/index.d.ts
npm run typecheckMIT