Measure how long Claude Code and Codex sat waiting for your reply

Every Monday: how many times your agents asked you something, the median wait for your answer, and whether the longest waits ended in a merged PR.

Runs
Mondays at 8:30
Posts
Stat tile

From your apps to your board

How the skill works: your agent reads last week's sessions from ccusage; each pr's outcome from GitHub; repositories from What you tell it, mondays at 8:30, and gives you median wait for your reply and the report in the chat.

Reads

  • ccusageLast week's sessions
  • GitHubEach PR's outcome
  • What you tell itRepositories
reads
Your agentClaude Code, Codex, Cursor or GeminiMondays at 8:30
posts

You get

  • Median wait for your replyA stat tile on your board, with its trend
  • The report in the chatEvery run, with or without Briefkin

What you get

  • Median wait for your reply this week, against previous weeks.
  • Asks answered, waits over an hour, and waits parked overnight.
  • The 5 longest waits: day, project, agent, wait and whether the PR merged.
  • Merged against not merged: the median wait on each.
  • One line on what to do first, for example "Turn on accept-edits mode for acme-web: most of its long waits were edit approvals".

The card on the right is a sample. Yours shows your own numbers and updates in place every run.

What lands on your board

acme-webMedian wait for your replyLast 7 days42min-11% vs previous period, bettervs last report
Asks answered31+11% vs previous period
Waits over 1 h9-10% vs previous period, better
Parked overnight4
An example with made-up numbers. Your agent posts your real ones.

What it does

For developers and founders who run several agent sessions at once and suspect the agents are faster than they are. Every question an agent asks and every permission prompt it raises sits idle until you look. The session logs on your computer have the timestamps; GitHub has what became of the work.

The agent measures each wait from the log timestamps, ties the session to its repository and branch, and checks whether that PR merged. The card shows only counts and times, never what was said. The usual finding is that the long waits cluster on the work that never shipped.

How it works

  1. 1List last week's sessions

    Run npx ccusage@latest claude session --json --since <last Monday> --until <last Sunday> and the same with codex to get the session IDs worth reading, with firstActivity and lastActivity. ccusage summarizes per session, so the per-message timing comes from the logs themselves.

  2. 2

    2Measure each wait in the logs

    In ~/.claude/projects/*/<sessionId>.jsonl, a wait starts at the last assistant line of a turn that ended on a question to you, or on an Edit or Write tool call whose result came 30 seconds or more later (a permission prompt), and ends at the next line you typed. Tool results also appear as user lines, so skip those, and skip subagent lines. In Codex rollout files under ~/.codex/sessions/, use the agent message and user message events the same way. Waits over 12 hours count as parked, outside the median. Decide what is a question locally; keep only timestamps.

  3. 3

    3Join each wait to its PR

    Each Claude Code line carries cwd and gitBranch; Codex records the working folder at the start of the file. Map the folder to owner/repo with git -C <folder> remote get-url origin, then gh pr list --repo <owner/repo> --head <branch> --state all --json number,state,mergedAt,url. Waits on the default branch or a branch with no PR are listed as "no PR"; when a branch has several PRs, take the one open at the time of the wait.

  4. 4Read each PR's outcome

    Mark each PR merged, closed without merge or still open, from state and mergedAt. Compare the median wait on merged PRs with the median on the rest.

  5. 5

    5Post counts and times only

    Read last week's card with GET https://briefkin.dev/v1/cards/insight-ccusage-agent-wait-time for the history, then post the median wait, the number of asks answered, and the 5 longest waits with day, project folder name, agent, minutes and PR outcome. Never include prompt, question or code text.

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

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/ccusage-agent-wait-time/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the ccusage-agent-wait-time skill

    Or paste the prompt instead of installing:

    promptOn this computer, read my Claude Code transcripts (~/.claude/projects/*/*.jsonl) and Codex session files (~/.codex/sessions) for last Monday to Sunday. Measure each time an agent waited for me: from the last assistant message of a turn that ended on a question or a permission prompt (an Edit or Write call whose result came 30 seconds or more later) to my next typed message, skipping tool results and subagent lines. Waits over 12 hours count as parked. Use each line's working folder and git branch, map the folder to owner/repo with git remote get-url origin, and find the PR with gh pr list --head <branch> --state all. Tell me the number of asks I answered, the median wait, waits over an hour, the 5 longest waits with day, project, agent and whether the PR merged, and the median wait on merged against unmerged PRs. Never quote any transcript text; counts and times only.
  3. Put it on a schedule

    Mondays at 8:30, from cron on any machine where Claude Code is signed in:

    crontab30 8 * * 1 claude -p "Run the ccusage-agent-wait-time 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: ccusage-agent-wait-time
description: "Every Monday: how many times your agents asked you something, the median wait for your answer, and whether the longest waits ended in a merged PR. Use when the user asks for this, or when it runs on a schedule."
---

# Where your agents waited on you: session logs and GitHub

Every Monday: how many times your agents asked you something, the median wait for your answer, and whether the longest waits ended in a merged PR.

For developers and founders who run several agent sessions at once and suspect the agents are faster than they are. Every question an agent asks and every permission prompt it raises sits idle until you look. The session logs on your computer have the timestamps; GitHub has what became of the work.

The agent measures each wait from the log timestamps, ties the session to its repository and branch, and checks whether that PR merged. The card shows only counts and times, never what was said. The usual finding is that the long waits cluster on the work that never shipped.

## 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

- Runs on the computer where Claude Code and Codex ran, with read access to `~/.claude/projects/` and `~/.codex/sessions/` and Node for `npx ccusage@latest`.
- The shared key: one branch per piece of work, and a GitHub `origin` remote in each project folder; `gh` signed in with read access to pull requests.

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

### Steps

1. **List last week's sessions** (ccusage): Run `npx ccusage@latest claude session --json --since <last Monday> --until <last Sunday>` and the same with `codex` to get the session IDs worth reading, with `firstActivity` and `lastActivity`. ccusage summarizes per session, so the per-message timing comes from the logs themselves.
2. **Measure each wait in the logs**: In `~/.claude/projects/*/<sessionId>.jsonl`, a wait starts at the last assistant line of a turn that ended on a question to you, or on an Edit or Write tool call whose result came 30 seconds or more later (a permission prompt), and ends at the next line you typed. Tool results also appear as user lines, so skip those, and skip subagent lines. In Codex rollout files under `~/.codex/sessions/`, use the agent message and user message events the same way. Waits over 12 hours count as parked, outside the median. Decide what is a question locally; keep only timestamps.
3. **Join each wait to its PR**: Each Claude Code line carries `cwd` and `gitBranch`; Codex records the working folder at the start of the file. Map the folder to `owner/repo` with `git -C <folder> remote get-url origin`, then `gh pr list --repo <owner/repo> --head <branch> --state all --json number,state,mergedAt,url`. Waits on the default branch or a branch with no PR are listed as "no PR"; when a branch has several PRs, take the one open at the time of the wait.
4. **Read each PR's outcome** (GitHub): Mark each PR merged, closed without merge or still open, from `state` and `mergedAt`. Compare the median wait on merged PRs with the median on the rest.
5. **Post counts and times only**: Read last week's card with `GET https://briefkin.dev/v1/cards/insight-ccusage-agent-wait-time` for the history, then post the median wait, the number of asks answered, and the 5 longest waits with day, project folder name, agent, minutes and PR outcome. Never include prompt, question or code text.

## Route B: the browser

### What you need

- Signed in to GitHub with read access to the repositories where your agents open PRs and comment.

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

### Steps

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

1. **Find PRs where an agent asked you something**: Search `is:pr involves:@me updated:>=<last Monday>`. Open PRs where your agent posts as a bot account (Claude in GitHub Actions, Codex cloud tasks) and look for its comments that end in a question to you.
2. **Measure each wait**: For each such comment, note its time and the time of your next comment or review on the PR. Hover the relative time to see the exact timestamp. Waits over 12 hours count as parked.
3. **Read each PR's outcome**: At the top of the PR, note Merged, Closed or Open. List the 5 longest waits with day, repository, wait and outcome.
4. **Sum up**: Give the number of asks answered, the median wait, waits over an hour, and the median wait on merged against unmerged PRs.

Note: A browser cannot read the session logs on your computer, so this route sees only the questions agents ask on GitHub. Local Claude Code and Codex sessions, their permission prompts and most day-to-day waits are invisible here; for those, run the skill on the computer itself.

## The report

- **Median wait** for your reply this week, against previous weeks.
- **Asks answered**, waits over an hour, and waits parked overnight.
- **The 5 longest waits**: day, project, agent, wait and whether the PR merged.
- **Merged against not merged**: the median wait on each.
- One line on what to do first, for example "Turn on accept-edits mode for acme-web: most of its long waits were edit approvals".

## 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": "ccusage-agent-wait-time/<date of this run, e.g. 2026-10-16>",
  "item_key": "ccusage-agent-wait-time",
  "project": "acme-web",
  "source": "Where your agents waited on you: session logs and GitHub skill",
  "kind": "metric",
  "title": "Your 3 longest waits sat on the 2 PRs that did not merge",
  "summary": "You answered **31 asks**, median wait **42 minutes**. The 3 longest waits sat on PR 412 (closed) and PR 98 (still open).",
  "metric": {
    "label": "Median wait for your reply",
    "value": 42,
    "unit": "min",
    "period_label": "Last 7 days",
    "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": "Asks answered",
            "value": 31,
            "delta": 11
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Waits over 1 h",
            "value": 9,
            "delta": -10,
            "better": "lower"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Parked overnight",
            "value": 4,
            "better": "lower"
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "When",
          "Project",
          "Agent",
          "Wait",
          "PR"
        ],
        "align": [
          "left",
          "left",
          "left",
          "right",
          "left"
        ],
        "rows": [
          [
            "Tue 15:10",
            "acme-web",
            "Claude Code",
            "6.2 h",
            "PR 412, closed unmerged"
          ],
          [
            "Thu 11:40",
            "acme-api",
            "Codex",
            "4.8 h",
            "PR 98, still open"
          ],
          [
            "Wed 16:55",
            "acme-web",
            "Claude Code",
            "3.9 h",
            "PR 412, closed unmerged"
          ],
          [
            "Mon 10:05",
            "acme-api",
            "Claude Code",
            "1.7 h",
            "PR 97, merged"
          ],
          [
            "Fri 13:20",
            "acme-web",
            "Codex",
            "1.4 h",
            "PR 415, merged"
          ]
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "Median wait on merged PRs: 28 minutes. On PRs that did not merge: 2.9 hours.",
        "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 8:30 (`30 8 * * 1`). From cron, with the agent signed in on that machine:

```bash
30 8 * * 1 claude -p "Run the ccusage-agent-wait-time 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/ccusage-agent-wait-time#schedule

Source: https://briefkin.dev/skills/ccusage-agent-wait-time

What your agent needs

  • Runs on the computer where Claude Code and Codex ran, with read access to ~/.claude/projects/ and ~/.codex/sessions/ and Node for npx ccusage@latest.

  • The shared key: one branch per piece of work, and a GitHub origin remote in each project folder; gh signed in with read access to pull requests.

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

Does any of my code or conversation leave the computer?

No. The agent reads the logs locally and classifies each turn there; the card carries only counts, durations, project folder names, agent names and PR numbers. If a folder name is itself sensitive, map it to a neutral label in the skill's settings.

How does it know a wait was a permission prompt?

Claude Code does not write a separate line for the prompt. The skill treats an Edit or Write tool call whose result arrived 30 seconds or more later as a prompt you had to approve, since those tools finish in well under a second. Bash calls are left out because a long test run looks the same as a slow approval.

Do I need Briefkin to use the Where your agents waited on you: session logs 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 github.com/pulls 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 median wait for your reply 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.