You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Orchestrator V2 branch (#2829) ships Pi as a first-class provider (from #7211), but the Usage page only knows Codex, Claude Code and Grok. Every Pi session — including the ones T3 itself drives — is invisible in cost, tokens and the model breakdown. For anyone running Pi as their main provider the dashboard reads $0 while the real spend is elsewhere.
The mechanism already fits: UsageService scans each provider CLI's own on-disk transcripts (~/.claude/projects, ~/.codex/sessions, ~/.grok/sessions), and Pi keeps the same kind of per-session JSONL under ~/.pi/agent/sessions/**/*.jsonl (PI_CODING_AGENT_DIR-aware), with per-message usage blocks (input / output / cacheRead / cacheWrite / cost / model / provider) that map 1:1 onto the existing UsageRecord.
What we have
We've been running the V2 branch daily with a small patch that adds Pi to the usage dashboard, since 2026-08-19, across five upstream rebases:
packages/contracts/src/usage.ts — "pi" added to UsageProviderKind.
apps/server/src/usage/usageTranscripts.ts + usageTranscriptReader.ts — Pi transcript reader (session header + message entries with usage), model normalised as <provider>/<model> so Anthropic-via-Pi and OpenAI-via-Pi rows stay distinguishable.
apps/server/src/usage/UsageService.ts — one driver === "pi" branch inside the existing per-provider-instance transcript-dir loop, resolving the home through the merged instance environment (same shape as the Codex/Claude branches).
apps/web/src/components/usage/usageProviders.ts — one presentation entry (driverKind: ProviderDriverKind.make("pi"), so it picks up the shared provider icon).
~400 lines including tests; no new dependencies, no schema/migration change (the usage contract version is untouched — pi is additive on the wire).
After
(Before = the same page with only the Codex and Claude Code rows and a $0.70 total; the Pi row and the Pi-served models in the breakdown are what the patch adds.)
Ask
Is this something you'd take as a PR against the V2 branch? Per CONTRIBUTING I'm asking here first rather than opening it cold. If yes I'll open it small and focused (the five files above + tests, before/after screenshots). If Pi-in-Usage is something you'd rather do yourselves or not at all, no problem — we'll keep carrying it locally.
For what it's worth, we double-checked the accounting while running this: UsageAggregator dedupes by provider message id across the whole scan before summing, so resumed Pi sessions (which repeat a shared prefix in a second transcript file) are counted once in the UI. The Pi reader emits the same dedupeKey shape as the other readers, so it inherits that correctly.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The gap
The Orchestrator V2 branch (#2829) ships Pi as a first-class provider (from #7211), but the Usage page only knows Codex, Claude Code and Grok. Every Pi session — including the ones T3 itself drives — is invisible in cost, tokens and the model breakdown. For anyone running Pi as their main provider the dashboard reads $0 while the real spend is elsewhere.
The mechanism already fits:
UsageServicescans each provider CLI's own on-disk transcripts (~/.claude/projects,~/.codex/sessions,~/.grok/sessions), and Pi keeps the same kind of per-session JSONL under~/.pi/agent/sessions/**/*.jsonl(PI_CODING_AGENT_DIR-aware), with per-messageusageblocks (input / output / cacheRead / cacheWrite / cost / model / provider) that map 1:1 onto the existingUsageRecord.What we have
We've been running the V2 branch daily with a small patch that adds Pi to the usage dashboard, since 2026-08-19, across five upstream rebases:
packages/contracts/src/usage.ts—"pi"added toUsageProviderKind.apps/server/src/usage/usageTranscripts.ts+usageTranscriptReader.ts— Pi transcript reader (session header +messageentries withusage), model normalised as<provider>/<model>so Anthropic-via-Pi and OpenAI-via-Pi rows stay distinguishable.apps/server/src/usage/UsageService.ts— onedriver === "pi"branch inside the existing per-provider-instance transcript-dir loop, resolving the home through the merged instance environment (same shape as the Codex/Claude branches).apps/web/src/components/usage/usageProviders.ts— one presentation entry (driverKind: ProviderDriverKind.make("pi"), so it picks up the shared provider icon).~400 lines including tests; no new dependencies, no schema/migration change (the usage contract version is untouched —
piis additive on the wire).After
(Before = the same page with only the Codex and Claude Code rows and a $0.70 total; the Pi row and the Pi-served models in the breakdown are what the patch adds.)
Ask
Is this something you'd take as a PR against the V2 branch? Per CONTRIBUTING I'm asking here first rather than opening it cold. If yes I'll open it small and focused (the five files above + tests, before/after screenshots). If Pi-in-Usage is something you'd rather do yourselves or not at all, no problem — we'll keep carrying it locally.
For what it's worth, we double-checked the accounting while running this:
UsageAggregatordedupes by provider message id across the whole scan before summing, so resumed Pi sessions (which repeat a shared prefix in a second transcript file) are counted once in the UI. The Pi reader emits the samededupeKeyshape as the other readers, so it inherits that correctly.All reactions