Agent spend and agent work per engineer, across every coding agent #188
Build what g1t needs so a team can see agent spend and agent work per engineer, across every coding agent it uses, as well as or better than the products that already sell this. The research is done, and this item is the plan to build from it.
Read first
docs/research/agent-spend-per-engineer.md(committed 2026-10-18). It covers:- what each agent exposes (OTel, admin APIs, local files, hooks), with sources;
- what LinearB, Jellyfish, DX, Swarmia, Faros, Span, Weave, Waydev, Exceeds, Opsera, Cursor's and Copilot's dashboards and RadiantOps show, and what they charge;
- the privacy model;
- the ranked plan, each step with its exact endpoint, telemetry field or file.
apps/docs/src/content/docs/guides/home.md: Home after #167 (Ask first, Your move beside Live, This week day by day, then Since you were here).
Where things stand (2026-10-18)
- Spend comes from three places:
- g1t's metered agent runs (billing usage).
- Claude Code sessions.
plugins/claude-code/hooks/g1t.mjsreads the transcript'smessage.usageand sendsg1t session heartbeat --usage-json(CLI 0.4.1, plugin 0.3.1). The work service prices the usage withcrates/contracts/src/model_prices.rs, which has only Anthropic list prices, and storessessions.usageandsessions.cost_usd. - Provider cost reports (
services/billing/src/provider_costs.rs), which cover the whole organization and are never per user.
- Codex now has hooks: SessionStart, Stop, SubagentStop and SessionEnd, each carrying
transcript_pathandmodel.plugins/codexuses none of them. - Home's Live panel shows each live session's cost so far, but there's no per-person spend view anywhere. Members see each other's
sessions.cost_usd, while prompts stay with their author (services/work/src/coordination/shown.rs). - In a one-person, direct-push workspace like flagon-io, most findings never show. See the table in the report's "Where g1t stands".
The plan, in order
Open a work item for each step as you start it (g1t work claim --title "…"), linked to this one, with one pull request per step.
-
Check that session cost arrives. Every session recorded on 2026-10-18, subagents included, came back from coordination with
cost_usd: nullafter it ended. For a real session and its subagents, comparesessions.usageandcost_usdwith their transcripts. Find out whether the coordination payload leaves cost out, or whether usage fromSubagentStop/SessionEndnever arrives. Fix whatever is wrong before anything else. -
Spend for direct pushes and solo workspaces.
quarterSpendinapps/web/app/lib/signals.tsdrops sessions that aren't tied to a pull request. Group them by the work item their push closed (pushed.rstrailer_session), and otherwise by repository.- Allow a single group when the workspace has one person.
1b. Findings for one person, each measured against your own last four weeks:
- spend that never landed;
- cost per landed change;
- cache efficiency, from
sessions.usage; - the week's most expensive session and what it produced.
Scale the rework and gone-quiet thresholds to the workspace's volume.
-
A "Your spend" view and spend by person, with the report's privacy model:
- everyone sees their own spend in full;
- no leaderboards;
- a workspace setting
spend_visibility: owners (the default), members or nobody; - no rollup that covers fewer than 3 people.
Build the work service query over
sessions, withsession_linksandsession_touches, plus a-/spendroute andg1t spend. -
Codex cost.
- Add
plugins/codex/hooks.json. - Read
info.total_token_usagefrom the lastevent_msgtoken_countintranscript_path(.jsonland.jsonl.zst). - Add OpenAI list prices to
model_prices.rs. - Mark ChatGPT-plan sessions (
rate_limits.plan_type) as an estimate.
- Add
-
Check each person's spend against the provider.
- Anthropic:
GET /v1/organizations/usage_report/claude_code(per actor email, per day,estimated_costper model). - OpenAI:
/v1/organization/costs?group_by=user_id. - Add an
actorcolumn toprovider_costs, matched to verified emails. - Home and
-/spendsay how much of a person's spend g1t saw.
- Anthropic:
-
Cursor. Use hooks.json (
sessionStart,stop,sessionEnd, which carryconversation_id,user_emailandmodel). Cursor's hooks carry no tokens, so cost comes from the Admin API:POST /teams/filtered-usage-eventsjoined onconversationId, andPOST /teams/spend. -
An OTLP/HTTP receiver (
/v1/logs,/v1/metrics) for Claude Code, Codex, Cursor's server-side export, Copilot and Gemini, with a managed-settings snippet in the docs for each. Drop prompt and response content by default. -
Gemini CLI and Copilot CLI hooks.
-
Credit cloud agents' work to whoever started it: Copilot's
Agent-Logs-Urltrailer, Cursor Agent's co-author, Devin'spull_requests[]. -
Amp and Devin Desktop spend from their APIs.
Before you build step 2 or later, check the report's sources for anything that changed since 2026-10-18, because vendor APIs here move monthly.
Related: #187 (agent setup and AI as its own layer) and #203 (work gets recorded in every harness).
How to work on this repository
- Claim this item before you start (
g1t work claim <number>), and addG1t-Session: $G1T_SESSIONto every commit. - Other sessions share the main checkout: work in a worktree of your own and stage only your own files.
- Pushing to
maindeploys production, and pushes tomainand release tags are the owner's. Land the work through a pull request on this item, or commit locally and hand the owner the exactgit -C <path> push …. - Shipped means on
mainand deployed. Check it live with real data and look at the rendered pages: a status code doesn't show it works. - Docs ship in the same change as the feature (guides, reference, llms.txt), to a high standard.
- User-facing text never names other products or compares g1t to them. Internal notes and code comments may.
Repositories
- flagon-io/g1tOrigin
No pull request for it here yet.
Suggested
Repositories it may also need, and why.
- hello8 work items with the same labels landed there; 1 work item with like titles landed there.
- automation-lab2 work items with the same labels landed there.
Nobody has worked on this yet
flagon-io#188.