# Ship

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-jerry0022-dotclaude-ship`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Jerry0022](https://agentstack.voostack.com/s/jerry0022)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Jerry0022](https://github.com/Jerry0022)
- **Source:** https://github.com/Jerry0022/dotclaude/tree/main/plugins/devops/skills/ship

## Install

```sh
agentstack add skill-jerry0022-dotclaude-ship
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Ship

Ship completed work via PR using the `dotclaude-ship` MCP server tools.
Supports two modes: **direct** (branch → main) and **intermediate** (sub-branch → feature branch).

> **CRITICAL — `cwd` is required on every MCP tool call.**
> The ship MCP server runs in the plugin directory, NOT the target repo.
> Every `ship_*` tool call MUST include `cwd` set to the current working directory of this Claude session.
> Omitting `cwd` will cause the tool to operate on the wrong repository.

## Pre-Step A — Autonomous Lockout Detection

`/ship` is composed by unsupervised orchestrators (`run-backlog`
ships every queued issue this way; future AFK runners may too). Those runs are in
a **Post-Confirmation Lockout** — the user is AFK and **no `AskUserQuestion` can
ever be answered**. A modal raised mid-pipeline would hang the entire night run on
a single issue. Detect that state FIRST, before any other step:

```bash
node "$CLAUDE_PLUGIN_ROOT/scripts/autonomous-lockout.js" check
```

Parse the JSON. If `active: true`, set `$SHIP_LOCKOUT=true` for this whole run
**and persist it durably**: write a `.claude/.ship-lockout` marker in the repo
root (`node -e "require('fs').mkdirSync('.claude',{recursive:true});require('fs').writeFileSync('.claude/.ship-lockout','1')"`).
`$SHIP_LOCKOUT` is consumed at ~5 later gates, across a >5-min CI wait during
which the conversation may compact and drop the variable from memory. At every
interactive gate, re-derive `$SHIP_LOCKOUT=true` when the marker file exists
rather than trusting recall alone — a lost lockout that silently re-enables
`AskUserQuestion` is exactly the AFK-hang this guard exists to prevent. Clear the
marker in Step 5 cleanup (delete `.claude/.ship-lockout`). If the command errors
or the script is absent (older plugin), treat it as **not locked** — a normal
interactive ship — and continue. The guard only ever *adds* non-interactive
safety; it never blocks a normal ship.

**The rule when `$SHIP_LOCKOUT` is set: never call `AskUserQuestion`.** Every gate
that would normally ask takes its documented non-interactive branch instead. The
two shapes are:

- **BLOCK** → stop the pipeline, call `render_completion_card` with variant
  `ship-blocked` (reason stated), and return. The orchestrator treats the item as
  parked and moves on — one blocked issue never halts the queue.
- **RECORD & CONTINUE** → don't ask, don't block; fold the open point into a
  `userFinalTest` item for Step 6 and proceed. Only for genuinely non-fatal points.

| Interactive gate | Normal behavior | `$SHIP_LOCKOUT` behavior |
|---|---|---|
| Pre-Step B — session activity still in progress | ask Warten/Trotzdem/Abbrechen | in-scope activity pending → **BLOCK** ("session activity active"); otherwise proceed |
| Step 1b(e) — truly ambiguous rebase conflict | abort + ask which side wins | `git rebase --abort` → **BLOCK** ("unresolvable merge conflict — needs human decision") |
| Step 1d — high-impact purpose-alignment conflict | ask (batched) | apply mechanical fixes as usual; high-impact items → **RECORD & CONTINUE** |
| Step 2 — Codex judgment-required finding | ask Fixen/Ignorieren/Abbrechen | auto-fixable → fix inline; design/logic/security → **BLOCK** (finding named) |
| Step 3 — major version bump | always ask | **BLOCK** ("needs major-version decision — not shipped unattended") |

A BLOCK under lockout is the safe outcome, not a failure: the caller parks the
issue as a `⏸ Rückfrage` and the queue continues. Shipping an unreviewed
security finding, an ambiguous merge, or an unattended breaking change would be
the actual failure. When `$SHIP_LOCKOUT` is false (a normal interactive ship),
every gate behaves exactly as written elsewhere in this skill — unchanged.

## Pre-Step B — Session Activity Guard

Before anything else, check whether this session still has work in progress.

1. Check for **background agents** still running (Agent tool results pending)
2. Check for **background Bash commands** still executing
3. Check for **TodoWrite tasks** that are not yet marked `completed` or `cancelled`

If ANY of the above are active:

> **STOP. Do not proceed with shipping.**
>
> Inform the user which activities are still in progress (agent names, task descriptions, or command summaries).
> Ask via AskUserQuestion:
> - "Warten bis alles fertig ist" — pause and resume /ship automatically when all activity completes
> - "Trotzdem shippen" — user accepts the risk, continue with Step 0
> - "Abbrechen" — cancel /ship entirely

**If `$SHIP_LOCKOUT` (Pre-Step A):** do not ask. If genuine in-scope activity is
still pending, **BLOCK** (`ship-blocked`, "session activity active"); otherwise
proceed to Step 0.

This guard only applies to the **current chat session**, not external CI or other terminals.

> **Sentinel hygiene (every exit path).** `ship_preflight` writes a
> ship-in-progress sentinel that makes the main-branch Edit guards
> (`pre.main.guard` / `pre.edit.branch`) stand down for the ship's duration. It is
> cleared by `ship_cleanup` on a *successful* ship — but a **ship-blocked / abort**
> return (any `render_completion_card` variant `ship-blocked` below) skips cleanup
> and would leave the sentinel stranded, silently disarming main-branch protection
> until it ages out. **Rule:** before rendering ANY `ship-blocked` card, first call
> `ship_cleanup({ branch, cwd, keep: true })` — keep-mode deletes no branch/worktree,
> it only clears the sentinel so main-branch protection resumes immediately.

## Step 0 — Load Extensions

Check for optional overrides. Use **Glob** to verify each path exists before reading.
Do NOT call Read on files that may not exist — skip missing files silently (no output).

1. Global: `~/.claude/skills/ship/SKILL.md` + `reference.md`
2. Project: `{project}/.claude/skills/ship/SKILL.md` + `reference.md`
3. Merge: project > global > plugin defaults

Project extensions define: quality gate commands, deploy targets, version files, CI specifics.

Also capture, if present in the merged `reference.md`, for use later in this run:
- `outOfBandDeploy:` — a list of path globs for artifacts a code merge does NOT
  deploy (DB migrations, edge/serverless functions). Pass them to `ship_preflight`
  in Step 1a. Omit when absent — the tool applies stack-agnostic defaults.
- `deploy:` — a deploy handler (e.g. `supabase`) that can actually APPLY those
  artifacts post-merge. Used by Step 4d. When absent, Step 4d raises the deploy
  gate instead of deploying.

4. Codex context: Read `{PLUGIN_ROOT}/deep-knowledge/codex-integration.md` — this skill has a **mandatory** Codex review gate (§1 in that doc), which MUST be called via `{PLUGIN_ROOT}/scripts/codex-safe.sh` (5-min hard timeout, see "Hard Timeout & Failure-Tolerance" section), NEVER via the `/codex:rescue` Agent tool. Detect Codex availability now so Step 2 can act on it.

## Step 0.5 — Load Deferred MCP Schemas

Ship tools from the `dotclaude-ship` MCP server are often **deferred** in large-tool-inventory sessions (their names appear in the SessionStart deferred-tools list, but their schemas are NOT loaded yet). Calling them directly before the schema is loaded fails with `InputValidationError`.

See `{PLUGIN_ROOT}/deep-knowledge/mcp-deferred-tools.md` for the full pattern.

**Before Step 1**, load all ship tool schemas in ONE `ToolSearch` call:

```
ToolSearch({
  query: "select:mcp__plugin_devops_dotclaude-ship__ship_preflight,mcp__plugin_devops_dotclaude-ship__ship_build,mcp__plugin_devops_dotclaude-ship__ship_version_bump,mcp__plugin_devops_dotclaude-ship__ship_release,mcp__plugin_devops_dotclaude-ship__ship_cleanup",
  max_results: 5
})
```

If the `ToolSearch` result contains all five `` entries, proceed. If ANY are missing from the returned block, the server is genuinely not registered — STOP and report to the user (do NOT fall back to `gh pr create`; the guard hook will block it).

Do NOT skip this step even if you "think" the tools are available. `analysis` / `ready` / `test` cards have no ship-tool dependency and won't hit this — only the full pipeline does.

## Step 1 — Pre-Flight & Rebase Loop

Run preflight, resolve any merge-safety issues autonomously, and re-check — repeat until the branch is clean.

### 1a. Run preflight

Call `ship_preflight` MCP tool (dotclaude-ship server).
**CRITICAL:** Always pass `cwd` — the MCP server runs in the plugin directory, not the target repo.
Omit `base` to let the tool auto-detect it.
```
ship_preflight({ cwd: "" })
```

If Step 0 captured an `outOfBandDeploy:` glob list from the extension, pass it:
`ship_preflight({ cwd: "", outOfBandGlobs: ["**/migrations/**", ...] })`.
Otherwise omit it — the tool uses stack-agnostic defaults.

The result carries `outOfBandDeploys: { detected, files, kinds, globs }` — artifacts
this diff touches that a code merge will NOT deploy (#243). **Carry this value
forward to Step 4d.** It is informational, never a hard gate (`ready` is unaffected).

The tool **auto-detects** the correct base branch:
- If on a sub-branch like `feat/42-video-filters/core`, it detects `feat/42-video-filters` as the parent and uses it as base.
- Otherwise it uses the repository's default branch (resolves `origin/HEAD` — typically `main`, but `master` or any other name works too). Falls back to `main` if `origin/HEAD` is not set.
- You can override by passing an explicit base: `ship_preflight({ base: "feat/42", cwd: "" })`.

Check the result:
- `autoDetectedBase` — non-null if a parent branch was detected (confirms intermediate merge).
- `intermediate` — `true` if merging into a feature branch instead of main.
- `ready: false` → report errors and **STOP**. Do not proceed.
- `needsRebase: true` → continue to 1b (do NOT stop).

The tool checks: clean tree, commits ahead, all pushed, version consistency (skipped for intermediate), worktree detection, and unresolved conflict markers (`no-conflict-markers`).

The marker check has two scopes. A marker in the files **this ship would land** is a hard error — `ship_release` re-scans immediately before committing, so one left behind by the rebase in 1b is caught there too. A marker anywhere else in the repo is a **warning**: it predates this branch, so report it and open a separate fix rather than holding an unrelated release hostage.
Merge-safety issues (`base-ahead`, `file-overlap`, `config-conflictstyle`) are **warnings, not errors** — they are resolved autonomously below.

### 1a-ii. Read `mode` — the repo-mode fork

`ship_preflight` returns a `mode` field. **Read it.** It decides which of the
steps below can run at all, and ignoring it is how a ship in a repo-less
project marched into rebase/push/PR and reported a merge that never happened.

| `mode` | What it means | How the pipeline changes |
|---|---|---|
| `git` | Repo with an origin | Full pipeline, nothing changes. |
| `git-no-remote` | Local repo, no origin | Everything up to and including the **commit** runs. `ship_release` commits and then stops; push, PR, merge, tag and release are skipped and reported as skipped. |
| `file-only` | Not a git repo at all | Everything that is not a git action still runs — see below. |

**`file-only` is NOT "skip the ship".** A ship is worth running in a repo-less
project for everything it does besides git: the build, the test suite, the
doc-freshness check, the quality gates, the worktree/merge sanity questions,
and the honest report at the end. Only the git actions are meaningless there.

Concretely, in `file-only`:

- **Run** Step 2 (build + tests) and Step 3 (version bump) exactly as normal —
  `ship_build` and `ship_version_bump` already handle the mode.
- **Run** the documentation and quality checks you would otherwise run; a
  repo-less project benefits from them just as much.
- **Skip** Step 1b entirely (there is nothing to rebase onto) and Step 4b (no
  merge to watch).
- **Call** `ship_release` anyway — it returns
  `{ success: true, skipped: true, reason: "file-only-mode", delivered: "none" }`
  without touching git.
- **Call** `ship_cleanup` anyway — it clears the ship sentinel and refuses every
  destructive git call.
- **Render** the `ready-files` completion card, not `ship-successful`, and pass
  `state: { mode: "file-only", filesModified: , delivered: "none" }`. Never
  claim a commit, branch, PR or merge.

Report the outcome in plain terms: what was built, what the tests said, what
changed on disk — and that there is no repo, so nothing was pushed.

### 1b. Resolve merge-safety warnings

**Only runs when `needsRebase: true`.** Otherwise skip to Step 2.

1. **Set diff3** (if `config-conflictstyle` warning): `git config merge.conflictstyle diff3`

2. **Rebase onto base**:
   ```bash
   git fetch origin 
   git rebase origin/
   ```

3. **If rebase succeeds** (no conflicts): push and re-check (go to 1c).

4. **If rebase has conflicts** — resolve them autonomously (do NOT ask user):
   a. `git diff --name-only --diff-filter=U` to list conflicting files.
   b. For each conflicting file:
      - Read the file (contains `>>>>>>` markers with diff3 base section)
      - Analyze **both sides semantically**: what did our branch change vs. what did base change?
      - Check **chronological context**: which change is newer? Do they contradict or complement each other?
      - Produce a merged version that preserves **both** intents
      - Write the resolved file, then `git add ` — with **all four** marker
        lines removed, `|||||||` included. Deleting the familiar three and
        leaving the diff3 base marker is the failure `no-conflict-markers` exists
        for; it blocks the ship at Step 4 rather than landing on main.
   c. `git rebase --continue`
   d. If more conflicts appear (multi-commit rebase), repeat (b)–(c)
   e. **Truly ambiguous conflicts** (both sides change the same logic in contradictory ways and the correct resolution is not determinable from code context): abort the rebase (`git rebase --abort`) and ask the user via AskUserQuestion with a clear, developer-readable explanation:
      - Show the conflicting snippet (both sides + base)
      - Explain what each side intended
      - Ask which intent should win, or whether both need manual reconciliation

      **If `$SHIP_LOCKOUT` (Pre-Step A):** do not ask. After `git rebase --abort`,
      **BLOCK** (`ship-blocked`, "unresolvable merge conflict — needs human
      decision"); the caller parks the issue and the queue continues.

5. **Push**: `git push --force-with-lease` to update the remote branch.

6. **Verification test**: Run the full test suite to confirm nothing broke. If tests fail, diagnose and fix before proceeding.

### 1c. Re-run preflight

After rebase + push + tests pass, **re-run `ship_preflight`** with the same parameters.
- `needsRebase: false` and `ready: true` → proceed to Step 2.
- `needsRebase: true` → someone pushed to base during our rebase. Go back to 1b.
- `ready: false` (hard errors) → report errors and **STOP**.

This loop naturally terminates — each iteration brings the branch closer to base.

### 1d. Purpose Alignment Gate

After the preflight loop stabilizes (`ready: true`), verify the ship against
the **purposes** of recently merged work — not just its code. Full protocol:
`deep-knowledge/purpose-alignment.md`.

- **Light check (every ship, direct + intermediate):** gather the purposes of
  the last 3–5 merged PRs into `` (Claude-authored bodies preferred;
  fallback: merge commits / CHANGELOG), extract cross-cutting conventions, and
  audit **in both directions**: (a) the current diff honors prior conventions —
  e.g. a prior branch's "all elements get hotkeys" must also cover an element
  added on THIS branch, even though the hotkey task never belonged to it; and
  (b) a convention THIS branch introduces is retro-applied to the existing
  artifacts on `` as part of this ship (reverse propagation).
- **Full check (a rebase/merge happened in 1b, or re-entry after
  `baseAdvancedDuringChecks`):** additionally verify the merged content sti

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Jerry0022](https://github.com/Jerry0022)
- **Source:** [Jerry0022/dotclaude](https://github.com/Jerry0022/dotclaude)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jerry0022-dotclaude-ship
- Seller: https://agentstack.voostack.com/s/jerry0022
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
