From ship-pr
Single-command handoff: user says 'ship it', agent owns the PR from pre-flight self-check through merge. Marks the PR ready, blocks on review-quill and merge-steward via --wait gates, reacts to requested changes and failing checks by fixing code and pushing, re-enters the wait, and finishes when merge-steward reports merged. Use when the user has completed their work on a branch and wants an agent to deliver the PR.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ship-pr:ship-prThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When the user invokes this skill, they are handing you the PR. They have done the work, they think it is ready, and they expect **one command** to get it merged. From this point you own the loop. Do not ask the user what to watch for, do not spin up a cron timer, do not hand back partway.
When the user invokes this skill, they are handing you the PR. They have done the work, they think it is ready, and they expect one command to get it merged. From this point you own the loop. Do not ask the user what to watch for, do not spin up a cron timer, do not hand back partway.
You are delivering the PR into a stack with two GitHub-native services:
review-quill reviews every merge-ready head and publishes a normal APPROVE / REQUEST_CHANGES review.merge-steward admits approved, green PRs into a merge queue, speculatively integrates each one on top of the latest main, validates, and fast-forwards main to the tested result.Both tools expose pr status --wait with stable exit codes. That is the contract you block on. You only wake when there is real work.
The user handed you a PR. First make sure the PR you are about to publish is worth publishing. Most requested-changes loops are avoidable if you catch trivial issues here instead of making a reviewer catch them.
gh pr view --json number,isDraft,title,body,headRefName. If no PR exists yet, create one as a draft (gh pr create --draft) with a title + body that reflect the actual commits. If the branch is not pushed, push it first.git diff origin/main...HEAD (or the repo's base branch). Look for:
npm run ci, cargo test, pytest — whatever the repo uses). Green locally is a cheap sanity gate.gh pr ready <num>) once the above is clean. This is the moment review-quill and merge-steward start caring.Push any fixups before moving on. A clean head SHA gets reviewed once; a dirty one costs you a full review cycle.
From the PR's checkout (cwd resolves repo+PR automatically):
review-quill pr status --wait --timeout 1800 --poll 10 --json
Interpret the exit code:
0 (approved or skipped) — review-quill is done. Go to Phase 3.
2 (declined, errored, cancelled) — read the failureDetails block of the JSON:
reviewRequest.body and reviewRequest.inlineComments[] (path, line, body, author) when a reviewer requested changes.failedChecks[] and pendingChecks[] (name, status, conclusion, detailsUrl) when CI blocked the review.Triage before you fix — see Triage before you fix below. Restore review-readiness, not just the cited line. Then push a new commit and re-enter Phase 2. The latest head SHA supersedes prior attempts automatically.
4 — wait timed out. Before extending, run review-quill attempts --json to see if a review is actually in flight. If yes, extend --timeout and rerun. If not, something is wrong — surface it.
1 — usage or config error. Fix the invocation (unattached repo, bad flags). Do not retry blindly.
review-quill's approval fires a webhook that the steward already listens to. You do not enqueue manually. Then:
merge-steward pr status --wait --timeout 3600 --poll 15 --json
Interpret the exit code:
0 (merged or merged_outside_queue) — shipped. You are done.2 — terminal failure. Read kind:
changes_requested — a reviewer requested changes after approval was recorded. Restart from Phase 2.checks_failing — required CI checks failed on the PR head or the speculative integrated SHA. The JSON's github.checks[] lists failing names and detailsUrl. Pull the actual failure with gh run view <run-id> --log-failed, triage the root cause (see Triage before you fix), fix it plus any adjacent jobs at risk of the same cause, push, restart from Phase 2.evicted / dequeued — the queue removed the entry. Run merge-steward queue show --pr <num> --json for the event / incident trail. Typical causes: stale speculative branch, conflicting main advance (rebase needed), upstream incident. Fix the root cause, push, restart from Phase 2.closed — the PR was closed without merging. Stop and ask the user.4 — timed out. Run merge-steward queue show --pr <num>. If healthy and slow, extend the timeout. If an incident is pending, treat as exit 2.1 — usage or config. Fix.Both exit-2 paths are easy to get wrong in opposite directions. Avoid both.
A reviewer's comment on line 42 is evidence the branch is not review-ready, not an isolated chore. A failing CI job is one instance of a root cause that may affect other jobs in the suite. Before pushing a fix:
gh api repos/<owner>/<repo>/pulls/<num>/comments?per_page=100 is the quickest way. The goal is to see the full surface of what the reviewer thinks is unready.review-quill diff when available, or git diff origin/main...HEAD as a fallback. Do not infer from the comment alone.gh run view <run-id> --log-failed), identify the root cause, and check whether that same cause would fail other jobs in the suite. Fix the root cause, not the first visible symptom.You are restoring review-readiness, not refactoring the codebase. The reviewer did not hand you a license to restructure the module.
If the underlying concern is not a mechanical fix — the reviewer is asking for a different approach, the failing check is infrastructure-level, the merge conflict is a semantic contradiction between two intents — stop and surface it to the user instead of guessing. Two iteration cycles on the same failure with no clear diagnosis is the other hard stop. See Failures to escalate below.
Every time you push a fix, restart from Phase 2. review-quill must re-approve the new head before merge-steward admits it again. A clean sequence looks like:
gh run rerun --failed <run-id>), pushIf the same fix gets bounced twice with unclear signal, surface to the user instead of guessing a third time. Two cycles is enough to rule out simple bugs; a third indicates something the agent cannot see from the diff.
These are the patterns where you should not escalate. Fix and keep going:
main since you branched. Rebase, rerun local checks, push.detailsUrl shows a failure clearly unrelated to the diff that reproduces intermittently, the steward's flakyRetries may already handle it; otherwise gh run rerun --failed <run-id>.main, resolve, push.These are the patterns where you should stop and ask the user:
kind: closed — someone closed the PR out from under you.review-quill and merge-steward (exit 1 with "not attached"). The user needs to attach it first.--wait form is the contract. Do not wrap these commands in a cron, /loop, or busy-poll.--wait. If you are running pr status in a while loop, you are doing it wrong.failureDetails before pushing a fix. Speculative "maybe this helps" commits cost another full review + queue cycle.gh pr merge a PR attached to merge-steward. The steward is the one that writes to main.review-quill pr status --wait exited 0 on the final head SHA.merge-steward pr status --wait exited 0 with kind: merged or merged_outside_queue.Report back to the user with the merge commit SHA and any notable events that happened during the loop (number of iterations, what got fixed).
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub krasnoperov/patchrelay-agents --plugin ship-pr