agentsclimarketplace

Ship

Skill thettwe/nyann/skills/ship

Open a PR and merge it in one step — combines `bin/pr.sh` create with `bin/wait-for-pr-checks.sh` polling and `gh pr merge`. Default mode enables GitHub's native auto-merge so the terminal returns immediately; `--client-side` polls in the foreground and merges when CI goes green. TRIGGER when the user says "ship this PR", "ship it", "open and merge", "PR and merge", "create PR and auto-merge it", "wait for CI then merge", "block until merged", "/nyann:ship". Do NOT trigger on "open a PR" alone (no merge intent) — that's the `pr` skill. Do NOT trigger on "merge this existing PR #N" — ship is PR-creation + merge, not standalone merge of an already-open PR. Do NOT trigger on "release X.Y.Z" — that's the `release` skill, which tags a merged commit rather than creating one.From its SKILL.md

Install
npx -y skills add thettwe/nyann --skill ship

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.2 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it

ship

Wraps bin/ship.sh. The script composes bin/pr.sh (PR creation), bin/wait-for-pr-checks.sh (poll), and gh pr merge (merge) into a single ShipResult. The output schema is at schemas/ship-result.schema.json.

0. Drift check (quick, non-blocking)

Run bash bin/session-check.sh --flow=ship. If it produces output, surface the line to the user verbatim. Do not block the flow.

1. Pick the mode up front

Two modes, decided at invocation. They have very different terminal behavior, so confirm with the user when it isn't obvious which they want.

ModeDefaultTerminal behaviorUse when
auto-mergeyesreturns ~instantly with outcome:"queued"repo allows auto-merge, user wants to walk away
client-side (--client-side)opt-inblocks until ship-or-failrepo doesn't allow auto-merge, or user wants the wait surfaced

If the user says "ship it and let me know when it's in" or "block until merged", use --client-side. If they say "queue it for merge" or "ship and I'll come back later", use the default.

When the user's intent doesn't clearly map to either mode, you MUST call the AskUserQuestion tool (not plain text):

{
  "questions": [
    {
      "question": "How should this PR be merged after CI passes?",
      "header": "Ship mode",
      "multiSelect": false,
      "options": [
        { "label": "Auto-merge (Recommended)", "description": "Returns immediately; GitHub merges when checks pass" },
        { "label": "Client-side", "description": "Blocks here until CI is green, then merges" }
      ]
    }
  ]
}

2. Pre-flight (same as pr skill)

  • bin/ship.sh runs the same gh guard as bin/pr.sh. Skip records with reason gh-not-installed or gh-not-authenticated short-circuit before any PR is created. Relay these as-is.
  • The current branch must not be main/master. The underlying pr.sh enforces this; if it dies, route the user to /nyann:branch first.
  • Synthesize the title + body the same way the pr skill does: bin/pr.sh --target <cwd> --context-only first, then build a Conventional-Commits title and a Summary/Test-plan markdown body.

Pre-action guards

bash bin/pre-action-guard.sh --flow ship --target <cwd> [--profile <resolved-profile.json>]

By default ship runs the PR-flow guards (branch-pushed, wip-commits). A guards.ship array REPLACES that default set (subset semantics — it does not append) and may promote severities.

coverage-delta is an opt-in guard — off by default. Since guards.ship replaces the default set, enable it by re-listing the built-ins alongside it: "guards":{"ship":[{"name":"branch-pushed"},{"name":"wip-commits"},{"name":"coverage-delta"}]}. Naming only coverage-delta would silently drop them. It warns (advisory by default; promote to confirm via the profile) when the branch lowers test coverage versus the cached .nyann/coverage-baseline.json, tolerant up to guards.coverage_delta_threshold percentage points (default 0). It reuses an existing CI coverage artifact and soft-skips when none is present (it never runs the suite), so it's best paired with a profile/CI that already produces coverage. Refresh the baseline on the base branch / post-merge with bash bin/guards/coverage-delta.sh --update-baseline.

ExitMeaningAction
0PassContinue
3Critical guard failedRefuse to ship. The user has to fix the underlying issue or pass --skip-guards.
4Confirm-severity guard failedAskUserQuestion: "Proceed with ship?" — explicit confirm required.

3. Confirm before shipping

Show the user the proposed title, body, and mode before invoking.

  • Auto-merge: "Ship it via auto-merge? (returns immediately; GitHub merges when checks pass)"
  • Client-side: "Block here while CI runs and merge when green? Default timeout is 30 minutes (polling every 30 seconds). Override with --timeout / --interval if your CI is slower."

Skip the confirmation only when the user said "just ship it" / "don't ask, ship it now".

4. Invoke

bin/ship.sh \
  --target <cwd> \
  --title "<conventional-title>" \
  --body  "<markdown-body>" \
  [--base <branch>] \
  [--draft] \
  [--client-side] \
  [--merge-strategy squash|rebase|merge] \
  [--timeout <sec>] [--interval <sec>] \
  [--allow-no-checks]

--draft opens as draft (auto-merge will wait for ready-for-review + checks; client-side mode merges as draft if you pass --draft, which is rarely what you want). --merge-strategy defaults to squash; respect the user's preference if they name a different one. --timeout and --interval are forwarded to the wait phase in client-side mode (defaults: 30 min / 30 s).

--allow-no-checks is a safety opt-out for client-side mode. By default, the script refuses to merge when the waiter reports no-checks — that outcome on a fresh PR almost always means "workflows haven't attached yet" rather than "this repo has no PR CI", so silently merging would defeat the gate. Pass --allow-no-checks only when you know the repo runs no PR-side checks (no GitHub Actions, no required reviews, etc.) and the empty state is intentional. Auto-merge mode doesn't need this flag — GitHub's server-side auto-merge already handles required-checks state correctly.

5. Interpret the outcome

Branch on .outcome:

OutcomeModeWhat happenedWhat the user should do
queuedauto-mergeGitHub's auto-merge enabled; merge happens server-side when checks + reviews passtrust it, walk away
shippedclient-sidemerge call succeeded after green CIdone; PR is merged + branch deleted
ci-failedclient-sideone or more checks failed OR the PR had no checks attached without --allow-no-checks; loop bailedinspect ci_failed_reason in the JSON; for the no-checks case re-run with --allow-no-checks if the empty state is intentional, otherwise wait for workflows to attach and retry
ci-timeoutclient-sidewait deadline hit, some still in_progressretry with --timeout higher, or investigate runners
merge-failedeitherauto-merge couldn't be enabled (e.g. branch protection) or gh pr merge failedinspect merge_failed_reason; common causes: required reviews missing, branch protection forbids the strategy
pr-failedeitherbin/pr.sh died before producing a URLrerun /nyann:pr to surface the underlying error
skippedeithergh missing/unauthed; nothing was createdtell the user; can't proceed

The script always exits 0. Branch on the .outcome field in the JSON to determine what happened.

6. Handling errors

  • merge-failed with reason like "auto-merge is not allowed" → suggest retrying with --client-side, which polls then calls gh pr merge directly (works even when server-side auto-merge is disabled).
  • merge-failed with reason like "required reviews" → relay verbatim; the user needs a reviewer to approve before merge can proceed.
  • ci-failed → don't suggest re-running ship; route the user to fix the failing job first. Mention they can check it via gh pr checks <num> directly.

When to hand off

  • "Just open the PR" / "don't merge yet" → pr skill.
  • "Wait for CI but don't merge" → wait-for-pr-checks skill.
  • "Tag a release after merge" → release skill — invoke after ship reports shipped or after the auto-merge actually lands.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.