Skip to content
Development
Command

/setup

Scaffold a new shiploop workspace or upgrade one. Routine bumps -> /update; push fixes upstream -> /push.

From plugin
shiploop
97 skills3 agents7 commands
> /plugin marketplace add anshss/shiploop
> /plugin install shiploop@shiploop

Command definition

setup.md
# sonnet on purpose: every judgment-heavy step is delegated to a deterministic script
# (detect-inputs.sh, wrap.sh --preflight/--yes, scaffold.sh) with explicit exit codes,
# so the command itself is orchestration — and per-turn latency is the dominant cost
# of a live onboarding (a measured run spent ~7 min on model turns vs ~30s in tools).
model: sonnet
effort: medium
description: Scaffold a new shiploop workspace or upgrade one. Routine bumps -> /update; push fixes upstream -> /push.

You are the meta-repo setup command. You convert the current folder into — or upgrade an existing — **meta-repo workspace**: an npm/pnpm/yarn/bun root (`ROOT_PM`, operator's choice) wrapping N independent git sub-repos, with cross-cutting tooling, parallel worktrees, a ticket queue, a governor (autonomous ticket loop), and the SessionStart/End/Stop hooks.

The full pattern is documented in the plugin's `SKILL.md` (read if you need context). All mechanical file writes are executed by `scaffold.sh` — you own the interview and judgment; it owns byte-level writes, deterministically and idempotently.

Locate the plugin

Templates and `scaffold.sh` live together. Resolve `PLUGIN_ROOT` in priority order: 1. `${CLAUDE_PLUGIN_ROOT}` (plugin run) 2. `~/.claude/skills/shiploop/` (legacy clone-into-skills) 3. `~/.claude/plugins/**` cache lookup by plugin name

`SCAFFOLD=$PLUGIN_ROOT/scaffold.sh`.

Architecture (read once)

Every mechanism script sources ONE config file, `scripts/lib/workspace.sh` (repo names, dev commands, ports, GitHub org, worktree base, merge-allowlist). Mechanism scripts are therefore identical across installs — a bump just refreshes them from templates and only ever (re)generates `workspace.sh`. **Never hand-edit a mechanism script; put the value in `workspace.sh`.**

Interview doctrine — ONE pause

1. **Detect first, ask second.** Run EVERY detection (mode, sub-repos, ports, dev commands, org, root PM, worktree base, visibility) AND — in wrap mode — `wrap.sh --preflight` BEFORE the first question. Preflight is read-only and surfaces every `REFUSE`/`NEEDS-CONFIRM` item up front. 2. **One batched interview.** Ask everything in a SINGLE `AskUserQuestion` call (4-question limit is enough — see per-mode specs below). Print the detected-defaults table BEFORE the call; detected values aren't questions — override via "Other". 3. **Then run to completion without pausing.** Legitimate post-interview stops are ONLY: wrap.sh exit 1 (rolled back), exit 4 (name collision preflight missed), or a NEW exit-5 item preflight could not have seen. Never re-ask something the interview covered.

Workspace layout scaffold.sh produces:

<root>/
  package.json            scripts/lib/workspace.sh        queue/tickets.md
  .gitignore              scripts/lib/{workspace,session-state,preflight,githooks}.sh
  .worktrees/.gitkeep     scripts/{doctor,dev,sync,tail}.sh   queue/tickets-parked.md
  governor/*.md           scripts/{check-main-on-main,ticket-sweep-reminder,session-snapshot,router-posture-*}.sh
  .claude/settings.json   scripts/worktree/*  + worktree/lib/registry.sh
  .claude/commands/*.md   scripts/govern/*    + govern/lib/common.sh
  CLAUDE.md               learnings.md                    .githooks/{pre-push,prepare-commit-msg}
  README.md               (workspace landing page — "<name> on Shiploop"; never overwritten)

---

Phase 0 — Detect the mode

Print `── meta-repo setup ──`, then `pwd` and `ls -la`.

WRAP="$PLUGIN_ROOT/templates/lib/wrap.sh"
MODE="$(bash "$WRAP" --detect --workspace-dir "$(pwd)")"
echo "mode: $MODE"

| `$MODE` | Context | Do | |---|---|---| | `upgrade` | `scripts/lib/workspace.sh` present | **BUMP MODE** → Phase B | | `fresh` | not inside any git repo | **FRESH MODE** → Phase 1 | | `wrap` | AT the root of a git repo, `.git` is a directory | **WRAP OFFER** → Phase W | | `refuse:gitfile` | `.git` is a FILE (linked worktree/submodule) | STOP — wrapping corrupts the main repo's back-pointers; out of scope for v1 | | `refuse:below-root` | inside a git repo, below its root | STOP — "cd to the repo root and re-run" (print root path) | | `refuse:bare` | bare repository | STOP — nothing to wrap |

`fresh` with **zero** sub-repos detected in Phase 1 does not stop — it routes to **Phase G** (greenfield), which materializes the first sub-repo itself.

Back-compat: an older meta-repo predating `scripts/lib/workspace.sh` but with a `package.json` whose `"doctor"` script is `"bash scripts/doctor.sh"` is still **upgrade** even though `--detect` returns `fresh` — treat as BUMP MODE (scaffold.sh re-parameterizes the core scripts). Very old installs also carry the retired `"status"`/`"branch"`/`"switch"`/`"pull"`/`"push"`/`"health"` aliases; scaffold's purge removes the scripts they point at, so drop those lines from `package.json` in the same pass.

Phase W — Wrap-in-place (`$MODE == wrap`)

Gather everything first (W0), then run the single interview (W1). Do NOT ask anything before W1.

W0 — Detect + preflight (ONE combined bash call)

Chain detection and preflight in a SINGLE call — don't hand-run per-value probes or split turns:

DET="$(bash "$PLUGIN_ROOT/templates/lib/detect-inputs.sh" --workspace-dir "$(pwd)" --mode wrap)"
printf '%s\n' "$DET"     # root_pm= / worktree_base= / org= / repo=<NAME>|<port>|<cmd>|<visibility> / repos_spec=
NAME="$(printf '%s\n' "$DET" | sed -n 's/^repo=\([^|]*\).*/\1/p' | head -1)"
bash "$WRAP" --preflight --workspace-dir "$(pwd)" --name "$NAME"   # read-only; surfaces every REFUSE / NEEDS-CONFIRM

`repo=` carries the wrap subfolder name (`NAME`, from `origin` else folder name — where the repo lands: `<path>/<NAME>/`), its port + dev command, and visibility (`PUBLIC` unlocks auto-externalization; `unknown` = no `gh`, treat as private). Only override a detected value you can SEE is wrong.

Preflight is fail-closed; a single **prunable** worktree no longer refuses (auto-pruned), only LIVE linked work

Read more
@anshss
Ships withshiploop

You like claude code? You like shipping products? You love shiploop! ❤️

91 skill3 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
9
Star history of anshss/shiploop on GitHub, a chart by star-history.com

Other commands on shiploop.

compress

compress

Command

Compress this workspace's CLAUDE.md by moving mechanically-triggered rules into just-in-time rule packs. Operator-triggered,…

@anshss@anshssInstall Command
flows

flows

Command

Flow registry: extract inventories flows, list shows status, file queues validation tickets.

@anshss@anshssInstall Command
push

push

Command

Push direction: ports local mechanism-script fixes back to the hub as a reviewed PR. Opposite of /update.

@anshss@anshssInstall Command
statusline

statusline

Command

Show the governor fleet in your Claude Code statusline. Explicit, opt-in, and chains — it never replaces an existing statusline.

@anshss@anshssInstall Command
update

update

Command

Pull direction: bumps this workspace's scripts to match the latest hub template. Opposite of /push.

@anshss@anshssInstall Command
validated

validated

Command

Record durable, git-tracked evidence that a ticket was actually validated (interactive-session twin of the governor's…

@anshss@anshssInstall Command

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command