Launch the Interlock ship workflow — take a reviewed OpenSpec change from tasks to commit in one uninterrupted run (waves, verify, commit). Default is lean; pass --strict for review, handoff and conformance. Use when the user ran /interlock:ship, asked to ship a reviewed change, or spec --continue passed the readiness gate. Never invoke after spec unless they asked.
Installs into .claude/skills of the current project.
Are you the author of Ship?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/renzrollon-ship)
---
name: ship
description: Launch the Interlock ship workflow — take a reviewed OpenSpec change from tasks to commit in one uninterrupted run (waves, verify, commit). Default is lean; pass --strict for review, handoff and conformance. Use when the user ran /interlock:ship, asked to ship a reviewed change, or spec --continue passed the readiness gate. Never invoke after spec unless they asked.
license: MIT
compatibility: Requires Claude Code v2.1.154+ with dynamic workflows enabled. Node.js >= 18 for the bundled interlock CLI.
argument-hint: "[<change-name>] [--apply-only] [--no-commit] [--skip-e2e] [--skip-coverage] [--solo] [--waves] [--tdd] [--no-tdd] [--review] [--handoff] [--conformance] [--strict]"
disallowed-tools: AskUserQuestion
allowed-tools: Read
metadata:
type: execution
---
This skill does not implement the ship loop. It launches `${CLAUDE_PLUGIN_ROOT}/workflows/ship.js` on the Workflow runtime. Implementing waves, review, remediation, verification, or a commit from this conversation is a bug.
The loop lives in that script on purpose: a skill is instructions a model can talk itself out of, and ship is sold as a run that asks nothing. Keep it that way.
Default is **lean**: waves → unit verify → commit. Adversarial review, handoff artifacts and conformance are opt-in. `--strict` restores the previous full loop.
## 1. Parse arguments
From `$ARGUMENTS` (or the Skill `args` payload) build an **object**. Prefer `{ change: "<name>" }`. A bare string or a one-element array is also a change name — the script accepts all three — but never omit the name when the user gave one. A nameless validate against several active changes is a halt, not a prompt.
| Input | `args` field |
|---|---|
| First non-flag token | `change` (omit if none — the script resolves the active change) |
| `mode=continue` / this run is spec `--continue` | `mode: "continue"` (omit otherwise; the script defaults to `checkpoint`) |
| `--apply-only` `--no-commit` `--skip-e2e` `--skip-coverage` | `flags: ["apply-only", ...]` |
| `--review` `--handoff` `--conformance` | `flags: ["review", ...]` — enable that tail piece |
| `--strict` | `flags: ["strict"]` — review + handoff + conformance + autonomy record (previous default) |
| `--solo` | `flags: ["solo"]` — force one agent to implement the whole change in order |
| `--waves` | `flags: ["waves"]` — force the parallel plan, refusing a solo recommendation |
| `--tdd` | `flags: ["tdd"]` — run the change's leading failing-test section first |
| `--no-tdd` | `flags: ["no-tdd"]` — never run a leading failing-test wave |
| `--max-parallel N` | `maxParallel: N` |
Pass a shape flag only when the user asked for one. Absent both, the classifier recommends a shape and the planner honours it inside a published envelope; the plan preview names the mode and why before a single implementer is spawned, so there is nothing to decide here. `--solo` and `--waves` together is a halt, not a preference to resolve.
The **task** shape is a different decision and has its own default: absent `--tdd` and `--no-tdd`, the CLI reads it from the `Failing tests first` heading `/interlock:spec` writes into `tasks.md`, so a change authored test-first runs that way with no flag at all and every other change is planned exactly as before. Pass a flag only to override the file. `--tdd` and `--no-tdd` together is a halt, for the same reason `--solo --waves` is.
Do not invent `--strict` because the change looks large. Continuity (`spec --continue`) also launches default lean unless the user passed a tail flag.
## 2. Launch the workflow
If the **Workflow tool** is available, this skill invocation is your authorization. Call it **once**, then stop. Do not narrate the loop. Do not implement tasks. Do not commit yourself.
```
Workflow({
scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/ship.js",
args: { change: "<name or omit>", mode: "checkpoint" | "continue", flags: ["..."] }
})
```
When it returns, you are done. Print the summary. **Do not call Workflow again in this conversation.** Leftover `- [ ]` boxes after a run are a report, not authorization to call Workflow again — those are failed or unticked tasks, and a second ship is a full new 20+ agent run. Only a **new user message** that explicitly asks to ship leftover tasks (or `/interlock:ship` again) is a relaunch.
If a `/goal` is active, it is satisfied when the transcript contains `GOAL MET: interlock ship`. Leftover checkboxes do not continue the goal. Do not launch another Workflow to "finish the goal." Do not invoke `/goal` from this skill.
`mode` matters more than it looks. The outcome corpus compares continuity runs against checkpoint runs; a continuity run filed as a checkpoint makes that comparison say the opposite of the truth.
## 3. If the Workflow tool is not available
**Halt.** Do not fall back to implementing the change in this conversation.
`/interlock:ship` needs Claude Code **v2.1.154+** with Dynamic workflows enabled (`/config`). They are also off under `disableWorkflows`, org policy, `CLAUDE_CODE_DISABLE_WORKFLOWS`, or a Pro plan that has not turned the row on. Some IDE surfaces never expose the Workflow tool.
Tell the user that, and that everything else in Interlock still works — `spec`, the reviews, `commit`. Do not offer to "just start on the first task".
There is a second, experimental host — `bin/interlock-run`, which runs the same loop over a vendor coding CLI the user names (`--host claude | acp | codex | qwen`), `--strict` included: every step, the review and remediation rounds and the handoff among them, is emitted by `interlock run` and interpreted there as it is here. It is still a **separate binary this skill never invokes**, and it is still not a fallback for a missing Workflow tool. A user runs it themselves from a terminal; `/interlock:ship` is Claude Code only, and the runner refuses `--host workflow` from the other side.