ship-setup
Interviews the owner, one topic at a time, and writes `.claude/rules/ship.md` — the ordered string of shipping steps (push, open a pull request, review rounds, merge, release, and whatever the contrac
SKILL.mdpackages/skills/ship-setup/SKILL.md
GitHubship-setup
.claude/rules/ship.md is owner-governed: it is the standing authorization for every
outward-facing act /ship-build takes (a merge, a deploy, a command run on the owner's
behalf). This skill is the only way it gets written or changed — running it IS the owner's
approval of each step it records, so there is no confirmation step after the interview.
Until it has run, ship.md lists no step and /ship-build only pushes.
When it applies
- A new project, right after
/init-projectcopies the template with an empty## Ship. /ship-buildended by saying there is no policy and how to set one.- Any time the owner wants to add, drop, reorder or re-parameterise a step.
Inputs
| Input | Where it comes from |
|---|---|
| The current file | .claude/rules/ship.md, or template.md (this skill's own directory) when the file is absent |
| The current shape | template.md — the shipped template, with its worked examples |
| The steps on offer | one file per step, .claude/contracts/ship-primitive-<name>.md; the list of steps is the list of files. Never a list held in this skill |
| What a step asks | each contract's front matter params:, its ## Input text and, when present, its ## Setup section — see Per-step questions |
| Whether a deploy command exists | readFullDeploy in .claude/lib/functional-verification.js, run over .claude/rules/verification.md section 2 |
| Whether the project has a design | docs/ui/*/design-map.json |
| The workflow template | ensemble-ship-resume.yml (this skill's own directory) |
Topics
One AskUserQuestion call per topic, detected value first, then the current file's value
where it differs, then "keep". Skipping a topic leaves that part of the file untouched.
- The default string. Offer it first, as the first option, so accepting it is one
answer. It is the string labelled "the default string" in
template.md's examples: push, open a pull request, a bounded review-and-fix block, merge, wait-ci (CI on the merge commit), release, then the after-shipping steps. Show the whole string in the question. If the owner accepts it, go to Per-step questions for the values it leaves blank (thereleaseenvironment, command and identity); otherwise go to topic 2. - Build the string. Offer the steps from the contracts directory, in the order the owner
chooses, using each contract's one-line description (the line under its heading). Two are
special-cased by what the project has, not by name in the contract:
sync-designis offered only whendocs/ui/*/design-map.jsonexists. With no design, it is not offered and is not mentioned as a gap.await-approvalis offered with its trigger. Choosing it also raises the trigger workflow (topic 4). A repeating block is written asrepeatwith indented- <step>lines, no nesting; it is the sequencer's own construct, not a contract.
- After shipping. The steps the owner wants run once the work is merged or released, from
the contracts whose
section:isafterorany. - The trigger workflow. Asked only when the chosen string contains
await-approval. Say what it does in one sentence (a reviewer's approval runs/ship-build --resumein GitHub Actions), where its credential lives (the repository secretANTHROPIC_API_KEY, which the owner adds themselves — this skill never sees or writes the value), and that it only takes effect once the file is on the default branch. On a yes, install it (see Writing); on a no, write the string withouttrigger=github-actionsso nothing claims a trigger that is not there.
Re-running on a filled file asks only what changed: a step the contracts now offer that the file does not use, a parameter a contract gained, or a value the file leaves blank. Everything else is left alone and listed as unchanged in the closing summary.
Per-step questions
For every step the owner chose, ask for each parameter its contract declares. Read them from
the contract, never from this file: params: in the front matter lists them, where name=value
is optional with that default, name= is optional with none, and a bare name is required.
Quote the contract's ## Input text beside the question and offer its default as the first
option. A step whose contract declares a parameter this skill has never heard of is asked
that parameter all the same — a new step needs no edit here.
A contract may also carry an optional ## Setup section: extra things to ask or warn about
for that step. Read it and ask what it says; its absence means nothing more to ask.
What the contracts declare today, so the owner is not surprised (the contract is the authority, not this list):
repeat—rounds(default 2), the most passes the block makes.untilis left out: arepeatwith nountil=takes the one its body's contract declares.collect-findings—bar(defaultsignificant), the level of finding the work must fix before it ships; below it, findings are recorded and filed, not fixed.release—env,command,identity:env: ask which environment, as named inverification.mdsection 1. Where exactly one environment declares a full-deploy command, offer it.command: ask only wherereadFullDeploy(<verification.md text>, <env>)returns no command. Where it returns one, say thatreleasewill reuse it and ask nothing. Where it returns none, ask for the command to run; with no answer, leavereleaseout rather than write a step that stops every run.identity: ask for a command that prints the commit the deployed environment is running, and say plainly that it must report the commit released from this work, not merely the environment's latest build — the release check compares its output to the commit the run pushed, and a command that reports something else fails every release.
run— the command, verbatim, to the end of the line.
Writing
Once every topic has an answer, write the whole file at once in the template's shape: the
template's preamble kept verbatim, ## Ship and ## After shipping filled in the line format
N. <step> key=value key="quoted value", and the template's ## Examples (not run) section
kept as it is. There is no preview step and no second confirmation. A part the interview did
not change keeps its content verbatim.
On a yes to the trigger workflow, also write .github/workflows/ensemble-ship-resume.yml as a
copy of ensemble-ship-resume.yml from this skill's directory, unchanged. That is the only
other file this skill writes.
After writing, re-parse with the sequencer, so there is one parser and not a second one here:
node .claude/lib/ship-sequencer.js parse --policy .claude/rules/ship.md
Any entry in its errors is this skill's own defect: report each in ISSUES, with the line
number, rather than leaving a file the next /ship-build would refuse.
Then check the authorization the written steps need:
node .claude/lib/ship-sequencer.js authorization --policy .claude/rules/ship.md
When it prints "sentence":"absent" and refused is not empty, those steps would stop the next
/ship-build with not authorized. In ISSUES, name each refused step, quote the sentence
A step listed in \.claude/rules/ship.md` is the owner's standing authorization for that act.and say the owner adds it to.claude/rules/autonomy.md; this skill never edits that file. Say so in NEXT as well, ahead of /ship-build`.
Never
- Write a credential's value. Name where one lives (a repository secret's name, a vault item, an environment variable's name) — never the token, password or key. If an answer looks like a value rather than a location, do not write it; ask for the location.
- Edit any file other than
.claude/rules/ship.mdand, on the owner's yes, the workflow file. Never.claude/settings.json, neververification.md, never a contract. - Contact or probe anything. Detection reads files in the repository; it makes no network call and runs no deploy, merge or push.
- Start a ship. Running
/ship-buildis the owner's own next invocation.
Readout
Ends with the framework's standard four-section readout (STATE / DECISIONS / ISSUES / NEXT,
.claude/rules/command-status.md). STATE lists the string written, step by step, whether the
workflow was installed, and what stayed unchanged. DECISIONS lists every default applied where
no answer came in. ISSUES lists parse errors from the re-check, a release left out for want of
a command, and a workflow written but not yet on the default branch (the owner must merge it,
and add the secret, before it fires). NEXT gives /ship-build when a policy now exists.
Then the ═══ COMMAND COMPLETE: /ship-setup ═══ banner, and a call to
.claude/hooks/notify-complete.sh ship-setup complete "<one-line summary>" — the same close
every workflow command uses, so the run-state marker autonomy.md's Judgment B depends on is
actually cleared.