A pull request review skill with four parallel reviewers

One long review prompt mixes concerns and keeps findings that do not hold up. This graph splits the diff to four specialist subagents that run at the same time, then a verifier that never saw their reasoning keeps only findings that point at a real file and line.

7 steps in 4 stages · 7 subagents · a kit of 12 files

Free. Built in your browser; nothing is uploaded. No API key, no account.

How it runs

Steps in the same stage start at the same time. Each subagent gets only what its incoming edges carry, and a step in a fresh context never sees the reasoning of the steps before it. A gate decides whether the work passes, and a failed gate re-runs the work it checks.

  1. Stage 1
    • Split · Planner

      sonnet · Read

  2. Stage 24 in parallel
    • Security & Auth · Worker

      haiku · Read, Grep, Glob, Bash

    • Performance & Memory · Worker

      haiku · Read, Grep, Glob, Bash

    • Architecture & Style · Worker

      haiku · Read, Grep, Glob, Bash

    • Test Coverage · Worker

      haiku · Read, Grep, Glob, Bash

  3. Stage 3
    • VERIFIER (Fresh Context) · Checker

      opus · Read, Grep, Glob · fresh context

      Gate: Every kept finding points at a file and line in the diff.

  4. Stage 4
    • Final answer · Writer

      sonnet · Read

Use it when

  • You want Claude Code to review a branch or pull request before a human does.
  • Reviews from a single prompt are long and full of guesses.
  • You want each reviewer on a cheap model and only the final check on a strong one.

Change these first

  • Swap a reviewer for what your team cares about, such as accessibility or API compatibility.
  • Point the verifier's gate at your own rule, for example that every finding cites a line of the diff.

Need a workflow built for your team? Fixed-price packages

What you get

An orchestrating SKILL.md, one Claude Code subagent per step with its own tools and model, and the same skill as a Cursor rule. Your agent runs it with its own subagents; nothing on this site calls a model.

pr-review-graph-skill-kit.zip12 files
  • .claude/skills/pr-review-graph/SKILL.mdorchestrator
  • .claude/skills/pr-review-graph/graph.skill.mdgraph source
  • .claude/agents/pr-review-graph-splitter.mdsubagent
  • .claude/agents/pr-review-graph-review-security.mdsubagent
  • .claude/agents/pr-review-graph-review-performance.mdsubagent
  • .claude/agents/pr-review-graph-review-architecture.mdsubagent
  • .skill-graph/.gitignoresupport
  • .cursor/rules/pr-review-graph.mdcCursor rule
  • README.mdreadme
  • + 3 more subagents
.claude/skills/pr-review-graph/SKILL.md
---
name: pr-review-graph
description: "Reviews a pull request with four parallel specialists, filters false positives in a fresh context, and writes prioritized PR comments."
---

# pr-review-graph

Reviews a pull request with four parallel specialists, filters false positives in a fresh context, and writes prioritized PR comments.

This skill is a graph: each step has its own prompt and context, and only the payloads named below move between steps.

## Plan

Run the stages in order. Every model step runs in its own subagent; do not do a step's work yourself. Only command steps and approvals are yours to run. Steps in the same stage do not depend on each other: start them together, in one message with several subagent calls.

The input (`goal`) is the user's goal: their request, word for word, handed on under `### goal`. Ask for it if the user has not given one.

### Stage 1 · 1 step

- **SPLIT** (`splitter`) → subagent `pr-review-graph-splitter`
  - Hand it: the user's goal.
  - Expect: `subtask_json` (json).
  - Contract check (`subtask_json`): save its output to `.skill-graph/pr-review-graph/splitter.json`, then run `node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));const k=['review_security','review_performance','review_architecture','review_tests'];const ok=d!==null&&typeof d==='object'&&Array.isArray(d)===false;const m=ok?k.filter((x)=>Object.hasOwn(d,x)===false):k;if(m.length>0){console.error('Missing keys: '+m.join(', '));process.exit(1)}" .skill-graph/pr-review-graph/splitter.json` with Bash. Exit code 0 passes.
  - If a contract check fails: re-run this step once with its previous answer and the error output. If it fails again, stop and show the user the output.

### Stage 2 · 4 steps in parallel

- **Security & Auth** (`review_security`) → subagent `pr-review-graph-review-security`
  - Hand it: only the `review_security` value from the JSON of SPLIT (`splitter`).
  - Expect: `review_findings` (markdown).
- **Performance & Memory** (`review_performance`) → subagent `pr-review-graph-review-performance`
  - Hand it: only the `review_performance` value from the JSON of SPLIT (`splitter`).
  - Expect: `review_findings` (markdown).
- **Architecture & Style** (`review_architecture`) → subagent `pr-review-graph-review-architecture`
  - Hand it: only the `review_architecture` value from the JSON of SPLIT (`splitter`).
  - Expect: `review_findings` (markdown).
- **Test Coverage** (`review_tests`) → subagent `pr-review-graph-review-tests`
  - Hand it: only the `review_tests` value from the JSON of SPLIT (`splitter`).
  - Expect: `review_findings` (markdown).


… 37 more lines in the kit

Or let Claude adapt it

Add Skill Graph to Claude Code as a connector, then ask. Claude loads this starter, changes it for your project, checks it and hands you the kit.

Set up the connector

Ask Claude

Use Skill Graph: get the pr-review-graph template, adapt it to this project, validate it until it has no errors, and compile it for Claude Code.

The graph file

The whole workflow is one Markdown file, graph.skill.md: the steps and edges in the frontmatter, one prompt per step below it. The guide explains every field.

graph.skill.md · 154 lines
---
name: pr-review-graph
description: Reviews a pull request with four parallel specialists, filters false positives in a fresh context, and writes prioritized PR comments.
spec: skill-graph/1
topology:
  nodes:
    - id: goal
      type: input
      label: PULL REQUEST (diff or link)
    - id: splitter
      type: orchestrator
      label: SPLIT
      model: sonnet
      tools:
        - Read
    - id: review_security
      type: worker
      label: Security & Auth
      model: haiku
      tools:
        - Read
        - Grep
        - Glob
        - Bash
    - id: review_performance
      type: worker
      label: Performance & Memory
      model: haiku
      tools:
        - Read
        - Grep
        - Glob
        - Bash
    - id: review_architecture
      type: worker
      label: Architecture & Style
      model: haiku
      tools:
        - Read
        - Grep
        - Glob
        - Bash
    - id: review_tests
      type: worker
      label: Test Coverage
      model: haiku
      tools:
        - Read
        - Grep
        - Glob
        - Bash
    - id: verifier
      type: verifier
      label: VERIFIER (Fresh Context)
      isolated_context: true
      model: opus
      tools:
        - Read
        - Grep
        - Glob
      gate: Every kept finding points at a file and line in the diff.
      on_fail: retry
      max_retries: 1
    - id: merger
      type: synthesizer
      label: FINAL ANSWER
      model: sonnet
      tools:
        - Read
  edges:
    - from: goal
      to: splitter
    - from: splitter
      to:
        - review_security
        - review_performance
        - review_architecture
        - review_tests
      contract: subtask_json
    - from:
        - review_security
        - review_performance
        - review_architecture
        - review_tests
      to: verifier
      contract: review_findings
    - from: verifier
      to: merger
      contract: verified_findings
contracts:
  subtask_json:
    format: json
    description: One key per worker id; each value is that worker's task.
  review_findings:
    format: markdown
    description: A numbered list; every item has its evidence and a confidence of high, medium or low.
  verified_findings:
    format: markdown
    description: Only the items that passed verification, then the rejected ones with the reason.
---

# Node Prompts & Edge Contracts

## @node: splitter
You are the review lead. Read the pull request and give each reviewer the files and concerns that matter for their specialty.

Input:
{{goal}}

Output strictly as JSON with one key per worker: `review_security`, `review_performance`, `review_architecture`, `review_tests`. Each value is the exact task for that worker.

## @node: review_security
Review ONLY for security: injection, authn/authz gaps, secrets, unsafe deserialization, SSRF, missing input validation.

Your task: {{splitter.review_security}}

Return findings as a numbered list. For each one give the evidence (file, line, quote or source) and a confidence of high, medium or low.

## @node: review_performance
Review ONLY for performance: N+1 queries, unbounded loops or payloads, leaks, blocking calls on hot paths, missing caching.

Your task: {{splitter.review_performance}}

Return findings as a numbered list. For each one give the evidence (file, line, quote or source) and a confidence of high, medium or low.

## @node: review_architecture
Review ONLY for architecture: layering violations, duplicated logic, naming, consistency with existing patterns in the codebase.

Your task: {{splitter.review_architecture}}

Return findings as a numbered list. For each one give the evidence (file, line, quote or source) and a confidence of high, medium or low.

## @node: review_tests
Review ONLY test coverage: untested branches, missing edge cases, brittle or meaningless assertions.

Your task: {{splitter.review_tests}}

Return findings as a numbered list. For each one give the evidence (file, line, quote or source) and a confidence of high, medium or low.

## @node: verifier
You are an independent auditor. Re-check each finding against the diff itself and remove false positives.

You only see the raw worker outputs below, not their reasoning. Drop any claim without concrete evidence, merge duplicates, and mark what you rejected and why.

Original input: {{goal}}

Worker outputs:
{{workers.output}}

## @node: merger
Write the final review as prioritized PR comments (blocking, should fix, nit). Each comment names the file and line and says what to change.

{{verifier.output}}