---
name: crew
version: 0.3.6
description: Coordinate work as a lead delegating features to managed worktree children — spawn a child per feature on its own branch, run it as a loop until done, and pull finished work back to the base branch with merge-and-close. Use when one session should run a project and farm out features instead of piling many sessions on one working tree.
---

# Crew — a lead session that delegates features to managed worktree children

This skill turns one session into a **lead** that delegates each feature to an isolated
**worktree child** and pulls the finished work back to the base branch automatically — so
you talk to **one** session per project instead of shepherding a dozen that all fight over
the same working tree.

A **crew** is emergent, not a heavy object: it is just plain sessions linked by
`parentSessionId` + a `crew.role`. A **feature child** always (a) has the lead as its
parent and (b) lives in its own `.dev/worktree/<n>` on its own branch.

> **⚠ Whether the child is GATED depends on how you started it (#1604).**
>
> | You ran | Gate |
> |---|---|
> | `crew start "<brief>"` (no `--oracle`) | **none** — the child works, then runs `feature done` when *it* decides it is complete. Nothing judges it. |
> | `crew start "<brief>" --oracle "<cmd>"` | a loop with `parent: <lead>` — the oracle gates each stop and **the lead is the judge** of done. |
>
> The CLI tells you which you got: it prints `gate: none — child runs 'feature done' when complete`
> on the ungated path. This is deliberate, not an oversight — `featureStart` attaches the loop only
> when there is an oracle, because a no-oracle child would otherwise fire `approved` on its very
> first stop, which is worse than no gate at all.
>
> **What this means for you as a lead:** if the feature has any objective success condition, pass
> `--oracle`. Without one you are the only thing standing between a child and a premature
> `feature done`, so read the merge request rather than trusting the verdict.
>
> This block used to claim every feature child runs as a loop with the lead as judge. It did not,
> and an agent that believed it would skip `--oracle`, skip checking on the child, and read "no
> verdict yet" as "still working" rather than "nothing will ever judge this".

## The verbs (these are your tools)

```
svamp feature start "<brief>" [--oracle "<test cmd>"] [--base <branch>] [--action nudge|block]
                             [--issue <id>] [--max N] [--model <id>]
        # (lead) create a worktree child on a new branch, run it as a loop until done
        # (oracle → parent verdict), and brief it. Prints the child id.
        # --action nudge|block: how the lead learns the child reported or finished.
        #   nudge (default) = normal urgency: queued, NOT a wake. The inbox drains one
        #     entry per idle turn, so the lead may not see it for hours if its queue is
        #     deep (#0349) — this is not "the lead's next turn";
        #   block = urgent, which WAKES the lead. Use block for a child whose result
        #   gates your next step; nudge for one you will collect when convenient.
        # --issue <id> links the child to an EXISTING backlog issue: its verdict routes
        #   ONTO that issue instead of onto a new one. This is the seam that joins crew
        #   to the backlog the loop oracle (`svamp issue pending`) reads.
        #   Pass it whenever the feature came from an issue, so the verdict lands on the
        #   item you are already tracking rather than creating a second one to reconcile.
        #   NOT passing it does NOT make the child invisible: `crew start` auto-creates a
        #   tracking issue at status `in_progress`, and `isPendingIssue` counts anything
        #   that is neither `archived` nor `paused` — so an unlinked child still holds the
        #   loop oracle RED until its issue is resolved. Do not treat an unlinked child as
        #   fire-and-forget; a lead waiting for `svamp issue pending` to empty will wait
        #   for it.
        # --max N bounds the child's loop iterations (a hard stop, unlike the soft
        #   progress-based cap); --model <id> picks the child's model.
svamp feature start "<brief>" --no-worktree --dir <folder>
        # (lead) STANDALONE child: run a child directly IN <folder> (a subdir or sibling
        # project) with NO worktree/branch. Still attached (parentSessionId), shows in
        # `feature list`. `done`/`merge` just detach & close it — nothing to merge back.
svamp feature list [--json]
        # (lead) your children: branch, ahead/behind base, dirty, idle/active.
svamp feature report "<text>" [--blocker]
        # (child) push a progress note or blocker to your lead.
svamp feature done [--summary "<text>"]
        # (child) signal completion: sends a merge-request to your lead.
svamp feature merge <child-id> [--keep-child]
        # (lead) verify → merge branch into base → remove worktree → archive the child.
```

## If you are a LEAD

You coordinate the project. Keep your own working tree (the base branch, e.g. `main`) clean —
**delegate features, don't do them in your own tree.**

- **Delegate:** for each distinct feature, run `svamp feature start "<brief>"`. Give a crisp,
  self-contained brief and, when there's a test/build that proves the feature, pass
  `--oracle "<cmd>"` so it's auto-checked.
- **Stay aware:** run `svamp feature list` when you start working and whenever you manage the
  crew. Your children also **push** to you: progress notes, blockers, merge-requests, and
  loop verdicts all arrive in your inbox as `<feature-progress>`, `<feature-blocker>`,
  `<merge-request>`, and `<supervision-verdict>` messages (the verdict's wire tag name is
  unchanged for back-compat).
- **Review & merge — this is the gradient that closes the loop.** When a child sends a
  `<merge-request>` or you receive a `<supervision-verdict … verdict="approved">` from a
  child, **run `svamp feature merge <child-id>`**. With an oracle that passed, this is the
  default path — merge promptly. The merge verifies the child's worktree is clean, merges its
  branch into the base, removes the worktree, and archives the child. On a conflict or a dirty
  worktree the merge is **deferred to rework** (the child is re-woken with guidance and left
  alive — un-merged work is never destroyed); help it resolve, then merge again.
- **A merge can also HARD-fail.** When the failure is not something the child can fix by editing
  (e.g. the base tree is on the wrong branch or is dirty), `feature merge` exits 1 and sends the
  child `<crew-blocked>` instead of `<crew-rework>`. The child is told to STOP and hold; it will
  not retry. Resolving it is **yours or the operator's** — fix the blocker in the base tree, then
  re-run `svamp feature merge <child-id>`. A blocked child left unattended is idle, not working,
  so do not wait for it to report again.
- **Nudge stalled children.** If `feature list` shows a child idle with committed, ahead-of-base
  work that hasn't been reported done, send `svamp session inbox send <child> "status?"` (or
  `feature report`-style ping) to move it along.

## If you are a FEATURE CHILD

You own one feature in an isolated worktree on your own branch, reporting to your lead.

**Your brief arrives ONCE, as the first message of this session — it is not repeated (#1607).**
Nothing re-injects it, so keeping it in view is your job: re-read it before you decide you are done,
and restate it in your own words in `feature report` notes so drift is visible to your lead. (If your
lead started you *with* `--oracle`, the native `/goal` gate does restate the "until" criteria at each
turn-end — but on the default no-oracle path there is no loop at all. See the gate table above.)
This line previously promised per-turn injection of both; no such mechanism was ever built, and
`docs/crew-design.md` §7 already recorded those hooks as never shipped.

- **Work in your worktree.** Implement the feature. Commit as you go. Keep the oracle/tests green.
- **Report.** Use `svamp feature report "<note>"` for milestones and `--blocker` when stuck —
  your lead is watching.
- **Finish cleanly.** When the feature is complete and committed (worktree clean, tests green),
  run `svamp feature done --summary "<what changed>"`. This sends a merge-request to your lead.
- **Do not merge your own branch or remove your own worktree** — the lead does the merge-back so
  the base tree isn't corrupted. After the lead merges, your worktree is removed and you are
  archived. Three control messages can arrive from your lead — they look similar and mean
  different things, so read the tag:
  - `<crew-freeze>` — stop editing immediately.
  - `<crew-rework>` — the merge was **deferred**; address the guidance and run
    `svamp feature done` again.
  - `<crew-blocked>` — the merge **hard-failed**. "Stop editing and hold — do not keep working.
    Once the blocker is resolved, the lead can retry `svamp feature merge`." Do **not** run
    `svamp feature done` again: nothing you can do from here changes the outcome, and re-sending
    a merge-request into a hard-failed state just burns loop turns toward the cost ceiling. Hold
    until the lead retries the merge. Your un-merged work is preserved.

## Standalone (no-worktree) children — managing a fleet of folders

By default a child gets its own git worktree + branch. For a session sitting in a **big
parent folder** (e.g. a monorepo or `../`) you often want children that work **in existing
subfolders or sibling projects** instead — no isolated branch, just an attached session you
manage from one place. Use `--no-worktree --dir <folder>`:

```
svamp feature start "tidy the docs site" --no-worktree --dir ./packages/site
```

The child runs directly in `<folder>`, is still linked by `parentSessionId`, and appears in
`svamp feature list` with a `standalone` state showing its folder (no branch / ahead-behind).
Because there is **no branch to merge**, finishing is just a detach: the child runs
`svamp feature done` (raising a `<done-request>` instead of a `<merge-request>`), and the lead
runs `svamp feature merge <child-id>` which simply archives (detaches) the child. If the folder
is itself a git repo, the child commits there directly. Worktree mode remains the default and is
unchanged.

## Why this design

- **One conversation, many features.** The lead is your single point of control; children run in
  parallel isolation and report up.
- **Merge-and-close is the default, not a chore.** The loop gate routes a verdict to the lead,
  the lead merges, the child closes — the "gradient" that keeps finished work from rotting on a
  stale branch.
- **Isolation by worktree — and ONLY by worktree (#2123).** Each feature has its own branch + tree,
  so children never collide on one working directory (the mess this skill exists to fix). That is
  the whole of the isolation: "isolated" here means *a separate checkout*, not a sandbox.
  Concretely, a crew child is:
  - **`permissionMode: 'bypassPermissions'`, hardcoded, with no flag to change it.** `crew start`
    sets it unconditionally at the `machine.spawnSession(...)` call in `crew/commands.ts`; the
    documented flags are `--oracle --base --max --model --dir --no-worktree --issue --action` and
    none of them touches permission mode. So the child auto-approves every tool call.
  - **NOT sandboxed.** `crew start` passes no `securityContext` and does not set `--isolate`, so the
    child runs on the owner's real HOME and environment.
  This matters because it is the fifth thing in svamp that erases an explicit `--require-approval`
  (CLAUDE.md enumerates the other four): a lead you deliberately hardened can fan out children that
  do not inherit that hardening. If you need an approval gate or a sandbox on delegated work, spawn
  the child yourself with `svamp session spawn --require-approval` / `--security-context` rather
  than through `crew start`.
- **Safety:** merges only proceed from a clean child worktree and a clean base tree; conflicts and
  dirty trees defer to rework. Crew never destroys un-merged work.

See `docs/crew-design.md` and the frozen `docs/supervisor-gate-design.md` for the full model.
