Skip to content
DocsWhen to recruit

When to recruit

Sorting work into do, quiet, and crew: no model, a model without a pane, or a model with one.

A pane plus a model is the most expensive thing a captain can spend, and the easiest to spend on work that needs neither. Every task sorts into three buckets: no model at all, a model without a pane, or a model and a pane.

The decision rule#

text
No model needed?                              -> captain do
A model, and you can write the whole
  instruction now, and one answer ends it?    -> captain quiet
A model, and you will learn the next
  instruction from what it does?              -> captain crew

The discriminator between the last two is steering. Not risk, not size, and not whether the work writes files. If the captain already knows everything it would say to an agent, a pane buys nothing: there is no next instruction to type into it. If the captain will only know what to ask after seeing the agent's first move, nothing but a pane will do.

What each path costs
PathCostExamples
captain do / captain inspectOne subprocess, zero tokensA commit, a push, a declared Makefile target, finding which files changed
captain quietOne headless turn, a three-line promptA question about the code, a short review, a drafted commit message, one bounded edit
captain crewPane, instruction block, assignment, wait, reportDesign, debugging, anything you will steer as it goes

Deterministic work: captain do#

captain do performs work with no crew and no model at all. It is the answer whenever the outcome is already determined by its inputs, so a commit or a declared build target never costs a pane.

shell
captain do commit --message "Fix the off-by-one" src/parser.py
captain do push
captain do branch docs-site
captain do switch main
captain do fetch
captain do pull
captain do run test
captain do subcommands
CommandArgumentsDoes
do commit--message MESSAGE (required), [path ...]Stages the named paths and commits them. Omit the paths to commit what is already staged.
do pushnonePushes the current branch, setting upstream on the first push.
do branchnameCreates and switches to a new branch.
do switchnameSwitches to a branch that already exists.
do fetchnoneFetches from the remote, touching no file in the worktree.
do pullnoneFast-forwards the current branch. It never merges, rebases, or conflicts.
do runtargetRuns one target the project declares in its Makefile.

do run accepts only a declared target from a fixed vocabulary: build, check, clean, fmt, format, gate, help, install, lint, test, typecheck, vet. It is not a shell: a target the project does not declare is refused rather than guessed at.

Reads without a model: captain inspect#

captain inspect answers read-only questions with no model and no Herdr lookup. Paths are literal and project-bounded. Reads go here; writes and anything needing the real environment go to do.

shell
captain inspect files src
captain inspect read README.md
captain inspect search "literal text" src
captain inspect state repo graph.json
captain inspect git diff --staged
captain inspect git branches
captain inspect git grep --text "literal text"
captain inspect subcommands
CommandArgumentsDoes
inspect files[path]Enumerates files under a path.
inspect readpathReads one regular UTF-8 text file.
inspect searchtext [path]Searches for literal, case-sensitive text. Not a regex.
inspect statesession|project|repo [path]Reads a literal path within one stored scope. Crew are limited to repo.
inspect gitstatus|log|current-branch|root|diff|branches|ls-files|grep [--staged] [--text TEXT]Fixed Git queries. --staged diffs the index instead of the worktree, and grep takes its literal, case-sensitive pattern from --text.
  • Results are JSON, bounded to 64 KiB, 200 results, 10,000 entries, 8 MiB searched, and five seconds. Hitting a limit produces a truncation marker or an explicit error, never a quietly short answer.
  • No shell, no arbitrary flags, no external helpers. The Git operations above are the whole set.

What inspect refuses#

Git requires a trusted system installation and an ordinary stable local checkout. Linked worktrees, partial clones, alternates, and unsupported config are refused. Git must be root-owned at /usr/bin/git on Linux, or the Command Line Tools installation on macOS — the macOS /usr/bin/git launcher is not used.

Reads accept regular UTF-8 text files. Enumeration skips symlinks and .git, and a direct symlink read fails. Filesystem deadlines are cooperative. Native sandbox permissions still apply on top of all of this — see ownership and guardrails.

One model turn without a pane: captain quiet#

A pane buys two things: somewhere to approve a native permission prompt, and somewhere to steer a running turn. Work that needs neither should pay for neither. captain quiet spends one headless model turn with no pane, no assignment, and no wait: the result is printed and recorded, and that ends it. Quiet turns covers it in full.

shell
captain quiet --task "Does anything else call parse_header?"
captain quiet --task "Draft a commit message" --diff staged
captain quiet --task "Review this against AGENTS.md" --diff worktree
captain quiet --task "Fix the typo in the heading" --write src/content/docs/cli.tsx
captain quiet --task "Name a branch for a docs rewrite" --model cheap
captain quiet flags
FlagDoes
--task TEXTThe whole instruction. Required, and the only required flag.
--diff worktree|stagedAppends that diff to the task. A headless turn has no shell, so Git is the one thing it cannot read itself.
--write PATHA file the turn may edit, repeatable. Without it the turn is read-only.
--model MODELA tier or model name. Falls back to [crew] model, cheap by default.
--timeout SECONDSSeconds to allow. 900 by default.

The turn reads the checkout itself, so paste nothing you can name instead. A read-only turn is also handed this session's own directory, letting it triage the event log, mail, and assignment records. A turn given --write is not: an unwatched editing turn can never reach that state, and it leaves its edits unstaged.

Stopping a crew without losing it#

When a crew is working the wrong problem, interrupt stops its current turn while keeping its pane, conversation, and assignment. It is the middle ground between a tell that queues behind the current turn and a dismiss that throws the pane away.

shell
captain interrupt Jack
captain interrupt Jack --reason "wrong file, reassigning"

--reason is recorded in session memory, so why a turn was cut short survives into the next wait and the session's history.