End-to-end walkthroughs plus recovery scenarios. The native-primitives routing table and CLI surface live in SKILL.md — this doc is the operational manual.
There are two ways work enters the fleet: native spawn (preferred — agent teams or background agents do the parallel work) and manual spawn (fleet init creates lanes you point sessions at). Landing is identical for both.
Use whichever native primitive fits (agent teams for collaborating teammates, background agents for independent fire-and-forget sessions):
claude --bg "Add JWT middleware. Work on branch auth-mw. <lane brief>"
claude --bg "Add rate limiting. Work on branch rate-limiter. <lane brief>"
Background sessions automatically isolate into worktrees under .claude/worktrees/. Embed the lane brief from references/session-prompt.md so each session commits to a named branch, respects its scope, and signals when green.
Once branches exist with commits:
fleet track auth-mw rate-limiter
Registers each existing branch as a lane (RUNNING), deploys signal.sh, touches no worktrees. Never delete or relocate a native session's .claude/worktrees/ entry — worktree cleanup belongs to agent view / claude rm, after the branch has landed.
Either manually, in the order you choose:
fleet land auth-mw # scrub → clean-base check → merge --no-ff → test gate → rebase others
fleet land rate-limiter
Or via the daemon + signal.sh READY gates (see Path B steps 3–4) if sessions signal their own readiness.
fleet init)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
One panel: every lane grouped by state (RUNNING / READY / CONFLICT / FAILED / LANDED) with age and commits-ahead. fleet status --verbose adds worktree paths and notes.
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 fleet-created worktree lane
rm -rf .claude/fleet # nuke fleet state
Only remove worktrees that fleet init created. Native sessions' worktrees under .claude/worktrees/ are cleaned up through agent view (Ctrl+X) or claude rm — not by hand.
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 (for background agents: open it from claude agents and reply). 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 (or fleet land it manually).
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.
Lead reports teammates done. fleet track <b1> <b2> <b3>, then fleet land in dependency order. Each landing rebases the rest, so the second and third merges are tested against a main that already contains the first.
Path B default. 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 — that sequencing is the point. If batch mode becomes a real need, the next iteration adds --batch.