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
1List last week's sessions
Run
npx ccusage@latest claude session --json --since <last Monday> --until <last Sunday>and the same withcodexto get the session IDs worth reading, withfirstActivityandlastActivity. ccusage summarizes per session, so the per-message timing comes from the logs themselves.- 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
3Join each wait to its PR
Each Claude Code line carries
cwdandgitBranch; Codex records the working folder at the start of the file. Map the folder toowner/repowithgit -C <folder> remote get-url origin, thengh 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. 4Read each PR's outcome
Mark each PR merged, closed without merge or still open, from
stateandmergedAt. Compare the median wait on merged PRs with the median on the rest.- 5
5Post counts and times only
Read last week's card with
GET https://briefkin.dev/v1/cards/insight-ccusage-agent-wait-timefor 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. Post it to the board
With
BRIEFKIN_TOKENset, 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.
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.
shell
curl -fsSL https://briefkin.dev/skills/ccusage-agent-wait-time/install | shRun it
Ask Claude Code:
prompt
Run the ccusage-agent-wait-time skillOr paste the prompt instead of installing:
prompt
On 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.Put it on a schedule
Mondays at 8:30, from cron on any machine where Claude Code is signed in:
crontab
30 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.Send it to your board
Connect Briefkin once with
curl -fsSL https://briefkin.dev/install | shand 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 fornpx ccusage@latest.The shared key: one branch per piece of work, and a GitHub
originremote in each project folder;ghsigned in with read access to pull requests.
Connecting ccusage
- 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.
- CLI.
npx ccusage@latest session --json --since 2026-10-20(orpnpm 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
- GitHub MCP Server, GitHub's official server, hosted at
https://api.githubcopilot.com/mcp/. Sign in with OAuth or a personal access token; add/readonlyto the URL, or use a toolset URL such ashttps://api.githubcopilot.com/mcp/x/pull_requests/readonly, to expose only read tools. It also runs locally (source). - The
ghCLI. Rungh auth loginonce, or setGH_TOKENfor scheduled runs.gh pr list --search "review-requested:@me" --json number,title,url,createdAtandgh api repos/{owner}/{repo}/dependabot/alertscover most reports. - 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.