ship
Orchestrate the full spec → implement → review → fix → commit pipeline. Use when shipping a complete feature end-to-end.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Orchestrate the full spec → implement → review → fix → commit pipeline. Use when shipping a complete feature end-to-end.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Create well-structured atomic commits with conventional commit messages. Use when ready to commit working changes.
Write a feature spec from requirements in .claude/input/. Use when starting a new feature, before implementation begins.
Break a concept document, draft, or product brief into independent PRDs that each feed into /ship. Use when input contains multiple features or a big-picture vision.
Ship decomposed PRDs in parallel. Analyzes file conflicts, groups into batches, runs /ship in isolated worktrees, merges results. Use after /decompose.
Implement a feature from a spec file in .claude/specs/. Use after a spec is written and approved.
Audit dependencies for vulnerabilities and scan for committed secrets. Use periodically or when security alerts flag a dependency.
| name | ship |
| description | Orchestrate the full spec → implement → review → fix → commit pipeline. Use when shipping a complete feature end-to-end. |
| disable-model-invocation | true |
| argument-hint | <feature description> [--dry-run] [--no-finalize] [--auto-finalize] |
| model | claude-opus-4-6 |
| effort | high |
Orchestrate the full spec-to-commit pipeline for the feature described in $ARGUMENTS or in .claude/input/.
--dry-run mode: If $ARGUMENTS contains --dry-run, run only Steps 1–2 (questions + spec), then print a scope report and stop. No branch, no implementation, no commits. Use this to preview complexity and scope before committing to a full pipeline run.
--no-finalize mode: If $ARGUMENTS contains --no-finalize, run the full pipeline (spec → implement → review → fix → commit) but skip Step 7 entirely — neither gate nor push nor state change. The feature stays on its branch with all commits applied and checks passing, but is not merged to main and the work item stays in its current state. Used by /fleet to manage merges centrally.
--auto-finalize mode: If $ARGUMENTS contains --auto-finalize, skip the Step 7a finalize gate and go straight to push + state transition. Use only when you trust the pipeline output without a manual smoke-test (doc-only commits, trivial refactors, hotfixes under time pressure). Default is the gated flow — the user sees a summary and must confirm before anything is pushed or the ticket state changes.
Architecture: The main session is a thin orchestrator only — it never reads code files or accumulates implementation context. Each phase runs in a dedicated subagent with a clean context. The spec file, review file, and git diff are the handoff mechanism between phases.
Progress updates: After each subagent returns, print a one-line status update so the user can track progress. Use this format:
✓ Step N — <phase> complete. <key detail from subagent summary>
Examples: ✓ Step 2 — Spec complete. 7 files, 3 new. · ✓ Step 3 — Implementation complete. All checks pass. · ✓ Step 4 — Review: pass with fixes (2 major). · ✓ Step 4 — Fix cycle 1 complete. 2/2 issues resolved.
Main session (orchestrator — reads summaries only)
├── Step 0: branch setup → creates ticket branch (or stays on current branch)
├── Step 0b: ticket resolution → loads work item + comments from tracker (if configured), sets state
├── Step 1b: historical patterns → reads metrics-pipeline.csv → builds spec guidance
├── Subagent A: spec [opus] → writes .claude/specs/<name>.md (informed by patterns)
├── Step 2b: decision review → reads spec "Decisions made by Claude" → user approval
│
├── Subagent B: implement [opus] → single subagent, returns summary
├── Subagent C: review [opus] → writes .claude/reviews/<name>-review.md
├── Subagent D: fix [opus if rework, sonnet if fixes]→ loop back to C
├── Step 4b: lesson graduation → graduates mature lessons → CLAUDE.md
├── Step 4c: integration check [opus] → cross-phase glue review (phased only)
├── Step 5: final verify → typecheck → lint → tests → build
├── Step 5b: changelog entry → writes changelog/<branch>.md (per-ticket, merge-conflict-free)
├── Subagent E: commit [sonnet]→ atomic commits on feature branch
├── Step 6b: tracker feedback → posts non-obvious context to work item (sparingly)
├── Step 7a: finalize gate → show summary + test hints, wait for user confirm
└── Step 7b: push + finalize → pushes branch to origin, updates ticket state
Skip this step entirely if --dry-run is set — dry-run never creates branches.
Before doing anything else:
.claude/rules/branch-management.md exists. If it does, read it and note the branch naming convention. This determines how the branch will be named in step 0.4 below.git branch --show-currentmain or master), stay on it — this is the working branch. Note its name. Try to parse it for a ticket ID (see branch-management.md for the pattern). Do NOT switch to main to create a new branch. Create a checkpoint from the current HEAD: git branch checkpoint/<spec-name>main or master and the project requires a ticket-based branch name (from branch-management.md), set branch_pending = true — defer branch creation until after Step 1 where the ticket metadata will be collected. If no project convention exists, run: git checkout -b feat/<spec-name> where <spec-name> is derived from $ARGUMENTS or the most recently modified file in .claude/input/. Then create checkpoint: git branch checkpoint/<spec-name>If $ARGUMENTS contains a number (e.g. /ship 1234 → ticket ID 1234), resolve the ticket using this fallback chain:
Local input file first: Glob for .claude/input/{id}* or .claude/input/*{id}*. If a file is found, read it and use its content as the feature description. Extract any ticket metadata (type, application) from the file if present.
Work-item tracker lookup (if MCP tools available): If no local file was found, check which work-item tracker MCP tools are configured (Azure DevOps, Jira, Linear, GitHub Issues, or any other tracker with an MCP integration). Use whatever "get work item" tool is available to fetch the ticket by ID, including comments and linked items if the tool supports it. If the work item is found:
branch-management.md, if the convention maps work item types to branch types)ticket_resolved = true — Step 1 can skip asking for ticket metadataResolved, Closed), skip the transition and warn the user — resuming a completed ticket needs confirmation.No tracker configured? Skip this step entirely — the pipeline works fully without a work-item tracker. The user will provide ticket metadata manually in Step 1.
Inspect prior implementation work in linked items: From the related, parent, and duplicates arrays of the context response, identify any item with state Resolved, Closed, or completed. For each such item, examine artifacts.commits, artifacts.branches, and artifacts.pullRequests:
git show <sha> --stat (and git show <sha> if the diff is small) to see what was implementedgit log master..<branch> --oneline to see what's on itSummarize the prior work (which fields/methods/files already exist, what behaviour is already in place) into a prior_work_context block. This prevents the spec subagent from re-scoping work that is already done in a sibling ticket.
Fallback: If all lookups fail, proceed to Step 1 and ask the user for ticket metadata as usual.
Store the resolved ticket data (id, title, type, description, acceptanceCriteria, comments, linked items, prior_work_context) in a ticket_context variable for use in subsequent steps. The spec subagent prompt in Step 2 must include prior_work_context so it can fold the existing implementation into the spec.
Read only CLAUDE.md, .claude/rules/branch-management.md (if it exists), and .claude/input/ to understand the feature scope and project conventions.
Ticket metadata (mandatory if branch-management.md requires it): If ticket_resolved is true (from Step 0b), skip the ticket metadata questions — use the resolved data instead. Otherwise, include the ticket metadata questions required by the project's branch-management.md at the start of the batch.
Then ask any other clarifying questions about the feature in the same batch. Use selectable options where possible. Wait for answers. This is the only user interruption before commit.
Deferred branch creation: If branch_pending was set in Step 0, create the branch now using the collected ticket metadata, following the pattern defined in branch-management.md. Then create checkpoint: git branch checkpoint/<spec-name>.
If requirements are fully unambiguous and you are already on a correctly named ticket branch, skip the questions and proceed to Step 1b.
Read .claude/metrics-pipeline.csv if it exists. If the file has fewer than 3 rows (excluding the header), skip this step — not enough data for meaningful patterns.
Analysis:
area for the current feature from $ARGUMENTS and .claude/input/ context (e.g. "add payment webhook" → api or payment)area matches (or is closely related to) the current feature's areareview_cycles across matching rowsissue_categories values that appear in 2+ matching rowsfiles_changed across matching rowsBuild a historical_context block (plain text, 2-5 lines max) to pass to the spec subagent. Examples:
Features in the
apiarea averaged 2.3 review cycles. Recurring issue categories: validation, edge-cases. Spec should include explicit input validation rules and edge case handling for each endpoint.
Features in the
uiarea averaged 1.0 review cycles. No recurring issues. No additional spec guidance needed.
Not enough historical data for this area. No additional spec guidance.
If no meaningful patterns are found, set historical_context to empty and proceed — this step is purely additive.
Launch a subagent (model: opus) with:
"Read
.claude/skills/0_spec/SKILL.mdand follow all steps exactly. The feature to spec is: $ARGUMENTS. The user has already answered clarifying questions; their answers are: [paste answers from Step 1 here, or 'none — requirements are unambiguous']. Do not ask further questions — skip step 6. Historical pattern analysis from prior pipeline runs: [paste historical_context from Step 1b here, or 'none — no historical data']. Prior work already implemented in linked tickets: [paste prior_work_context from Step 0b here, or 'none — no linked work items found']. You are running as a subagent. The prior work context tells you which fields/methods/behaviour already exists from sibling tickets — fold this into 'Affected files', 'Implementation notes', and adjust scope accordingly; do NOT re-spec work that is already done. Skip Step 2b in 0_spec since I have already resolved the ticket context. Write the spec and return: (1) the spec filename, (2) the file count from Affected files + New files, (3) a one-paragraph summary of what will be built, (4) the full Decisions made by Claude section if present."
Read the returned summary. Do not read the spec file itself.
Complexity gate: if the returned file count exceeds complexity_gate_max_files from CLAUDE.md (default: 10), stop and tell the user — suggest decomposing into sub-specs. Do not continue without user confirmation.
If the spec subagent returned a "Decisions made by Claude" section with any decisions:
If no decisions were made (or the section is empty), skip to Step 3.
If --dry-run was passed in $ARGUMENTS, print the following scope report and stop — do not continue to Step 3:
## Dry-run scope report
- **Spec:** .claude/specs/<name>.md
- **Files affected:** N (affected) + N (new) = N total
- **Complexity gate:** pass / ⚠ exceeds threshold (N > max)
- **Estimated phases:** 1 (single session) / multiple (suggest decomposition)
- **Summary:** [one-paragraph summary from spec subagent]
Ready to run the full pipeline? → `/ship <same arguments without --dry-run>`
Do not create a branch, do not implement, do not commit. The spec file is written to disk so the user can review it before running the full pipeline.
Launch a subagent (model: opus) with:
"Read
.claude/skills/1_implement/SKILL.mdand follow all steps exactly for spec: . Auto-proceed through plan mode (step 7) without waiting for approval. You are running as a subagent. Return: (1) list of files changed, (2) verify suite status (pass/fail), (3) any blockers that prevented completion."
Read the returned summary. Do not read any changed files.
If the subagent reports a blocker (verify suite failing after two attempts), stop and report to the user — do not continue to review.
review_fix_max_cycles from CLAUDE.md, default: 3)Maintain a cycle counter starting at 0.
Launch a subagent (model: opus) with:
"Read
.claude/skills/2_review/SKILL.mdand follow all steps exactly for spec: . You are running as a subagent. Return: (1) the overall assessment (pass / pass with fixes / needs rework), (2) the full numbered issue list with severities."
Read the returned assessment. Do not read the review file itself.
Route:
git checkout <working-branch> && git reset --hard checkpoint/<spec-name>." (use the actual branch name from Step 0/1). Otherwise proceed to Fix subagent. Note the verdict for model selection below.Select the model based on the review verdict:
Launch a subagent (model: opus or sonnet per above, maxTurns: 15) with:
"Read
.claude/skills/3_fix/SKILL.mdand follow all steps exactly for spec: . You are running as a subagent. Return: (1) list of issues fixed, (2) any issues skipped and why, (3) verify suite status, (4) any lessons written to.claude/context/lessons.md."
Read the returned summary. Loop back to Review subagent.
After the review/fix loop passes, graduate mature lessons into permanent CLAUDE.md rules.
.claude/context/lessons.mdscope: framework AND is older than lesson_graduation_age_days from CLAUDE.md (default: 14) AND was not triggered again since it was written (no similar issue appeared in subsequent review cycles). Extract a single-line rule (the "Rule:" part, stripped of the "What went wrong" narrative) and append it to the ## Learned Rules section in CLAUDE.md. If that section doesn't exist yet, create it at the bottom of CLAUDE.md.scope: project AND is already enforced by code (e.g., a test exists that catches the exact scenario, or a linter rule covers it). Project-scoped lessons are never graduated to CLAUDE.md — they stay in lessons.md or get deleted when enforced.scope: tag — treat as scope: project (legacy default)lessons.mdlessons.md and CLAUDE.md will be included in the commit (Step 6 — Commit subagent)Format for graduated rules in CLAUDE.md:
## Learned Rules
- Never use global regex with `.test()` in a loop — remove the `g` flag
- `log_event()` before `db.commit()`, never after
- Worker ORM stubs must include every column accessed by code in the same file
One line per rule. No dates, no "what went wrong" narrative. Just the rule.
Skip this step if no phase manifest exists (.claude/specs/<name>-phases.md). For single-phase features, proceed directly to Step 5.
If a phase manifest exists and all phases are done, launch a subagent (model: opus) with:
"You are performing a cross-phase integration review. Read the spec
.claude/specs/<name>.mdand the phase manifest.claude/specs/<name>-phases.md. Then read all files listed in the spec's 'Affected files' and 'New files' sections. Check:
- Data flow continuity — do outputs from earlier phases correctly feed into later phases? (e.g., API routes return what the frontend expects, shared types are consistent)
- Interface contracts — do function signatures, prop types, API schemas, and store shapes match across phase boundaries?
- Missing glue code — are there any integration points that no single phase owned? (e.g., wiring a new route into the router, registering a provider, adding a nav link)
- Import/dependency consistency — do all cross-phase imports resolve? Are there circular dependencies?
Return: (1) 'pass' if all integration points are sound, or (2) a numbered list of integration issues found, each with severity (critical/major) and the two phases involved."
Route:
Run the project's full verify suite (typecheck → lint → tests → build) one last time. Late-stage changes from the fix cycle may have introduced regressions.
git checkout <working-branch> && git reset --hard checkpoint/<spec-name>." (use the actual branch name from Step 0/1).Note: Smoke testing against Docker (/smoke <spec-name>) is a separate manual step the user can run before or after /ship. It is not part of the automated pipeline because Docker infrastructure issues should not block the ship flow.
Write a per-ticket changelog file so the commit subagent picks it up as part of the feature commit. One file per branch keeps changelog updates merge-conflict-free on master (vs. a single shared CHANGELOG.md).
Path: changelog/<working-branch>.md — use the full branch name as the filename.
Idempotent: if the file already exists (e.g. a previous /ship pass on the same branch), overwrite it with the current state.
Template:
# <working-branch>
**Ticket:** #<ticketId> — <type> · <module>
**Branch:** `<working-branch>`
## Summary
<2-5 sentences summarising what was built and why. Plain language — the audience is QA, product, and future devs, not just engineers. Call out behaviour changes, new config surface, and any manual follow-up. Do NOT restate file names — they are listed below.>
## Changed files
- <path1>
- <path2>
- ...
Data sources:
<ticketId>, <type>, <module> — from ticket_context (Step 0b). Fallback: parse from the branch name with the regex in branch-management.md.Do not commit here — the commit subagent (Step 6) stages the new file along with the rest of the diff.
Launch a subagent (model: sonnet) with:
"Read
.claude/skills/commit/SKILL.mdand follow all steps exactly. Split into atomic commits if multiple concerns are present. You are running as a subagent. Return the commit hash(es) and message(s)."
Skip this step if no ticket was resolved in Step 0b (i.e. ticket_context is empty or no work-item comment tool is available).
Default: do not post a comment. Branch, commits, and PR are auto-linked to the work item via the #<ticketId> suffix in the commit message (see branch-management.md) and via the PR. A comment that just repeats Branch: X / Commits: Y / Spec: Z is noise — it buries the discussion tab under boilerplate and adds no information a reviewer cannot get from the Development tab.
Only post a comment if there is non-obvious context a reviewer cannot derive from code, commits, or the spec file. Build a bullet list from the following triggers and post only if the list is non-empty:
New files include a new test project / e2e suite / fixture setup. Post a short "how to run" (command + prerequisites).(high) decision from Step 2b changed scope vs. the acceptance criteria, or an implementation blocker forced a narrower/wider scope than the ticket describes.Do not post:
If nothing worth posting exists, skip silently — do not post a placeholder.
Do NOT update the work item state here — that happens in Step 7b after push.
Skip this step entirely if --no-finalize is set — proceed directly to Final report without pushing or transitioning state.
Skip the gate and go straight to Step 7b if --auto-finalize is set — no user prompt, push + state change happen immediately.
Otherwise: the state transition hands the ticket off to QA/review and is visible on the team board — it is the kind of action that deserves an explicit "yes" before it happens. Print a summary and wait for user confirmation.
Summary to print:
## Ready to ship?
Branch: <working-branch> (local only — not pushed yet)
Commits: <count> (see `git log master..HEAD --oneline`)
Changelog: changelog/<working-branch>.md
Ticket: #<ticketId> — currently "<current-state>" → will move to "<target-state>"
### Verify locally before confirming
The pipeline already ran typecheck / lint / tests / build (Step 5), but manual
smoke-tests catch what automated checks miss. Recommended based on what this
feature touches (<list of touched areas from Step 3 summary>):
- <project-specific verify command 1 from CLAUDE.md for the touched areas>
- <project-specific verify command 2>
- Review the diff once in the IDE for anything obvious the review subagent
may have glossed over.
### Confirm
- `y` — push to origin + transition ticket state
- `n` — pause here. Branch stays local, ticket stays in current state.
You can resume later with `git push` + a manual state change (or re-run
`/ship` after adding follow-up commits).
- `q` — abort (same as `n` — nothing destructive).
Deriving the recommended test commands: Read CLAUDE.md for the project's build / verify commands and pick the ones that cover the areas touched in Step 3's file list. Do not invent commands — only suggest commands documented in CLAUDE.md.
Wait for input. Route on the answer:
y → proceed to Step 7b.n or q → skip Step 7b entirely, go to Final report with outcome: paused (not shipped). Note in the Final report: "Branch not pushed, ticket stays in current state. Resume with git push when ready."Push the branch to origin:
git push -u origin <working-branch>
If push fails, report the error to the user — do not force-push.
status: completed to the spec's YAML frontmatter (or add a ## Status: completed line at the top if the spec has no frontmatter). This makes it easy to distinguish shipped specs from in-progress ones..claude/specs/<name>-phases.md exists, mark all phases as done (they should already be, but this is a consistency safeguard).Resolved, Done, Development finished — use whatever the project's workflow defines). If the transition fails, try common alternatives and surface the error to the user. Do NOT set Closed — that is typically reserved for QA/UAT sign-off.git branch -d checkpoint/<spec-name> (if it exists).Print a summary assembled from subagent return values. Adapt the wording to the actual outcome — shipped (pushed + state changed), paused (gate declined), or skipped (--no-finalize):
<working-branch> → pushed / local only (reason).claude/specs/<name>.md--no-finalize / push failed)git push when readyAppend one row to .claude/metrics-pipeline.csv. Create the file with a header row if it doesn't exist.
Format:
date,spec,area,files_changed,review_cycles,issues_found,issues_critical,issues_major,issue_categories,commits,outcome
Fields:
date — ISO date (YYYY-MM-DD)spec — spec filename without path/extensionarea — primary codebase area affected (e.g. scoring, auth, ui, api, infra). Derive from the dominant directory in the changed files list. Use a single word, lowercase. If unclear, use generalfiles_changed — count from Step 3 summaryreview_cycles — how many review/fix iterations (0 = passed first review)issues_found — total issues across all review cyclesissues_critical — count of critical-severity issuesissues_major — count of major-severity issuesissue_categories — semicolon-separated list of issue types found across all review cycles (e.g. validation;edge-cases;types). Use short lowercase labels. Empty if no issuescommits — number of commits created in Step 6outcome — shipped (pushed + state changed) / paused (gate declined — local only) / escalated (stopped due to circuit breaker) / abortedThis is append-only — never modify or delete existing rows. The CSV is a lightweight log for spotting trends (e.g., rising review cycles, recurring issue categories). No tooling required — open in any spreadsheet or column -t -s, .claude/metrics-pipeline.csv.