Skip to main content
ClaudeWave
Slash Command89 repo starsupdated 1mo ago

ship

Deploy feature through automated staging validation to production with rollback testing

Install in Claude Code
Copy
mkdir -p ~/.claude/commands && curl -fsSL https://raw.githubusercontent.com/marcusgoll/Spec-Flow/HEAD/.claude/commands/deployment/ship.md -o ~/.claude/commands/ship.md
Then start a new Claude Code session; the slash command loads automatically.

ship.md

# /ship — Unified Deployment Orchestrator (Thin Wrapper)

> **v11.0 Architecture**: This command spawns the isolated `ship-phase-agent` via Task(). Deployment operations run in isolated context with question batching for production approval.

<context>
**Arguments**: $ARGUMENTS

**Active Feature**: !`ls -td specs/[0-9]*-* 2>/dev/null | head -1 || echo "none"`

**Interaction State**: !`cat specs/*/interaction-state.yaml 2>/dev/null | head -10 || echo "none"`

**Deployment Model**: !`test -f .github/workflows/deploy-staging.yml && echo "staging-prod" || (git remote 2>/dev/null && echo "direct-prod" || echo "local-only")`
</context>

<objective>
Spawn isolated ship-phase-agent to orchestrate deployment workflow.

**Architecture (v11.0 - Phase Isolation):**
```
/ship → Task(ship-phase-agent) → Q&A for prod approval → deployment
```

**Agent responsibilities:**
- Auto-detect deployment model (staging-prod, direct-prod, local-only)
- Execute pre-flight validation
- Deploy to staging (auto-proceed)
- Request approval for production deployment (returns question)
- Create GitHub release
- Record deployment metadata

**Deployment Models** (auto-detected):

1. **staging-prod**: Automated staging validation before production (recommended)

   - Detection: Git remote + staging branch + `.github/workflows/deploy-staging.yml`
   - Workflow: pre-flight + optimize (parallel) → deploy-staging → automated validation → deploy-prod → finalize

2. **direct-prod**: Direct production deployment without staging

   - Detection: Git remote + no staging branch
   - Workflow: pre-flight + optimize (parallel) → deploy-prod → finalize

3. **local-only**: Local build and integration only
   - Detection: No git remote
   - Workflow: pre-flight + optimize (parallel) → build-local → merge to main → finalize

**Automation Features**:

- Pre-flight + optimize run in parallel (saves ~10 minutes)
- Zero manual gates (removed /preview, interactive version selection)
- Auto-generated validation reports (E2E, Lighthouse, rollback tests)
- Platform API-based deployment ID extraction (no log parsing)
- Auto-fix CI failures via GitHub Actions

**Arguments**:

- (empty): Start deployment workflow from beginning
- `continue`: Resume from last completed phase (if failure occurred)
- `status`: Display current deployment status and exit
- `rollback [version]`: Rollback to previous deployment version (v10.14+)
- `recover`: Recover corrupted state.yaml from git history (v10.14+)
- `budget`: Display deployment quota status
- `--auto`: Full autopilot mode - skip prompts, auto-merge when CI passes, continue to finalize (v11.7)

**Dependencies**: Requires completed `/implement` phase

**Timing**: 25-35 minutes fully automated
</objective>

## Anti-Hallucination Rules

**CRITICAL**: Follow these rules to prevent deployment failures from false assumptions.

1. **Never assume deployment configuration you haven't read**

   - ❌ BAD: "The app probably deploys to Vercel"
   - ✅ GOOD: Read .github/workflows/, package.json, vercel.json to detect deployment config

2. **Cite actual workflow files when describing deployment**

   - When describing CI: "Per .github/workflows/deploy.yml:15-20, staging deploys on push to staging branch"
   - When describing environment vars: "VERCEL_TOKEN required per .env.example:5"

3. **Verify deployment URLs exist before reporting them**

   - Extract actual URLs from deployment tool output
   - If URL unknown, say: "Deployment succeeded but URL not captured in logs"

4. **Never fabricate deployment IDs or version tags**

   - Only report deployment IDs extracted from actual tool output
   - Don't invent git tags - verify with `git tag -l`

5. **Quote state.yaml exactly for phase status**

   - Don't paraphrase phase completion - quote the actual status value
   - If state file missing/corrupted, flag it - don't assume status

6. **TodoWrite is MANDATORY for all ship workflows**
   - Create full todo list immediately after Step 1
   - Update after EVERY phase transition (don't batch updates)
   - Only ONE todo should be in_progress at a time
   - When errors occur: Add "Fix [specific error]" as new todo

**Why this matters**: False assumptions about deployment config cause production incidents. Accurate reading of actual configuration prevents failures.

---

<process>

## TODO TRACKING REQUIREMENT

**CRITICAL**: You MUST use TodoWrite to track all ship workflow progress.

**Why**: The /ship workflow involves 5-7 phases over 25-35 minutes, fully automated. Without TodoWrite, user loses visibility and cannot resume after errors.

**TodoWrite pattern**:

1. After Step 1 (loading context) - Create full todo list based on deployment model
2. After every phase completes - Mark completed, mark next as in_progress
3. When errors occur - Add "Fix [specific error]" todo, keep current phase in_progress
4. On completion - Mark all todos as completed

**Only ONE todo should be in_progress at a time.**

---

### Step 0: Route Consolidated Arguments

**Check $ARGUMENTS for routing to scripts or archived commands:**

**Rollback or Recover Operations** (v10.14+):

If `$ARGUMENTS` starts with `rollback`:

1. Extract version if provided (e.g., `rollback v1.2.3` → `v1.2.3`)
2. Run rollback script:
   ```bash
   python .spec-flow/scripts/spec-cli.py ship-rollback [version]
   ```
3. Display rollback results and EXIT

If `$ARGUMENTS` is `recover`:

1. Run state recovery script:
   ```bash
   python .spec-flow/scripts/spec-cli.py ship-recover --feature-dir "$FEATURE_DIR"
   ```
2. Display recovered state and EXIT

**Route budget command:**

If `$ARGUMENTS` is `budget`:

```
SlashCommand: /deployment/budget
```

Display deployment quota status and EXIT.

**If none of the above, continue to Step 0.1.**

---

### Step 0.1: DRY-RUN AND AUTO MODE DETECTION

**Check for --dry-run and --auto flags:**

```bash
DRY_RUN="false"
AUTO_MODE="false"

if [[ "$ARGUMENTS" == *"--dry-run"* ]]; then
  DRY_RUN="true"
  ARGUMENTS=$(echo "$ARGUMENTS" | sed 's