Run the full spec-to-merge pipeline as one command: spec, plan, small-batch build, code review, and a PR with auto-merge — pausing at the existing human gates. Idempotent per issue — a re-invocation for work already shipped or in-flight resumes/monitors instead of re-running the pipeline. Use when the user says "ship this", "take this feature end to end", "implement this issue", "we need to build", or wants the spec->plan->build->PR flow without re-assembling it each time.
Install
npx skillscat add bdfinst/agentic-dev-team/ship Install via the SkillsCat registry.
Ship
Role: orchestrator. This command chains the existing pipeline skills end to end; it
does not implement, review, or merge anything itself — each phase is delegated to the
skill that owns it, and the existing human approval gates are preserved.
You have been invoked with the /ship command.
Orchestrator constraints
- Delegate every phase. Call the owning skill (
/specs,/plan,/build,/code-review,/pr); do not re-implement their logic here. - Honor the human gates. Do not advance past a gate without explicit approval —
this command sequences phases, it does not remove their review points. - Confirm the approach first. Before planning, screen the request against
${CLAUDE_PLUGIN_ROOT}/knowledge/decision-defaults.mdand confirm any ambiguous high-reversal-cost axis
(replace-vs-merge, format fidelity, migrate-vs-edit-stub, scope) in one batch. - Be concise. Report each phase's outcome and the next gate, nothing more.
- Agent-dispatch capability is a pipeline-wide precondition, enforced by the delegated skills, not duplicated here (issue #1461).
/plan(Step 5b),/build(Steps 3, 4, 6), and/code-review(Step 4) each independently confirm theAgent/Tasktool is present before dispatching any review agent, and each hard-fails — STOP, no self-applied review, no gate file written — when it is missing./shipdoes not re-check or restate that logic; if a delegated phase halts on missing dispatch capability,/shipreports that halt and stops with it (per constraint 2, "Honor the human gates") rather than working around it or advancing past the phase that failed. - Idempotent per issue. Never re-run the pipeline for an issue that is
already shipped or in-flight. The Step 1 resume guard decides this from
durable tracker/PR state — not conversation memory — so a re-fired command
string (e.g. aScheduleWakeup/loop prompt that repeats) lands on
resume/monitor, not a second spec→plan→build→PR pass.
Parse Arguments
Arguments: $ARGUMENTS
- Positional: the feature description (required).
--skip-spec: Skip the spec phase (use when a spec already exists for this work).--no-auto-merge: Pass through to/prso the PR is not set to auto-merge.--force-restart: Bypass the Step 1 resume guard and re-run the pipeline from
the start even when prior artifacts exist. Use only for a deliberate rebuild —
it accepts the risk of duplicate spec issues, sub-issues, and PRs.--issues <comma-separated-list>: dispatch this run as a batch covering
every listed issue number, producing one shared spec, one shared plan, and
one PR that closes every member issue. Mutually exclusive with treating$ARGUMENTS's positional feature description as a single-issue identifier —
when--issuesis given, the feature description still describes the
batch's overall work, but the resume guard and every downstream phase
operate over the full issue-number set, not one issue. Each token must be
a bare issue number (^[0-9]+$after trimming); reject the whole
invocation with a clear error naming the offending token otherwise — never
coerce or best-effort parse. Issue numbers are passed toghas separate
argv elements, never interpolated into a shell string. When--issueswas
given,<issue-identifier>for every iteration-journal-gate call in this
run is the batch's stable key: the sorted member issue numbers joined asissues-<n1>-<n2>-...(e.g.issues-101-102-103) — used identically
across every phase of this run, never re-derived differently per phase.
Workflow-state transitions (#1166)
At the start of each phase below (2-6), append one state-transition event so/run-report and friends can derive dwell time per phase — never skip this
even when a phase resumes/monitors rather than running fresh:
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/workflow_state.py" record \
--workflow ship --prior-state <PRIOR> --new-state <NEW> --session "$CLAUDE_SESSION_ID"Map phases to canonical states: Spec→SPEC, Plan→PLAN, Build→BUILD,
Review→REVIEW, PR→PR (an extra COMMIT transition is optional — most
commits happen inside /build). Omit --prior-state only for the very first
transition of a run. This is a model-authored, fail-open append (same
convention as .claude/metrics/review-value.jsonl) — never let it block a phase.
Iteration journal gate (#1168)
Before advancing from one phase (2-6) to the next, append a structured
decision entry and confirm the gate allows advancement — a hard block,
distinct from the advisory, plan-step-keyed progress-guardian gate:
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/iteration_journal_gate.py" record \
--round-id "<issue-identifier>" \
--attempted "<short note: which phase just ran>" \
--outcome "<short note: passed|failed|blocked>" \
--next-action "<short note: next phase or stop>" \
--session "$CLAUDE_SESSION_ID"
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/iteration_journal_gate.py" check \
--round-id "<issue-identifier>" \
--session "$CLAUDE_SESSION_ID"<issue-identifier> is the same identifier the Step 1a resume guard resolves
(explicit issue number/URL, or feature slug) — or, when --issues was given,
the batch key defined in Parse Arguments (issues-<n1>-<n2>-...). If check
exits non-zero, do not advance to the next phase — retry record before
continuing.
Steps
1. Approach contract
1a. Resume guard — run before anything else
/ship is idempotent per issue. Before screening the approach or invoking/specs, check whether this work has already been shipped or is in-flight,
so a re-invocation resumes or monitors instead of duplicating the spec issue,
the sub-issues, and the PR. Skip this guard only when --force-restart was
given (a deliberate rebuild).
Resolve the issue set from $ARGUMENTS: the explicit issue number(s)
(--issues list, or one number/URL), else stop and ask — the guard keys off
tracker/PR state, never off conversation memory, so a re-fired command
string (a ScheduleWakeup/loop prompt) lands on the same verdict. Then run the
deterministic guard (issue numbers are separate argv elements, validated^[0-9]+$; the script rejects anything else):
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ship_resume_guard.py" --issues <n1[,n2,...]>It probes PR state (Closes #N bodies and issue-<N> / issues-<n1>-<n2>-...
head branches, cross-repo heads never qualify as /ship's own), issue state,
and spec/plan artifacts, and prints a JSON verdict plus the signal that
fired. Report the signal so the decision is auditable, then act:
| verdict | action |
|---|---|
shipped |
Report the merged PR / closed issues and stop. No phase re-runs. |
monitor |
Report the PR and gh pr checks <pr>. If BEHIND main, rebase onto main and hand back to its checks; otherwise wait on the open gate — a re-check timer follows `knowledge/long-run-waiting.md`. Do not re-enter spec→plan→build. |
resume |
Continue from the earliest incomplete phase against the existing artifacts (--skip-spec when the epic exists; build onto the existing branch). Before writing any artifact that would duplicate one, AskUserQuestion to confirm resume-vs-restart. |
partial-batch |
Some --issues members closed, others open, no own batch PR: halt, report which members closed and how, and AskUserQuestion whether to re-form the batch from the still-open members or halt. |
batch-blocked |
A foreign open PR covers a member: halt the whole batch (no partial subset ships), post one comment on every member issue naming the in-flight PR — only if an equivalent /ship halt comment does not already exist (check first) — and take no further action this round. |
first-run |
Proceed to the approach screen. |
probe-failed |
Do not assume first-run: report the error and AskUserQuestion. |
For a batch, the stable key is issues-<n1>-<n2>-... (sorted), as defined in
Parse Arguments.
1b. Approach screen
Once the guard confirms a genuine first run (or --force-restart was given),
screen the request against ${CLAUDE_PLUGIN_ROOT}/knowledge/decision-defaults.md. Surface any ambiguous
axis to the user in a single batch and get the answers before proceeding. Stop here if
a genuinely blocking ambiguity remains.
2. Spec (unless --skip-spec)
Invoke /specs for the feature. /specs runs the Ambiguity Resolution Protocol
before finalizing acceptance criteria — any finding classified requires-stakeholder-input
is surfaced to the human as a required answer, not an optional confirmation.
When --issues was given, /specs is invoked once for the whole batch's
combined feature description — one shared spec covering every member issue.
If /specs' own Scope Split Protocol determines the members describe
genuinely unrelated features, that split is /specs' existing human gate —
surface it and stop, rather than overriding it to force one spec.
These unresolved items ARE the human gate. Do not auto-approve past them, even in
non-interactive mode. The only exception is --skip-spec (when a reviewed spec already
exists). A spec that passed its consistency gate with undocumented assumptions is not
an approved spec.
Present the completed spec (Intent, Architecture, Acceptance Criteria, and Ambiguity
Log) for human review. Human gate — wait for approval before planning.
3. Plan
Invoke /plan with the (approved) spec. The plan decomposes the feature into vertical
slices with Gherkin scenarios and states the chosen stance on any decision-defaults
axis. Human gate — wait for plan approval before building.
When --issues was given, /plan is likewise invoked once for the whole
batch — one shared plan covering every member issue, never one plan per issue.
4. Build
Invoke /build to execute the approved plan in small per-behavior batches (code-first),
with inline review checkpoints and verification evidence. Do not proceed until the build reports a green
suite.
5. Review
First check whether /build's checkpoints already reviewed this exact change:
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/ship_review_gate.py" --files <the branch's changed files>{"skip": true} means every applicable lens has a ledger pass at each file's
current content — skip the pass and say so in the Step 7 report (list the
cleared lenses). Anything else (including any doubt: no ledger, edited since,
unhashable file) runs the pass as below. --force-restart never skips.
Invoke /code-review over the changes and let its fix loop converge. Surface any
findings that need human judgment.
This dispatch deliberately omits --internal: /ship is a top-level,
human-typed command, and this Review phase is its pipeline's human-facing
quality gate, so /code-review writing its usual .dev-team-reports/code-review.md
report here is intentional — see knowledge/report-output-location.md's
"Report exception: /ship" section, not an unfixed oversight.
6. PR
Invoke /pr (passing --no-auto-merge only if it was given to /ship). /pr runs
the pre-PR quality gate, opens the PR, and — by default — enables auto-merge so it
lands once checks pass. Human gate — the PR is the final review artifact.
When --issues was given, the resulting PR body must carry one Closes #<N>
line per member issue — not just one — so merging it closes every batch
member. /pr's existing closing-keyword-lint guidance
(python3 "${CLAUDE_PLUGIN_ROOT}/scripts/pr_close_keyword_lint.py", seeskills/pr/SKILL.md) needs no change to support this: it already lints eachCloses #<N> line independently, so a batch PR body simply carries more of
them. /ship confirms the created PR body actually carries one such line
per member before reporting success; if any is missing, state the gap
explicitly rather than silently reporting the batch as shipped.
7. Report
Report the PR URL, the quality-gate result, and whether auto-merge is armed.
Notes
/shipis sequencing only: every gate, fix loop, and evidence requirement comes from
the underlying skills. If any phase stops at a gate,/shipstops with it.- For a plan-only pass, use
/plan; for build-only, use/build./shipis for the
whole loop in one invocation. - Re-invoking
/shipfor an issue that is already shipped or in-flight is safe:
the Step 1 resume guard (1a) reports/monitors instead of re-running. Pass--force-restartonly when a deliberate rebuild is intended.