# How to Define Roles in SwarmForge: A Complete Guide to Role Configuration

> Learn how to define roles in SwarmForge. Configure project roles using prompt files and map them to worktrees for efficient development workflow.

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

---

**You do not define roles in [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf)—that file only configures the AI lieutenant (model selection and arguments). Roles are defined per-project using prompt files in `swarmforge/roles/` and mapped to worktrees via `.swarmforge/roles.tsv`.**

Understanding how to define roles in SwarmForge requires knowing where the system actually stores role definitions. According to the unclebob/swarm-forge source code, [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) only handles top-level lieutenant configuration—model selection and extra arguments—not role definitions. Roles are managed through a two-layer system that separates static prompts from dynamic worktree mappings.

## What swarmforge.conf Actually Does

The [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) file in your repository root configures which AI model drives the swarm and what parameters to pass it:

```text

# Host lieutenant. Default is grok with no extra args.

# Lieutenant grok --yolo

# Lieutenant claude --yolo

```

This file lives at [`swarmforge/swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/swarmforge.conf) and **never contains role definitions**. Modifying it to add roles would break the configuration parser, as demonstrated in the test suite at `test/swarmforge/script_test.clj`.

## Where Roles Are Actually Defined

SwarmForge uses a per-project, two-file approach for role management:

### 1. Role Prompt Files (Static Definitions)

Each role requires a `<role>.prompt` file in the `swarmforge/roles/` directory. The filename becomes the role name, and the file contents become the system prompt passed to the lieutenant.

Common built-in roles found in the repository include:
- `coder.prompt` — drives code generation and refactoring tasks
- `architect.prompt` — handles high-level design decisions
- `reviewer.prompt` — performs code review and quality analysis

The `swarmforge/roles/` directory keeps these prompts version-controlled alongside your project code.

### 2. Role Mapping File (Dynamic Assignments)

The hidden file `.swarmforge/roles.tsv` in your project root maps worktree names to role names. This TSV uses two columns:

| Column | Purpose |
|--------|---------|
| 1 | Worktree name (e.g., `feature-auth`, `hotfix-login`) |
| 2 | Role name (must match a `.prompt` file base name) |

When [`pack_board.sh`](https://github.com/unclebob/swarm-forge/blob/main/pack_board.sh) or [`pack_web.sh`](https://github.com/unclebob/swarm-forge/blob/main/pack_web.sh) creates a worktree, they append entries to this file. The core hand-off logic in `swarmforge/scripts/handoff_lib.bb` reads this mapping to load the correct prompt for each session.

## How to Create a New Role: Step-by-Step

Follow this exact workflow to define roles in SwarmForge:

**Step 1: Create the prompt file**

```bash
cat > swarmforge/roles/designer.prompt <<'EOF'
You are a UI/UX designer focused on accessibility and user-centered design.
Prioritize semantic HTML, color contrast compliance (WCAG 2.1 AA), and
keyboard navigation in all recommendations.
EOF

```

**Step 2: Map a worktree to the role**

```bash

# Using literal tab character between columns

echo "design-worktree	designer" >> .swarmforge/roles.tsv

```

Or manually edit `.swarmforge/roles.tsv`:

```text
design-worktree	designer
api-worktree	coder
docs-worktree	architect

```

**Step 3: Start a session with the new role**

```bash
swarm_tool.sh start-session design-worktree

```

This launches a tmux session where the lieutenant receives your `designer.prompt` content as its system prompt.

## Complete Working Example

Here's a real-world scenario defining a QA engineer role:

```bash

# 1️⃣ Define the role prompt

cat > swarmforge/roles/qa.prompt <<'EOF'
You are a QA engineer tasked with writing comprehensive test plans.
When reviewing code:
- Identify missing edge cases and boundary conditions
- Suggest specific test data sets for each scenario
- Flag potential race conditions and concurrency issues
- Verify error handling paths are exercised
EOF

# 2️⃣ Create worktree and map to role (or do separately)

echo "qa-session	qa" >> .swarmforge/roles.tsv

# 3️⃣ Launch with the role active

swarm_tool.sh start-session qa-session

```

The session now operates with QA-specific guidance without touching [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf).

## Architecture Benefits

This separation provides three key advantages verified by the test suite in `test/swarmforge/script_test.clj`:

- **Version control integration** — Prompt files live in `swarmforge/roles/` and commit with your codebase
- **Clean repository state** — Dynamic mappings stay in `.swarmforge/`, excluded from git via standard ignore patterns
- **Lieutenant stability** — [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) remains unchanged when adding or modifying roles

The `handoff_lib.bb` script enforces this by validating that every role in `roles.tsv` has a corresponding `.prompt` file before starting sessions, with explicit checks for duplicate role definitions and proper TSV formatting.

## Common Mistakes to Avoid

- **Editing [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) for roles** — This breaks lieutenant configuration
- **Missing `.prompt` extension** — Role files must use `.prompt` suffix to be detected
- **Spaces instead of tabs in TSV** — Use literal tab characters between worktree and role columns
- **Forgetting to create the worktree** — The mapping alone doesn't create the worktree; use [`pack_board.sh`](https://github.com/unclebob/swarm-forge/blob/main/pack_board.sh) or equivalent

## Summary

- **[`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf)** configures the AI lieutenant (model + args), not roles
- **`swarmforge/roles/*.prompt`** files define static role prompts with system instructions
- **`.swarmforge/roles.tsv`** maps worktree names to role names dynamically
- **`handoff_lib.bb`** orchestrates prompt loading and session routing
- Create roles by writing `.prompt` files and appending TSV mappings—never modify [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf)

## Frequently Asked Questions

### Why can't I put role definitions in swarmforge.conf?

[`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) uses a simple line-based parser that only recognizes `Lieutenant` directives for model configuration. The `handoff_lib.bb` script explicitly sources role data from separate locations to maintain clean separation between infrastructure configuration (the lieutenant) and project-specific behavior (roles). Mixing these concerns would complicate testing and version control.

### What happens if a worktree has no role mapping?

Without a matching entry in `.swarmforge/roles.tsv`, `handoff_lib.bb` cannot resolve which prompt to load. The script either fails with a clear error message or falls back to a default role if one is configured—behavior verified in `test/swarmforge/script_test.clj` under role propagation tests. Always ensure mappings exist before starting sessions.

### Can multiple worktrees share the same role?

Yes. The TSV format allows multiple worktree names to reference a single `.prompt` file. For example, `auth-feature` and `oauth-refactor` can both map to `coder`, while each maintains separate git state. This is the intended design: one prompt definition, many worktree instances.

### How do I version control role definitions without exposing worktree mappings?

Commit `swarmforge/roles/*.prompt` files normally—they contain reusable, shareable role instructions. Add `.swarmforge/` to your `.gitignore` since `roles.tsv` contains local worktree names specific to each developer's environment. The test suite confirms this pattern through `handoff_lib.bb`'s handling of generated versus static paths.