# How Swarm Forge Creates and Manages Git Worktrees in the `.worktrees/` Directory

> Discover how Swarm Forge manages Git worktrees in .worktrees/. Learn about isolated worktrees for agent roles and special master role handling.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: how-to-guide
- Published: 2026-09-01

---

**Swarm Forge automatically creates isolated Git worktrees under a hidden `.worktrees/` directory for each agent role, with special handling for the `master` role that runs directly in the main repository checkout.**

Swarm Forge uses Git worktrees to give each AI agent its own isolated working directory while sharing repository history. This architecture, implemented in the `unclebob/swarm-forge` repository, manages worktree lifecycle through Clojure functions in `swarmforge/scripts/swarmforge.bb`, handling path resolution, Git ignore management, creation, and validation.

## Worktree Path Resolution

Swarm Forge builds worktree paths using the `worktree-path-for-name` helper function. This joins the configured `worktrees-dir` (`.worktrees` by default) with the role name.

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

```

This simple path construction is defined at `swarmforge/scripts/swarmforge.bb` lines 72–73. The function returns a `java.nio.file.Path` that feeds into both Git commands and tmux window configuration.

## Git Ignore Configuration

Before creating any worktrees, Swarm Forge ensures Git never tracks the `.worktrees/` directory. It updates two locations:

- **`.gitignore`** — appends `.worktrees/` for general repository hygiene
- **`.git/info/exclude`** — adds `.worktrees/` to the local exclude file

```clojure
(spit (str gitignore) ".swarmforge/\n.worktrees/\n")
(ensure-in-file! exclude-file ".worktrees/")

```

These writes happen at lines 111–120 of `swarmforge/scripts/swarmforge.bb`. The dual approach ensures the directory stays hidden regardless of `.gitignore` sharing practices.

## Creating Worktrees with `prepare-worktrees!`

The `prepare-worktrees!` function orchestrates worktree creation during system startup. It iterates over every role defined in the configuration and executes `git worktree add` for each non-special role.

```clojure
(defn prepare-worktrees! [ctx]
  ;; ctx contains :worktrees-dir pointing at ".worktrees"
  ...)

```

For a role named `coder`, the equivalent shell command is:

```bash
git worktree add .worktrees/coder origin/main

```

This creation logic spans lines 321–327. After successful creation, each worktree name is added to an in-memory `worktrees` set for duplicate detection.

## Validating Worktree Assignments

Each tmux window definition may specify a `worktree` name. Swarm Forge validates these declarations to prevent multiple windows from accidentally sharing the same worktree.

```clojure
(reject-if (and (not (special-worktree? worktree))
                (contains? worktrees worktree))
           ...)

```

The validation at lines 172–179 rejects duplicate non-special worktrees. A worktree is either:
- **Already registered** — known from `prepare-worktrees!`
- **Newly added** — first mention triggers registration

This ensures one-to-one mapping between windows and worktree directories.

## Special Handling for the `master` Worktree

The `master` worktree (and `none`) are **special cases**. Swarm Forge **never** creates a `.worktrees/master` directory. Instead, the agent works directly in the main project checkout on its current branch.

As documented in [`README.md`](https://github.com/unclebob/swarm-forge/blob/main/README.md) lines 191–199 and `swarmforge/constitution/articles/workflow.prompt` lines 5–6:

> "If your assigned worktree is `master`, work in the main project checkout on its current branch; do not expect or create a `.worktrees/<role>` directory for that role."

```clojure
(if (special-worktree? "master")
  (println "Use main repo checkout – no worktree needed")
  (create-worktree! ctx "master"))

```

This design lets the orchestrator or master agent operate on the primary branch without worktree overhead.

## Complete Worktree Lifecycle Example

```clojure
;; 1. Path resolution
(let [role "coder"
      wt-path (worktree-path-for-name ".worktrees" role)]
  ;; 2. Git worktree creation
  (shell/sh "git" "worktree" "add" wt-path "origin/main")
  
  ;; 3. Registration for duplicate detection
  (swap! worktrees conj role))

;; 4. Window parsing validates the worktree reference
(parse-window-line ctx 42 
                   "coder\tcoder\t${project}/.worktrees/coder\tcoder\tCoder\tcodex\ttask"
                   role-config 
                   @worktrees)

```

## Key Source Files

| File | Purpose |
|------|---------|
| `swarmforge/scripts/swarmforge.bb` | Core functions: `worktree-path-for-name`, `prepare-worktrees!`, validation logic |
| [`README.md`](https://github.com/unclebob/swarm-forge/blob/main/README.md) | User-facing documentation of worktree behavior and `master` exception |
| `swarmforge/constitution/articles/workflow.prompt` | Constitutional rule defining special worktree handling |
| `test/swarmforge/*.clj` | Unit tests for creation, duplicate detection, and edge cases |

## Summary

- **Path construction**: `worktree-path-for-name` joins `.worktrees/` with role names
- **Git hygiene**: `.worktrees/` is added to both `.gitignore` and `.git/info/exclude`
- **Creation**: `prepare-worktrees!` runs `git worktree add` for each non-special role
- **Validation**: Window parsing prevents duplicate worktree assignments
- **Special case**: `master` runs in main checkout; no `.worktrees/master` directory is created

## Frequently Asked Questions

### How does Swarm Forge prevent Git from tracking worktree directories?

Swarm Forge writes `.worktrees/` to both `.gitignore` and `.git/info/exclude` during startup. This dual coverage ensures the directory remains untracked even if `.gitignore` is later removed or overridden, as implemented in `swarmforge/scripts/swarmforge.bb` lines 111–120.

### What happens if two windows request the same worktree name?

The `parse-window-line` function rejects the configuration with an error. It maintains a `worktrees` set tracking all non-special worktree names, and throws if a duplicate is detected. This validation runs at lines 172–179 of the main script.

### Why doesn't the `master` role get its own worktree directory?

The `master` role operates directly in the main repository checkout to simplify orchestration and avoid unnecessary Git overhead. This behavior is hardcoded as a special case in `special-worktree?` and documented in both the README and constitution prompt files.

### Can I customize the `.worktrees/` directory location?

Yes—the `:worktrees-dir` key in the context map controls the base directory. The default is `.worktrees` relative to project root, but this can be overridden in configuration before `prepare-worktrees!` executes.