Skip to content

Latest commit

 

History

History
94 lines (64 loc) · 5.26 KB

File metadata and controls

94 lines (64 loc) · 5.26 KB

@pify/usage

Token and cost reporting for pi sessions — a live footer, a /usage dashboard, and an agent-callable status tool. Local by default: no network calls, and no LLM tokens spent asking about tokens.

Part of the Pify suite. Install with pify install usage or pi install npm:@pify/usage.

Why

Spend is invisible until the invoice arrives, and by then you cannot tell which session did it. Everything needed to answer that is already on disk — pi writes usage and cost into every session file — so the answer should cost nothing to produce.

Live footer

📊 12.3k tok · $0.45

Folded from each message's usage.cost, which pi already computes. It survives /reload by replaying the session branch rather than keeping a running total in memory.

/usage

Session
  tokens   in 120.3k · out 8.2k · cache 1.1M read / 0 write
  cost     $0.45 (23 responses)
  context  ~34% of the window

History (214 local session files)
  today    $1.23 · 450.2k tok
  7 days   $8.90 · 3.2M tok
  30 days  $21.40 · 9.8M tok
By model (all time)
  anthropic/claude-fable-5  $12.30 · 4.1M tok
  openai/gpt-5.5            $9.10 · 5.7M tok
By project (all time)
  D--project-pify-plugins   $14.80 · 6.2M tok
  D--project-shop-api       $6.60 · 3.6M tok

History counts every usage-bearing entry in pi's session JSONL — assistant turns plus the tool-result and compaction usage pi persists — so a session's total matches what you were billed rather than what the visible messages add up to. Negative and NaN fields clamp to zero, days are your local calendar days, and a per-file mtime cache keeps repeat scans instant.

Per-project totals come for free: pi stores sessions one directory per project, so the dashboard can show where the money actually went.

/usage context

Context window: 22.6k of 200.0k used (11%)
  System prompt     ····························  <1%  11
  Context files     ····························   1%  3.0k
  Tool definitions  ····························  <1%  371
  Tool results      ██··························   8%  16.8k
  Conversation      ····························   1%  2.4k
  Free space        █████████████████████████···  89%  177.4k

"Why am I at 60%?" usually has a boring answer — one read of a 4,000-line file — and this is where you find it.

Computed entirely from what pi already holds: the assembled system prompt, the files and skills embedded in it, the enabled tool definitions, and the entries that would be sent. No network, no model call.

Context files and skills are counted only when their text is genuinely embedded in the prompt, and the system-prompt row is the remainder after subtracting them, so the rows sum to the whole instead of double-counting. When the provider reports more than can be attributed, the difference is shown as Other rather than quietly dropped.

/usage quota

The one command here that touches the network, and only when you run it:

Quota (OpenRouter · sk-or-v1-abc...xyz)
  spent    $0.33 (no credit limit on this key)
  window   day $0.01 · week $0.33 · month $0.33

Quota (DeepSeek · granted 10 · topped up 100)
  balance  CNY 110.00

Documented endpoints only. OpenRouter's /api/v1/key and DeepSeek's /user/balance are published APIs that report a real balance. The subscription-quota endpoints available for some other providers are undocumented private APIs reverse-engineered from vendor CLIs — they break without notice and were never offered to third parties, so this package does not call them. A provider you have not configured is simply not shown; that is not a failure.

A credentialed request is pinned down, because it carries your provider key:

  • HTTPS only, and the host must be on that provider's allowlist.
  • Redirects are refused outright. Following one lets whatever answered choose where the next request goes, with the header already attached.
  • A non-2xx body is never read. Error bodies echo request details back, and an echoed Authorization header pasted into a notification is exactly the leak this must not cause — the status alone becomes the message.
  • Raw exception text is dropped rather than shown, and everything printed passes a redactor as a last line of defence.
  • An 8-second timeout per provider; any failure renders as unavailable — the provider rejected the key rather than throwing.

The key comes from pi, resolved through modelRegistry rather than by reading auth.json. pi owns credential storage — env precedence, OAuth, whatever it grows next — and parsing that file here would mean handling secrets this package has no business touching, using a stale copy of pi's rules. Only the provider's own masked label is ever printed.

Tool

usage_status

No parameters. Returns session and today's totals, so the agent can check the cost before committing to expensive work — a wide subagent fan-out, a large read — instead of finding out afterwards.

License

MIT © Pify maintainers