Use when authoring a code review of a pull request or merge request — "review this PR", "do a code review on PR
71
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Produce a code review that reads like a sharp human wrote it and opens a conversation. You draft, the user steers, the user approves before anything is posted or saved.
Decide the mode before starting the workflow, and state it in one line — the workflow branches on it.
/review-style tools also do this, but less reliably and without the human-gated, house-style flow here. Uses references/local.md.Choosing: if the request clearly signals local (the trigger words above, or a bare branch with no PR), use local. If it clearly targets a specific remote PR (a PR URL or owner/repo#N), use public. If it's ambiguous, ask with AskUserQuestion, offering Public as the default.
Resolve the platform before step 1 and state it alongside the mode. Resolve in this precedence order, taking the first that answers — a later signal never overrides an earlier one:
git remote (git remote get-url origin);gh auth status / glab auth status).github.com or a GitHub Enterprise host → references/github.md. gitlab.com or a self-managed GitLab host → references/gitlab.md. If none of the three resolves, ask with AskUserQuestion — never guess, since the wrong reference posts nothing or posts to the wrong place.
The workflow below is platform-agnostic and names operations (preflight, fetch-pr-context, create-draft-review, …); the selected reference defines them. It says "PR" throughout — on GitLab read merge request, and <NUM> as the MR iid. Local mode needs none of this.
This skill orchestrates existing review engines rather than reinventing analysis (both modes). It depends on two plugins and degrades gracefully if absent — see references/analysis.md:
code-reviewer, comment-analyzer, pr-test-analyzer, silent-failure-hunter, type-design-analyzer) for depth on the dimensions a diff actually touches.Review voice and formatting rules are in references/house-style.md.
args is a PR reference (public) or a branch/base hint (local): a PR URL, owner/repo#N, a bare N inside the repo, a branch name, or empty (use the current branch). Parse what you can; if public mode needs a PR you can't resolve, ask for a PR URL.
- [ ] 1. Gather the change and context
- [ ] 2. Find issues (code-review + applicable pr-review-toolkit agents)
- [ ] 3. Triage in a fresh subagent (merge, discipline; public: reconcile)
- [ ] 4. Draft in house style: summary, architectural notes, inline findings
- [ ] 5. Results gate: print the draft and ask — back with sources / proceed / change
- [ ] 6. Deliver (public: draft review; local: review file)
- [ ] 7. Summarize; loop on re-review (public)preflight, fetch-pr-context, and fetch-existing-comments from the platform reference (selected above), before any analysis — so you know what the PR does, what's already been said, which threads are open, and whether you (or the user) have reviewed it before. preflight also settles whether draft delivery is available on this platform and instance — carry that answer to step 5, which needs it before it can ask the user anything. fetch-existing-comments includes an explicit pass to list your own prior comments; do it — they're the easiest set to duplicate. When the existing conversation is large, don't read the raw dump yourself: hand it to a subagent that returns a structured scratchpad — open threads, settled points, your own prior comments, each with path:line — and run that digest in parallel with fetching the diff. It's extraction, not judgment, so a small/fast model suffices if agent dispatch lets you pick one; with no agent dispatch, compact it inline. Either way the scratchpad, not the raw conversation, is what the analysis pass carries. Comment only on lines the PR changed.resolve-base and get-local-diff from references/local.md. There's no existing conversation to fetch.Follow references/analysis.md — the same engines work on a PR diff or a local diff. Run the code-review plugin's confidence-scored sweep and dispatch the pr-review-toolkit agents that match what the diff changed. Collect both engines' raw findings with each one's confidence and source; the merge, the false-positive discipline, and reconciliation all happen inside step 3's triage subagent, not here.
A review is worth only as much as its independence, and the merge is where independence quietly dies: deciding which findings survive, and at what confidence, is exactly the judgment a session that wrote, planned, or debated this change would bend toward its own decisions. A model is a poor judge of its own anchoring, so don't self-assess independence; remove the need for it: triage runs in a fresh subagent that never sees this conversation, whether the session touched the change or not.
Dispatch one triage subagent with the Agent tool (subagent_type: "general-purpose" — a fresh context; not "fork", which inherits this conversation and defeats the isolation). Hand it exactly:
$ME's prior comments, each with path:line — plus any off-platform source material (verbatim or an extractive digest of what was decided, never your conclusions about the change);Withhold everything else — what this session intended, designed, or argued about the change. The diff, the engines' output, and the recorded conversation are the subagent's whole world, so its verdicts can't be a defense of decisions it never saw.
The subagent merges and dedupes both engines into one findings list, then applies the false-positive discipline — it has repo access, and the verification work there (Read the file, Grep the sibling artifact) is its job; for a long list it may fan the mechanical per-finding checks out to its own nested subagents (duplicate-of-thread, $ME-commented line, line-in-diff — matching, not judgment, so a small/fast model suffices). Public: it also reconciles against the scratchpad: for any finding on a path:line $ME already commented on, plan a reply-to-thread that builds on that thread rather than a second comment — even if the prior thread is resolved; for any open thread, plan a reply-to-thread (agree, build on, or push back) instead of a duplicate inline comment; drop points already raised and settled — in a PR thread or off-platform — and keep only what's new. It returns the surviving findings (confidence and source intact) and the thread-reply plan. Local: same subagent, no scratchpad — nothing to reconcile.
If agent dispatch is unavailable (rare — e.g. running at the subagent nesting depth limit, where the engines already degraded to the inline pass): merge, apply the discipline, and reconcile inline, re-deriving each verdict from the diff and the engines' output rather than from what you remember intending, and carry a one-line independence caveat into the step 7 summary (never into the posted review).
Turn the survivors into a review per references/house-style.md. Separate the two buckets explicitly:
path:line, each a plain-voice comment.No severity badges, plain citations. Order by what matters, explained in words. Draft a one-line verdict intent for public mode (request changes / comment / approve), but don't act on it until delivery.
Pick the verdict from what the remaining findings can cost, not from how many there are. Classify each survivor by two things: how often that code actually runs, and what goes wrong when it does.
Holding a PR open over log-field quality and comment accuracy costs more in cycle time than those findings cost in risk — and it costs most on a late round, where the remainder is nearly always visibility and hygiene. Approving is a statement about the verdict, never a reason to drop or soften a finding: post them all, and say plainly in the summary why you're approving anyway. This is the verdict intent either way — the user picks the verdict at delivery.
Materialize the draft with Write to the review/ folder of the repo whose code is under review — the same one local mode delivers into (create it if missing; it stays out of commits, gitignored or per the user's preference): review/pr-<N>-draft.md. In a multi-repo or orchestrator checkout, that means the service's own clone, not the parent — say which path you used, since a sibling review/ from an earlier session is easy to confuse it with. A draft composed only in thinking does not exist — the Write call is the verifiable proof it does, and an in-repo file is one the user can open in their editor no matter what happens to the chat. Don't proceed to the gate without this file.
Print the complete draft as message text — summary, architectural notes, and the inline findings (each with path:line) — then ask the user with AskUserQuestion how to proceed. The user can only approve what they can read: if the draft isn't in the message, the gate is void. Any session-wide brevity or compression mode (terse-output instructions, token-saving styles) governs your commentary, never the deliverable — a file path, a recap, or "the review is above" does not satisfy this step.
Read the draft once more before printing it, against references/house-style.md's "What never goes in a posted review". Four things to strike, every one of which reached a real MR: a finding that opens on mechanism instead of the defect; a sentence carrying more than one claim; any phrasing that implies you ran, tried, or reproduced something (this skill never executes anything); and any line about the review itself — what you read, how you checked, what you couldn't check. Then confirm the summary opens on the MR and your overall read, not on the first bug.
Pre-gate protocol — the draft is the step 4 file, not your memory. Present it by printing the file's full content as message text, then call AskUserQuestion — and always include the file path in the question itself ("full draft in review/pr-<N>-draft.md"), so even if the print gets squeezed out, the user opens the draft in their editor from the path alone. The documented failure of this step (three sessions running): composing the draft in thinking, then gating on "the draft is above" while the message contains nothing — your memory of having printed is not evidence; only the Write call from step 4 and text visible in this turn are. If there is no step 4 file, you have no draft: go back and write it.
Check delivery capability before you ask, not after. preflight established whether this platform and instance support a draft. If they don't (a GitLab instance without the Draft Notes API, a token missing the scope, an MCP fallback with no draft tool), the options below are wrong as written — "Proceed" would publish the review immediately under a label the user read as "draft". Say plainly in the gate that draft delivery isn't available here and why, then offer publish now (post the findings and summary for real, right away) or write to a file and post nothing (local mode's artifact, so nothing reaches the platform) — and let the user pick with full knowledge of what lands. Never present a publishing action as a draft.
Respect the user's granularity choices — don't fold a distinct observation into the summary if they want it inline, and don't merge separate points. Post or write nothing before the user picks Proceed.
find-pending-review. If a draft already exists, apply the never-destroy rule (never delete or recreate it — it may hold the user's own comments; stop and ask, or append if the platform supports it and the user agrees). Otherwise create-draft-review — a pending review the user submits in the platform UI, the default. Only if the user explicitly chose to submit now, submit-review with the verdict. Send any approved reply-to-thread replies. Verify the summary actually posted, in whatever form the platform carries it. If the gate established that drafts aren't available here, deliver what the user chose there instead — publish now, or write the file and post nothing.write-review-file and print the path. Nothing is sent anywhere.Posting/saving is automated after approval; judgment is not. In public mode, if the platform rejects a comment for an out-of-diff line, move it into the summary body and retry rather than dropping it silently.
Print what was delivered (the draft review URL and inline count, or the file path and counts) with the PR URL on its own line in public mode.
Public mode: end the turn with the summary body verbatim, copy-paste ready. Print the full summary text in a fenced markdown block, then the verdict intent and any thread replies sent, and make clear it's a draft awaiting their submit. A recap or description of the summary does not satisfy this — only the verbatim text does, and no session-wide brevity or compression mode shrinks it. Run the same self-check as the results gate: if the turn's final message doesn't visibly contain the fenced summary block, it wasn't delivered — text composed in thinking renders nothing. It applies to every turn that ends with the draft created or partially delivered, including turns cut short by errors or permission walls. The platform may not show the draft's summary until submit — or may have silently dropped it at creation — so this final message can be the user's only copy of the text to paste when submitting.
Amendments after delivery (public). The workflow doesn't end at step 6 — the user will ask for changes to what you just posted ("add architectural notes", "that finding is unclear", "cut the last one"). Every one of those re-enters step 5 before anything is written to the platform: draft the new or revised text, update the step 4 file, print it, AskUserQuestion, then post. Amend in place with the platform's edit operation; never delete and recreate.
A request to change something approves the action, never the wording — "yes, add architectural notes" is permission to draft them, not to publish whatever you draft. The failure this prevents was observed across six consecutive amendments in one session: each was drafted and posted in a single step, with the text shown to the user only afterwards, so the gate that governs first delivery silently stopped applying to everything after it. Post-delivery is exactly when the user is most engaged and most likely to be surprised.
Re-review loop (public). This skill works under /loop. On a later round, repeat steps 1–6, but diff against your previous review's timestamp and treat your own prior comments as part of the conversation — raise only what's new or unaddressed and converge toward approve. Don't itemize the fixes the author made since the last round — not even a one-line recap of which items now look right; "everything from the last round is addressed" covers it. Confirm whether it's all addressed or say what still stands, thank them, and go straight to what's new — see the re-review summary example in references/house-style.md. The user still approves each round; the loop automates the cadence, not the judgment.
sleep/until loops, and never read agent transcripts to recover them — see references/analysis.md.298fce7
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.