# How SwarmForge Manages Git Worktrees Under the `.worktrees/` Directory

> Learn how SwarmForge manages Git worktrees in .worktrees/ using swarmforge.bb for automated creation, registration, and synchronization. Keep worktrees out of version control.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: internals
- Published: 2026-08-10

---

**SwarmForge treats each role in a swarm as a separate Git worktree stored in `.worktrees/`, using the `swarmforge.bb` script to automate creation, registration, and synchronization while keeping worktrees ignored from version control.**

SwarmForge is a multi-agent orchestration framework by Uncle Bob that isolates different AI roles into dedicated Git worktrees. Understanding how SwarmForge manages git worktrees under the `.worktrees/` directory reveals the foundation of its role-based isolation architecture.

## Worktree Lifecycle Management

The entire worktree lifecycle is orchestrated through `swarmforge/scripts/swarmforge.bb`. This single script handles discovery, creation, Git registration, and runtime setup for every role-specific worktree.

### Defining the Worktrees Root

SwarmForge establishes a central location for all worktree metadata. In `swarmforge.bb` at line 469, the script stores the path to the hidden worktrees directory in the runtime context:

```clojure
:worktrees-dir (fs/path project-root ".worktrees")

```

This becomes the anchor point for all subsequent worktree operations.

### Building Worktree Paths

The helper function `worktree-path-for-name` (lines 71-73) constructs absolute paths for any given worktree name:

```clojure
(defn worktree-path-for-name [ctx name]
  (fs/path (:worktrees-dir ctx) name))

```

This ensures consistent path resolution across all worktree operations.

## Configuration-Driven Worktree Discovery

SwarmForge parses [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) to determine which roles receive dedicated worktrees. During configuration parsing (lines 175-183), each role entry yields a worktree name.

Roles configured with worktree names **other than** `master` or `none` trigger worktree creation:

```text
window coder  codex  coder
window architect  claude  architect
window coordinator  codex  master

```

In this example:
- `coder` → worktree created at `.worktrees/coder`
- `architect` → worktree created at `.worktrees/architect`
- `coordinator` → no worktree; runs in main project directory

## Creating and Registering Git Worktrees

The `prepare-worktrees!` function (lines 251-260) executes the actual Git commands to register each worktree:

```bash
git -C /path/to/project worktree add --force -B swarmforge-coder \
    /path/to/project/.worktrees/coder HEAD

```

This command:
1. Creates the directory `.worktrees/<name>`
2. Establishes a dedicated branch `swarmforge-<name>` tracking current `HEAD`
3. Uses `--force` to allow re-creation if the worktree already exists

## Preventing Accidental Commits

SwarmForge actively prevents `.worktrees/` from entering version control. The `ensure-worktrees-ignored!` function (lines 107-114) writes the entry to both `.gitignore` and Git's internal exclude file:

```bash

# Added to .gitignore and .git/info/exclude

.worktrees/

```

This dual protection ensures worktree metadata never appears in diffs or commits.

## Synchronizing Shared Resources

After creation, `sync-worktree-scripts!` (lines 70-85) copies the shared `swarmforge/scripts/` directory into each worktree. This allows every agent to execute helper scripts locally without cross-worktree dependencies.

## Per-Worktree Runtime Isolation

The `prepare-handoff-dirs!` function (lines 61-64) creates isolated runtime directories inside each worktree:

```clojure
(fs/create-dirs (fs/path worktree-path ".swarmforge" "handoffs" "outbox"))
(fs/create-dirs (fs/path worktree-path ".swarmforge" "handoffs" "inbox"))

```

This keeps handoff state completely separated between roles while maintaining a consistent structure.

## Complete Context Example

After parsing configuration and preparing worktrees, the runtime context contains structured worktree metadata:

```clojure
{:worktrees-dir (fs/path "/project" ".worktrees")
 :roles [{:role "coder"
          :worktree-name "coder"
          :worktree-path (fs/path "/project/.worktrees/coder")}
         {:role "coordinator"
          :worktree-name "master"
          :worktree-path (fs/path "/project")}]}

```

## Summary

- **SwarmForge uses `.worktrees/` as a hidden directory** containing one subdirectory per non-master role
- **The `swarmforge.bb` script automates the entire lifecycle** from path resolution through Git registration
- **Worktrees are created with `git worktree add --force`** on dedicated `swarmforge-<name>` branches
- **Version control exclusion is enforced** in both `.gitignore` and Git's internal exclude file
- **Shared scripts and runtime directories are synchronized** into each worktree after creation

## Frequently Asked Questions

### What happens if a role uses "master" as its worktree name?

The role runs directly in the main project directory without creating a separate worktree. The `prepare-worktrees!` function explicitly skips entries where `worktree-name` equals `"master"` or `"none"`, treating the project root as the execution context.

### Can multiple roles share the same worktree?

No. Each role with a unique worktree name receives its own isolated directory under `.worktrees/`. The `worktree-path-for-name` function generates distinct paths for every name, and Git worktrees enforce that no two worktrees can point to the same path.

### Why does SwarmForge use --force when adding worktrees?

The `--force` flag allows the script to be idempotent. If a worktree already exists from a previous run, the command recreates it cleanly rather than failing. This supports iterative development and recovery from interrupted sessions.

### What files exist inside a prepared worktree?

Each worktree contains a full Git checkout at the `HEAD` commit, a copy of `swarmforge/scripts/` for local execution, and a `.swarmforge/handoffs/` subdirectory with `inbox/`, `outbox/`, `public/`, and `archive/` folders for agent communication.