Ship a change: edit until tests pass, review, approve once
The implement step repeats until your test command exits 0, so a program decides it is done, not the model. The diff then goes to two reviewers in fresh contexts, a gate holds back anything with an open blocking finding, and nothing is pushed before you approve.
8 steps in 7 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.
- Stage 1
Plan · Planner
sonnet · Read, Grep, Glob
- Stage 2
IMPLEMENT (loops on tests) · Worker
sonnet · Read, Grep, Glob, Edit, Write, Bash · repeats until npm test passes
- Stage 3
Collect diff · Command
runs git diff --stat && git diff
- Stage 42 in parallel
REVIEW: Correctness · Worker
haiku · Read, Grep, Glob · fresh context
REVIEW: Security · Worker
haiku · Read, Grep, Glob · fresh context
- Stage 5
GATE (Fresh Context) · Checker
opus · Read, Grep, Glob · fresh context
Gate: No blocking finding is left open, and every finding cites a line of the diff.
- Stage 6
Approve pull request · Your OK
asks you
- Stage 7
Open pull request · Helper
haiku · Bash · irreversible
Use it when
- You hand Claude Code a feature or fix and want it finished, tested and reviewed.
- You want the pull request opened for you, but only after a yes from you.
- Agents keep saying done while tests still fail.
Change these first
- Change the loop's check from npm test to your own test command.
- Narrow the publish step's Bash to the git and gh commands you allow.
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.
- .claude/skills/ship-a-change/SKILL.mdorchestrator
- .claude/skills/ship-a-change/graph.skill.mdgraph source
- .claude/agents/ship-a-change-plan.mdsubagent
- .claude/agents/ship-a-change-implement.mdsubagent
- .claude/agents/ship-a-change-review-correctness.mdsubagent
- .claude/agents/ship-a-change-review-security.mdsubagent
- .skill-graph/.gitignoresupport
- .cursor/rules/ship-a-change.mdcCursor rule
- README.mdreadme
- + 3 more subagents
--- name: ship-a-change description: "Implements a change in a loop on the test suite, reviews the diff in parallel, gates it in a fresh context, and opens a pull request after one approval." --- # ship-a-change Implements a change in a loop on the test suite, reviews the diff in parallel, gates it in a fresh context, and opens a pull request after one approval. 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. ### Before stage 1 · lessons - Read `.skill-graph/ship-a-change/EXPERIENCE.md` if it exists (there is none before the first run). Each lesson starts with `- [L<n>] <step id>:`. - When you hand a step its task, add the lessons for its id, verbatim, under `### Lessons from earlier runs`. Note which lessons each step got. - While the run goes, keep a failure log: every check or command that exited non-zero (the command and its last 20 lines of output), every `GATE: FAIL` line, and every retry. Also note which steps passed their check or gate on the first try. ### Stage 1 · 1 step - **PLAN** (`plan`) → subagent `ship-a-change-plan` - Hand it: the user's goal; its lessons from earlier runs, if any. - Expect: `change_plan` (markdown). ### Stage 2 · 1 step - **IMPLEMENT (loops on tests)** (`implement`) → subagent `ship-a-change-implement` · loop until `npm test` exits 0, at most 3 iterations - Hand it: the output of PLAN (`plan`); its lessons from earlier runs, if any. - Loop, before iteration 1: read `.skill-graph/ship-a-change/implement.loop.md` if it exists (it keeps notes from earlier runs), and append a heading `# Run <date>: <the first line of the user's goal>` for this run (create the file and folder if needed). If the file is over 200 lines, delete the oldest `# Run` sections first. - Loop, each iteration: hand it the same inputs plus `### Loop` with "iteration <n> of 3", the whole ledger and, from iteration 2, the last 40 lines of the check's output. - After each iteration: append its `## Loop note` section to `.skill-graph/ship-a-change/implement.loop.md` under `## Iteration <n>`, with the check's exit code. - The loop ends when `npm test` (run with Bash after each iteration) exits 0. Otherwise start the next iteration. - If iteration 3 ends without that, stop the run and show the user the ledger for this run and the last answer. - Its output is the last iteration's answer, without its `## Loop note` section. - Add every iteration that did not end the loop to the failure log, with what stopped it. … 70 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 connectorAsk Claude
Use Skill Graph: get the ship-a-change 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 · 148 lines
---
name: ship-a-change
description: Implements a change in a loop on the test suite, reviews the diff in parallel, gates it in a fresh context, and opens a pull request after one approval.
spec: skill-graph/1
experience:
max_lessons: 20
topology:
nodes:
- id: goal
type: input
label: CHANGE REQUEST
- id: plan
type: orchestrator
label: PLAN
model: sonnet
tools: [Read, Grep, Glob]
- id: implement
type: worker
label: IMPLEMENT (loops on tests)
model: sonnet
tools: [Read, Grep, Glob, Edit, Write, Bash]
check: npm test
loop:
until: check
max_iterations: 3
risk: wide
- id: diff
type: code
label: COLLECT DIFF
run: git diff --stat && git diff
- id: review_correctness
type: worker
label: "REVIEW: Correctness"
isolated_context: true
model: haiku
tools: [Read, Grep, Glob]
- id: review_security
type: worker
label: "REVIEW: Security"
isolated_context: true
model: haiku
tools: [Read, Grep, Glob]
- id: gate
type: verifier
label: GATE (Fresh Context)
isolated_context: true
model: opus
tools: [Read, Grep, Glob]
gate: No blocking finding is left open, and every finding cites a line of the diff.
on_fail: retry
max_retries: 2
retry_target: implement
- id: approve
type: approval
label: APPROVE PULL REQUEST
- id: publish
type: agent
label: OPEN PULL REQUEST
model: haiku
tools: [Bash]
risk: irreversible
on_fail: stop
edges:
- from: goal
to: plan
- from: plan
to: implement
contract: change_plan
- from: implement
to: diff
- from: diff
to:
- review_correctness
- review_security
- gate
contract: diff_text
- from:
- review_correctness
- review_security
to: gate
contract: review_findings
- from: gate
to:
- approve
- publish
contract: verdict
- from: approve
to: publish
contracts:
change_plan:
format: markdown
description: The files to change, what changes in each, and the tests that prove it.
diff_text:
format: text
description: The output of git diff, unchanged.
review_findings:
format: markdown
description: A numbered list; each finding cites a file and line of the diff and says blocking or minor.
verdict:
format: markdown
description: PASS or FAIL, the findings kept with their evidence, and a three-line summary of the change.
---
# Node Prompts & Edge Contracts
## @node: plan
Read the code this request touches and write a short plan: the files to change, what changes in each, and the tests to add or update.
The request:
{{goal}}
## @node: implement
Implement this plan. Change only the files it names; add or update the tests it lists.
{{plan.output}}
Return a short summary of what you changed.
## @node: review_correctness
Review ONLY correctness: logic errors, missed edge cases, broken contracts and tests that do not test the change.
{{diff.output}}
## @node: review_security
Review ONLY security: injection, missing authorization, secrets, unsafe input handling.
{{diff.output}}
## @node: gate
You see only the diff and the two reviews, not how the change was made. Keep the findings that the diff supports, drop the rest, and decide whether anything blocking is left.
Diff:
{{diff.output}}
Reviews:
{{review_correctness.output}}
{{review_security.output}}
## @node: approve
Show the verdict and the diff summary, then ask: open a pull request with this change?
## @node: publish
The user approved: {{approve.output}}
Commit the change on a new branch, push it, and open a pull request. Use the summary in this verdict as its description:
{{gate.output}}
More starter graphs
- PR reviewSecurity, performance, architecture and test coverage reviewers
- Bug triageStack trace, logs, recent commits and a minimal repro
- RFC discoveryFeasibility, prior art, interface design and failure modes
- Review each fileOne fresh-context review per changed file, however many there are, then merge and gate
- Parallel auditResearch, compare, check and find gaps, then verify in a fresh context
- Research reportSources, figures, counterpoints and open questions, fact-checked in a fresh context
- Write an articleAngle, outline, facts and reader in parallel, then an editor check before the draft
- Analyze a datasetProfile, clean, analyze and sanity-check a table in parallel, then re-check every figure
- Design an appUsers, features, screens and data model in parallel, then a product review before the spec