ship
Ship - Full PR Lifecycle
When this skill is invoked, IMMEDIATELY output the banner below before doing anything else. Pick ONE tagline at random — vary your choice each time. CRITICAL: Reproduce the banner EXACTLY character-for-character. The first line of the art has 4 leading spaces — you MUST preserve them.
{tagline}
⠀ ██╗███████╗██╗ ██╗██╗██████╗
██╔╝██╔════╝██║ ██║██║██╔══██╗
██╔╝ ███████╗███████║██║██████╔╝
██╔╝ ╚════██║██╔══██║██║██╔═══╝
██╔╝ ███████║██║ ██║██║██║
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝
Taglines:
- 🚚 Special delivery!!!
- 📦 If it compiles, it ships!
- 🚢 Anchors aweigh!
- 🙏 git push and pray!
- ⚡ Shipping faster than Amazon Prime!
- 🏀 Yeet the code into production!
- 📬 Another one for the merge queue!
- 🟢 LGTM — Let's Get This Merged!
Output Formatting
After the banner, display parsed input:
┌─ Input ────────────────────────────────────────
│ {Field}: {value}
│ Flags: {parsed flags or "none"}
└────────────────────────────────────────────────
Pre-flight results:
── Pre-flight ───────────────────────────────────
✅ {dep} {version or "found"}
⚠️ {dep} not found → {fallback detail}
❌ {dep} missing → stopping
──────────────────────────────────────────────────
Stage/phase headers: ━━ {N} · {Name} ━━━━━━━━━━━━━━━━━━━━━━━━━
Status icons: ✅ done · ❌ failed · ⚠️ degraded · ⏳ working · ⏭️ skipped
Ship changes through the complete PR lifecycle. Deterministic stages (sync, CI
polling, merge) run as bash scripts for speed and reliability. Only stages that
require reasoning (commit/PR authoring, CI fix analysis) use LLM subagents.
Stage prompts are in references/stage-prompts.md.
Flags
Parse optional flags from the request:
--pr-only: Stop after creating the PR--no-squash: Use regular merge instead of squash--keep-branch: Don't delete the source branch after merge
Platform Detection
Detect the hosting platform before pre-flight so dependency checks are platform-specific:
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
if echo "$REMOTE_URL" | grep -qiE 'dev\.azure\.com|visualstudio\.com'; then
PLATFORM="azdo"
elif echo "$REMOTE_URL" | grep -qi 'github\.com'; then
PLATFORM="github"
else
PLATFORM="github" # default fallback
fi
Pass {PLATFORM} into all stage prompts. Each stage uses the appropriate
CLI tool: gh for GitHub, az repos/az pipelines for Azure DevOps.
Display the detected platform to the user immediately after detection:
⚙️ Platform: GitHub (github.com)
or:
⚙️ Platform: Azure DevOps ({AZDO_ORG}/{AZDO_PROJECT})
Pre-flight
Before starting, check all dependencies in this table. The table contains all dependencies — some are platform-conditional (see notes after table).
| Dependency | Type | Check | Required | Resolution | Detail |
|---|---|---|---|---|---|
| git | cli | git --version |
yes | stop | Install from https://git-scm.com |
| gh | cli | gh --version |
yes | url | https://cli.github.com |
| az devops | cli | az devops -h 2>/dev/null |
no | fallback | Falls back to REST API with PAT; see AzDO tooling below |
Platform-conditional rules:
gh: Only required whenPLATFORM == github. Skip for AzDO repos.az devops: Only checked whenPLATFORM == azdo. Skip for GitHub repos.
For each applicable row, in order:
- Skip rows that don't apply to the detected
{PLATFORM} - Run the Check command (for cli/npm) or test file existence (for agent/skill)
- If found: continue silently
- If missing: apply Resolution strategy
- stop: notify user with Detail, halt execution
- url: notify user with Detail (install link), halt execution
- install: notify user, run the command in Detail, continue if successful
- ask: notify user, offer to run command in Detail, continue either way (or halt if required)
- fallback: notify user with Detail, continue with degraded behavior
- After all checks: summarize what's available and what's degraded
- Always show the commit/PR agent:
✅ commit agent general-purpose
AzDO Tooling Detection
When PLATFORM == azdo, determine which tooling is available. Set AZDO_MODE
for use in all subsequent stages:
if az devops -h &>/dev/null; then
AZDO_MODE="cli"
else
AZDO_MODE="rest"
fi
cli: Useaz repos/az pipelinescommands (preferred)rest: Use Azure DevOps REST API viacurl. Requires a PAT (personal access token) inAZURE_DEVOPS_EXT_PATorAZDO_PATenv var. If no PAT is found, prompt the user to either install the CLI or set the env var.
Report in pre-flight:
- ✅
az devops cli— version found - ⚠️
az devops cli— not found → using REST API fallback - ❌
az devops cli— not found, no PAT configured → halt with setup instructions
AzDO Configuration Validation
When PLATFORM == azdo, extract organization and project from the remote URL
and validate they are usable. These values are needed by every az repos /
az pipelines command and every REST API call.
# Extract org and project from remote URL patterns:
# https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
# https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
# {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
# HTTPS format: https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
# Also handles: https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
# SSH format: {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/\([^/]*\)/.*|\1|p')
AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
elif echo "$REMOTE_URL" | grep -q 'visualstudio\.com'; then
# Legacy HTTPS format: https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}
AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
fi
# URL-decode for CLI/display; keep URL-safe versions for REST API paths
AZDO_PROJECT_URL_SAFE="$AZDO_PROJECT"
AZDO_ORG=$(printf '%b' "${AZDO_ORG//%/\\x}")
AZDO_PROJECT=$(printf '%b' "${AZDO_PROJECT//%/\\x}")
if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
echo "❌ Could not extract organization/project from remote URL"
echo " Remote: $REMOTE_URL"
echo ""
echo "Ensure the remote URL follows one of these formats:"
echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
# HALT — cannot proceed without org/project context
fi
When AZDO_MODE == cli, also configure the defaults so commands work correctly:
az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
When AZDO_MODE == rest, store these for API calls:
- Base URL:
$AZDO_ORG_URL/$AZDO_PROJECT_URL_SAFE/_apis - Auth header:
Authorization: Basic $(echo -n ":$PAT" | base64)
Report in pre-flight:
- ✅
azdo context— org:{AZDO_ORG}, project:{AZDO_PROJECT} - ❌
azdo context— could not parse from remote URL → halt with instructions
Pass {AZDO_MODE}, {AZDO_ORG}, {AZDO_PROJECT}, {AZDO_PROJECT_URL_SAFE},
{AZDO_ORG_URL} into
all stage prompts alongside {PLATFORM}.
Read default_branch and remote from Stage 1's SYNC_REPORT. These are
substituted into all stage prompts as {REMOTE} and {DEFAULT_BRANCH}.
Stage 1: Sync
Run the sync script directly (no LLM needed):
SKILL_ROOT="<resolved plugin root>"
bash "$SKILL_ROOT/skills/sync/scripts/sync.sh" "{REMOTE}" "{DEFAULT_BRANCH}"
Parse SYNC_REPORT from output markers. Extract remote and default_branch.
Abort if exit code is 1 (fatal).
Stage 2: Commit, Push & Create PR
This stage needs to read and understand code to write good commit messages and PR descriptions — it's one of the few stages that requires an LLM.
Launch general-purpose subagent (reads diffs + source files):
Task(
subagent_type: "general-purpose",
description: "Analyze, commit, push, and create PR",
prompt: <read from references/stage-prompts.md#stage-2>
)
Substitute {USER_INTENT}, {FILES_TO_INCLUDE}, {FILES_TO_EXCLUDE},
{REMOTE}, {DEFAULT_BRANCH}, {PLATFORM}, {AZDO_MODE}, {AZDO_ORG},
{AZDO_PROJECT}, {AZDO_ORG_URL}, {PAT} into the prompt.
Parse SHIP_REPORT. Abort if failed.
Rollback: If push succeeds but PR creation fails, report the error and suggest the manual PR creation command. Do NOT revert the push.
- GitHub:
gh pr create --head {branch} - Azure DevOps (cli):
az repos pr create --source-branch {branch} --target-branch {DEFAULT_BRANCH} --org {AZDO_ORG_URL} --project {AZDO_PROJECT} - Azure DevOps (rest): Create PR via
{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/git/repositories/{repo}/pullrequests?api-version=7.0
If --pr-only flag: Stop here and report PR URL to user.
Stage 3 + 4: CI Watch & Fix Loop
Run CI monitoring in the foreground so failures are caught and fixed immediately. This stage loops: watch → detect failure → fix → push → watch again.
Maximum 2 fix attempts. If CI still fails after 2 rounds, report to user and stop.
Watch
Run the CI watch script directly (no LLM needed — just polling):
SKILL_ROOT="<resolved plugin root>"
bash "$SKILL_ROOT/skills/ship/scripts/ci-watch.sh" \
"{PLATFORM}" "{PR_NUMBER}" "{BRANCH}" \
--azdo-mode="{AZDO_MODE}" --azdo-org-url="{AZDO_ORG_URL}" \
--azdo-project="{AZDO_PROJECT}" --azdo-project-url-safe="{AZDO_PROJECT_URL_SAFE}"
Briefly inform the user: ⏳ Watching CI for PR #{pr_number}...
Parse CHECKS_REPORT from output markers. Exit code 0=passed, 1=failed, 2=timeout.
Fix (if needed)
If CHECKS_REPORT shows some_failed, immediately launch a fix subagent —
do not wait, do not ask the user:
Task(
subagent_type: "general-purpose",
description: "Fix CI failures",
prompt: <read from references/stage-prompts.md#stage-4>
)
Substitute {PR_NUMBER}, {BRANCH}, {FAILING_CHECKS}, {PLATFORM},
{AZDO_MODE}, {AZDO_ORG}, {AZDO_ORG_URL}, {AZDO_PROJECT}, {PAT} into the prompt.
The fix subagent MUST commit and push before returning. Once it returns, immediately loop back to Watch to re-check CI.
Loop summary
attempt = 0
while attempt < 2:
CHECKS = run_watch()
if CHECKS.status == "all_passed" or CHECKS.status == "no_checks":
break → proceed immediately to Stage 5 (do NOT ask user to confirm merge)
attempt += 1
run_fix(CHECKS.failing_checks)
→ loop back to watch
if attempt == 2 and still failing:
report failures to user, stop
Stage 5: Merge & Final Sync
Once checks pass, immediately proceed to merge — do not ask the user for
confirmation. The user invoked /ship expecting the full lifecycle; stopping
to ask defeats the purpose. Squash merge and delete the source branch are the
defaults (override via --no-squash and --keep-branch flags only).
5a. Merge the PR
Run the merge script directly (no LLM needed):
SKILL_ROOT="<resolved plugin root>"
bash "$SKILL_ROOT/skills/ship/scripts/merge.sh" \
"{PLATFORM}" "{PR_NUMBER}" \
{MERGE_FLAGS} {BRANCH_FLAGS} \
--azdo-mode="{AZDO_MODE}" --azdo-org-url="{AZDO_ORG_URL}" \
--azdo-project="{AZDO_PROJECT}" --azdo-project-url-safe="{AZDO_PROJECT_URL_SAFE}"
Parse LAND_REPORT from output markers. Exit code 0=merged, 1=failed.
5b. Sync local repo
After the merge script succeeds, run the sync script to checkout the default branch, pull the merge commit, and clean up stale branches:
bash "$SKILL_ROOT/skills/sync/scripts/sync.sh" "{REMOTE}" "{DEFAULT_BRANCH}"
What's Next?
After a successful merge, determine what work comes next by checking these sources (in priority order):
- Active tasks — check
TaskListfor any in-progress or pending tasks in the current session - Session context — review the conversation so far for any stated plans, follow-up items, or deferred work the user mentioned
- Memory — if the
claude-memplugin is available, search for recent checkpoints or plans related to this project
Summarize the result as 1–3 short bullet points for the ⚡ Next section of
the report. If nothing is found, omit the section entirely — do not fabricate
next steps.
Final Report to User
Compile all stage reports into a summary:
┌─ Ship · Report ────────────────────────────────
│
│ ✅ Ship complete
│
│ 🌿 Branch: {branch}
│ 🔗 PR: {pr_url}
│ 🔀 Merged: {merge_commit} ({merge_type})
│
│ 📝 Commits
│ • {commit message 1}
│ • {commit message 2}
│
│ 📊 {count} files changed ({diff_summary})
│
│ ⚡ Next
│ • {next item 1}
│ • {next item 2}
│
└─────────────────────────────────────────────────
If nothing was found for "What's Next?", omit the ⚡ Next section.
If any stage failed, add:
│ ❌ Failed at: {stage name}
│ {error description}
│ {suggested resolution}
More from slamb2k/mad-skills
prime
Load project context before implementing features or making architectural decisions. Invoke proactively at the start of significant work on any project. Scans CLAUDE.md, README, specs/, docs/, and source structure to build a context summary. Supports optional domain hints to focus on specific areas of the codebase. Use when you need project conventions, architecture understanding, or domain context before coding.
16distil
Generate multiple unique web design variations for any website or web application. Accepts site specifications from a file (--spec path) or pasted text block. Creates a Vite + React + TypeScript + Tailwind project with Bun and produces N different creative designs accessible at /1, /2, /3, etc. Use when prototyping or exploring design directions for any web interface.
16sync
Sync local repository with origin/main. Use before starting new work, after completing a PR, or when needing latest upstream changes. Safely stashes uncommitted changes, fetches and pulls origin/main, restores stash, and cleans up stale local branches (merged or with deleted remotes). Invoke when switching contexts or preparing for new feature work.
15rig
Idempotently bootstrap any repository with standard development tools, hooks, and workflows. Use when starting work on a new repo, onboarding to an existing project, or ensuring a repo has proper CI/CD setup. Configures: git hooks (lefthook), commit message templates, PR templates, and GitHub Actions for lint/format/type-check/build. Prompts for user confirmation before changes. Triggers: "bootstrap repo", "setup hooks", "configure CI", "rig", "standardize repo".
15build
Context-isolated feature development pipeline. Takes a detailed design/plan as argument and executes the full feature-dev lifecycle (explore, question, architect, implement, review, ship) inside subagents so the primary conversation stays compact. Use when you have a well-defined plan and want autonomous execution with minimal context window consumption.
14speccy
Deep-dive interview skill for creating comprehensive specifications. Reviews existing code and docs, then interviews the user through multiple rounds of targeted questions covering technical implementation, UI/UX, concerns, and tradeoffs. Produces a structured spec in specs/. Use when starting a new feature, system, or major change that needs a spec.
10