---
name: github-agent-cost-per-merged-pr
description: "Every Monday: agent tokens at API list price divided by the PRs that merged, Claude Code against Codex, with the review rounds each PR needed. Use when the user asks for this, or when it runs on a schedule."
---

# Agent cost per merged PR: ccusage and GitHub

Every Monday: agent tokens at API list price divided by the PRs that merged, Claude Code against Codex, with the review rounds each PR needed.

For developers and founders who run Claude Code or Codex all week and want to know what a shipped change costs in agent effort. ccusage knows the tokens and the list-price dollars per session; GitHub knows which pull requests merged and how many review rounds they took. Neither knows the other. The agent ties each session to the branch it worked on, the branch to its PR, and divides.

The number to watch is the ratio, not the total. A week where spend went up but the cost per merged PR fell is a good week. And when one agent's PRs need a second review round far more often, it shows up next to its price.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- The skill must run on the computer where Claude Code and Codex ran, with Node for `npx ccusage@latest` and read access to `~/.claude/projects/` and `~/.codex/sessions/`.
- The shared key: agents work on one branch per PR, and each project folder has a GitHub `origin` remote.
- The `gh` CLI signed in (or `GH_TOKEN`) with read access to pull requests on those repositories.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Pull last week's sessions with cost** (ccusage): Run `npx ccusage@latest claude session --json --since 2026-10-19 --until 2026-10-25` and the same with `codex` in place of `claude`, so every session carries its agent. Keep `sessionId`, `totalTokens`, `totalCost`, `firstActivity` and `lastActivity` per session.
2. **Find each session's folder and branch**: For Claude Code, open `~/.claude/projects/*/<sessionId>.jsonl`: every line has `cwd`, `gitBranch` and, on assistant lines, the token usage. For Codex, the rollout file under `~/.codex/sessions/YYYY/MM/DD/` whose name ends with the session ID records the working folder on its first line. Run `git -C <folder> remote get-url origin` and normalize it to `owner/repo` (drop `.git`, turn `git@github.com:` into the same form, lowercase). Read only these fields, never message text.
3. **List merged PRs per repository** (GitHub): For each repository found, `gh pr list --repo <owner/repo> --state merged --search "merged:2026-10-19..2026-10-25" --json number,title,headRefName,createdAt,mergedAt,commits,reviews,url --limit 200`.
4. **Join sessions to PRs**: The key is repository plus branch: a session matches the PR whose `headRefName` equals its `gitBranch` (exact, case-sensitive). When a Claude Code session switched branches, split its cost by the tokens on each branch's lines. For Codex sessions with no branch, match the PR that has commits authored in that folder between `firstActivity` and `lastActivity`. Sessions on the default branch, on unpushed branches or on PRs still open go to a "no merged PR" bucket that stays in the cost; merged PRs with no session are counted as human-only and left out of the ratio.
5. **Count review rounds**: Per merged PR, take `reviews` from people (skip logins ending in `[bot]`) and count one round per review, merging reviews with no new commit between them into one. Average per agent: a PR belongs to the agent with the larger share of its cost.
6. **Compare with last week and post**: Read last week's card with `GET https://briefkin.dev/v1/cards/insight-github-agent-cost-per-merged-pr` and post under the same `item_key`. Headline: all agent cost divided by merged PRs that had a session, in dollars at list price, with tokens per PR and the merged count in the glance, and the split per agent and per project when the card opens.

## Route B: the browser

### What you need

- Signed in to the Claude Console with a role that can see Usage and Cost, to the OpenAI platform if Codex uses an API key, and to GitHub with read access to the repositories.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://platform.claude.com/usage. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Read Claude API usage for the week**: On the Usage page pick the workspace, choose the API key Claude Code uses and set the dates to last Monday through Sunday. Note input and output tokens. Then open **Cost** (`https://platform.claude.com/cost`) and add up the daily bars for the same seven days.
2. **Read Codex usage if it runs on an API key**: Open `https://platform.openai.com/usage`, set the same dates and read tokens and spend for the project or key Codex uses. Codex signed in with a ChatGPT plan has no dollar figure here; say so and leave it out.
3. **Count merged PRs and review rounds**: Open `https://github.com/pulls` and search `is:pr is:merged merged:2026-10-19..2026-10-25 repo:<owner/repo>`. For each PR, open the Conversation tab and count the human reviews, treating reviews with no commit between them as one round.
4. **Divide and compare**: Divide the week's API spend by the merged PRs, and tokens by the same count. Give average review rounds per PR, and compare with last week's figures if you have them.

Note: The consoles only see usage billed to an API key, and only by key, model and day: no project, branch or session. So the browser route gives one all-in ratio, cannot split Claude Code from Codex unless each has its own key, and shows nothing for subscription use, which lives only in the local session logs that ccusage reads.

## The report

- **Agent cost per merged PR** at API list price, with the change on last week.
- **Tokens per merged PR** and the number of merged PRs that had agent sessions.
- **Per agent**: Claude Code and Codex, each with merged PRs, cost, cost per PR and average review rounds.
- **Per project**: the same ratio for each repository.
- **No merged PR**: what the sessions that led to nothing cost.
- One line on what to do first, for example "Look at the 3 Claude Code PRs that needed 4 review rounds before handing it more of that kind of work".

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "github-agent-cost-per-merged-pr/<date of this run, e.g. 2026-10-16>",
  "item_key": "github-agent-cost-per-merged-pr",
  "project": "acme-web",
  "source": "Agent cost per merged PR: ccusage and GitHub skill",
  "kind": "metric",
  "title": "$38 of agent tokens per merged PR, down from $52",
  "summary": "Codex PRs took **1.4 review rounds** on average, Claude Code PRs **2.3**. Cost at API list price, not your bill.",
  "metric": {
    "label": "Agent cost per merged PR",
    "value": 38,
    "prefix": "$",
    "period_label": "Last week, list price",
    "better": "lower",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "Tokens per merged PR",
            "value": "2.1M",
            "delta": -22,
            "better": "lower"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Merged PRs",
            "value": 14,
            "delta": 40
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Agent cost",
            "prefix": "$",
            "value": 532,
            "delta": 2,
            "better": "lower"
          }
        }
      ]
    },
    {
      "type": "Badges",
      "props": {
        "items": [
          {
            "label": "Codex: 1.4 review rounds",
            "tone": "ok"
          },
          {
            "label": "Claude Code: 2.3 review rounds",
            "tone": "warn"
          }
        ]
      }
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Agent",
          "Merged PRs",
          "Cost",
          "Per PR",
          "Tokens per PR",
          "Review rounds"
        ],
        "align": [
          "left",
          "right",
          "right",
          "right",
          "right",
          "right"
        ],
        "rows": [
          [
            "Claude Code",
            9,
            "$380",
            "$42",
            "2.2M",
            2.3
          ],
          [
            "Codex",
            5,
            "$152",
            "$30",
            "1.9M",
            1.4
          ],
          [
            "All agents",
            14,
            "$532",
            "$38",
            "2.1M",
            2
          ]
        ]
      }
    },
    {
      "type": "Table",
      "props": {
        "columns": [
          "Project",
          "Merged PRs",
          "Cost",
          "Per PR"
        ],
        "align": [
          "left",
          "right",
          "right",
          "right"
        ],
        "rows": [
          [
            "acme-web",
            8,
            "$336",
            "$42"
          ],
          [
            "acme-api",
            6,
            "$196",
            "$33"
          ]
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "$96 of the $532 went to sessions with no merged PR: 3 branches still open and 2 never pushed. On a Claude or ChatGPT subscription you pay the flat fee; these dollars measure effort.",
        "tone": "info"
      }
    }
  ],
  "size": "md"
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: Mondays at 9:00 (`0 9 * * 1`). From cron, with the agent signed in on that machine:

```bash
0 9 * * 1 claude -p "Run the github-agent-cost-per-merged-pr skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/github-agent-cost-per-merged-pr#schedule

Source: https://briefkin.dev/skills/github-agent-cost-per-merged-pr
