Ship PR
A repo-agnostic worktree -> branch -> PR -> squash-merge -> cleanup workflow. Works in any git repo with an origin remote and gh configured; the scripts detect the package manager and default branch rather than assuming pnpm/Turborepo/main.
This is the atomic unit of the ship stack: parallel-ship and epic-ship both call this skill internally (per fanned-out agent and per phase respectively). Invoke it directly for anything that is one PR-sized change.
Naming note: if a repo you work in defines its own project-level ship-pr skill (tuned to that repo's quirks), rename this personal-level copy (e.g. ship-pr-global) - in Claude Code's skill resolution, a personal-level skill overrides a project-level one of the same name, so an identical name would silently shadow the tuned version.
Step 1: Pick the branch type
| Change scope |
Prefix |
Docs only (markdown, docs/**) |
docs/ |
| New behavior |
feat/ |
| Bug correction (behavior existed, broke) |
fix/ |
| Tooling/refactor, no behavior change |
chore/ |
| Production is broken right now |
hotfix/ |
If unsure between feat/ and fix/: did this behavior exist and work correctly before? Correcting it is fix/. Adding something new is feat/.
Step 2: Worktree -> implement -> verify -> ship -> merge -> cleanup
Worktree: bash ${CLAUDE_SKILL_DIR}/scripts/worktree-new.sh <prefix>/<slug>. Run from anywhere inside the target repo. It fetches the remote default branch (detected locally via refs/remotes/origin/HEAD, falling back to a git remote show origin network call only if that's unset, then to main), creates .worktrees/<slug>/ at the repo root (added to .gitignore automatically if missing), installs dependencies with whatever package manager the repo's lockfile indicates, and copies untracked .env* files from the repo root if present.
Implement: do the actual work. Implement directly rather than just writing a plan, unless the user asked for a plan. For large files (200+ lines), make incremental targeted edits rather than rewriting the whole file in one shot.
Verify - do not skip, do not just document it: check package.json (or the repo's equivalent - Makefile, Cargo.toml, etc.) for what's actually available and run it:
- A build script (
build, compile) if present.
- A typecheck script (
typecheck, tsc, or tsc --noEmit directly) if the repo is TypeScript.
- The test suite (
test).
- Lint (
lint) if configured.
- UI/visual change: run the app, take a screenshot, and actually look at it (use a screenshot-verification skill if you have one).
- Deps added/updated: install with
--frozen-lockfile/ci (not a plain install) to catch a drifted lockfile the way CI would.
- Markdown touched: the skill-scoped hook on this skill greps added lines in every touched
.md file for em-dashes before git push/gh pr create and blocks if it finds any. Note this checks the diff, not the whole file - if this repo's CI whole-file-scans touched markdown (verify by checking the CI config), pre-existing em-dashes you didn't write can still fail CI even though this hook passed.
- If the repo has branch protection requiring CI to pass, wait for it. If it doesn't (check repo settings or just try merging), CI is a second-opinion signal - don't sit and wait on a slow/queued run when the manual checks above already cover it.
Recommended CI job naming, if this repo is setting up checks from scratch: docs-check for doc-only PRs (link/em-dash checks), code-quality for lint, unit-tests for the test suite - scoped by changed-path so doc-only PRs skip the code checks.
Ship: commit, push, gh pr create --fill.
Merge: note that on private repos under GitHub's free plan there is no branch protection at all - nothing platform-side stands between a green PR and the default branch, so this skill's rules are the actual merge gate. The policy:
| Change |
Merge behavior |
Why |
| Docs-only |
Self-merge immediately |
Trivial verification, nothing platform-side to wait for |
| feat / fix / chore |
Self-merge after verification |
Same default; step 3 just has more to clear first |
| Payments, auth, data-integrity |
Leave PR open for human review |
The one exception - never self-merge, even on green CI |
Glance at gh pr checks <PR#>. Still running/queued and not required to merge -> proceed, don't block on it. Red for something step 3 already predicted and fixed -> proceed. Red for something unpredicted -> stop and investigate before merging, don't merge blind. Otherwise: gh pr merge --squash --delete-branch, then bash ${CLAUDE_SKILL_DIR}/scripts/worktree-close.sh <slug> immediately, not "later" - don't batch cleanup.
Model economics
This skill runs as a fork (context: fork), and a forked skill always inherits the invoking session's model - the Skill tool has no model parameter. Invoked from a frontier-tier session, every run costs frontier rates (~180k tokens per full implement-verify-merge cycle observed). For a mechanical, fully-specified change - and especially when fanning out several at once via parallel-ship - spawn Agent(model: sonnet) (or the cheapest tier that can do the job) with this skill's workflow steps written into the prompt instead of forking this skill. Reserve same-tier forks for changes needing real judgment. Five parallel frontier-tier forks once burned ~1M tokens and hit a session usage cap mid-epic; the Sonnet-agent rerun did equal-quality work at roughly 40% of the cost.
Hard rules
- Never push directly to the default branch. Every change is its own PR.
- Fork fresh from the remote default branch (
worktree-new.sh does this automatically) - never build on top of another unmerged branch.
- Close the worktree immediately after merge.
- One PR-sized change per invocation. If what you're doing is several independently shippable PRs from one analysis pass, use
parallel-ship instead. If it's sequential dependent phases (PR N+1 builds on PR N), use epic-ship - it calls this skill once per phase in order.
- High-risk changes (payments, auth, data-integrity, anything a human should eyeball before it goes live) should not self-merge on green CI - leave the PR open for human review instead of completing step 5 automatically.
Enforcement
The skill-scoped hook (scripts/check-em-dashes.sh) fires on every git push/gh pr create while this skill is active and blocks on em-dashes added to touched markdown. It cannot catch everything CI might check (lockfile drift, lint, types, whole-file em-dash scans) - the manual verify step above still matters.
1---2name: ship-pr3description: Ship a single change through a worktree -> branch -> PR -> squash-merge -> cleanup workflow - pick the right branch type (feat/fix/chore/docs/hotfix), implement, verify with this repo's real build/typecheck/test commands, open the PR, check CI, merge, and clean up. Use for any single PR-sized change in any git repo with a GitHub remote - a bug fix, a small feature, a doc edit, a dependency bump. For 3+ independently shippable PRs from one analysis pass, see parallel-ship. For sequential phases where each PR builds on the last, see epic-ship.4---56# Ship PR78A repo-agnostic worktree -> branch -> PR -> squash-merge -> cleanup workflow. Works in any git repo with an `origin` remote and `gh` configured; the scripts detect the package manager and default branch rather than assuming pnpm/Turborepo/`main`.910This is the atomic unit of the ship stack: `parallel-ship` and `epic-ship` both call this skill internally (per fanned-out agent and per phase respectively). Invoke it directly for anything that is one PR-sized change.1112> **Naming note:** if a repo you work in defines its own project-level `ship-pr` skill (tuned to that repo's quirks), rename this personal-level copy (e.g. `ship-pr-global`) - in Claude Code's skill resolution, a personal-level skill overrides a project-level one of the same name, so an identical name would silently shadow the tuned version.1314## Step 1: Pick the branch type1516| Change scope | Prefix |17| ---------------------------------------- | ---------- |18| Docs only (markdown, `docs/**`) | `docs/` |19| New behavior | `feat/` |20| Bug correction (behavior existed, broke) | `fix/` |21| Tooling/refactor, no behavior change | `chore/` |22| Production is broken right now | `hotfix/` |2324If unsure between `feat/` and `fix/`: did this behavior exist and work correctly before? Correcting it is `fix/`. Adding something new is `feat/`.2526## Step 2: Worktree -> implement -> verify -> ship -> merge -> cleanup27281. **Worktree**: `bash ${CLAUDE_SKILL_DIR}/scripts/worktree-new.sh <prefix>/<slug>`. Run from anywhere inside the target repo. It fetches the remote default branch (detected locally via `refs/remotes/origin/HEAD`, falling back to a `git remote show origin` network call only if that's unset, then to `main`), creates `.worktrees/<slug>/` at the repo root (added to `.gitignore` automatically if missing), installs dependencies with whatever package manager the repo's lockfile indicates, and copies untracked `.env*` files from the repo root if present.292. **Implement**: do the actual work. Implement directly rather than just writing a plan, unless the user asked for a plan. For large files (200+ lines), make incremental targeted edits rather than rewriting the whole file in one shot.303. **Verify - do not skip, do not just document it**: check `package.json` (or the repo's equivalent - `Makefile`, `Cargo.toml`, etc.) for what's actually available and run it:31 - A build script (`build`, `compile`) if present.32 - A typecheck script (`typecheck`, `tsc`, or `tsc --noEmit` directly) if the repo is TypeScript.33 - The test suite (`test`).34 - Lint (`lint`) if configured.35 - UI/visual change: run the app, take a screenshot, and actually look at it (use a screenshot-verification skill if you have one).36 - Deps added/updated: install with `--frozen-lockfile`/`ci` (not a plain install) to catch a drifted lockfile the way CI would.37 - Markdown touched: the skill-scoped hook on this skill greps **added lines** in every touched `.md` file for em-dashes before `git push`/`gh pr create` and blocks if it finds any. Note this checks the diff, not the whole file - if this repo's CI whole-file-scans touched markdown (verify by checking the CI config), pre-existing em-dashes you didn't write can still fail CI even though this hook passed.38 - If the repo has branch protection requiring CI to pass, wait for it. If it doesn't (check repo settings or just try merging), CI is a second-opinion signal - don't sit and wait on a slow/queued run when the manual checks above already cover it.3940 Recommended CI job naming, if this repo is setting up checks from scratch: `docs-check` for doc-only PRs (link/em-dash checks), `code-quality` for lint, `unit-tests` for the test suite - scoped by changed-path so doc-only PRs skip the code checks.414. **Ship**: commit, push, `gh pr create --fill`.425. **Merge**: note that on private repos under GitHub's free plan there is no branch protection at all - nothing platform-side stands between a green PR and the default branch, so this skill's rules are the actual merge gate. The policy:4344 | Change | Merge behavior | Why |45 | --- | --- | --- |46 | Docs-only | Self-merge immediately | Trivial verification, nothing platform-side to wait for |47 | feat / fix / chore | Self-merge after verification | Same default; step 3 just has more to clear first |48 | Payments, auth, data-integrity | Leave PR open for human review | The one exception - never self-merge, even on green CI |4950 Glance at `gh pr checks <PR#>`. Still running/queued and not required to merge -> proceed, don't block on it. Red for something step 3 already predicted and fixed -> proceed. Red for something unpredicted -> stop and investigate before merging, don't merge blind. Otherwise: `gh pr merge --squash --delete-branch`, then `bash ${CLAUDE_SKILL_DIR}/scripts/worktree-close.sh <slug>` **immediately**, not "later" - don't batch cleanup.5152## Model economics5354This skill runs as a fork (`context: fork`), and **a forked skill always inherits the invoking session's model - the Skill tool has no `model` parameter**. Invoked from a frontier-tier session, every run costs frontier rates (~180k tokens per full implement-verify-merge cycle observed). For a mechanical, fully-specified change - and especially when fanning out several at once via `parallel-ship` - spawn `Agent(model: sonnet)` (or the cheapest tier that can do the job) with this skill's workflow steps written into the prompt instead of forking this skill. Reserve same-tier forks for changes needing real judgment. Five parallel frontier-tier forks once burned ~1M tokens and hit a session usage cap mid-epic; the Sonnet-agent rerun did equal-quality work at roughly 40% of the cost.5556## Hard rules5758- Never push directly to the default branch. Every change is its own PR.59- Fork fresh from the remote default branch (`worktree-new.sh` does this automatically) - never build on top of another unmerged branch.60- Close the worktree immediately after merge.61- One PR-sized change per invocation. If what you're doing is several independently shippable PRs from one analysis pass, use `parallel-ship` instead. If it's sequential dependent phases (PR N+1 builds on PR N), use `epic-ship` - it calls this skill once per phase in order.62- High-risk changes (payments, auth, data-integrity, anything a human should eyeball before it goes live) should not self-merge on green CI - leave the PR open for human review instead of completing step 5 automatically.6364## Enforcement6566The skill-scoped hook (`scripts/check-em-dashes.sh`) fires on every `git push`/`gh pr create` while this skill is active and blocks on em-dashes added to touched markdown. It cannot catch everything CI might check (lockfile drift, lint, types, whole-file em-dash scans) - the manual verify step above still matters.