Worktrees

Swarm uses git worktrees to provide each agent with an isolated working directory and branch. This prevents file conflicts between agents working in parallel and enables clean merging of results back to the main branch.

Prerequisites

  • Git 2.20+ — Required for git worktree lock/unlock support. Checked automatically at startup.
  • Not detached HEAD — Swarm requires a branch checkout for merge-back to work.
  • Clean working tree — Either commit/stash changes first, or use --stash to auto-stash.

Path and Branch Conventions

ItemPatternExample
Swarm directory<repo>/.swarm//home/user/project/.swarm/
Worktree path<repo>/.swarm/worktrees/<name>.swarm/worktrees/backend
Agent branchswarm/<session_id>/<name>swarm/20250115-a3f2/backend
Supervisor branchswarm/<session_id>/supervisorswarm/20250115-a3f2/supervisor
Beads branchswarm/<session_id>/beadsswarm/20250115-a3f2/beads

The .swarm/ directory is automatically added to .git/info/exclude so it doesn't appear in git status.

Worktree Creation

During session start (Step 7), the orchestrator creates worktrees for each agent and the supervisor:

# For each agent:
git worktree add .swarm/worktrees/<name> -b swarm/<session_id>/<name> <base_commit>
git worktree lock .swarm/worktrees/<name>

# For the supervisor:
git worktree add .swarm/worktrees/supervisor -b swarm/<session_id>/supervisor <base_commit>
git worktree lock .swarm/worktrees/supervisor

# Shared beads branch:
git branch swarm/<session_id>/beads <base_commit>

Each worktree starts from the same base commit (HEAD at session start), ensuring all agents begin with identical codebases.

Worktree Locking

Worktrees are locked immediately after creation using git worktree lock. This prevents git worktree prune from accidentally removing them during the session. Worktrees are unlocked during cleanup.

Worktree Cleanup

When a session stops, worktrees are cleaned up in order:

  1. Auto-commit dirty — If the worktree has uncommitted changes, stage and commit them:

    git -C .swarm/worktrees/<name> add -A
    git -C .swarm/worktrees/<name> commit -m "swarm: auto-commit on stop"
    
  2. Unlockgit worktree unlock .swarm/worktrees/<name>

  3. Removegit worktree remove .swarm/worktrees/<name>

  4. Prunegit worktree prune to clean stale references

  5. Delete branches — Remove all swarm/<session_id>/* branches

Merge Operations

After cleanup, agent branches are merged based on the stop mode:

Merge (--merge, default)

Non-fast-forward merge in config order (agents first, then supervisor):

git merge --no-ff swarm/<session_id>/backend -m "Merge agent: backend"
git merge --no-ff swarm/<session_id>/frontend -m "Merge agent: frontend"
git merge --no-ff swarm/<session_id>/supervisor -m "Merge supervisor"

Squash (--squash)

Squash-merge each agent branch into a single commit:

git merge --squash swarm/<session_id>/backend
git commit -m "Squash agent: backend"

Discard (--discard)

Delete branches without merging — all agent work is discarded.

Recovery

Swarm handles crash recovery for stale sessions:

Stale Session Detection

A session is stale when its pid (from session.json) no longer corresponds to a running process. This is detected via libc::kill(pid, 0).

Recovery Flow

When a stale session is detected (during swarm start or swarm stop):

  1. Auto-commit any dirty worktrees
  2. Remove all session worktrees (unlock + remove)
  3. Prune stale worktree references
  4. Delete all swarm/<session_id>/* branches
  5. Remove session.json and lockfile

Clean Command

swarm clean provides manual cleanup:

swarm clean          # Interactive — asks for confirmation
swarm clean --force  # Removes artifacts without confirmation

This handles cases where automatic recovery isn't sufficient (e.g., corrupted worktree state).