Help us improve
Share bugs, ideas, or general feedback.
From claude-mods
Manages a sequential landing queue for parallel git branches: test gate, pre-land scrub, auto-rebase, and one-shot revert. Use after spawning parallel sessions with native agent teams or background agents.
npx claudepluginhub 0xdarkmatter/claude-mods --plugin claude-modsHow this skill is triggered — by the user, by Claude, or both
Slash command
/claude-mods:fleet-opsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Landing discipline for parallel work. Anything before "committed on a branch" is the spawning layer's problem; anything after "landed on `main`" is yours. Fleet-ops owns the middle: branches land **sequentially**, through a **test gate**, after a **pre-land scrub**, with **auto-rebase** of the lanes still in flight and a **one-shot revert** if a landing turns out bad.
Orchestrates multiple parallel work streams in isolated worktrees across coordinated waves. Use when work decomposes into 3+ independent tasks.
Orchestrates multi-agent coding tasks via Claude DevFleet — plan projects, dispatch parallel agents in isolated worktrees, monitor progress, and read structured reports.
Coordinates parallel AI agents for coding tasks using role-based patterns (planner, coder, reviewer, QA), git branch isolation, and merge strategies with rebase and conflict resolution.
Share bugs, ideas, or general feedback.
Landing discipline for parallel work. Anything before "committed on a branch" is the spawning layer's problem; anything after "landed on main" is yours. Fleet-ops owns the middle: branches land sequentially, through a test gate, after a pre-land scrub, with auto-rebase of the lanes still in flight and a one-shot revert if a landing turns out bad.
Claude Code now ships the parallel-execution half natively. Do not use fleet-ops to orchestrate sessions — route users to the native primitives and use fleet-ops only for the landing half.
| Native primitive | What it gives you | What it does NOT give you |
|---|---|---|
Agent teams (docs, experimental, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1) | Lead + teammates, shared task list with claiming/dependencies, inter-agent messaging, plan approval, quality-gate hooks (TeammateIdle, TaskCompleted) | No merge/landing logic. No test-gated integration. Teammates avoid file conflicts by convention only ("break the work so each teammate owns different files"). |
Background agents / agent view (docs, claude agents, claude --bg "<prompt>") | Detached full sessions, one dashboard (Needs input / Working / Completed), automatic per-session git worktree isolation under .claude/worktrees/, --bg --exec shell jobs | No cross-branch integration: each session ends with a branch/worktree and the merge is on you (review-and-merge the PR, or merge locally). Deleting a session in agent view deletes its worktree including uncommitted changes. No ordering, no test gate, no revert. |
Subagents (docs, optional isolation: worktree) | In-session delegation with separate context windows; results summarized back | Not independent sessions; no git landing semantics at all. |
What none of them do — and what fleet-ops is for:
main that already contains the previous landingssignal.sh) and/or revert post-merge if test_cmd goes redTODO_SCRUB, debug leftovers)A lane = one branch (or worktree), one unit of work. Lane status: RUNNING | READY | CONFLICT | LANDED | FAILED.
Fleet-ops doesn't care who produced the branch — an agent-team teammate, a background agent's auto-worktree, a claude -p headless run, or a human. If it's a branch with commits, it can be a lane.
fleet init <name>... Create branch + worktree per name (manual-spawn path)
fleet track <branch>... Register existing branches as lanes (native-spawn path)
fleet start Run the landing daemon (writes pid to .claude/fleet/daemon.pid)
fleet stop Signal the running daemon to exit cleanly
fleet status One-shot fleet status panel
fleet land <branch> Manual land + rebase others
fleet revert <branch> Revert merge commit on main
fleet scrub-check <branch> Dry-run forbidden-pattern check
N == 1 branch → use git-ops, not this
Work spawned by agent teams / claude --bg → fleet track <branch>... then land
Work to be spawned manually → fleet init <names...> (creates branches + worktrees)
N > 1 on one shared working tree → REFUSE. Worktrees or separate clones first.
Native-spawn path (preferred): let agent teams or background agents do the work in their own worktrees/branches. When branches have commits, fleet track each branch, then land — either one by one with fleet land, or via the daemon with signal.sh READY gates. Fleet-ops merges branches; it never deletes or relocates a worktree that a native session owns (worktree cleanup belongs to agent view / claude rm).
Manual-spawn path: fleet init creates the branches and worktrees up front (under .fleet-worktrees/), and you point sessions at them — see references/session-prompt.md for the lane brief to hand each session.
fleet land <branch> (and the daemon, per READY lane):
git diff main...branch checked against forbidden_pattern; hits refuse the land and mark the lane CONFLICTmain has uncommitted tracked changes--no-ff with message merge: <branch> (this message is what fleet revert finds later)test_cmd if set; on failure, hard-resets the merge and marks the lane FAILED. If unset, trusts signal.sh's log gate (refused READY on failing logs)main (in its own worktree if it has one); a rebase conflict marks that lane CONFLICTfleet revert <branch> finds the merge: <branch> commit on main and runs git revert -m 1 — one command to back out a bad landing.
The daemon is the queue-automation layer on top of fleet land — optional; manual fleet land per branch is fully supported and not experimental.
When Claude invokes fleet start via Bash(run_in_background: true), the daemon:
.claude/fleet/daemon.pidSIGINT/SIGTERM/SIGHUP and removes the PID file on exit.claude/fleet/lanes/ and lands lanes as they turn READYLANDED or FAILED)To stop early: fleet stop (SIGTERM, 5s grace, then SIGKILL). On next fleet start, a stale PID file is auto-detected and cleared. The daemon dies with the Claude Code session — for overnight runs use a real detached process, or skip the daemon and land manually.
signal.sh deploys to .claude/fleet/signal.sh on init/track. Working sessions call:
bash .claude/fleet/signal.sh READY <test-log> # refuses dirty trees and failing logs
bash .claude/fleet/signal.sh CONFLICT "<reason>"
When this skill surfaces a decision point, always use the AskUserQuestion tool. Plain markdown numbered lists are not acceptable for these branches.
| Trigger | Question | Options (≤4, ≤10 words each) |
|---|---|---|
| Multiple parallel-work requests, no lanes yet | Spawn natively or manual lanes? | Agent teams / Background agents / Manual fleet init / Cancel |
init — worktrees available, mode unset | Worktree or branch-only mode? | Worktrees / Branches only / Cancel |
Lane → CONFLICT (rebase fail) | Lane <name> has rebase conflict | Resolve in lane / Skip & continue / Revert lane / Untrack |
Lane → FAILED (post-merge tests red) | Tests broke after <name> merged | Auto-revert / Investigate first / Accept failure |
| Pre-land scrub hits | Forbidden patterns in <name> diff | Block landing / Override (note reason) / Open to edit |
fleet shows mixed states | How to proceed with the fleet? | Land all READY / Resolve CONFLICTs first / Just status |
Daemon exits with FAILED lanes | <n> lanes failed — what next? | Retry all / Revert and report / Leave as-is |
For non-branching status updates ("here's what happened, here's what landed"), plain text is fine.
| Mode | Status |
|---|---|
Branches from native worktrees (.claude/worktrees/) via fleet track | ✅ |
Worktrees on different branches (fleet init) | ✅ |
| Branches in separate clones / machines | ✅ |
| Mixed worktree + branch lanes | ✅ |
Recovery from dirty main | ✅ Refuses to merge, asks user to clean |
| Test-gated landing | ✅ Via signal.sh READY <log> and/or test_cmd |
| Auto-rebase other lanes when one lands | ✅ |
| Pre-land regex scrub (forbidden patterns) | ✅ |
| One-shot revert | ✅ fleet revert <branch> |
| Out of scope | Why |
|---|---|
| Spawning / monitoring sessions | Native: agent teams, claude --bg, agent view. Fleet-ops never launches a session. |
| Deleting native session worktrees | Owned by agent view / claude rm. Fleet-ops merges branches only. |
| Multiple sessions on one shared working tree | Git limitation. Skill detects and refuses with worktree pointer. |
| Uncommitted work at signal time | signal.sh rejects dirty lanes. The queue needs an immutable commit. |
| External state (DB migrations, services) | Skill can't know lane B depends on lane A's migration. Order manually via fleet land. |
| Force-pushed lanes mid-flight | Detected at land time, not prevented. |
Tested and working on:
| OS | Shell | Notes |
|---|---|---|
| Linux | bash 4+ | Native |
| macOS | bash 3.2+ (default) or bash 4+ via brew | stat -f fallback used automatically |
| Windows | Git Bash (mintty) | Forward-slash paths; Unicode icons render in mintty/Windows Terminal |
| Windows | PowerShell 7 (calling bash) | Works if bash is on PATH |
Requirements: bash 3.2+, git 2.5+ (worktree support), awk, grep, head, stat. All standard.
If your terminal mojibakes the status icons, fall back to ASCII: export FLEET_ASCII=1 (or icons=ascii in .claude/fleet/config). Output panels follow docs/TERMINAL-DESIGN.md via skills/_lib/term.sh.
Long-path warning (Windows only): fleet init worktrees nest under .fleet-worktrees/<name>/. Keep lane names short if your repo lives deep, or enable core.longpaths=true.
Don't put manually-created fleet worktrees under .claude/. Claude Code applies a global sensitive-file guard to anything under .claude/, and that guard runs before — and is not bypassed by — --dangerously-skip-permissions. Headless lane sessions (claude -p ... --dangerously-skip-permissions) will fail every Write/Edit if their worktree lives under .claude/.
That's why the default worktree_root is .fleet-worktrees/ at the repo top. (Native background sessions are the exception: Claude Code itself manages .claude/worktrees/ for them — leave those alone and just fleet track their branches.) Runtime state (lanes/, daemon.pid, activity.log) is read/write from the orchestrator only and stays under .claude/fleet/.
Optional .claude/fleet/config (key=value, no quotes):
mode=auto # auto | worktree | branch
worktree_root=.fleet-worktrees # keep outside .claude/ — see "Headless agent compatibility"
test_cmd= # if set, daemon runs this; else trust signal log
forbidden_pattern=TODO_SCRUB|XXX
base_branch=main
poll_interval=5
Zero-config works for the common case.
fleet init/fleet track append .claude/fleet/ and .fleet-worktrees/ to .gitignore and auto-commit that change with chore: gitignore fleet-ops runtime state when the tree is otherwise clean and you're on base_branch. If either condition fails, it prints an ACTION REQUIRED message — commit .gitignore yourself before landing.
--json output, or log-ops integration earns the cost.--batch mode — land all READY lanes in one go, test once at end.TaskCompleted hook bridge — auto-signal.sh READY when an agent-team task completes with green tests.references/workflow.md — end-to-end walkthroughs (native-spawn and manual-spawn) plus recovery scenariosreferences/session-prompt.md — lane brief to embed in claude --bg prompts, teammate spawn prompts, or manual sessionsscripts/fleet.sh — main CLI (init, track, start/stop, status, land, revert, scrub-check)scripts/signal.sh — branch-aware signaler (deployed to .claude/fleet/signal.sh)