When to use this
- Before merging a PR, or when someone asks "can you review this?" / "look over this diff."
- As a second opinion on a change you're not fully confident in, before you ship it.
- Not for general code questions, explaining how something works, or open-ended refactors -- use a narrower ask for those.
Why the verify pass matters
The single biggest failure mode for an LLM-driven code review isn't missing bugs -- it's reporting bugs that aren't real. A model reading a diff in isolation will confidently flag a "null pointer risk" on a variable that's guaranteed non-null three lines up, or a "race condition" in code that's single-threaded by construction. Each false positive costs the reviewer trust, and after two or three, humans stop reading the output at all.
The fix is procedural, not a smarter prompt: for every candidate finding, force a second pass that asks "what specific input makes this fail?" If that question can't be answered concretely, the finding gets dropped before it's ever shown to a human. This is the same idea behind why this site's own /code-review tooling separates a review pass from a verify pass -- and why the interactive-labs fix earlier on this site started from "reproduce it in a real browser," not "read the diff and guess."
The skill file
Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.
--- name: code-review description: Review a diff, PR, or set of changed files for correctness bugs, security issues, and unnecessary complexity. Use when the user asks to review code, check a PR, or "look over" a change before it merges -- not for general code questions. --- # Code Review You are reviewing a *change*, not grading a codebase. Every finding must be something introduced or made worse by this diff, or a pre-existing landmine that this diff walks directly into. Don't review-drift into the rest of the file. ## Scope 1. Establish the diff: `git diff main...HEAD` (or the PR's changed files if given a PR number/URL). If no diff exists yet, review the working tree changes (`git diff` + `git diff --staged`). 2. Read each changed file with enough surrounding context to understand what calls it and what it depends on -- a five-line hunk in isolation hides the bugs that matter most. 3. Skip generated files, lockfiles, and vendored code unless the user specifically asks about them. ## What to look for, in priority order 1. **Correctness** -- will this produce a wrong result, crash, or silently corrupt data under some real input? Off-by-one, null/undefined access, wrong operator, inverted condition, race condition, resource leak, swallowed exception, incorrect error handling on a partial failure. 2. **Security** -- injection (SQL/command/template), unsanitized input reaching a sink, broken auth/authz check, secret committed in plaintext, unsafe deserialization, missing bounds check on user-controlled size. 3. **Data integrity** -- a migration or write path that can leave the store in an inconsistent state; a retry that isn't idempotent; a cache that can serve stale/wrong data after this change. 4. **Test coverage** -- does a new branch or edge case introduced by this diff have no test that would catch a regression in it? Flag the gap, not "please add more tests" in general. 5. **Simplification / reuse** -- only when it's clearly cheaper and no riskier: an existing helper that does the same thing, an abstraction that isn't earning its complexity, dead code this diff should have removed. Do **not** flag: formatting/whitespace, naming preferences without a correctness angle, "add a comment here," or anything a linter/formatter already enforces in this repo. ## Verify before reporting For each candidate finding, re-read the actual code path end to end and state the concrete input or sequence of events that triggers it. If you can't articulate a specific failing scenario, it's not a finding -- drop it or downgrade it to a question. This step removes more false positives than anything else in this file. ## Output format Order findings most-severe first. For each: - **File:line** of the anchor - **One-sentence summary** of the defect - **Failure scenario**: concrete input/state -> wrong output/crash - **Suggested fix**, if it's a one-liner; otherwise describe the shape of the fix without writing the whole patch If nothing survives the verify step, say so explicitly -- "no correctness or security issues found in this diff" is a valid and useful review. ## Guardrails - Never invent a vulnerability class that doesn't apply to this language or framework (don't flag SQL injection in a diff with no SQL). - Never soften a real finding to be polite, and never inflate a nitpick to sound serious -- match tone to actual severity. - If the diff is large, review it in logical chunks (by file or by feature) rather than skimming the whole thing at low resolution.
Installing it elsewhere
The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:
Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /code-review.
Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.
Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.
Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.
Worked example
Given this hunk:
+function getDiscount(user) {
+ if (user.plan = 'pro') {
+ return 0.2;
+ }
+ return 0;
+}A finding that survives the verify pass:
getDiscount() always returns 0.2. Line 2 uses = (assignment) instead of === in the condition, so user.plan = 'pro' unconditionally sets user.plan to 'pro' and evaluates truthy. Every caller gets the pro discount regardless of actual plan. Fix: change = to ===.
That's concrete, has a triggering scenario (any call at all), and a one-line fix -- exactly the bar the verify pass enforces.
- Reviewing the whole file instead of the diff -- you'll drown a real finding in twenty pre-existing style complaints nobody asked about.
- Skipping the verify pass under time pressure is how false positives reach the PR thread and burn the team's trust in the review.
- Treating "could theoretically fail" as a finding without a concrete trigger -- if you can't name the input, it's a question, not a bug report.