End-to-end walkthrough plus recovery scenarios. The decision tree and CLI surface live in SKILL.md — this doc is the operational manual.
fleet init auth-mw rate-limiter cache-layer
Creates: a branch per name (off main), a worktree at .fleet-worktrees/<name>/ (top-level so headless lane sessions can write — see "Headless agent compatibility" in SKILL.md), a status file at .claude/fleet/lanes/<name> (state: RUNNING), and deploys signal.sh to .claude/fleet/signal.sh.
fleet init also appends .claude/fleet/ and .fleet-worktrees/ to .gitignore and auto-commits that change (chore: gitignore fleet-ops runtime state) when the tree is otherwise clean and you're on main. If it can't auto-commit safely, you'll see an ACTION REQUIRED notice — commit .gitignore yourself before fleet start or the daemon will refuse to land with uncommitted tracked changes.
Force branch-only mode: mode=branch in .claude/fleet/config. Use this when each session is in a separate clone or remote machine — no worktrees needed.
For each lane, open a Claude session pointing at that worktree (or that clone). Use references/session-prompt.md as the template — fill in LANE, SCOPE, TASK, TESTS.
Each session works in isolation, commits atomically, runs tests, and signals when ready:
bash .claude/fleet/signal.sh READY tests/test_auth.log
signal.sh will refuse if the lane has uncommitted changes or if the test log shows failures.
fleet start
Polls .claude/fleet/lanes/ every 5 seconds. When a lane shows READY:
main is dirty--no-fftest_cmd if set; otherwise trusts signal.sh's log gateLANDED, deletes branch, rebases all other active lanesmain, marks lane FAILEDfleet status
── Fleet ──────────────────────────────────────────────────────
BRANCH STATUS AGE
────────────────────────────────────────────────────────────────
⏳ auth-mw RUNNING 23m
✅ rate-limiter READY 1m
🚀 cache-layer LANDED 8m
⚠️ error-handling CONFLICT 12m
────────────────────────────────────────────────────────────────
When all lanes are terminal (LANDED or FAILED), the daemon exits. To tear down:
fleet stop # if daemon still running
git worktree remove .fleet-worktrees/<name> # for each worktree lane
rm -rf .claude/fleet # nuke fleet state
fleet init is idempotent — keep .claude/fleet/ for the next round if you want.
If a previous daemon was killed without cleanup, fleet start auto-detects the stale daemon.pid and clears it.
CONFLICT lane (rebase or merge failed)Pop into that session's terminal. Tell Claude:
"Rebase conflict on
<file>. Lane that landed modified<symbol>. Resolve and re-signal READY."
Or resolve manually:
git checkout <lane-branch>
# fix conflicts
git rebase --continue
bash .claude/fleet/signal.sh READY <test-log>
FAILED lane (tests broke main post-merge)Daemon already reverted the merge. Branch still exists:
git checkout <lane-branch>
# fix the test
bash .claude/fleet/signal.sh READY <test-log>
Daemon picks it up on next poll.
fleet revert <branch>
Finds the merge commit on main (by message merge: <branch>), runs git revert -m 1, logs the action. No git surgery while you're panicking.
Default mode. Each lane is independent. Cleanest case — daemon handles everything.
Land the foundational lane first via fleet land <branch>, others rebase against it automatically. Daemon will pick them up after.
Land the quick fixes first. The long-running lane rebases against each landing. By the time it's done, main has all the small wins.
Currently the daemon lands them strictly one at a time. If batch mode becomes a real need, the next iteration adds --batch.