Token totals include assistant messages, nested tool usage, compactions, and branch summaries across the session.
The token label uses input (↑) and output (↓) counts, plus the cache-hit percentage of the latest assistant prompt.
Cache-read and cache-write totals are deliberately absent: as raw counts they are unreadable, while the hit percentage carries the decision-relevant part.
Cache-hit percentage is prefixed with the cache icon.
No token usage shows ↑0.
Counts use k and M units; costs of $1000 or more use k as well.
Outside TUI mode the status text is spelled out, for example
in 1.6M, out 448k, cache hit 100%, turn $0.16, session $70.70, month $3.1k,
because other clients render the status line as text in an unknown font.
Without UI, nothing is published.
Uses provider-reported usage.cost.total when present and greater than zero.
If reported cost is zero or missing, estimates cost only for built-in zai and
minimax pricing rows.
Unknown provider/model prices produce $0 estimated cost.
Session cost is summed from assistant messages in the active branch.
Turn cost is the increase since the previous telemetry sync.
Monthly cost is summed from .jsonl session files whose names start with the
current YYYY-MM, scanning dirname(getSessionDir()) and its direct child
directories.
This includes persisted child sessions in those directories.
Startup and agent_end refreshes cache file subtotals by modification time and size, rereading only new or changed files.
Deleted files and previous-month entries leave the cache on refresh.
Overlapping refresh requests coalesce; shutdown and session replacement invalidate stale results.
Cost label shows turn cost, Σ session cost, and monthly cost.
Monthly cost is shown only when it is greater than session cost.
Cost label is hidden when all costs are zero.
Telemetry publishes only when UI exists.
Duplicate snapshots are skipped by signature.
Read/parse/update errors are swallowed so the agent loop keeps running.
Debug
Opt in through debug logging.
Safe events: session.start, session.shutdown, monthly.refresh.start, monthly.refresh.finish, monthly.refresh.error.
# cost
Token and spend telemetry for Pi.
## Install / load
Loaded through the root `pi-ext` package.
See [root README](../../README.md).
## Commands / tools / settings
Commands:
none.
Tools:
none.
Settings:
none.
Hooks:
- `session_start`:
reads current-month session files, resets counters, publishes first snapshot when UI exists.
- `agent_start`, `agent_end`, `tool_execution_end`:
refresh telemetry.
`agent_end` also schedules a background monthly refresh.
- `model_select`, `session_compact`:
clears snapshot signature, then refreshes telemetry.
- `session_shutdown`:
clears published status/footer segments.
Events emitted:
- `footer:segment` when `@bugabinga/pi-ext-footer` is loaded:
`tokens`, `cost` in the `llm` zone.
`tokens` uses `muted`, order `2`.
`cost` uses `success`, order `3`.
UI status:
- `cost` status fallback when shared footer is not loaded.
## Behavior
Shows cumulative session token usage, turn cost, session cost, and current-month cost.
Token totals include assistant messages, nested tool usage, compactions, and branch summaries across the session.
The token label uses input (`↑`) and output (`↓`) counts, plus the cache-hit percentage of the latest assistant prompt.
Cache-read and cache-write totals are deliberately absent: as raw counts they are unreadable, while the hit percentage carries the decision-relevant part.
Cache-hit percentage is prefixed with the cache icon.
No token usage shows `↑0`.
Counts use `k` and `M` units; costs of `$1000` or more use `k` as well.
Outside TUI mode the status text is spelled out, for example
`in 1.6M, out 448k, cache hit 100%, turn $0.16, session $70.70, month $3.1k`,
because other clients render the status line as text in an unknown font.
Without UI, nothing is published.
Uses provider-reported `usage.cost.total` when present and greater than zero.
If reported cost is zero or missing, estimates cost only for built-in `zai` and
`minimax` pricing rows.
Unknown provider/model prices produce `$0` estimated cost.
Session cost is summed from assistant messages in the active branch.
Turn cost is the increase since the previous telemetry sync.
Monthly cost is summed from `.jsonl` session files whose names start with the
current `YYYY-MM`, scanning `dirname(getSessionDir())` and its direct child
directories.
This includes persisted child sessions in those directories.
Startup and `agent_end` refreshes cache file subtotals by modification time and size, rereading only new or changed files.
Deleted files and previous-month entries leave the cache on refresh.
Overlapping refresh requests coalesce; shutdown and session replacement invalidate stale results.
Cost label shows turn cost, `Σ` session cost, and `` monthly cost.
Monthly cost is shown only when it is greater than session cost.
Cost label is hidden when all costs are zero.
Telemetry publishes only when UI exists.
Duplicate snapshots are skipped by signature.
Read/parse/update errors are swallowed so the agent loop keeps running.
## Debug
Opt in through [debug logging](../DEBUG.md).
Safe events: `session.start`, `session.shutdown`, `monthly.refresh.start`, `monthly.refresh.finish`, `monthly.refresh.error`.