pi-tokenburn

Pi extension for live token usage monitoring and budget tracking (hour / day / week / month / year / all). 0 prompt tokens.

Packages

Package details

extension

Install pi-tokenburn from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-tokenburn
Package
pi-tokenburn
Version
0.8.2
Published
Nov 2, 2026
Downloads
2,793/mo · 411/wk
Author
greenspand
License
MIT
Types
extension
Size
126.3 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/tokenburn.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-tokenburn

npm npm downloads CI License: MIT Audit Fuzz

Token usage and cost monitor with budgets, directly in your Pi session.

TypeScript port of the pi collector from tokenburn. Reads Pi's local session logs (~/.pi/agent/sessions/**/*.jsonl). No network, zero prompt tokens. Totals match the tokenburn CLI exactly.

Features

  • Status bar: 🔥 1.2M ($5.10) [today] · 52k/h · 95% hit · ~$12.40 saved: tokens, cost, burn rate, cache hit ratio and estimated savings (prompt cache, plus pi-context-diet and pi-squeeze when installed) for the chosen period (each extra toggleable). Turns red with OVER BUDGET past your limit.
  • Tables: usage per model, provider, project and session, for any period, with cache hit %, savings, cost and share.
  • Filter and export: limit everything to a provider, model or project; write csv or json.
  • Pricing: a price table fills in (or overrides) costs the logs don't have.
  • Report chart: /tokenburn shows the summary plus a vertical column chart (y-axis, budget line, current period marked, over-budget columns in red, peak/avg footer). Daily (14 days), weekly (8 weeks), monthly (6 months), yearly (5 years) or all-time.
  • Status line: /tokenburn hour|day|week|month|year|all (or cycle) changes the period shown at the bottom. Charts live under /tokenburn chart <view>.
  • Window panel (optional): Today / Week / Month / Year / Total below the editor, with in/out tokens and cost.
  • Budgets per day, week and month, in tokens and/or dollars.
  • Live: the bottom line updates after every assistant message, not only when a turn ends, at no measurable cost (see Performance).
  • Fast: per-file cache keyed on mtime+size. First scan of ~400 MB of sessions takes under a second; refreshes after that take milliseconds. Refresh never blocks the agent loop.

Install

From npm:

pi install npm:pi-tokenburn

Or from git:

pi install git:github.com/sorinirimies/pi-tokenburn

Commands

Command What it does
/tokenburn hour|day|week|month|year|all Switch the bottom status line: last 60 minutes, today, this week (from Monday), this month, this year, or the all-time total. today and total work as aliases of day and all
/tokenburn chart <view> Report + chart. Views: day (14 days), week (8 weeks), month (6 months), year (5 years), all (whole history; monthly columns up to 18 months, yearly beyond)
/tokenburn Report + daily chart (same as /tokenburn chart day)
/tokenburn cycle Rotate the status line: hour → today → week → month → year → total
/tokenburn status <hour|today|week|month|year|total> Explicit form of the first row
/tokenburn models hour|day|week|month|year|all Table of usage per model (tokens, in/out, cache hit %, cache savings, cost, share). period (optional, default all): hour (rolling last 60 min), day (since local midnight), week (since Monday), month, year, all. Optional provider=x, model=x, project=x (substring, this call only) narrow any table, e.g. models week provider=anthropic
/tokenburn providers hour|day|week|month|year|all Same table per provider; same period and filter arguments
/tokenburn projects hour|day|week|month|year|all Same table per project (session working directory)
/tokenburn sessions hour|day|week|month|year|all Leaderboard of the n costliest sessions: add a number for n (default 10), e.g. sessions week 5 (top is an alias)
/tokenburn session Spend of the current session, and its share of today
/tokenburn filter <provider|model|project> <value> Limit everything (status line, report, tables, export) to matching usage (case-insensitive substring). filter shows it, filter all clears it
/tokenburn export csv|json Optional [period] and [path] follow the format. Writes one row per day × provider × model × project (default tokenburn-<period>.<format> in the current directory)
/tokenburn warn <pct> Notify once when a budget reaches pct percent (default 80) and once when it is exceeded
/tokenburn rate Toggle the burn rate in the status line (42k/h: tokens per hour averaged over the status period)
/tokenburn hit Toggle the cache hit ratio (95% hit) in the status line
/tokenburn saved Toggle the estimated savings (~$12.40 saved: prompt cache, pi-context-diet, pi-squeeze) in the status line
/tokenburn pricing Where costs come from (session logs vs your price table) and which models are unpriced
/tokenburn price <model> <in> <out> Set a price in $ per million tokens (key model or provider/model); price remove <model> deletes it. pricing mode <fill|override>: use the table only where the log has no cost (default), or always
/tokenburn window Toggle the panel below the editor
/tokenburn budget <day|week|month> <tokens> Token budget, e.g. budget day 5000000
/tokenburn budget <day|week|month> $<cost> Dollar budget, e.g. budget week $50
/tokenburn cache Toggle counting cache read/write tokens
/tokenburn live Toggle refreshing after each assistant message (on by default)
/tokenburn disable (off) Turn tokenburn off: status line and panel cleared, nothing runs in the background. chart still works on demand
/tokenburn enable (on) Turn it back on. Both are remembered across sessions

Previews

Recorded from a real pi with only this plugin loaded, on synthetic data.

Switch what the bottom line shows (/tokenburn hour, day, week, month, year, all, or cycle):

Status line: week, month, year, all, day, then cycle through every period

Charts (/tokenburn chart day|week|month|year|all): the current period is green, with a peak and average footer:

Charts: day, week, month, year and all-time

Budgets (/tokenburn budget day 150000, budget week $2.5): the footer turns red past the limit, and the chart draws the budget line with over-budget columns in red:

Budgets: OVER BUDGET in the footer and red columns in the chart

Live refresh: the footer updates after every assistant message, not only when a turn ends (here a local mock model answers; pi writes the turn to its session log and the counter moves by itself):

Live refresh: the counter and cost tick up as the reply lands

Enable / disable: off means off (nothing runs in the background), and charts still work on demand:

Disable clears the footer, a chart still works, enable brings it back

Tables (/tokenburn models week, providers month, projects, sessions week 5): who spends what, with cache hit %, estimated savings and share:

Tables: models, providers, projects and sessions

Filter and export (/tokenburn filter model acme-large, export csv week usage.csv): the footer, tables and the file all follow the filter:

Filter to one model, see it in the table, export csv, clear the filter

Footer extras (/tokenburn hour, rate, hit, saved): the burn rate, cache hit ratio and cache savings follow the chosen period, and each can be switched off:

Footer: hour and week periods, rate, hit and saved toggled off and on

Pricing (/tokenburn pricing, price acme-large 3 15 0.3 3.75): where costs come from, and a price table that can fill in or override them:

Pricing: cost sources, set a price, switch to override

Tab-completion uses pi's own menu, with a description for every option:

Autocomplete for /tokenburn and its chart sub-menu

Tab-completion works for all of these. Unknown input prints usage instead of failing. report <view> is kept as an alias of chart <view>.

Chart example (/tokenburn chart day, with a 150k day budget):

Daily tokens · last 14 days  ┄ budget 150.0k
 291.9k │                                 ██ ▄▄    
        │                                 ██ ██    
        │      ▃▃          ▅▅             ██ ██    
        │┄┄┄┄┄┄██┄┄┄┄┄┄┄┄┄┄██┄┄┄┄┄┄┄▆▆┄┄┄┄██┄██┄▅▅┄
 146.0k │      ██          ██       ██    ██ ██ ██ 
        │      ██    ▂▂ ▇▇ ██       ██ ▇▇ ██ ██ ██ 
        │▁▁    ██    ██ ██ ██       ██ ██ ██ ██ ██ 
        │██ ▇▇ ██ ▅▅ ██ ██ ██ ▃▃ ▁▁ ██ ██ ██ ██ ██ 
        └──────────────────────────────────────────
         26 27 28 29 30 01 02 03 04 05 06 07 08 09 
         Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr 
                                                ▲  
Σ 1.74M ($4.81) · avg 124.4k/day · peak 291.9k (10-07 Wed)

Weeks start on Monday, in local time.

Config

~/.pi/agent/tokenburn.json (written by the commands, editable by hand):

{
  "enabled": true,
  "liveRefresh": true,
  "refreshMs": 750,
  "includeCache": true,
  "chartColor": true,
  "showStatus": true,
  "showWidget": false,
  "statusWindow": "today",
  "showRate": true,
  "showHit": true,
  "showSaved": true,
  "warnPct": 80,
  "filter": { "model": "acme-large" },
  "prices": { "acme-large": { "input": 3, "output": 15, "cacheRead": 0.3, "cacheWrite": 3.75 } },
  "priceMode": "fill",
  "budgets": { "dayTokens": 5000000, "weekCost": 50 }
}
  • enabled (default true): master switch, same as /tokenburn enable|disable.
  • liveRefresh (default true): refresh after each assistant message. false = only when a turn ends. refreshMs (default 750, range 250 to 60000) is the coalescing delay.
  • includeCache (default true): count cache read/write tokens in totals, like the tokenburn CLI. Cache reads dominate (often 95%+ of tokens) but are billed far cheaper; set false to budget on input + output only.
  • chartColor (default true): color the chart using your pi theme (current period green, over-budget red, budget line yellow). Set false for plain text.
  • showStatus / showWidget (defaults true / false): the bottom status line and the panel below the editor.
  • statusWindow (default today): the status-line period, one of hour, today, week, month, year, total.
  • showRate / showHit / showSaved (default true): the burn rate, cache hit ratio and estimated savings in the status line.
  • warnPct (default 80): notify once at this budget percentage and once when exceeded; 0 turns it off.
  • filter: only count usage whose provider, model or project contains the value (case-insensitive); set by the filter command.
  • prices / priceMode (default fill): price table in $ per million tokens, used where the log has no cost (fill) or always (override); set by the price command.
  • budgets: dayTokens, weekTokens, monthTokens, dayCost, weekCost, monthCost.

Environment overrides for the session directory: TOKENBURN_PI_SESSIONS, PI_CODING_AGENT_SESSION_DIR, PI_CODING_AGENT_DIR.

Performance

Refreshing is designed to cost nothing you can notice:

  • Incremental: pi's session logs are append-only, so after the first parse only the bytes added since then are read (with a cheap integrity check that falls back to a full parse if a file was rewritten or truncated). On a 35 MB active session a refresh after one new message takes ~1.2 ms, down from ~18 ms, and the cost no longer grows with the session.
  • Fast start: pi waits for nothing: the first refresh runs in the background. The parse state is saved in tokenburn-cache.json (pi's agent dir, at most once a minute and at shutdown), so a new pi run reads only what was appended since; on a 2.4 GB session history the status line appears in ~40 ms instead of ~4 s, and pi starts ~5 s sooner. Delete the file any time: the next start parses everything once.
  • Coalesced: a burst of messages triggers one refresh (trailing delay, refreshMs), never two at once.
  • Never blocks: refreshes are fire-and-forget and errors are swallowed; the timer is unref'd and cancelled at shutdown.
  • Off means off: /tokenburn disable (or "enabled": false) reads no files and starts no timers.

Demo recordings

The GIFs above live in examples/vhs/generated/ and are stored with Git LFS (git lfs install once). They are recorded with VHS from a real pi that loads only this extension, on synthetic data (examples/vhs/fixture.sh: 900 days of made-up sessions across fictional projects, providers and models in /tmp, with deliberately small numbers, and a local mock model for the live-refresh demo), never from real logs, paths or credentials:

just vhs-all          # every tape (examples/vhs/*.tape): needs vhs, ttyd, ffmpeg, pi, bun, python3
just vhs-tape charts  # one tape
just vhs-list         # list the tapes
just demo             # try it yourself in a real pi on the same synthetic data

Security notes

  • Local. It reads pi's session logs, its own tokenburn.json and the savings logs of pi-context-diet / pi-squeeze, and writes only tokenburn.json and its parse cache tokenburn-cache.json. Nothing leaves your machine: no network, no telemetry, no shell commands, zero runtime dependencies.
  • Never breaks pi. Stats refreshes are fire-and-forget and swallow their own errors, so a failure here cannot interrupt a turn or a session start.
  • Hand-edited config is sanitised. Unknown or non-numeric budget values are dropped.

Development

bun install
just check          # typecheck + tests + pack check + nushell tests (what CI runs)
just test           # bun test only (with coverage)
just coverage       # tests + a coverage table
just push-all       # push main to every configured remote (origin + the Gitea instances)
just --list         # everything else: pull-all, push-tags-all, release-all, sync-gitea-*, the *-force variants

Coverage: every bun test collects coverage (bunfig.toml) and fails below 95% lines / 95% functions. CI shows the table on the run page and uploads lcov.info.

Code layout

One folder per feature under extensions/features/, each with its logic and its /tokenburn commands:

extensions/
  tokenburn.ts            wiring only: pi events + the /tokenburn command
  core/                   types, config, session-log parser (incremental cache, saved between runs), aggregation, filters + prices, paint
  command/                parse + completions (pure), handler table, the Host handlers receive
  features/
    status-line/          footer text, optional panel, burn rate / cache hit / savings
    report/               the /tokenburn summary and the column charts
    budgets/              budgets, projection ("runs out Thu 14:05"), one-time warnings
    breakdown/            tables per model / provider / project / session, current session
    filter/               limit everything to a provider / model / project
    pricing/              cost sources, price table
    export/               csv / json
    live/                 refresh scheduling

To add a command: add its kind to command/parse.ts, a handler in the owning feature's commands.ts (the Handlers type makes a missing one a compile error), and a test.

CI scripts are nushell (scripts/), the same ones locally and in GitHub / Gitea Actions. just --list shows every task.

Releases (automatic)

Workflow When What
CI push / PR quality gate on Linux; tests on macOS and Windows, and in extreme time zones
Fuzz nightly (GitHub 04:00 UTC, Gitea 04:30), and when the extension changes seeded randomised robustness tests (tests/fuzz.test.ts), 200 000 runs per property nightly (5 000 when the extension changes; just fuzz [iterations] [seed] locally); a failure prints the seed that reproduces it
Security nightly (GitHub 03:00 UTC, Gitea 03:30), and when dependencies change bun audit: fails on any known vulnerability
Auto-merge library updates CI finished on a Dependabot PR patch and minor updates (GitHub Actions) are merged automatically, but only after CI is green on that exact commit; a major update waits for you. Needs the GH_PAT secret: action bumps change .github/workflows/*, which GITHUB_TOKEN may not merge
Gitea Actions Update Mondays 03:15 UTC Gitea has no Dependabot: moves the sha pins in .gitea/workflows to the newest release of the same major and commits ci(deps); a new major is only reported
Nightly Dependency Update every night (GitHub 02:00 UTC) and after each auto-merge bun update within ranges, verify on all platforms, commit chore(deps); then build, tag and publish a new patch whenever a library was upgraded or merged, or feat/fix/perf commits are waiting since the last tag
Mirror GitHub (Gitea) hourly Gitea has no nightly of its own: fast-forwards its main to GitHub's and pushes the new tags (starting Gitea's release for each), so the hosts never diverge; fails loudly if they did
Release tag vX.Y.Z, or run it with a bump validates the tag against package.json, runs the gate, npm publish (idempotent, with provenance), creates the release

So library updates need no human: they are merged once CI passes, built, versioned and published as a patch. A downgrade, a failing check, or a major update stops the chain and waits for review.

Release from CI: Actions → Release → Run workflow with a bump (patch, minor, major), or just release-ci minor: runs the gate, bumps, writes the changelog, tags, pushes and publishes. Manual release: just release patch (or minor / major / X.Y.Z) bumps, tags and pushes to GitHub; just release-all patch pushes to every configured remote; just push-release-all pushes an existing bump.

Secrets (repo settings): NPM_TOKEN is an npm granular access token with publish rights and "bypass 2FA" (required for CI publishing). GH_PAT (classic PAT, repo + workflow: needed to auto-merge GitHub Actions bumps; also lets a tag push trigger the release itself). Optional: GITEA_TOKEN (Gitea).

Commits follow Conventional Commits; the changelog is generated by git-cliff.

Scope

Pi sessions only. For Zed, Claude Code, Codex, Gemini and more, use the Rust tokenburn.

Related plugins

Four small pi extensions that save tokens without adding anything to the system prompt:

Plugin What it does
pi-edit-first Blocks whole-file write rewrites and hand-written project manifests, steering the agent to targeted edit calls and scaffolders
pi-read-guard Blocks full reads of large files, steering the agent to offset/limit or search
pi-tokenburn Live token and cost counter in pi's footer, with charts and budgets
pi-context-diet Drops stale tool results from the context when the prompt cache is already cold, so long sessions cost less
pi install npm:pi-edit-first
pi install npm:pi-read-guard
pi install npm:pi-tokenburn
pi install npm:pi-context-diet

MIT