Reviewing Pull Requests
Follow these phases in order. The user provides a PR number, URL, or
owner/repo#number. The repo must be cloned locally and gh must be
authenticated.
Not this skill: Creating PRs, resolving review feedback, fixing CI
failures, or merging. This skill only reviews code changes.
Phase 1 — Gather context
PR metadata:
gh pr view <PR> --json title,body,baseRefName,headRefName,state,labels,author,additions,deletions,changedFiles,reviewRequests,reviews
Diff:
gh pr diff <PR>
If diff exceeds 50 changed files (too large to process as a single
diff without truncation), list files first with
gh pr diff <PR> --name-only and read high-risk files individually.
Linked issues — parse PR body for Fixes #N, Closes #N,
Resolves #N, Related to #N. For each:
gh issue view <N> --json title,body,labels,state
Existing review comments — fetch both PR-level and inline:
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
gh api --paginate repos/$REPO/issues/<PR>/comments \
--jq '.[] | {body, user: .user.login}'
gh api --paginate repos/$REPO/pulls/<PR>/comments \
--jq '.[] | {path, line, body, user: .user.login}'
CI status:
gh pr checks <PR>
If checks failed: gh run view <RUN_ID> --log-failed
Phase 2 — Understand repo conventions
Read each file if it exists (skip silently if absent):
CONTRIBUTING.md, CODEOWNERS, .github/PULL_REQUEST_TEMPLATE.md
AGENTS.md or CLAUDE.md
- Linter/formatter configs (
.eslintrc*, biome.json, .prettierrc*,
pyproject.toml, ruff.toml, .rubocop.yml, .golangci.yml)
- CI workflows (
.github/workflows/*.yml) — understand what automated
checks already exist
Judge the PR against project conventions, not abstract ideals.
Phase 3 — Analyze code changes
Summarize the PR's intent in one sentence before proceeding. If you
cannot, note the unclear intent as the first finding.
Review the diff against these priorities (highest first). See
references/review-checklist.md for
detailed checks and false-positive guidance per category.
- Goal alignment — Does the PR achieve what linked issue(s) describe?
- Bugs and logic errors — Focus on added/modified lines only.
- Security — HIGH-confidence findings only. Trace data flow from
source to sink before reporting.
- Codebase consistency — Compare against surrounding code, not
abstract ideals.
- Test coverage — Are the riskiest new code paths tested?
- Performance — Flag only concrete, demonstrable findings.
- Documentation — Are public APIs and breaking changes documented?
Rules:
- Focus on CHANGED code. Do not flag pre-existing findings outside the diff.
- Never block on style when a linter or formatter is configured.
- If the author left comments explaining a non-obvious choice, acknowledge
their reasoning before suggesting alternatives.
- If nothing significant is found, say so — do not invent findings.
Phase 4 — Run available checks locally
Detect commands from package.json scripts, Makefile, pyproject.toml,
and CI workflow files. Run in order, skip any that are unavailable:
- Lint — e.g.
npm run lint, ruff check ., golangci-lint run
- Type-check — e.g.
npx tsc --noEmit, mypy ., pyright
- Tests — prefer running tests relevant to changed files only
Guardrails:
- Do NOT run commands that modify state (deploy, migrate, publish, seed,
--write, --fix).
- If unsure what a command does, skip it and note it in the report.
- If no checks are available, note this and proceed.
Phase 5 — Produce the report
Classify every finding:
| Tag |
Severity |
Criteria |
[B] |
Blocking |
Must fix before merge — bugs, security, data loss, broken functionality. Include what's wrong, why it matters, and how to fix it. |
[S] |
Suggestion |
Should fix — better approaches, missing edge cases, maintainability. Explain the alternative and why it's better. |
[N] |
Nit |
Optional — style, minor naming. One sentence max. |
[P] |
Praise |
Good work — be specific about what's well done. |
Verdict:
- ✅ Approve — Zero blocking findings
- ⚠️ Approve with comments — Zero blocking findings, but suggestions
worth noting
- ❌ Request changes — One or more blocking findings
Every finding must cite a specific file:line. Rank blocking findings:
security > bugs > logic errors > breaking changes. Include at least one
praise if anything positive stands out.
Generate the report using
references/report-template.md.
Phase 6 — Post review to GitHub (only if user requests)
Always confirm with the user before posting.
# Approve
gh pr review <PR> --approve --body "<summary>"
# Request changes
gh pr review <PR> --request-changes --body "<report>"
# Comment only
gh pr review <PR> --comment --body "<report>"
Edge cases
- Empty PR description: Flag as first finding — a PR without context
is a review anti-pattern.
- Very large PR (30+ files or 1000+ lines): Note it should be split.
Review the highest-risk files regardless.
- Draft PR: Review normally, note draft status in summary.
- No linked issue: Review as-is. Note missing link as a suggestion.
- Failing CI on changed code: Include as a blocking finding.
- Bot PRs (Dependabot, Renovate): Focus on changelog/breaking changes
and test results. Skip style review.
- Author disagreement: Focus on impact (why it matters), not authority.
Yield on non-blocking items.
References
- references/review-checklist.md —
Detailed checks by category with false-positive guidance
- references/report-template.md —
Report template with example findings
1---2name: reviewing-pull-requests3description: Reviews GitHub pull requests end-to-end using gh CLI. Gathers PR metadata, diff, linked issues, and CI status. Analyzes code for bugs, security risks, performance issues, and goal alignment against repo conventions. Runs available lint, type-check, and test commands locally. Produces a prioritized report with severity-classified feedback (blocking, suggestion, nit, praise) and an approve/request-changes verdict. Optionally posts the review to GitHub after user confirmation. Use when asked to review a PR, check a pull request, audit code changes, evaluate if a PR is ready to merge, provide code review feedback, assess PR quality, or when the user says review PR #N, is this PR ready, look at this pull request, or code review.4---56# Reviewing Pull Requests78Follow these phases in order. The user provides a PR number, URL, or9`owner/repo#number`. The repo must be cloned locally and `gh` must be10authenticated.1112**Not this skill:** Creating PRs, resolving review feedback, fixing CI13failures, or merging. This skill only *reviews* code changes.1415## Phase 1 — Gather context16171. **PR metadata:**18 ```bash19 gh pr view <PR> --json title,body,baseRefName,headRefName,state,labels,author,additions,deletions,changedFiles,reviewRequests,reviews20 ```21222. **Diff:**23 ```bash24 gh pr diff <PR>25 ```26 If diff exceeds 50 changed files (too large to process as a single27 diff without truncation), list files first with28 `gh pr diff <PR> --name-only` and read high-risk files individually.29303. **Linked issues** — parse PR body for `Fixes #N`, `Closes #N`,31 `Resolves #N`, `Related to #N`. For each:32 ```bash33 gh issue view <N> --json title,body,labels,state34 ```35364. **Existing review comments** — fetch both PR-level and inline:37 ```bash38 REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)39 gh api --paginate repos/$REPO/issues/<PR>/comments \40 --jq '.[] | {body, user: .user.login}'41 gh api --paginate repos/$REPO/pulls/<PR>/comments \42 --jq '.[] | {path, line, body, user: .user.login}'43 ```44455. **CI status:**46 ```bash47 gh pr checks <PR>48 ```49 If checks failed: `gh run view <RUN_ID> --log-failed`5051## Phase 2 — Understand repo conventions5253Read each file if it exists (skip silently if absent):5455- `CONTRIBUTING.md`, `CODEOWNERS`, `.github/PULL_REQUEST_TEMPLATE.md`56- `AGENTS.md` or `CLAUDE.md`57- Linter/formatter configs (`.eslintrc*`, `biome.json`, `.prettierrc*`,58 `pyproject.toml`, `ruff.toml`, `.rubocop.yml`, `.golangci.yml`)59- CI workflows (`.github/workflows/*.yml`) — understand what automated60 checks already exist6162Judge the PR against **project conventions**, not abstract ideals.6364## Phase 3 — Analyze code changes6566Summarize the PR's intent in one sentence before proceeding. If you67cannot, note the unclear intent as the first finding.6869Review the diff against these priorities (highest first). See70[references/review-checklist.md](references/review-checklist.md) for71detailed checks and false-positive guidance per category.72731. **Goal alignment** — Does the PR achieve what linked issue(s) describe?742. **Bugs and logic errors** — Focus on added/modified lines only.753. **Security** — HIGH-confidence findings only. Trace data flow from76 source to sink before reporting.774. **Codebase consistency** — Compare against surrounding code, not78 abstract ideals.795. **Test coverage** — Are the riskiest new code paths tested?806. **Performance** — Flag only concrete, demonstrable findings.817. **Documentation** — Are public APIs and breaking changes documented?8283**Rules:**8485- Focus on CHANGED code. Do not flag pre-existing findings outside the diff.86- Never block on style when a linter or formatter is configured.87- If the author left comments explaining a non-obvious choice, acknowledge88 their reasoning before suggesting alternatives.89- If nothing significant is found, say so — do not invent findings.9091## Phase 4 — Run available checks locally9293Detect commands from `package.json` scripts, `Makefile`, `pyproject.toml`,94and CI workflow files. Run in order, skip any that are unavailable:95961. **Lint** — e.g. `npm run lint`, `ruff check .`, `golangci-lint run`972. **Type-check** — e.g. `npx tsc --noEmit`, `mypy .`, `pyright`983. **Tests** — prefer running tests relevant to changed files only99100**Guardrails:**101102- Do NOT run commands that modify state (deploy, migrate, publish, seed,103 `--write`, `--fix`).104- If unsure what a command does, skip it and note it in the report.105- If no checks are available, note this and proceed.106107## Phase 5 — Produce the report108109Classify every finding:110111| Tag | Severity | Criteria |112|-----|----------|----------|113| `[B]` | Blocking | Must fix before merge — bugs, security, data loss, broken functionality. Include what's wrong, why it matters, and how to fix it. |114| `[S]` | Suggestion | Should fix — better approaches, missing edge cases, maintainability. Explain the alternative and why it's better. |115| `[N]` | Nit | Optional — style, minor naming. One sentence max. |116| `[P]` | Praise | Good work — be specific about what's well done. |117118**Verdict:**119120- **✅ Approve** — Zero blocking findings121- **⚠️ Approve with comments** — Zero blocking findings, but suggestions122 worth noting123- **❌ Request changes** — One or more blocking findings124125Every finding must cite a specific `file:line`. Rank blocking findings:126security > bugs > logic errors > breaking changes. Include at least one127praise if anything positive stands out.128129Generate the report using130[references/report-template.md](references/report-template.md).131132## Phase 6 — Post review to GitHub (only if user requests)133134**Always confirm with the user before posting.**135136```bash137# Approve138gh pr review <PR> --approve --body "<summary>"139140# Request changes141gh pr review <PR> --request-changes --body "<report>"142143# Comment only144gh pr review <PR> --comment --body "<report>"145```146147## Edge cases148149- **Empty PR description**: Flag as first finding — a PR without context150 is a review anti-pattern.151- **Very large PR (30+ files or 1000+ lines)**: Note it should be split.152 Review the highest-risk files regardless.153- **Draft PR**: Review normally, note draft status in summary.154- **No linked issue**: Review as-is. Note missing link as a suggestion.155- **Failing CI on changed code**: Include as a blocking finding.156- **Bot PRs (Dependabot, Renovate)**: Focus on changelog/breaking changes157 and test results. Skip style review.158- **Author disagreement**: Focus on impact (why it matters), not authority.159 Yield on non-blocking items.160161## References162163- [references/review-checklist.md](references/review-checklist.md) —164 Detailed checks by category with false-positive guidance165- [references/report-template.md](references/report-template.md) —166 Report template with example findings