What happened
Pi is a shipped provider on main since the Orchestrator V2 merge (#2829). The Usage page still never counts it. Every Pi session's tokens and cost are missing from the totals, the per-provider rows and the model breakdown. On a machine where Pi is the main provider, the dashboard shows only the other providers' spend, and nothing on the page says Pi was left out.
Diagnosis
The Usage pipeline is keyed by a closed provider list, and Pi is the only shipped CLI provider that is not on it:
packages/contracts/src/usage.ts: UsageProviderKind = claude, codex, grok, cursor, opencode, antigravity. There is no pi.
apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts ships PI_PROVIDER = ProviderDriverKind.make("pi"). Every other *AdapterV2 provider with on-disk transcripts has a usage reader. (acpRegistry is generic.)
apps/server/src/usage/UsageService.ts resolves transcript dirs per provider instance (driver === "codex", "claudeAgent", …). It has no Pi branch.
apps/web/src/components/usage/usageProviders.ts and apps/mobile/src/features/usage/usageProviders.ts have no Pi presentation entry.
The data is already on disk, in the same shape the existing readers consume. Pi writes one JSONL file per session under ~/.pi/agent/sessions/<cwd-slug>/*.jsonl (PI_CODING_AGENT_DIR-aware). The file starts with a session header line, followed by message entries. Each assistant message carries provider, model and a usage block (input, output, cacheRead, cacheWrite, cost.total). That maps 1:1 onto UsageRecord. This was verified on Pi 1.0.0, session format version: 3.
Steps to reproduce
- Run T3 Code built from
main, with the Pi provider enabled and logged in.
- Run a few turns in a Pi thread.
- Open Usage.
- There is no Pi row, and the totals and model breakdown exclude every Pi turn. The Pi session files under
~/.pi/agent/sessions/ contain the per-message usage blocks that should have been counted.
Version
main @ cc1e634 (V2 merged as de34391); the same on 0.0.46-preview.20261002.2598
Environment
macOS 26.6.2, Node 26.10.0, pi 1.0.0
Evidence
# main: the usage contract's provider list
$ git show main:packages/contracts/src/usage.ts | sed -n '/UsageProviderKind = /,/]);/p'
export const UsageProviderKind = Schema.Literals([
"claude",
"codex",
"grok",
"cursor",
"opencode",
"antigravity",
]);
# main: Pi is a shipped provider
$ git grep -n 'PI_PROVIDER =' main -- apps/server/src
apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts:97:export const PI_PROVIDER = ProviderDriverKind.make("pi");
# a Pi 1.0.0 session transcript line (assistant message, trimmed to the usage-relevant fields)
{"type":"message", "message":{"role":"assistant","provider":"anthropic","model":"claude-opus-5-5",
"usage":{"input":4,"output":260,"cacheRead":0,"cacheWrite":80557,"totalTokens":80821,"cost":{"total":0.649672}}}}
Related issues
Ideas discussion #12288 (2026-09-17) proposed this against the V2 branch before it merged, and got no replies. This issue reports the gap on main, now that Pi is a released provider. No existing issue covers it.
Fix applied or workaround
We have run a fix in our own build every day since 2026-08-19. It has been carried through 18 rebases of the V2 branch and now sits on main, as one commit on a clean branch:
It adds "pi" to UsageProviderKind, which is additive on the wire with no migration. It also adds a Pi transcript reader with an entry in the streaming USAGE_FIELDS selector, so oversized lines keep their usage. A driver === "pi" branch inside UsageService's per-instance transcript-dir loop resolves the Pi home through the merged instance environment. Web and mobile each get a presentation entry. It includes reader, aggregation and scan-cache tests.
The fix makes 13 files change, 463 insertions, no new dependencies. On that branch, server tsc is clean and the usage suites pass: 136/136 server, 64/64 web. Resumed Pi sessions that repeat a shared prefix in a second file are counted once, because the reader emits the same dedupeKey shape that UsageAggregator already dedupes on.
With the fix, the Usage page shows the Pi row and the Pi-served models:

Happy to open it as a focused PR if you want it.
Filed by
Pi (claude-opus-5-5) on behalf of @astarktc
What happened
Pi is a shipped provider on
mainsince the Orchestrator V2 merge (#2829). The Usage page still never counts it. Every Pi session's tokens and cost are missing from the totals, the per-provider rows and the model breakdown. On a machine where Pi is the main provider, the dashboard shows only the other providers' spend, and nothing on the page says Pi was left out.Diagnosis
The Usage pipeline is keyed by a closed provider list, and Pi is the only shipped CLI provider that is not on it:
packages/contracts/src/usage.ts:UsageProviderKind=claude, codex, grok, cursor, opencode, antigravity. There is nopi.apps/server/src/orchestration-v2/Adapters/PiAdapterV2.tsshipsPI_PROVIDER = ProviderDriverKind.make("pi"). Every other*AdapterV2provider with on-disk transcripts has a usage reader. (acpRegistryis generic.)apps/server/src/usage/UsageService.tsresolves transcript dirs per provider instance (driver === "codex","claudeAgent", …). It has no Pi branch.apps/web/src/components/usage/usageProviders.tsandapps/mobile/src/features/usage/usageProviders.tshave no Pi presentation entry.The data is already on disk, in the same shape the existing readers consume. Pi writes one JSONL file per session under
~/.pi/agent/sessions/<cwd-slug>/*.jsonl(PI_CODING_AGENT_DIR-aware). The file starts with asessionheader line, followed bymessageentries. Each assistant message carriesprovider,modeland ausageblock (input,output,cacheRead,cacheWrite,cost.total). That maps 1:1 ontoUsageRecord. This was verified on Pi 1.0.0, session formatversion: 3.Steps to reproduce
main, with the Pi provider enabled and logged in.~/.pi/agent/sessions/contain the per-messageusageblocks that should have been counted.Version
main@ cc1e634 (V2 merged as de34391); the same on 0.0.46-preview.20261002.2598Environment
macOS 26.6.2, Node 26.10.0, pi 1.0.0
Evidence
Related issues
Ideas discussion #12288 (2026-09-17) proposed this against the V2 branch before it merged, and got no replies. This issue reports the gap on
main, now that Pi is a released provider. No existing issue covers it.Fix applied or workaround
We have run a fix in our own build every day since 2026-08-19. It has been carried through 18 rebases of the V2 branch and now sits on
main, as one commit on a clean branch:It adds
"pi"toUsageProviderKind, which is additive on the wire with no migration. It also adds a Pi transcript reader with an entry in the streamingUSAGE_FIELDSselector, so oversized lines keep their usage. Adriver === "pi"branch insideUsageService's per-instance transcript-dir loop resolves the Pi home through the merged instance environment. Web and mobile each get a presentation entry. It includes reader, aggregation and scan-cache tests.The fix makes 13 files change, 463 insertions, no new dependencies. On that branch, server
tscis clean and the usage suites pass: 136/136 server, 64/64 web. Resumed Pi sessions that repeat a shared prefix in a second file are counted once, because the reader emits the samededupeKeyshape thatUsageAggregatoralready dedupes on.With the fix, the Usage page shows the Pi row and the Pi-served models:
Happy to open it as a focused PR if you want it.
Filed by
Pi (claude-opus-5-5) on behalf of @astarktc