| 1 | # Agent spend and agent work per engineer |
| 2 | |
| 3 | Research, 2026-10-18. The question: how g1t should show agent spend and agent work per engineer, across every coding agent a team uses, as well as or better than the products that already do it. |
| 4 | |
| 5 | Sources are vendor docs, API references and changelogs, linked inline. **UNCONFIRMED** marks a claim that rests on a secondary source, on vendor source code without docs, or on nothing I could open. Vendor marketing claims are labelled as such. |
| 6 | |
| 7 | ## Where g1t stands |
| 8 | |
| 9 | These are the integration points the plan below changes. |
| 10 | |
| 11 | **Claude Code** is the only agent that reports spend. |
| 12 | |
| 13 | - `plugins/claude-code/hooks/g1t.mjs` reads `message.usage` from the transcript on `Stop`, `SubagentStop` and `SessionEnd`, and removes duplicates by message id plus `requestId`. |
| 14 | - It sends the totals with `g1t session heartbeat --usage-json` (CLI 0.4.1 or later). |
| 15 | - That becomes `PATCH /repos/{owner}/{name}/sessions/{id}`, then the work service's `update_session`. |
| 16 | - The work service prices it with `crates/contracts/src/model_prices.rs`, which has Anthropic list prices only, and writes `sessions.usage` and `sessions.cost_usd` (`services/work/migrations/0053_session_cost.sql`). |
| 17 | |
| 18 | **Other agents** report no cost. |
| 19 | |
| 20 | - Codex (`plugins/codex`) has no hooks. |
| 21 | - Other agents use `plugins/other-harnesses/AGENTS.snippet.md`, manual CLI calls without usage. |
| 22 | - Even if they sent tokens, `model_prices.rs` would price a non-Anthropic model as unknown (`cost_partial`). |
| 23 | |
| 24 | **Provider reports**, in `services/billing/src/provider_costs.rs`: |
| 25 | |
| 26 | - Anthropic `cost_report` is grouped by `workspace_id` and `description`. |
| 27 | - OpenAI `organization/costs` is grouped by `line_item` and `project_id`. |
| 28 | - Neither is grouped by user. Both are stored in `provider_costs` for the whole organization. |
| 29 | |
| 30 | **How work is attributed** (`services/work/src/signals/base.sql`, `weeks.sql`, `pulls.sql`): |
| 31 | |
| 32 | - A pull request is an agent's when its `pulls.agent` is `agent`, its author is the g1t agent, or a session is tied to it through `session_links`, `sessions.pull`, or a branch touch. |
| 33 | - A session's cost is split evenly across the pull requests it is tied to. |
| 34 | - Direct pushes count only as `agent_commits`, built from the plugin's `session touch` reports. |
| 35 | |
| 36 | **Why a solo workspace sees almost nothing** (`apps/web/app/lib/signals.ts`): |
| 37 | |
| 38 | | Finding | Why it stays hidden for flagon-io | |
| 39 | | ------- | ------------------------------------------------------------------------------------------------------------- | |
| 40 | | spend | `quarterSpend` counts only per-pull cost, so direct-push sessions drop out. It also needs two or more groups. | |
| 41 | | review | Needs a non-owner review. | |
| 42 | | shipped | Needs a closed milestone. | |
| 43 | | stalled | Needs open pull requests. | |
| 44 | | rework | Needs 5 or more agent merges a week. | |
| 45 | | silos | Needs 3 people. | |
| 46 | | spread | Needs 2 people who adopted a harness later. | |
| 47 | |
| 48 | The pulse tiles do count direct-push spend (`signals.server.ts:140`). |
| 49 | |
| 50 | **Who can see what:** |
| 51 | |
| 52 | - There is no per-person spend view. Billing `Usage` has no actor dimension (`crates/contracts/src/billing.rs:311`). |
| 53 | - Session visibility is own, member or outside (`services/work/src/coordination/shown.rs`). Members see each other's `cost_usd`, but not each other's prompts. |
| 54 | |
| 55 | **Open question.** The sessions this research ran, including its own subagents, came back from coordination with `cost_usd: null` after they ended. Either the coordination payload leaves cost out, or subagent usage doesn't arrive. Step 0 checks which. |
| 56 | |
| 57 | ## 1. What each agent exposes |
| 58 | |
| 59 | ### Comparison of coding agents |
| 60 | |
| 61 | | Agent | Telemetry (OTel) | Admin / usage API | Local session files | Hooks | Per-user? | Cost field | |
| 62 | | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ | --------------------------------------------------- | |
| 63 | | **Claude Code** | Metrics `claude_code.cost.usage` (USD) and `claude_code.token.usage`; event `claude_code.api_request` with `cost_usd`, tokens, `request_id`. Attributes `session.id`, `user.email`, `user.account_uuid`, `organization.id`, `query_source` (main/subagent). Set centrally through the `env` of managed settings. [docs](https://code.claude.com/docs/en/monitoring-usage) | `GET /v1/organizations/usage_report/claude_code`: per actor (email or API key) per day: sessions, lines, commits, PRs, tool accept/reject, `model_breakdown[].tokens` and `estimated_cost` (cents). Admin key; no individual accounts; not Bedrock or Vertex. [docs](https://platform.claude.com/docs/en/manage-claude/claude-code-analytics-api). Enterprise (claude.ai) has a separate Analytics API (`read:analytics`). `usage_report/messages` and `cost_report` **cannot group by user**. [docs](https://platform.claude.com/docs/en/manage-claude/usage-cost-api) | `~/.claude/projects/<slug>/<session>.jsonl`, `message.usage` (input, output, cache read, cache write 5m/1h). No cost. Subagents in `<session>/subagents/agent-<id>.jsonl`. | 33 events; `session_id`, `transcript_path`, `prompt_id`; `SubagentStop` adds `agent_transcript_path`. No cumulative tokens in any hook. [docs](https://code.claude.com/docs/en/hooks) | Yes (email) | Yes: OTel, Analytics API. Estimate at list price. | |
| 64 | | **Codex** (CLI, IDE, app-server) | `[otel]` in `config.toml`: `exporter`/`metrics_exporter` `otlp-http\|otlp-grpc`. Events carry `conversation.id`, `user.email`, `user.account_id`, `model`; `codex.sse_event` has token counts. **Source-only:** `codex.turn_cost` event and `codex.turn.cost_microusd` metric; whether they fire in the plain CLI is UNCONFIRMED. Central defaults in `/etc/codex/managed_config.toml`. [docs](https://learn.chatgpt.com/docs/config-file/config-advanced) | API-key use: `GET /v1/organization/usage/completions` and `/v1/organization/costs` with `group_by=user_id\|api_key_id\|project_id` (no Codex-specific `api_source`). ChatGPT workspaces: Codex Enterprise Analytics API, scope `codex.enterprise.analytics.read`; paths UNCONFIRMED. [docs](https://learn.chatgpt.com/docs/enterprise/analytics-api) | `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`, compressed to `.jsonl.zst` when cold (2026). `event_msg` `token_count` holds `info.total_token_usage` (input, cached, cache write, output, reasoning) and `rate_limits`. No cost. | **Codex now has hooks** (on by default): `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `Stop`, `PostToolUse`, …; payload `session_id`, `transcript_path`, `model`, `turn_id`. No tokens. Legacy `notify` still exists. [docs](https://learn.chatgpt.com/docs/hooks) | Yes (email in OTel; `user_id` in Platform costs) | OTel (source-only); Platform costs API | |
| 65 | | **Cursor** | **Server-side** OTel export (beta; turned on in Team Settings, nothing installed on machines). Metric `cursor.cost.usage` (USD), `cursor.token.usage`; logs `cursor.api.request`, `cursor.cloud_agent.pull_request`, `cursor.cloud_agent.commit`. Resource `cursor.user.email`; logs `cursor.conversation.id`. Plan likely Enterprise (UNCONFIRMED). [docs](https://cursor.com/docs/enterprise/opentelemetry-export/wire) | Admin API (`api.cursor.com`, Basic auth): `POST /teams/daily-usage-data` (per user per day: lines, accepts, requests); `POST /teams/filtered-usage-events` (per request: `userEmail`, `model`, `tokenUsage`, `chargedCents`, `conversationId`); `POST /teams/spend` (`spendCents` per member). AI Code Tracking API `GET /analytics/ai-code/commits` (per commit: tab, composer and non-AI lines; Enterprise alpha). [docs](https://cursor.com/docs/account/teams/admin-api) | `state.vscdb` SQLite (`cursorDiskKV`); undocumented, changes between versions. Token fields UNCONFIRMED. | `hooks.json` (MDM, team, project or user): `sessionStart`, `sessionEnd`, `stop`, `afterFileEdit`, `subagentStop`, …; payload `conversation_id`, `generation_id`, `model`, `user_email`, `transcript_path`. No tokens. [docs](https://cursor.com/docs/agent/hooks) | Yes (email) | Yes: `chargedCents`, `spendCents`, OTel | |
| 66 | | **GitHub Copilot** | VS Code Copilot Chat: `github.copilot.chat.otel.*` / `COPILOT_OTEL_*`. `gen_ai.client.token.usage`, `gen_ai.conversation.id`; identity only with `captureIdentity`. No cost. [docs](https://code.visualstudio.com/docs/agents/guides/monitoring-agents) | The legacy `/copilot/metrics` API was retired 2026-04-02. New usage metrics reports: `GET /orgs/{org}/copilot/metrics/reports/users-1-day?day=` (download links). Per-user fields include `ai_credits_used`, `used_copilot_coding_agent`, `totals_by_cli.token_usage`. Billing: `GET /organizations/{org}/settings/billing/ai_credit/usage?user=` (`netAmount`). Seats: `/orgs/{org}/copilot/billing/seats`. [reports](https://docs.github.com/en/rest/copilot/copilot-usage-metrics), [billing](https://docs.github.com/en/rest/billing/usage) | Copilot CLI `~/.copilot/session-state/<id>/events.jsonl`; undocumented, token data UNCONFIRMED. | CLI and cloud agent: `.github/hooks/*.json`; `sessionStart`, `sessionEnd`, `agentStop`, …; payload `sessionId`, `cwd`, sometimes `transcriptPath`. No model, user or tokens. [docs](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-hooks-reference) | Yes (login) | AI Credits per user (since 2026-06-01, usage-based) | |
| 67 | | **Windsurf, now Devin Desktop** (renamed 2026-06-02) | None documented. | Enterprise: `POST server.codeium.com/api/v1/UserPageAnalytics` (`promptCreditsUsed` per email); `/CascadeAnalytics` (`cascadeRuns[].promptsUsed` per `cascadeId`). [docs](https://docs.devin.ai/windsurf/plugins/accounts/api-reference/user-page-analytics) | `~/.windsurf/transcripts/{trajectory_id}.jsonl`, only with a transcript hook. | Cascade hooks (`post_cascade_response`, …) with `trajectory_id`, `model_name`; Devin Local/CLI hooks with Claude Code names (`SessionStart`, `Stop`, …) and `session_id`. No tokens. [docs](https://docs.devin.ai/desktop/cascade/hooks) | Yes (email) | Credits, not dollars | |
| 68 | | **Gemini CLI** | `telemetry` in `settings.json`, or the `/etc/gemini-cli/settings.json` system file. `gemini_cli.token.usage`, `gemini_cli.api_response` (token counts), `session.id`, `user.email`. **No cost metric.** `logPrompts` defaults to **true**. [docs](https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/telemetry.md) | No per-user API. Code Assist metrics in Cloud Monitoring are aggregate; Vertex billing is per project. [docs](https://docs.cloud.google.com/gemini/docs/codeassist/generate-metrics) | `~/.gemini/tmp/<hash>/chats/session-*.json[l]`; each `gemini` message has `tokens{input,output,cached,thoughts,tool,total}` and `model`. No cost. | `SessionStart`, `SessionEnd` (best effort), `AfterModel`, …; `session_id`, `transcript_path`. [docs](https://github.com/google-gemini/gemini-cli/blob/main/docs/hooks/reference.md) | Via OTel only | No; tokens × price | |
| 69 | | **Amp** | None found. | `GET ampcode.com/api/v2/workspace/analytics/daily-usage` (per user per day: `metrics.usage` USD, lines); `GET /threads/{id}/usage` (USD per thread, per model, with tokens). [docs](https://ampcode.com/api/external) | Threads live on the server; `--stream-json` has `usage` and `session_id`. | TypeScript plugin API (`session.start`, `agent.end` with `thread.id`). No usage. [docs](https://ampcode.com/docs/plugin-api) | Yes | Yes: USD per user and per thread | |
| 70 | | **Devin** (cloud) | None documented. | Enterprise v3: `GET /v3/enterprise/sessions` (each with `user_id`, `pull_requests[]`, `acus_consumed`); `/v3/enterprise/consumption/daily/users/{id}`; `/metrics/prs`. [docs](https://docs.devin.ai/api-reference/v3/sessions/enterprise-sessions) | None (cloud). | No outbound session webhooks (UNCONFIRMED absence). | Yes | ACUs per session and per user | |
| 71 | |
| 72 | **How agents mark their own commits:** |
| 73 | |
| 74 | - **Copilot coding agent:** Copilot is the commit author, the assigning person is co-author, and an `Agent-Logs-Url` trailer links the session. [changelog](https://github.blog/changelog/2026-03-20-trace-any-copilot-coding-agent-commit-to-its-session-logs) |
| 75 | - **Cursor:** the CLI adds a `Made with Cursor` trailer. Cloud agents commit as "Cursor Agent" with the person as `Co-authored-by`. [docs](https://cursor.com/docs/cli/reference/configuration) |
| 76 | - **Devin:** the author is configurable: Devin, co-authored, or the person. |
| 77 | - **Claude Code:** `Co-Authored-By: Claude`. |
| 78 | |
| 79 | **What "cost" means differs by plan.** |
| 80 | |
| 81 | - On a subscription (Claude Max, ChatGPT plans, Cursor seats), every token-based figure is a list-price **estimate**: what the work would cost through the API, not what was paid. |
| 82 | - Swarmia calls this "token value". LinearB's docs say "Estimated consumption is not a billing total." |
| 83 | - g1t should say so too. The Claude Code Analytics API's `customer_type` (`api` or `subscription`) tells the two cases apart. |
| 84 | |
| 85 | ### Products that sell this |
| 86 | |
| 87 | | Product | Ingests | Attributes spend to work by | Per-engineer view, and its privacy stance | Pricing (public) | |
| 88 | | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | |
| 89 | | **LinearB** | Git/PR; Copilot, Cursor, Amazon Q; Claude Code via Admin API, Enterprise Analytics API or OTel. [docs](https://linearb.helpdocs.io/article/p4lfzfnu0w-ai-tools-integrations) | Tokens and cost in Metrics Builder; "estimated consumption … not a billing total". | User-level data; no stated stance. | $29 / $59 per contributor per month, 50+ and 100+ developers. [pricing](https://linearb.io/pricing/) | |
| 90 | | **Jellyfish** | Claude Code, Cursor, Copilot, Windsurf, Gemini, Amazon Q, review bots; Git, Jira. [press](https://jellyfish.co/newsroom/end-to-end-ai-impact-sdlc/) | "AI Spend Insights" by tool, team and initiative (marketing). | Says it offers individual ROI; no safeguards found. | Quote only. | |
| 91 | | **DX** (Atlassian since 2025-11-10) | Surveys; Git; Claude Code via analytics, Console or OTel; a **local daemon** that records commits for AI Code %. [docs](https://docs.getdx.com/reports/ai-code-percentage/) | AI % per commit, weighted by size; developers can correct their own commits. | Advises against individual evaluation: AI % is "a lens, not a KPI". Person-level drilldown still exists for admins. | Quote only. | |
| 92 | | **Swarmia** | Copilot, Cursor, Claude Code (OTel and Analytics API), Codex, custom tools. [docs](https://help.swarmia.com/features/ai-tools/ai-adoption) | **Each person's daily usage is split across the issues and PRs they touched that day, weighted by effort.** AI-PR detection in tiers: trailer, co-author or label (high confidence); used AI in the last 24 hours (low confidence). The UI shows which rule fired. [cost](https://www.swarmia.com/changelog/2026-08-05-ai-cost-beta/) | Team first, with drilldown to individuals. "Not a tool for spying on developers"; no stack ranking. | **Free under 10 developers**; AI cost add-on **$5 per developer per month**. [pricing](https://www.swarmia.com/pricing/) | |
| 93 | | **Faros AI** | Claude Code Analytics API (daily pull), OTel (real time), Git. [blog](https://www.faros.ai/blog/claude-code-analytics) | "Token Intelligence" by team and tool; headline metric "average estimated cost per commit". | Per-user data underneath; stance UNCONFIRMED. | Quote; free open-source Community Edition; Faros Desktop is free and local. | |
| 94 | | **Span** | span-detect-1, a code classifier that needs no telemetry; an **agent trace recorder on the developer's machine** (rolled out by MDM): prompts, tool calls, tokens, dead ends. [site](https://www.span.app/) | AI Code Ratio per PR; wages and token spend mapped to project and work type. | **"Reports are about repos and teams, never people … An engineer's sessions are theirs."** Private by default; engineers see their own; PII stripped. One help snippet lists a "person" breakdown (UNCONFIRMED which is current). | Quote, per contributor. | |
| 95 | | **Weave** (weaveos.com) | Git, PRs, reviews, AI telemetry from "50+ tools" (marketing); an LLM scores each PR in "Weave Hours". | "Connect token spend to engineering output" (marketing). | Explicit per-engineer table (AI Usage, AI Score, Output). | **$0 for teams under 5**; $50 per engineer per month for individual stats. [pricing](https://weaveos.com/pricing) | |
| 96 | | **Waydev** | Git, tickets, CI; Copilot, Claude Code, Cursor; "Agent Registry". | "AI Feature Spend" and "Human and Agent Spend" (marketing; per-PR cost UNCONFIRMED). | Contributor pages and benchmarks. | Quote; no free plan. | |
| 97 | | **Exceeds AI** | GitHub, GitLab, ADO; Cursor, Claude Code, Copilot. | AI share per commit and PR; an ROI example (marketing). | **Most individual-focused:** profiles, coaching, leaderboards. | Per manager seat: $65 per month. | |
| 98 | | **Opsera** | Copilot, Amazon Q, Cursor, Windsurf dashboards. | Acceptance and adoption only. | "Top users" panels. | Not public. | |
| 99 | | **Cursor dashboard** | First-party client telemetry. [docs](https://cursor.com/docs/account/teams/analytics) | Per-line signatures matched to later commits, on the device ("AI Share of Committed Code"). | Admins see everyone; members see themselves plus a top-10 leaderboard. | Included with Teams. | |
| 100 | | **Copilot dashboards** | First-party. [changelog](https://github.blog/changelog/2026-07-22-new-copilot-usage-metrics-impact-dashboard) | Repo report counts Copilot-authored and merged PRs. The impact dashboard shows **cohorts** (`ai_adoption_phase`), not individuals. | Dashboards are org-level; a per-user API exists for admins. | Included. | |
| 101 | | **RadiantOps** (radiantops.com; launched 2026-09-16, $7M seed; GitPrime founders) | GitHub, Bitbucket, Jira, Linear, Slack, Cursor, Codex, Bedrock. [site](https://radiantops.com/) | "Episodes of work" (code, tickets, chat, agent runs); agent share per change set, "spend per agent merge", rework, stalled, silos, "new ground", a daily Signal. | "A team is not a percentile": compares each team only with its own history. Individual view policy UNCONFIRMED. | Not public; enterprise. | |
| 102 | |
| 103 | RadiantOps' feature set is closest to what Home and the Workspace overview already show. Its inputs are other vendors' APIs; g1t's inputs are the forge and the sessions themselves. |
| 104 | |
| 105 | ### Solo developers and small teams |
| 106 | |
| 107 | What these tools have in common is that they're about **limits, not ROI**: |
| 108 | |
| 109 | - **Claude Code `/usage`:** session cost, per-model tokens, a cache-hit line, plan-limit bars, and which skills, subagents and MCP servers used the most. `--max-budget-usd` caps a run. Anthropic's benchmark is about $13 per developer per active day. [docs](https://code.claude.com/docs/en/costs) |
| 110 | - **ccusage:** daily, weekly, monthly and per-session reports, plus five-hour `blocks` with burn rate and a projection against the plan window. Covers Codex, Amp, Copilot CLI and Gemini CLI from their local files. [repo](https://github.com/ryoppippi/ccusage) |
| 111 | - **tokscale, Sniffly, Grafana stacks** (claude-code-otel and others): top sessions by cost, cost by model, clusters of errors. |
| 112 | - **Langfuse:** traces from Claude Code and Codex Stop hooks and from Copilot's OTel; cost per developer, project and session. [docs](https://langfuse.com/resources/engineering/coding-agent-tracing) |
| 113 | - **Git AI:** agent hooks write per-line authorship to `refs/notes/ai` (agent, model, session); the paid tier adds cost per PR. [docs](https://usegitai.com/docs/get-started/how-git-ai-works) |
| 114 | |
| 115 | **The gap:** almost no small-team tool connects spend to **work that landed**. They answer "how fast am I burning?", not "what did that buy, and what was thrown away?". |
| 116 | |
| 117 | ## 2. Patterns worth copying |
| 118 | |
| 119 | 1. **Three paths in, one number out.** Every vendor joins vendor APIs (daily, backfilled, per user), OTel (real time, any provider) and git. g1t has a fourth path, its own session record, which the others lack. |
| 120 | 2. **Call it an estimate and show the basis.** Show "list-price value" next to the actual invoice when a provider report exists. Use `customer_type` and plan to say which case applies. |
| 121 | 3. **Detection in tiers, with the rule shown** (Swarmia). For every change g1t calls an agent's, say why: a session trailer, a session tie, a co-author, the Copilot author, or a `Made with Cursor` trailer. |
| 122 | 4. **Cloud-agent work belongs to the person who started it** (DX, Swarmia, Devin's `user_id`, Copilot's co-author). |
| 123 | 5. **Spend split over work by effort** (Swarmia). Use it only where g1t lacks a direct link, and label it as a split. |
| 124 | 6. **Idle-seat and plan-fit checks first** (Swarmia, Cursor): token value against what the seat costs. |
| 125 | 7. **Self-view softens individual data** (Span, Cursor members, DX's AI % override, Devin Personal Analytics). |
| 126 | 8. **Compare only with your own history** (RadiantOps). This is also the only baseline that works for one person. |
| 127 | 9. **A daily digest that says what to act on** (RadiantOps Signal, Waydev and Swarmia assistants). g1t already has one: Home. |
| 128 | 10. **For solo users, lead with limits:** burn rate, cache efficiency, and which skill, subagent or MCP server is eating budget. |
| 129 | |
| 130 | ## 3. What g1t can do that they can't |
| 131 | |
| 132 | The products above infer the link between spend and work from outside. g1t is the forge and records the sessions, so it has the link directly: |
| 133 | |
| 134 | - **An exact join, not a heuristic.** |
| 135 | - A session's `G1t-Session` trailer ties its cost to the commit, the pull request, the work item it closes, and the merge-queue result. |
| 136 | - Swarmia needs a 24-hour window, Cursor needs line signatures, and Span needs an ML model to approximate this. |
| 137 | - **Spend that never landed.** g1t sees sessions that cost money and produced no commit, sessions whose branch was abandoned, and pull requests closed unmerged. Only Span claims to see dead ends, and only through a recorder on each machine. |
| 138 | - **Direct pushes.** Products built on PR data miss them. g1t receives the push and reads its trailers (`services/work/src/coordination/pushed.rs`). |
| 139 | - **Rework from the history itself.** g1t sees follow-up commits and reverts on the same lines, failed checks and fix-ups in the merge queue, and their cost. It doesn't depend on a "rework" heuristic over someone else's API. |
| 140 | - **One identity.** The session actor, the git pusher and the reviewer are one g1t account, so there is no email-to-author mapping page. Provider APIs keyed by email (Anthropic, Cursor, Amp, Windsurf) map onto g1t users through their verified addresses. |
| 141 | - **The cost of reviewing agent work.** Review time, the number of rounds, and the CI minutes an agent's pull request used are all g1t's own data. |
| 142 | - **Every harness in one place.** Claude Code, Codex, Cursor, Copilot CLI, Gemini CLI and Devin all have hooks now with `session_id` and `transcript_path`, so one plugin pattern covers them. The products above each need vendor admin keys, and most of those need Enterprise plans. |
| 143 | - **Useful for one person.** Because g1t records sessions itself, a solo developer gets cost per landed change and spend that never landed without any admin API. No product above serves that case. |
| 144 | |
| 145 | ## 4. Privacy model |
| 146 | |
| 147 | The stance: **spend is information about work, not a score for people.** |
| 148 | |
| 149 | 1. **Your own, in full.** Every engineer sees all of their own sessions, spend, prompts and what landed, on every harness. This matches what `Sight` already does for sessions. |
| 150 | 2. **Others' spend appears as the cost of work, not ranked by person.** |
| 151 | - Teammates see what a change, work item, milestone or team cost, and who worked on it, as today. |
| 152 | - There is no view that lists or sorts people by spend, and no leaderboard, score or percentile. |
| 153 | 3. **Per-person totals are a workspace setting.** "Spend by person" can be shown to: |
| 154 | - **Owners and billing managers**, the default; |
| 155 | - all members; |
| 156 | - or nobody. |
| 157 | |
| 158 | It is for budgets and plan fit, and the page says so. Every person always sees their own. |
| 159 | |
| 160 | 4. **A minimum group of 3 for rollups.** A team or group total is shown only when it covers three people or more. Otherwise it would reveal a person's figure to people the setting doesn't allow. A one-person workspace is all self-view, so this never hides anything there. |
| 161 | 5. **Provider data waits for consent.** Per-user rows from a provider API, such as an Anthropic Analytics email or a Cursor `userEmail`, are joined to a g1t user only through an address that person has verified. Unmatched rows stay in "not linked to anyone". |
| 162 | 6. **Content stays with its author.** Prompts and tool output stay own-only for members (as today) and are never sent to an outside service. |
| 163 | - g1t's own OTel receiver should drop `user_prompt`, `assistant_response` and body events unless the person turns them on. |
| 164 | - Gemini CLI's `logPrompts`, which defaults to true, should be set to false in the settings g1t writes. |
| 165 | 7. **Opting out is visible.** `G1T_RECORD=0` and `G1T_RECORD_PROMPTS=0` already exist. Totals show how much they leave uncounted ("3 sessions unrecorded"), so nobody mistakes missing data for zero. |
| 166 | 8. **No outside benchmarks.** Compare only with the workspace's own history, as Home already does. |
| 167 | |
| 168 | ## 5. Ranked plan |
| 169 | |
| 170 | The order is by what it unlocks for flagon-io first: one person, direct pushes, Claude Code and Codex. Then it widens to teams and other agents. Effort is S (a day or less), M (a few days) or L (a week or more). |
| 171 | |
| 172 | | # | Step | Effort | Unlocks | Exact integration | |
| 173 | | --- | -------------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 174 | | 0 | **Check that subagent and ended-session cost arrives** | S | Trust in every number below | Compare `sessions.cost_usd` and `usage` for this session and its subagents with the transcripts. Check `SubagentStop` → `agent_transcript_path` in `plugins/claude-code/hooks/g1t.mjs`, and whether coordination `session.ended` payloads leave out `cost_usd` (`services/work/src/coordination/shown.rs`). | |
| 175 | | 1 | **Spend for direct pushes and solo workspaces** | S–M | Spend findings show for flagon-io. | `quarterSpend` in `apps/web/app/lib/signals.ts`: add sessions not tied to a PR, grouped by the work item their push closed (`pushed.rs` `trailer_session`) or else by repo. Add a `direct` arm to `services/work/src/signals/pulls.sql`, keyed by `session_touches` with kind `commit`. Allow one group when the workspace has one person. | |
| 176 | | 1b | **Findings for one person** | M | Home says something useful with no reviews or milestones. | New findings in `signals.ts`, each compared with your own last 4 weeks: **spend that never landed** (sessions with cost and no commit or merged PR); **cost per landed change**; **cache efficiency** (cache read ÷ input from `sessions.usage`); **most expensive session this week**, with what it produced. Scale `rework` and `stalled` thresholds to the workspace's volume instead of fixed counts. | |
| 177 | | 2 | **"Your spend" and spend by person, with the privacy setting** | M | Per-engineer view (section 4). | Work service query over `sessions(actor_id, started_at, cost_usd, usage, harness, model, item_id)` joined to `session_links` and `session_touches`, by day, repo, work item, harness and model, split into landed and not landed. Route `apps/web/app/routes/workspace/spend.tsx` (`-/spend`, defaulting to you). CLI `g1t spend [--by repo\|item\|harness] [--since 7d]`. Workspace setting `spend_visibility = owners\|members\|nobody`, plus the 3-person rollup rule. | |
| 178 | | 3 | **Codex cost** | M | flagon-io's other harness reports spend. | `plugins/codex/hooks.json` for `SessionStart`, `Stop`, `SubagentStop` and `SessionEnd`, running a shared `g1t.mjs` that reads `transcript_path`: the last `event_msg` of type `token_count`, `info.total_token_usage` (`input_tokens`, `cached_input_tokens`, `cache_write_input_tokens`, `output_tokens`, `reasoning_output_tokens`), reading `.jsonl.zst` too. Send `model` from the hook payload with `g1t session heartbeat --usage-json`. Add OpenAI list prices to `crates/contracts/src/model_prices.rs`. Mark ChatGPT-plan sessions (`rate_limits.plan_type`) as an estimate. | |
| 179 | | 4 | **Check per-person spend against the provider** | M | "g1t saw 82% of your Claude Code spend". Per-engineer spend for people who don't use the plugin. | In `services/billing/src/provider_costs.rs`: daily `GET /v1/organizations/usage_report/claude_code?starting_at=` with paging, keeping `actor.email_address`, `model_breakdown[].estimated_cost.amount`, `customer_type`, `commits_by_claude_code` and `pull_requests_by_claude_code`. OpenAI `GET /v1/organization/costs?group_by=user_id`. Add an `actor` column to `provider_costs` (new migration) and match it to verified emails. | |
| 180 | | 5 | **Cursor** | M | The first agent g1t doesn't run itself. | `plugins/cursor`: `.cursor/hooks.json` or `~/.cursor/hooks.json` for `sessionStart`, `stop` and `sessionEnd`, sending `conversation_id`, `user_email`, `model` and `g1t session start --harness cursor`. Cost comes from the Admin API, as Cursor hooks carry no tokens: `POST /teams/filtered-usage-events` (`tokenUsage`, `chargedCents`, `conversationId`), joined on `harness_session_id`; `POST /teams/spend` for per-person totals. Key stored like the provider keys. Enterprise: `GET /analytics/ai-code/commits` for AI lines per commit. | |
| 181 | | 6 | **OTLP receiver** | L | Coverage with no plugin installed, rolled out through managed settings; real time; Cursor's server-side export with nothing on the machines. | `POST /v1/logs` and `/v1/metrics` (OTLP/HTTP, protobuf and JSON) on the API, authenticated with a workspace token in `OTEL_EXPORTER_OTLP_HEADERS`. Read Claude Code `claude_code.api_request` (`cost_usd`, tokens, `session.id`, `user.email`, `query_source`); Codex `codex.sse_event` tokens and `codex.turn_cost` (`usage.estimated_usd`, `conversation.id`); Cursor `cursor.cost.usage` and `cursor.api.request` (`cursor.conversation.id`, `cursor.user.email`); Copilot `gen_ai.client.token.usage`; Gemini `gemini_cli.api_response`. Join `session.id` or `conversation.id` to `sessions.harness_session_id`. Drop content events by default. Docs: a managed-settings snippet for each harness. | |
| 182 | | 7 | **Gemini CLI and Copilot CLI hooks** | M | Two more local harnesses. | Gemini: `~/.gemini/settings.json` hooks `SessionStart` and `SessionEnd`; read `transcript_path` (`session-*.jsonl`, `tokens{input,output,cached,thoughts}` per `gemini` message); add Gemini prices. Copilot CLI: `.github/hooks/*.json` `sessionStart` and `agentStop` (`transcriptPath`). Its tokens are UNCONFIRMED, so cost comes from `GET /organizations/{org}/settings/billing/ai_credit/usage?user=`. | |
| 183 | | 8 | **Cloud agents' work credited to whoever started it** | M | Copilot coding agent, Cursor cloud agents and Devin PRs count as the launcher's agent work, with cost. | In `services/work/src/signals/base.sql`'s `tied`, count as agent work: commits with the `Agent-Logs-Url` trailer or Copilot as author (credited to the co-author); `Co-authored-by` the Cursor Agent, or a `Made with Cursor` trailer; Devin's `GET /v3/enterprise/sessions` `pull_requests[]` with `acus_consumed` and `user_id`. Show the rule that matched. | |
| 184 | | 9 | **Amp and Devin Desktop spend** | S each, after 4 | Per-person dollars from their APIs. | Amp `GET /api/v2/workspace/analytics/daily-usage` (`metrics.usage` per `user.email`) and `/threads/{id}/usage`. Windsurf/Devin Desktop `POST /api/v1/UserPageAnalytics` (`promptCreditsUsed`, shown as credits). | |
| 185 | |
| 186 | **Recommended first slice:** steps 0, 1, 1b and 2, then 3. That gives flagon-io per-engineer spend, cost per landed change and spend that never landed, with the privacy setting in place, before any vendor integration. |