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
recordEngineUsage is called from exactly three places, all on the Coder path:
workers/api/src/workflows/coding-session.ts:347 and :645 (the Pilot)
workers/api/src/routes/coding.ts:691 and :1469 (capture / session end)
Every one is fed sanitizeEngineUsage(snap.usage), which originates in the stream-json result
event that packages/browser-runner/src/coding/headless.ts reads off the Claude Code child
process.
The terminal connector (packages/browser-runner/src/coding/terminal.ts, and the cloud-side workers/api/src/lib/connectors/terminal.ts / tmux.ts) contains no token or cost
instrumentation at all — grep -n "usage\|cost\|token" returns nothing. It drives a pane with terminal_send_keys and reads it back with terminal_capture; there is no structured event to
read a result from.
So a coding CLI running inside a tmux pane produces zero ai_usage rows. Not a low number —
no rows.
Why this matters right now
An A/B was just set up to compare the two drivers on the same repository:
Run as-is, the Usage page will show the tmux side costing a small fraction of the other, and a
reasonable person will conclude tmux is cheaper. It isn't cheaper, it is invisible. Same Claude
Code binary, same repo, same context — the transport does not change what is sent to the API.
This is the identical failure the Usage page already warns about for Codex and Grok ("deliberately
absent rather than shown as zero"), except here nothing warns about it, and it is about to be used
as the basis for a decision (#249).
OpenTelemetry export works on every setup and is the only option that streams per-user token
and cost metrics into your own observability stack in near real time.
The Session block at the top of /usage shows detailed token usage statistics for your current
session… The figures are approximate and computed from local session history on this machine.
Two transport-independent meters, then: OTel (real-time, push) and the local session history that /usage reads (after the fact, pull). Either measures the Claude Code process regardless of
whether PAGS talks to it over a pipe or a pane.
Fix
Do not show an unmetered driver as $0. Minimum viable honesty, and it should land before
any comparison is run: any session on a driver with no usage instrumentation is labelled unmetered, and its absence is stated on the Usage page the way Codex/Grok already are.
Meter it properly. OTel is the option the vendor endorses and the only one that works
across every engine and both drivers; reading the local session JSONL is the cheaper
after-the-fact alternative. Either would also fix Codex/Grok, which are unmetered today for the
same structural reason — no structured turn event.
Also, while here — the Repo Coder tells users it uses tmux
The engine setting on coder-repo is described as:
"Which CLI this agent drives in tmux."
It does not. headless.ts spawns the CLI as a child process over stream-json; tmux belongs to the
terminal connector. The string is in the seeded settingsSchema and shows on every Repo Coder
instance (Heartfull, FWS platform, PAS platform, FAS platform, FGS platform). Same class of
problem as #347: a surface asserting something the code does not do, which then gets believed.
Verification
A tmux-driven coding session is either metered or explicitly labelled unmetered — never silently
absent from a total.
The Usage page's "Not included" list names the terminal connector alongside Codex/Grok.
No settings copy claims the Repo Coder drives its CLI in tmux.
The gap
recordEngineUsageis called from exactly three places, all on the Coder path:workers/api/src/workflows/coding-session.ts:347and:645(the Pilot)workers/api/src/routes/coding.ts:691and:1469(capture / session end)Every one is fed
sanitizeEngineUsage(snap.usage), which originates in the stream-jsonresultevent that
packages/browser-runner/src/coding/headless.tsreads off the Claude Code childprocess.
The terminal connector (
packages/browser-runner/src/coding/terminal.ts, and the cloud-sideworkers/api/src/lib/connectors/terminal.ts/tmux.ts) contains no token or costinstrumentation at all —
grep -n "usage\|cost\|token"returns nothing. It drives a pane withterminal_send_keysand reads it back withterminal_capture; there is no structured event toread a
resultfrom.So a coding CLI running inside a tmux pane produces zero
ai_usagerows. Not a low number —no rows.
Why this matters right now
An A/B was just set up to compare the two drivers on the same repository:
f8ddc272-0390-4826-8812-94989e3d2ebd— Heartfull (Repo Coder)resulteventscda75e28-cace-4958-ac3e-6a7528e6b719— Heartfull (tmux) (tmux Operator)terminal_send_keysRun as-is, the Usage page will show the tmux side costing a small fraction of the other, and a
reasonable person will conclude tmux is cheaper. It isn't cheaper, it is invisible. Same Claude
Code binary, same repo, same context — the transport does not change what is sent to the API.
This is the identical failure the Usage page already warns about for Codex and Grok ("deliberately
absent rather than shown as zero"), except here nothing warns about it, and it is about to be used
as the basis for a decision (#249).
What the vendor docs offer
From Manage costs effectively:
Two transport-independent meters, then: OTel (real-time, push) and the local session history that
/usagereads (after the fact, pull). Either measures the Claude Code process regardless ofwhether PAGS talks to it over a pipe or a pane.
Fix
$0. Minimum viable honesty, and it should land beforeany comparison is run: any session on a driver with no usage instrumentation is labelled
unmetered, and its absence is stated on the Usage page the way Codex/Grok already are.
across every engine and both drivers; reading the local session JSONL is the cheaper
after-the-fact alternative. Either would also fix Codex/Grok, which are unmetered today for the
same structural reason — no structured turn event.
surface.
Also, while here — the Repo Coder tells users it uses tmux
The
enginesetting oncoder-repois described as:It does not.
headless.tsspawns the CLI as a child process over stream-json; tmux belongs to theterminal connector. The string is in the seeded
settingsSchemaand shows on every Repo Coderinstance (Heartfull, FWS platform, PAS platform, FAS platform, FGS platform). Same class of
problem as #347: a surface asserting something the code does not do, which then gets believed.
Verification
absent from a total.
Related
informed until item 1 lands.