Skip to content
Back to skills

Ship

ASecurity

Have the AI branch, commit, push, and create or update a pull request in the current repository. Use when the user says ship, asks to prepare a branch or commit, or wants help following the repo branch and PR workflow without pushing to the base branch.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 19, 2026
ai-agentsrustgoshellrailsgitapi

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add karloows/orchraft --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/karloows-ship/badge)](https://www.skillsdirectory.com/skills/karloows-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: Have the AI branch, commit, push, and create or update a pull request in the current repository. Use when the user says ship, asks to prepare a branch or commit, or wants help following the repo branch and PR workflow without pushing to the base branch.
---

# Ship Workflow

Use this skill when the user asks the AI to ship work.

## Contents

- [At A Glance](#at-a-glance)
- [Trigger Rules](#trigger-rules)
- [What This Is Not](#what-this-is-not)
- [Prerequisites](#prerequisites)
- [Default Path](#default-path)
- [Naming And Text](#naming-and-text)
- [Guardrails](#guardrails)
- [Stop Conditions](#stop-conditions)
- [Handoff](#handoff)
- [Response Examples](#response-examples)

## At A Glance

1. Inspect the current branch, status, and actual diff.
2. Validate the touched area.
3. Use the current topic branch, or create a policy-compliant branch from the
   base branch when currently on it or on the repository's default branch.
4. Stage only intended changes, commit with a policy-compliant message, then
   push.
5. Create or update the pull request and report the branch, commit, PR, and
   validation result.

## Trigger Rules

- Only start this workflow when the user's current message explicitly asks to
  ship, create a branch/commit/PR, or otherwise gives a clear go signal for the
  full ship workflow.
- Do not infer shipping approval from the fact that changes were just made,
  validation passed, a prior turn discussed shipping, or the work appears ready.
- If the user asks for edits, review, validation, or policy changes without a
  current-turn ship request, make the changes only and wait for an explicit
  ship/go confirmation before committing, pushing, or opening/updating a PR.

## What This Is Not

- Not a land workflow for merging pull requests or deleting topic branches.
- Not approval to commit unrelated local changes.
- Not permission to push directly to the base branch unless the user
  explicitly asks.
- Not permission to commit, push, or open/update a pull request after ordinary
  edits unless the user explicitly asks to ship in the current turn.
- Not a replacement for validation; run the smallest relevant checks before
  committing.

## Prerequisites

- Read `context/policies/approval-policy.md`,
  `context/policies/branch-policy.md`,
  `context/policies/commit-policy.md`,
  `context/policies/verification-policy.md`, and
  `context/policies/writing-guidelines.md`. Use the target repo's copy of each
  when it exists; otherwise use the bundled copy at
  `${CLAUDE_PLUGIN_ROOT}/context/policies/<file>`.
- Read the target repo's config file — `.orchraft.jsonc`, else
  `.orchraft.json` — when one exists, per `context/policies/config-policy.md`
  (the target repo's copy when it exists, otherwise
  `${CLAUDE_PLUGIN_ROOT}/context/policies/config-policy.md`). A missing file
  is the normal case and means the documented defaults apply.
- Check `git status --short --branch` before changing branch or commit state.
- Confirm there are intended changes to ship.
- Identify untracked files and include only the ones that belong to this work.
- If already on a topic branch, assume the user wants to ship additional
  work on that branch unless they explicitly ask for a different branch.
- Inspect the full intended change set before naming anything: current branch,
  `git status`, unstaged diff, staged diff, and relevant untracked files.
- Generate the branch name, commit message, and pull request text from that
  complete inspected change set, not from memory or the ticket title alone.

## Default Path

1. Inspect branch state and working tree.
2. Validate the touched area per `context/policies/verification-policy.md`.
   When the config file sets `validate`, run that command rather than
   discovering one from the repository; it is the answer the repo already
   gave, so there is nothing left to infer. Everything else in
   `verification-policy.md` still applies to it — a failure is a stop, and
   the command that ran is reported as written.
3. Resolve the base branch first: `baseBranch` from the config file when set,
   otherwise the repository's default branch. Do not assume `main` — a
   repository on `master` or `develop` does not use it. When `baseBranch`
   names a branch other than the default, the default branch is not a topic
   branch either: every rule in this skill that refers to the base branch —
   the guardrail, the stop condition, not pushing to it — applies to both.
   If on either, create a policy-compliant branch from the base branch; if
   already on a topic branch, keep using it. Before creating or renaming any
   branch, count the words after `/` (excluding an Optional Ticket Key
   segment, if used) against `context/policies/branch-policy.md`'s limit and
   check the allowed characters — verify the generated name against the
   policy text itself, not just against the rule from memory, before running
   `git checkout -b` or a rename. A name that fails this check gets fixed before
   it's used, not caught later by `roast`.
4. Stage only the intended changes.
5. Write a commit title using `<type>(<scope>): <summary>`.
6. Add a commit body only when the title doesn't fully explain the change,
   written as free-form prose with no headings, per
   `context/policies/commit-policy.md`.
7. Let local git hooks run normally during commit. If hooks auto-fix files,
   review the resulting diff, stage only intended hook changes, and commit
   again.
8. Confirm the commit succeeded and no intended hook changes remain unstaged.
9. Push the topic branch.
10. Create or update the branch pull request through the GitHub MCP connector
   when it is available in the session. Use `gh` only after the MCP path has
   been tried and is unavailable or blocked. When updating an existing PR,
   re-read the whole body against the branch as it now stands, not just the
   section the new commit belongs in: commit counts, the list of touched
   files, and the commit each validation claim ran against all go stale when
   a push only appends a line. Correct or re-run anything that no longer
   holds.
11. If the PR has open review threads from a prior `roast` pass and this
    diff fixes the finding one flags, resolve that specific thread via
    `pull_request_review_write` (method `resolve_thread`) once the user gives
    the current-turn go-ahead per `context/policies/approval-policy.md`.
    Match each resolution to the finding it actually fixes; do not resolve
    threads wholesale or resolve one whose finding this diff doesn't address.
    A finding that a statement is wrong is fixed only when every copy of it
    is: before committing the fix, search the repository for other places
    stating the same fact or rule, and fix those in the same commit. The
    flagged line is where a reviewer happened to look, not the only place
    the wording lives.
    A finding posted as an "outside diff range" or general PR comment (common
    from CodeRabbit and similar bots, since GitHub only allows threads on
    lines inside a diff hunk) has no review thread to resolve at all — say so
    plainly instead of treating it as resolved just because the diff fixes it.
12. If a review thread's finding — from `roast`, CodeRabbit, or a human
    reviewer — is being declined rather than fixed (a false positive, a
    deliberate tradeoff, out of scope for this PR), do not resolve it
    silently and do not leave it hanging with no response either. Draft a
    short, technical reply stating the concrete reason it won't be fixed,
    and once the user gives the current-turn go-ahead per
    `context/policies/approval-policy.md`, post it via
    `add_reply_to_pull_request_comment`. If that MCP path is unavailable,
    fall back to `gh api --method POST
    "repos/$owner/$repo/pulls/$number/comments" -f "body=$reply" -F
    "in_reply_to=$parent_review_comment_id"` — quoted shell variables, not
    bare angle-bracket placeholders, since an unquoted multiline reply can
    be parsed as redirection or split into multiple arguments. Never `gh
    pr comment`, which creates a top-level PR comment instead of a
    review-thread reply, so `reckoning` would never find it. This exact
    `gh api` form matches GitHub's documented review-comment-reply
    behavior but hasn't been exercised live in this repo; confirm the
    response actually carries a valid `id`/`html_url` the first time this
    fallback path fires, the same way `roast`'s own `gh` fallback
    validates its result, rather than trusting the command because it
    reads correctly. A reply is not a resolution: leave the thread
    unresolved unless the user separately asks to resolve it too. End the
    reply's visible text with a blank line and the hidden marker
    `<!-- orchraft:declined -->` so `reckoning` can find it later; the
    marker is metadata for that skill, not part of the stated reason
    itself.

## Naming And Text

- Always inspect the whole set of changes the user wants shipped before
  choosing the branch name, commit title/body, PR title, or PR body.
- Branch: follow `context/policies/branch-policy.md` exactly:
  `<type>/<short-kebab-description>`, using the same conventional type as the
  dominant change where possible.
- Commit title: follow `context/policies/commit-policy.md` exactly:
  `<type>(<scope>): <summary>`.
- Commit body: follow `context/policies/commit-policy.md` exactly: optional,
  free-form prose with no headings, describing only the staged diff.
- Pull request title: `<type>: <short technical summary>` per
  `context/policies/writing-guidelines.md` — keep the `<type>:` prefix, just
  omit the `(scope)` parentheses unless the user explicitly asks for one.
- Pull request body: follow `context/policies/writing-guidelines.md`. Describe
  the whole branch, not just the final commit. If the repository provides a PR
  template or PR body checks, follow that format first. Do not invent checklist
  items, screenshots, reviewers, or follow-up work.

## Guardrails

- Never commit or push directly to the base branch unless the user
  explicitly asks.
- Do not stop after push until the PR step is complete or clearly blocked.
- If the branch name would violate policy, stop and fix the branch name instead of improvising.
- Do not create a second topic branch from an existing topic branch unless
  the user explicitly asks to branch off or retarget the work.
- If branch creation fails with a git refs collision such as an existing
  `docs` ref blocking `docs/...`, diagnose the local and remote refs with the
  correct git commands before changing the branch name. Do not switch to a
  less accurate type or unrelated branch name just to bypass the error.
- If a git or network command fails because of the sandbox (read-only `.git`,
  blocked network), follow `context/policies/sandbox-policy.md` (the target
  repo's copy when it exists, otherwise
  `${CLAUDE_PLUGIN_ROOT}/context/policies/sandbox-policy.md`): rerun that
  command with escalation, never substitute the GitHub API for the local
  commit, and stop if escalation is declined.
- Never resolve a review thread whose finding this diff doesn't actually fix,
  and never resolve one without the user's current-turn go-ahead.
- Never post a decline reply to a review thread without the user's
  current-turn go-ahead, and never resolve a thread just because a decline
  reply was posted to it — a reply and a resolution are separate actions,
  each needing its own go-ahead.

## Stop Conditions

- Stop before commit, push, or PR mutation if the user has not explicitly asked
  to ship in the current turn.
- Stop if there are no changes to ship.
- Stop if the only available branch would be the base branch and the user did
  not explicitly allow committing to it.
- Stop if intended and unrelated changes cannot be separated safely.
- Stop if validation for the touched area fails, unless the user explicitly
  asks to ship despite the failure.
- Stop if a required git or network command remains blocked by the host
  sandbox after per-command escalation. Report the blocked command and tell
  the user the exact command to rerun with approved git mutation access; do
  not substitute a GitHub API for the local branch or commit steps.
- Stop if local git hooks fail, abort the commit, or leave unexpected changes.
- Stop if branch, commit, or pull request text would violate the policy files.

## Handoff

- Unless the user asked for plain output, open with a fresh one-line success
  phrase in the orc voice, speaking as the Raid Captain from
  `context/personality.md` (the target repo's copy when it exists, otherwise
  `${CLAUDE_PLUGIN_ROOT}/context/personality.md`). If they did, open with the
  plain result instead.
- Report the branch name.
- Report the commit title.
- Report the pull request URL or say why PR creation/update was blocked.
- Report validation that ran, or why validation could not run.
- Report which review threads, if any, were resolved and which finding each
  one fixed, and which threads, if any, got a decline reply and why.
- If shipping stops or fails, skip the shipping phrase and state the blocker
  plainly.

## Response Examples

Opening lines are samples of the orc voice; write a fresh one each time.

Successful ship:

```text
🚢 Grah! War party launched. PR #123 holds the beach for review, chief. ✨

Branch: `fix/login-null-token`
Commit: `fix(auth): guard null login token`
PR: https://github.com/example/repo/pull/123
Validation: `<project validation command>`
```

Successful ship with docs only:

```text
🚢 Battle scrolls packed for the march. The docs PR has taken the field.

Branch: `docs/land-workflow`
Commit: `docs(agents): clarify land workflow`
PR: https://github.com/example/repo/pull/124
Validation: reviewed markdown changes
```

Successful ship on existing branch:

```text
🚢 Reinforcements sent to the same front. PR #124 holds the new line.

Branch: `docs/land-workflow`
Commit: `docs(agents): document land trigger rules`
PR: https://github.com/example/repo/pull/124
Validation: reviewed markdown changes
```

Blocked ship:

```text
⚠️ Shipping is blocked: validation failed in `<project validation command>`.

No commit or push was performed.
```

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.