Structured, risk-aware code review of a GitHub pull request using the gh CLI, with diff triage, unresolved-thread suppression, and severity-grouped findings ending in an approve/request-changes verdict.
87%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Perform a structured, risk-aware code review of a GitHub pull request. Works in any coding-agent harness with the gh CLI authenticated.
owner/repo#123, or bare #123. Normalize before use with gh: URL → as-is; owner/repo#N → gh -R owner/repo pr diff N; bare #N → gh pr diff N (targets the repo whose remote the cwd's origin points at — if the cwd is not a git repo with a GitHub origin, error out rather than guessing). Only the bare #N form depends on the cwd; everything after normalization targets GitHub explicitly via -R.The skill fetches unresolved review threads itself — no caller needs to supply them.
gh api graphql -f query='
query($owner: String!, $name: String!, $number: Int!, $after: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100, after: $after) {
pageInfo { hasNextPage endCursor }
nodes { isResolved path line originalLine startLine originalStartLine }
}
}
}
}' -F owner=<owner> -F name=<repo> -F number=<number>(pass -F after=<cursor> for subsequent pages). Keep only unresolved threads (isResolved: false) that have a line number; collect all of line, originalLine, startLine, originalStartLine per thread.
Apply suppression window. Default ±5 lines. GitHub thread line/startLine are positions on the PR head; originalLine/originalStartLine are on the base. Match the finding's new-side line against the thread's current line (line/startLine); use originalLine/originalStartLine only when the current line is null (outdated thread). Skip any finding whose file matches a thread's path (also match the diff's old path if the file was renamed) AND whose line falls within ±5 lines (inclusive) of any thread line. Those locations are already under discussion — re-reporting them is noise.
Fallback. If the GraphQL call fails (missing pullRequest:read scope, token can't see the repo), run without suppression and note that in the report.
Report. After the findings, add one line: Suppressed N findings overlapping existing unresolved threads — flag if any suppressed finding was High severity, and let that weigh on the verdict rather than silently approving.
If the caller explicitly supplies a thread list (JSON array of {"path", "lines"}) or a different window, prefer the caller's values over the built-in fetch.
If a caller passes additional directives, honor them:
gh pr diff cannot override the base, so freeze via git instead:
git fetch origin +pull/<number>/head:refs/remotes/origin/pr/<number> <base>:refs/remotes/origin/<base>
git diff refs/remotes/origin/<base>...refs/remotes/origin/pr/<number> > "$diff_dir/pr-review.diff"gh pr diff and note the base override was not applied.gh pr comment/review submissions. Report findings in-conversation only.Caller directives take precedence over defaults in this skill (e.g. review-only overrides any temptation to fix things).
diff_dir="$(mktemp -d)"
gh -R <owner>/<repo> pr diff <number> > "$diff_dir/pr-review.diff"Also fetch metadata: gh -R <owner>/<repo> pr view <number> --json title,body,baseRefName,headRefName,additions,deletions,changedFiles. Read the PR description for intent; review the change against that intent. Keep $diff_dir for the whole session; clean it up only when the session ends — follow-up questions may still need the frozen snapshot.
1b. Fetch unresolved threads. Per "Review Thread Suppression" above — fetch the PR's unresolved review threads now so suppression is ready before analysis begins.
Triage the file list. Parse the diff per file. EXCLUDE from review (note them, don't review): lockfiles (*.lock, package-lock.json, yarn.lock, pnpm-lock.yaml, Cargo.lock, etc.), minified (.min.js/css), generated (.generated., .map, .snap), build output (dist/, build/, out/), vendor (node_modules/, vendor/), and binaries (images, fonts, archives). If nothing reviewable remains, report that.
Scale the review.
$diff_dir/pr-review.diff for its own files. Never re-derive the diff via local git diff — the frozen patch is the source of truth.Review each file for:
Across all four dimensions: read surrounding file context when a hunk alone is ambiguous — the diff is the delta, not the truth.
Report findings grouped by severity:
Each finding (all severities): file, line (old/new), what's wrong, why it matters, and a concrete suggested fix. End with an overall verdict: approve / approve-with-comments / request-changes, one sentence of justification.
$diff_dir was cleaned up and a follow-up query needs diff content, a single re-fetch for that query is acceptable.phatblat/dotfiles
4d65cab
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.