Track what each merged PR costs in Claude Code and Codex tokens

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.

Runs
Mondays at 9:00
Posts
Stat tile

What lands on your board

acme-webAgent cost per merged PRLast week, list price$38-27% vs previous period, bettervs last report
Tokens per merged PR2.1M-22% vs previous period, better
Merged PRs14+40% vs previous period
Agent cost$532+2.0% vs previous period, worse
Codex: 1.4 review roundsClaude Code: 2.3 review rounds
An example with made-up numbers. Your agent posts your real ones.

What it does

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.

How it works

  1. 1Pull last week's sessions with cost

    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. 2

    2Find 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. 3List merged PRs per repository

    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. 4

    4Join 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. 5

    5Count 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. 6

    6Compare 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.

  7. Post it to the board

    With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.

What you get

  • 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".

Install and run it

Pick your agent, where the data comes from and how to schedule it; the commands below follow.

Agent
Data
Schedule
  1. Install the skill

    One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.

    shellcurl -fsSL https://briefkin.dev/skills/github-agent-cost-per-merged-pr/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the github-agent-cost-per-merged-pr skill

    Or paste the prompt instead of installing:

    promptOn this computer, run `npx ccusage@latest claude session --json` and `npx ccusage@latest codex session --json` for last Monday to Sunday. For each session, find its transcript (~/.claude/projects/*/<sessionId>.jsonl, or the Codex rollout file under ~/.codex/sessions) and read only the working folder and git branch, never the text. Map the folder to owner/repo with `git remote get-url origin`. List PRs merged in that week with `gh pr list --state merged --json number,headRefName,reviews,commits`. Match sessions to PRs on repo plus branch; sessions with no merged PR stay in the cost. Tell me agent cost per merged PR at API list price, tokens per PR, merged PR count, and the same split by Claude Code and Codex and by repo, with average human review rounds per PR (reviews with no new commit between them count as one round). Say clearly the dollars are list price, not my bill. End with the one thing to look at first.
  3. Put it on a schedule

    Mondays at 9:00, from cron on any machine where Claude Code is signed in:

    crontab0 9 * * 1 claude -p "Run the github-agent-cost-per-merged-pr skill"

    Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.

  4. Send it to your board

    Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a stat tile. How setup works

View the SKILL.mdRaw file
SKILL.md---
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

What your agent needs

  • 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.

Connecting ccusage

  1. MCP server. None is needed: ccusage is a CLI and the data is local files. Any agent with a shell on the same computer can run it.
  2. CLI. npx ccusage@latest session --json --since 2026-10-20 (or pnpm dlx, bunx) with no install and no account. For Codex, npx ccusage@latest codex session --json. An agent can also read the JSONL files directly when it needs per-message timestamps, which ccusage summarizes away.

The skill must run on the computer where the agents ran; a cloud agent cannot see these logs. The transcripts hold your prompts and code, so the report should send only counts, costs and times, never transcript text.

Connecting GitHub

  1. GitHub MCP Server, GitHub's official server, hosted at https://api.githubcopilot.com/mcp/. Sign in with OAuth or a personal access token; add /readonly to the URL, or use a toolset URL such as https://api.githubcopilot.com/mcp/x/pull_requests/readonly, to expose only read tools. It also runs locally (source).
  2. The gh CLI. Run gh auth login once, or set GH_TOKEN for scheduled runs. gh pr list --search "review-requested:@me" --json number,title,url,createdAt and gh api repos/{owner}/{repo}/dependabot/alerts cover most reports.
  3. REST and GraphQL with a fine-grained token. Store it in GITHUB_TOKEN, limit it to the repositories in the report, and grant Read on Metadata, Contents, Pull requests and Issues, plus Dependabot alerts if you report on them.

With every permission on a fine-grained token set to Read, the agent can't push, merge, comment or close anything.

Questions

Why does the cost not match what I pay?

ccusage prices every token at the API list price for its model. On a Claude Max or ChatGPT plan you pay a flat fee, so read the dollars as a consistent measure of agent effort that you can compare week to week and between agents, not as an invoice.

What happens to sessions that switch branches or work on main?

Claude Code writes the current branch on every transcript line, so a session that moved from fix/login to feat/export has its cost split by the tokens on each branch's lines. Work on the default branch, on branches never pushed, or on PRs still open lands in the "no merged PR" bucket. It still counts toward the cost, because that is what the shipped PRs really cost.

Do I need Briefkin to use the Agent cost per merged PR: ccusage and GitHub skill?

No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.

Which agents can run it?

Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.

Can it work without an API or MCP server, from my browser?

Yes. Switch the data source to "Your browser" and the steps change to the ccusage and GitHub pages themselves: the agent opens platform.claude.com/usage in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.

Watch agent cost per merged pr on your board, run after run

Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.

Free during the open beta. No card.