Monitor one or more GitHub PRs and maintain a live status table showing title, link, check status, resolved/total comments, and reviewer approval. Shows a Windows dialog when a PR is ready to merge. Input: a comma-separated list of PR numbers, "mine", or "all".
58
68%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.github/skills/monitor-pr/SKILL.mdPoll GitHub PRs and print a live status table to the main chat. Alert when a PR is ready to merge.
Parse $ARGUMENTS:
| Value | Meaning |
|---|---|
Comma-separated numbers (e.g. 1234,5678) | Monitor those specific PRs |
mine | All open PRs authored by the current user |
all | All open PRs in the repo |
If $ARGUMENTS is empty, use the ask_user tool (not plain chat text)
to prompt the user with choices: mine, all, or a freeform list of PR
numbers. Do not proceed until the user has answered.
gh is installed and authenticated (gh auth status). If not,
link to https://github.com/cli/cli#installation and stop.powershell -Command "echo ok"). If
unavailable, skip dialog notifications and use text-only alerts.# Specific PRs — validate each exists
gh pr view <number> --repo "BabylonJS/Babylon.js" --json "number"
# "mine"
gh pr list --repo "BabylonJS/Babylon.js" -A "@me" --json "number,title,url"
# "all" (defaults to open)
gh pr list --repo "BabylonJS/Babylon.js" --json "number,title,url"For each PR, gather the following data (this table describes the columns — it is not the output format):
| Column | Source |
|---|---|
| PR | #<number> linked to the PR URL |
| Title | gh pr view --json "title" |
| Checks | gh pr view --json "statusCheckRollup" — ✅ all pass / ❌ N fail, M pending (ETA ~Xm) / ⏳ N pending (ETA ~Xm). See ETA note below. |
| Comments | GraphQL reviewThreads query — ✅ all resolved / ❌ N/M resolved |
| Approved | gh pr view --json "reviewDecision" — ✅ approved / ❌ not approved (the field is an enum, not a count) |
| Ready | ✅ ready if all checks pass AND approved AND all comments resolved, ❌ not ready otherwise |
Review threads require the GraphQL API since gh pr view --json does not
expose them:
gh api graphql -f query='
query {
repository(owner: "BabylonJS", name: "Babylon.js") {
pullRequest(number: <NUMBER>) {
reviewThreads(first: 100) {
totalCount
nodes { isResolved }
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads | {total: .totalCount, resolved: ([.nodes[] | select(.isResolved)] | length)}'If
totalCount > 100, the single-page query above will undercount resolved threads. Page through withpageInfo { hasNextPage endCursor }
after:until all threads are fetched, then sum the resolved counts.
When any checks are still running, compute a rough ETA before rendering the table. The Checks cell is incomplete without it.
status != COMPLETED):
elapsed = now - startedAt (from statusCheckRollup).gh pr list --repo "<owner>/<repo>" -s merged -L 5 --json "number"
gh pr view <recent-pr> --repo "<owner>/<repo>" --json "statusCheckRollup" \
--jq '.statusCheckRollup[] | select(.name == "<name>" and .status == "COMPLETED") | {startedAt, completedAt}'historical = completedAt - startedAt.remaining = max(historical - elapsed, 1m). If no history, use
elapsed as a lower bound and mark ETA as ~Xm+.status == QUEUED or
missing startedAt): remaining = historical (full duration).max(remaining) across all pending checks — not the sum.<1m.Cache historical durations per check name across PRs within a single
poll iteration to avoid redundant gh calls. Do not cache across
polls (stale data risk — see the polling rule below).
Only render the table after all per-PR data (including ETA) is
gathered. Every pending-checks cell MUST end with (ETA ~Xm) (or
~Xm+ / <1m) — no ETA means the data isn't ready yet.
Render as a markdown table, one row per PR, with the columns above
as headers in the same order. Do not transpose or split into per-PR
tables. Prefix with a header line showing the OS's local time, e.g.
PR Status — 2026-04-17 05:17 PM PDT (date or Get-Date).
Example:
When checks fail, read the CI logs. Source depends on which CI the
check is on — look at statusCheckRollup[].detailsUrl to tell:
GitHub Actions (detailsUrl on github.com) — use GitHub MCP
get_job_logs, or gh run view <run-id> --log-failed.
Azure DevOps Pipelines (detailsUrl on dev.azure.com) — the
Babylon.js ADO org (babylonjs) allows anonymous API access;
no auth needed. The detailsUrl looks like
https://dev.azure.com/<org>/<project-guid>/_build/results?buildId=<id>&view=logs&jobId=<job-guid>.
Fetch the build timeline and then the failing record's log:
# List all records (jobs/tasks) and their log URLs
curl -s "https://dev.azure.com/<org>/<project-guid>/_apis/build/builds/<buildId>/timeline?api-version=7.0"
# Fetch a specific record's log
curl -s "<record.log.url>"Filter timeline.records to the failing entries (result == "failed")
and read each .log.url. If a jobId is present in detailsUrl,
scope directly to that record's children.
Classification:
MANDATORY: You MUST implement a continuous polling loop. Do not display the status once and stop. Do not suggest the user re-invoke the skill to refresh. You must keep running and re-checking every ~5 minutes until every monitored PR is merged or closed. Use
sleep 300(or equivalent) between polls to wait 5 minutes, then re-fetch and print the updated table. This is the core purpose of this skill.
sleep 300gh and GraphQL commands as Step 2. Every column — checks, comments,
approval, state — must be queried fresh from the API. Do not reuse
or cache any data from a previous polling iteration. New commits
can restart all checks, so data from a previous poll may be stale.powershell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('PR #<number> — <title> — is ready to merge.', 'PR Ready', 'OK', 'Information')"Stop polling only when:
Do NOT stop for any other reason. Do not stop because "polling isn't practical in a chat session." Do not stop because "the user can re-invoke the skill." The entire point of this skill is continuous, autonomous monitoring.
If the user asks to retrigger CI (e.g. for flakes), push an empty commit:
git commit --allow-empty -m "retrigger CI"
git pushNever force push. Always use new commits.
787eedf
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.