Review PR Issues
End-to-end review of a pull request's health: CI checks, unresolved review threads (bugbot + human), and a prioritized fix plan.
Prerequisites
ghCLI installed and authenticated (gh auth status)- Inside a git repo with a GitHub remote
Workflow
Step 1: Identify the PR
If the user provides a PR number or URL, use it directly. Otherwise detect from the current branch:
gh pr list --head "$(git branch --show-current)" --json number,title,url
Extract owner/repo for API calls:
gh repo view --json owner,name --jq '.owner.login + "/" + .name'
Step 2: Check if CI actions are done running
gh pr checks <PR_NUMBER>
Parse each line for status: pass, fail, pending, skipping.
- If any checks are still
pending: report which checks are pending and stop here. Tell the user to re-run this skill once CI completes. - If all checks are terminal (pass/fail/skipping): proceed to Step 3.
Step 3: Inspect CI failures
For each failed check, fetch annotations via the check run ID (last segment of the job URL):
gh api repos/OWNER/REPO/check-runs/<JOB_ID>/annotations \
--jq '.[] | {level: .annotation_level, path: .path, line: .start_line, message: .message}'
Categorize annotations:
- Errors from our changes: lint errors, test failures in files we touched
- Pre-existing warnings: issues in files not modified by this PR (flag but deprioritize)
Present as:
## CI Failures
### <Job Name> (failed)
- **[error]** `file/path.ts` (line N): description
- **[warning]** `file/path.ts` (line N): description (pre-existing)
Step 4: Fetch unresolved review threads
Use GraphQL — the REST API does not include isResolved or isOutdated.
gh api graphql -f query='
{
repository(owner: "OWNER", name: "REPO") {
pullRequest(number: PR_NUMBER) {
reviewThreads(first: 100) {
totalCount
nodes {
id
isResolved
isOutdated
comments(first: 1) {
nodes {
author { login }
path
line
body
}
}
}
}
}
}
}'
Filter to isResolved == false. Split results into:
- Bugbot issues (author is
cursor[bot]orcursor): group by severity if title contains High/Medium/Low - Human reviewer comments (any other author): list by file
Present as:
## Unresolved Review Threads (X of Y total)
### Bugbot Issues
#### High Severity
1. **Issue title** — `file/path.tsx` (line N)
#### Medium Severity
...
### Human Reviewer Comments
1. **@reviewer**: comment summary — `file/path.tsx` (line N)
If all threads are resolved, report: "All N review threads are resolved."
If totalCount > 100, paginate using after cursor.
Step 5: Review all issues holistically
After collecting CI failures and unresolved review threads, analyze them together:
- Identify overlapping issues (e.g., a test failure caused by the same change a bugbot comment flagged)
- Identify root causes vs. symptoms (e.g., one code change may fix both a lint error and a test failure)
- Note any coverage concerns from Codecov bot comments (check issue comments for
codecov[bot]) - Flag issues that are pre-existing vs. introduced by this PR
Step 6: Create a prioritized fix plan
Present a numbered plan ordered by impact and dependency:
## Fix Plan
### Must fix before merge
1. **[CI: test]** Fix X — caused by Y change, affects N tests
2. **[CI: lint]** Fix Z — one-line change in file.ts
### Should fix (unresolved review threads)
3. **[Bugbot: High]** Issue title — file.ts (line N)
4. **[Human: @reviewer]** Comment summary — file.ts (line N)
### Can defer (low severity / pre-existing)
5. **[Bugbot: Low]** Issue title — file.ts (line N)
6. **[CI: warning]** Pre-existing warning in unrelated file
After presenting the plan, ask the user which items they want to tackle.
Resolving review threads
gh CLI cannot resolve threads via REST. Use the GraphQL mutation with thread IDs from Step 4:
gh api graphql -f query='
mutation {
resolveReviewThread(input: { threadId: "THREAD_NODE_ID" }) {
thread { isResolved }
}
}'
Edge cases
- No gh CLI: instruct user to install (
brew install gh) and authenticate (gh auth login) - No PR found: ask user for the PR number or URL directly
- Run still in progress:
gh run viewand--log-failedwon't work until the run completes — use annotations API instead which is available per-job even while the overall run is in progress - Large PRs: if there are many threads, summarize counts first and let the user drill into specific categories