Model usage analytics for pi
Track token & cost usage by model, project, and session — daily / weekly / monthly / 6-monthly / yearly — in an interactive TUI dashboard. Optional budgets fire a warning when a threshold is crossed.
⚠️ This project is no longer maintained. Issues, pull requests, discussions, and support requests are not actively monitored.
pi-tracker is a pi extension that turns every assistant turn into a record and gives you a live, drill-down analytics view:
- Capture — every finalized assistant message (
message_end) is logged with its token breakdown and cost. - Pivot — group by model, project, or session, across 6 time windows.
- Drill down — pick a model to see which projects use it, then which sessions, then back up. A breadcrumb keeps your bearings.
- Budgets — set token/cost limits per scope & period; get warned at a threshold and again when exceeded.
- Back-fill — import your full pi session history on day one so you start with real data, not an empty log.
pi-tracker — Model usage
window: All Time • 37 model(s) • filter: —
Model usage tokens cost turns
──────────────────────────────────────────────────────────────────────────────────
▶ anthropic/claude-opus-4-8 ████████████████████ 1,844,364,365 $2388.42 6155
openai-codex/gpt-5.5 ██░░░░░░░░░░░░░░░░░░ 1,212,486,248 $2096.32 10475
zai-anthropic/glm-5.2 ████████████████████ 14,798,725,266 n/a 4621
──────────────────────────────────────────────────────────────────────────────────
Total 17,855,575,879 $4484.74 21251
[1-6] window [d] dimension [enter] drill in [u] back [↑↓] move [q] close
n/a = that provider didn't return pricing (e.g. a model without published
costs), not $0.
pi-tracker is a pi package. Install it with pi directly:
pi install npm:pi-tracker
Or, from source (for development):
git clone git@github.com:alpertarhan/pi-tracker.git
cd pi-tracker && npm install
ln -s "$(pwd)" ~/.pi/agent/extensions/pi-trackerRestart pi (or /reload) and run /analytics. Then back-fill your history:
/analytics import
That scans ~/.pi/agent/sessions/ and recovers all past usage (idempotent —
safe to re-run).
In the TUI, running /analytics with no arguments opens an interactive main
menu — pick from:
- Dashboard — the analytics view
- Footer preset — pick what shows in the footer
- Budgets — view & add budgets
- Import history — back-fill from pi sessions
- Help — full command reference
Arguments still work directly for power users (see below).
Opens the interactive dashboard. Keys:
| Key | Action |
|---|---|
1–6 |
switch window (today / week / month / 6mo / year / all) |
d |
cycle grouping dimension (model / session / project) |
↑ ↓ |
move cursor (auto-scrolls) |
enter |
drill into the cursor row — pivot to the next dimension |
u / backspace |
pop the last filter (go back up a level) |
q / esc |
close |
Back-fill analytics from pi session history. Idempotent.
Show live analytics in pi's footer status line. Without an arg, opens a
SelectList picker; with an arg, sets it directly. Choice persists across
sessions (footer.json). The status refreshes on every assistant turn.
| Preset | Shows | Example |
|---|---|---|
off |
nothing | — |
today-tokens |
tokens used today | 📊 1.2M today |
today-cost |
USD spent today | 📊 $4.32 today |
budget |
most urgent budget + ⚠ | 📊 $4.32/$10.00 (43%) |
model |
top model today + turns | 📊 glm-5.2 · 23 turns |
When a budget is at/over its warn threshold, the budget preset shows ⚠.
View configured budgets. Add new ones two ways:
- Interactive (TUI):
/budget add— SelectList flow. - Args:
/budget add <scope> <period> <metric> <max> [warn]
scope: global | session | project (project uses the current cwd)
period: day | week | month | year
metric: cost | tot | in | out
max: positive number (USD if metric=cost, else tokens)
warn: fraction 0..1, default 0.8
- Data source — the
message_endevent is the only place token usage appears (event.message.usage).after_provider_responsehas only HTTP status. - Storage — append-only JSONL. O(1) write, zero dependencies, crash-safe. An in-memory accumulator (rebuilt once per session, updated incrementally) keeps per-message budget checks O(budgets) instead of O(log).
- Cost awareness — each record tracks whether the provider returned
pricing (
costKnown). A model row showsn/awhen none of its turns had pricing, and$as soon as any does.
~/.pi/agent/analytics/
├── usage.jsonl append-only raw log (one record per assistant message)
├── budgets.json budget limit config (optional)
├── warned.jsonl append-only dedup keys for fired warnings (resets per period)
└── footer.json chosen footer preset (optional)
Clean, layered, dependency-injected — dependencies point inward only:
src/
domain/ pure rules — ZERO dependencies (no fs, no pi)
types.ts data contracts (UsageRecord, BudgetLimit, …)
time.ts periodKey / windowStartMs / isoWeekKey
aggregate.ts aggregate / sumRows / dimensionKey
budget.ts budgetKey / statusForLimit / recordMatchesLimit
enums.ts DIMENSIONS / WINDOWS
format.ts fmtNum / fmtCost / fmtBar / padRight
session-parser.ts parse pi session history → UsageRecords
storage/ infrastructure — implements the ports
ports.ts UsageStore + ConfigStore interfaces (total, never throw)
jsonl-store.ts concrete JSONL/file adapter (real fs)
memory-store.ts in-memory fake (tests)
app/
accumulator.ts in-memory read-side cache (takes UsageStore)
ui/
dashboard.ts pure view — data injected, NO I/O during render, drill-down
budget-add.ts interactive /budget add flow (SelectList)
pi-tracker.ts composition root — wires pi events to the layers (DI seam)
index.ts re-exports factory for pi's dir-based discovery
There's a check:layers guard that enforces this in CI.
Why this shape: the domain layer has no deps, so it's unit-tested directly; storage is exercised through ports with an in-memory fake (no disk); the view never touches storage during render; every storage method is total (never throws) so a disk fault can't crash pi.
npm install
npm test # unit tests (pure domain + store fake)
npm run typecheck # typecheck (strict + unused checks)
npm run check:layers # architectural layer guard
npm run smoke # runtime smoke (DI + capture + render)
npm run ci # all of the above (what CI runs)See CONTRIBUTING.md for the full guide.
This project is no longer actively maintained, so issues, discussions, and pull requests are not monitored. Existing documentation remains available for historical reference.
MIT © Alper Tarhan