Skill: PR review
A ready-to-use skill that reviews pull requests for bugs, style issues, and missing tests. Copy the markdown file into your project and invoke it.
Every team has a code review checklist in their heads. Missing error handling, leftover debug statements, functions that grew too long, new code without tests. The problem is that mental checklists are inconsistent. You catch different things on Monday morning than you do on Friday afternoon.
This skill turns that mental checklist into a markdown file that an AI coding agent executes on demand. Point it at a PR or a git diff, and it walks through the changes methodically, checking for common issues and producing a structured review with severity levels. It won’t replace a human reviewer, but it catches the mechanical stuff so your human review can focus on design and intent.
The skill file
Create this file at .claude/skills/review-pr.md in your project:
# Skill: PR review
## Description
Review the current pull request or git diff for bugs, style issues,
and missing test coverage. Produce a structured report with severity
levels that the developer can act on immediately.
Invoke this skill with: /review-pr
Or by asking: "Review this PR" or "Review my changes"
## Steps
### 1. Gather the diff
First, determine what to review:
- If on a branch with an open PR, run `gh pr diff` to get the PR diff.
- If no PR exists, run `git diff main...HEAD` to compare against the
main branch (adjust the base branch name if the project uses a
different default).
- If there are only unstaged changes, run `git diff` for those.
Store the full diff output. Also run `git diff --stat main...HEAD`
(or the equivalent) to get a summary of changed files and line counts.
### 2. Identify the changed files
From the diff stat output, build a list of every file that was added
or modified. For each file, note:
- The file path
- The number of lines added and removed
- Whether this is a new file or a modification
Skip files that are purely generated (lock files, build output,
vendored dependencies). Focus review effort on source code, tests,
and configuration.
### 3. Read the full content of changed files
For each changed source file, read the complete file (not just the
diff hunks). You need the full context to evaluate whether new code
fits the existing style and patterns. If a file is very large
(over 1000 lines), focus on the changed sections plus 50 lines of
surrounding context.
### 4. Check for common issues
Review each changed file against this checklist. Only flag issues
that actually appear in the diff. Do not flag pre-existing issues
in unchanged code.
**Critical issues (bugs and security):**
- Unhandled errors: new async calls without try/catch or .catch(),
new operations that can throw without error handling
- Security problems: hardcoded secrets, SQL injection vectors,
unsanitized user input, missing authentication checks
- Data loss risks: destructive operations without confirmation,
missing null checks on database results
- Race conditions: shared mutable state without synchronization,
async operations that assume ordering
**Warnings (quality and maintainability):**
- Functions longer than 50 lines (suggest extraction)
- Deeply nested logic (more than 3 levels of nesting)
- Console.log, console.debug, or print statements left in
production code (not in test files)
- Commented-out code blocks (should be removed or explained)
- TODO/FIXME/HACK comments without associated issue numbers
- Magic numbers or strings that should be named constants
- Duplicated logic that appears in more than one place in the diff
**Suggestions (style and best practices):**
- Naming that doesn't match the project's existing conventions
(check surrounding code for patterns)
- Missing TypeScript types where the project uses strict typing
- Inconsistent formatting compared to surrounding code
- Missing JSDoc or docstrings on public functions (if the project
uses them elsewhere)
- Opportunities to simplify: ternaries that could be early returns,
complex conditionals that could be extracted to named functions
### 5. Check test coverage
For every new or modified source file, check whether corresponding
tests exist:
- Look in common test directories: `__tests__/`, `test/`, `tests/`,
`spec/`, or colocated `.test.*` / `.spec.*` files.
- If the changed file has new exported functions or classes, verify
that tests exist for them.
- If tests exist but don't cover the new code paths, flag it.
- If no test file exists at all for a new source file, flag that as
a warning.
Do NOT flag missing tests for:
- Configuration files
- Type definition files
- Migration files
- Files that are purely wiring or glue code with no logic
### 6. Check style consistency
Look at the existing code in the repository (not just the diff) to
identify the project's patterns:
- Naming conventions (camelCase vs snake_case, prefixes, etc.)
- Import ordering and grouping
- Error handling patterns (do they use Result types? Custom error
classes? Simple try/catch?)
- Comment style and density
Flag any places where the new code deviates from established patterns.
### 7. Produce the review
Output the review in this exact format:
```
## PR Review
**Files reviewed:** [count]
**Issues found:** [critical count] critical, [warning count] warnings, [suggestion count] suggestions
### Critical
- **[file:line]** [description of the issue]
*Why:* [one sentence explaining the risk]
*Fix:* [concrete suggestion for how to fix it]
### Warnings
- **[file:line]** [description of the issue]
*Why:* [one sentence explaining why this matters]
*Fix:* [concrete suggestion]
### Suggestions
- **[file:line]** [description]
*Fix:* [concrete suggestion]
### Test coverage
- [file] — [covered / partially covered / no tests]
[If gaps exist, describe what's missing]
### Summary
[2-3 sentences: overall impression of the changes, the most
important thing to address, and anything that looks particularly
good]
```
If a section has no items, include the heading with "None found."
beneath it.
## Rules
- Only flag issues in changed code. Do not review unchanged lines.
- Be specific. Every issue must reference a file name and line number.
- Be actionable. Every issue must include a concrete fix suggestion.
- Do not rewrite the code for the developer. Describe what to change.
- If you are unsure whether something is a real issue, classify it
as a suggestion, not a warning or critical.
- Keep the tone professional and constructive. No snark.
How to install it
- Create the directory if it doesn’t exist:
mkdir -p .claude/skills/ - Save the file above as
.claude/skills/review-pr.md - The skill is now available. Invoke it by typing
/review-prin Claude Code, or by asking “review this PR” or “review my changes.”
If you’re working in a team, commit the .claude/skills/ directory to your repository so everyone gets the same review checklist. You can also place it in ~/.claude/skills/ for a personal skill that works across all your projects.
For more on how skill files are structured and why each section matters, see How to design AI agent skills.
Example usage
Say you’re on a feature branch with three changed files. You type /review-pr and the agent produces something like this:
## PR Review
**Files reviewed:** 3
**Issues found:** 1 critical, 2 warnings, 1 suggestion
### Critical
- **src/api/users.ts:47** Unhandled promise rejection in createUser().
The database insert call has no try/catch, and the function is async.
*Why:* An insert failure will crash the request handler with an
unhandled rejection.
*Fix:* Wrap the db.users.insert() call in a try/catch block and
return a proper error response.
### Warnings
- **src/api/users.ts:23** console.log("debug user data", userData) left
in production code.
*Why:* This will log potentially sensitive user data to stdout in
production.
*Fix:* Remove the console.log statement.
- **src/api/users.ts:31** Function createUser is 67 lines long.
*Why:* Long functions are harder to test and maintain.
*Fix:* Extract the validation logic (lines 33-52) into a separate
validateUserInput() function.
### Suggestions
- **src/utils/format.ts:12** The function formatDate uses a ternary
with a nested ternary. The rest of the codebase uses early returns.
*Fix:* Replace the nested ternary with if/return statements to
match the project's style.
### Test coverage
- src/api/users.ts — no tests. New file with exported functions
createUser and deleteUser. Both need test coverage.
- src/utils/format.ts — partially covered. Existing tests cover
formatCurrency but not the new formatDate function.
- src/types/user.ts — type definitions only, no tests needed.
### Summary
The main concern is the unhandled error in the user creation endpoint,
which could cause production crashes. The rest of the changes are
clean. The formatDate utility is a nice addition. Recommend adding
tests for the new endpoints before merging.
How it works
The skill file is structured in a way that the agent can follow step by step, like a recipe. Here’s what makes it tick.
Steps are ordered deliberately. The agent gathers the diff first, then reads full file contents for context, then runs checks. This ordering matters. You can’t evaluate style consistency without seeing the existing code around the changes. If you’ve read Writing effective skill instructions, you know that explicit ordering prevents the agent from taking shortcuts.
The checklist is concrete, not abstract. Instead of saying “check for bugs,” the skill lists specific bug patterns: unhandled errors, hardcoded secrets, race conditions. Agents follow specific instructions far better than vague ones. Each item is something the agent can mechanically verify.
The output format is fixed. By specifying the exact output structure (headings, file:line references, Why/Fix fields), you get consistent results every run. The agent doesn’t have to decide how to format the review. It fills in a template.
Exclusions are explicit. The skill says what NOT to flag (pre-existing issues, generated files, config-only changes). Without these exclusions, the agent would produce noisy reviews full of irrelevant findings.
Customizing it
This skill works out of the box for most codebases, but you’ll get better results by tuning it to your project.
Add project-specific checks. If your team has rules like “all API endpoints must validate request bodies with zod” or “never use any in TypeScript,” add those to the checklist in step 4. The more specific you are, the more useful the review becomes.
Adjust the function length threshold. The skill flags functions over 50 lines. If your team prefers a different threshold, change the number. Some teams are fine with 80-line functions. Others want 30.
Change the base branch. The skill defaults to comparing against main. If your project uses develop or master or something else, update the git diff commands in step 1.
Modify severity levels. Maybe your team considers leftover console.logs to be critical (because they log PII) rather than warnings. Move items between severity categories to match your team’s priorities.
Add language-specific checks. The default checklist is language-agnostic. If you work primarily in one language, add targeted checks. For Python: missing type hints, bare except clauses, mutable default arguments. For Go: unchecked errors, missing context propagation. For Rust: unwrap() calls in non-test code.
Strip what you don’t need. If your team doesn’t write tests (no judgment), remove step 5 entirely. If you have a linter that catches style issues, you can slim down step 6. The skill should reflect your actual workflow, not an aspirational one.
Related articles
Skill: test writer
A skill that reads a source file and generates tests. Detects the language, framework, and existing patterns to match your style.
Skill: changelog generator
A skill that generates a clean changelog from git history. Reads commits between two refs, groups by type, and outputs formatted markdown.
Skill: commit message writer
A skill that reads your staged changes and writes a conventional commit message following your project's conventions.