Skip to content
Back to skills

Ship

ASecurity

Take a PR from open to merged and deployed without the user steering each step, using the `ship` CLI. Use when the user says ship it, take it e2e, get this merged, PR please and see it through, babysit/finish the PR, or after opening a PR when the task is not done until it lands.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 22, 2026
developmentgoreactgit

Works with

  • terminal
  • cli

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 22, 2026

npx -y skills add ohitslaurence/herdr-fleet --skill ship --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ship?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ship
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ohitslaurence-ship/badge)](https://www.skillsdirectory.com/skills/ohitslaurence-ship)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ship
description: Take a PR from open to merged and deployed without the user steering each step, using the `ship` CLI. Use when the user says ship it, take it e2e, get this merged, PR please and see it through, babysit/finish the PR, or after opening a PR when the task is not done until it lands.
argument-hint: "[<pr-url-or-number>]"
---

# Ship a PR

`ship` reads the PR's whole state from GitHub and prints ONE next action. You do
that action, then ask `ship` again. The loop ends only at a terminal state.

## Loop

1. No PR yet: commit, push and open it as a draft. With gritty: `gritty commit --accept`,
   `gritty pr --accept --draft`. Without: `git commit`, `gh pr create --fill --draft`.
   ship marks it ready once it's clean, so paid reviewers only see the finished work.
2. Run `ship --act --wait` (add the PR URL if you are not on its branch).
   `--act` does the mechanical steps itself: request a Greptile review when the
   budget allows, re-run cancelled CI, update a behind branch, mark ready,
   label, and merge when policy allows. `--wait` blocks while CI runs, Greptile
   reviews, or the deploy rolls out, so you don't poll.
   If the user says they merged it, or asks whether it's open, merged or deployed:
   run `ship pr <ref>` (about 1 s, read-only) and answer from that. Use `--wait` only
   when it shows a deploy still running.
3. Do what `next:` says. The states that need code:
   - `conflicts`: rebase onto the base, resolve, run the repo's checks, push `--force-with-lease`.
   - `ci-red`: read the failing job logs (`gh run view <id> --log-failed`), fix the cause, push.
   - `review-findings`: work the findings (below), push.
   - `self-review`: write the self-review (below) before the next review.
   - `cross-review`: just run `ship --act --wait`; it runs the free review.
   - `craft-review`: just run `ship --act --wait`; it runs the quiet craft review.
   - `craft-findings`: give every finding a verdict (below).
4. Go back to step 2.

## Re-reviews cost money: earn them

Every Greptile re-review is paid. `ship` decides when one is worth it from the
PR's tier (`ship policy` shows the numbers):

- **normal** PRs pass at 4/5. Minor (P2) findings get fixed or answered and
  the PR moves on with no re-review, as long as the fix is small.
- **critical** PRs (payments, ledger, auth, KYC, migrations, infra, or
  money-moving repos) need 5/5, and any real change after the last review gets
  re-reviewed, up to a budget. Then a human decides.

Our own models are free to use (subscriptions), so `ship` spends them first:

- **cross-review**: a fresh-context review by the *other* model family (Codex
  reviews Claude's PR and vice versa) runs headless on the PR head. It is
  required before every paid re-review on critical PRs, and on any PR once a
  paid re-review has failed to converge. `ship --act --wait` runs it and posts
  the verdict; treat its findings exactly like Greptile's.
- **churn**: if each paid review finds as many problems as the last, the fixes
  are creating new bugs and your context is the problem. `ship` says `churn`:
  run `ship rescue`, which hands the PR to a fresh agent from the other family,
  then STOP working on the PR. Don't keep patching.

Never re-tag Greptile yourself (`@greptileai`). Only `ship --act` does, and
only when the budget and the self-review allow it.

## Rescue

When `ship` reports `churn`, run `ship rescue [<pr>]`. It hands the PR and the
review history to a fresh agent from the other model family. Once the handoff
succeeds, stop editing the branch and report the handoff. If rescue fails, report
the error; do not claim another agent owns it until the command succeeds.

## Working findings: the thinking is the job

A reviewer's comment points at a symptom. Fixing exactly the line it names is
the lazy move, and it costs a paid re-review per round when the reviewer finds
the same mistake one function over. Instead, for each finding:

1. **Decide whether it's real.** Read the code around it. Greptile lacks
   codebase context and is often wrong; when it is, reply with the specific
   reason (`ship guide replies` covers reactions and replies) and
   move on. Don't "fix" a non-bug to make the reviewer happy.
2. **Name the cause, not the line.** What wrong assumption produced this? For
   example, "this code assumes the webhook arrives once", not "missing
   idempotency check on line 40".
3. **Find the siblings.** Search the diff and the code it touches for the
   same assumption (`rg`). Fix every instance, not just the one flagged.
4. **Prove it.** Add or extend a test that fails without the fix whenever the
   finding is about behaviour. Run the repo's checks.
5. **Pre-empt the next round.** Before pushing, reread the full diff the way
   the reviewer will: what would it flag next? Fix that now.

For minor findings (naming, a missing test case, a doc line): fix them
properly, reply on the thread, and don't ask for a re-review.

## Self-review (required before a paid re-review)

When `ship` says `self-review`, post one PR comment (`gh pr comment`) that ends
with the marker line, using the current head SHA (`git rev-parse HEAD`):

```
Self-review before re-review

Findings addressed:
1. <finding> → cause: <the wrong assumption> → fixed in <files>; siblings checked: <where> (<n> more fixed | none)
2. ...
Dismissed: <finding> — <why it isn't a bug>
Tests: <what now covers it>; checks: <command> passing
Risk I still see: <one line, or "none">

<!-- fleet-self-review sha=<HEAD> -->
```

Write it from the diff, not from memory. If you can't fill a "cause" or
"siblings checked" line honestly, you haven't finished: go back to the
findings. Then run `ship --act --wait`.

## Craft review

Where the repo turns it on (`ship.craft_review`), a fresh reviewer that didn't write the code
(the other model family when it can run sandboxed) reads the draft once for craft (with `merge = "auto"`, a PR opened ready too): architecture fit, readability, test quality, PR clarity, and anything
that didn't need to exist. Its findings stay on this machine, never on the PR. `ship findings`
lists them.

Judge each one like any review comment (`ship guide findings`): is it real here, in this repo's
conventions? Fix the real ones properly; dismiss the rest with the reason. Then record it:

```
ship findings c1 c3 fixed "split parse_args out of main; renamed x to retries"
ship findings c2 dismissed "the two loops differ on purpose: one must not block on GitHub"
```

Be honest in both directions. The verdicts are how the fleet learns: findings that keep getting
fixed become lint rules and agent instructions, and findings that keep getting dismissed teach
the reviewer what to stop raising. Dismissing a real finding to move on teaches it the wrong thing.
Once every finding has a verdict, `ship --act --wait` continues and marks the PR ready.

## Stop only at a terminal state

| state | what you do |
|---|---|
| `deployed` | If `next:` says to run after_deploy, run `ship --act` first (your config's post-deploy command; it runs once). Tell the user in one line: PR, merged, deployed. Then stop. Don't run or offer `dev done`: it closes this pane and worktree, and the user does that from the cockpit. |
| `awaiting-human` | Clean and green, but policy needs a human merge. One line: PR URL + why. |
| `needs-human` | Budget spent or review didn't converge. Summarise what's still open in ≤5 lines and ask one question. |
| `deploy-gated` | A deploy waits for environment approval. Say so with the run URL. |
| `deploy-failed` | Investigate the failed run; report. Never push to main to fix it. |
| `closed` | Say so. |
| `churn` | Run `ship rescue`, tell the user one line (PR, handed to a fresh agent), and stop. |

## Rules

- Do not ask the user before any step in this loop that `ship` tells you to do. Those steps are reversible and in scope. Ask only at `needs-human`.
- Never merge by hand with `gh pr merge`; only `ship --act` merges, because it applies the policy.
- If the same non-terminal state repeats three times with no progress, stop and report it as `needs-human`.

Files in this skill

  • SKILL.md7.9 KB
  • craft-brief.md2.8 KB
  • rescue-brief.md1.7 KB
  • review-brief.md1.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.