---
title: "Herdr + firstmate: running a crew of coding agents"
description: "How herdr and firstmate turn one pi session into a supervised crew of coding agents."
---

# Herdr + firstmate: running a crew of coding agents

Herdr and firstmate solve the same problem from opposite sides.
Herdr provides the terminal theater; firstmate provides the director.
Together they turn one pi session into a supervised crew of coding agents.

## The division of labor

Herdr is the terminal workspace manager.
It gives every agent a real pane in a named session, organizes panes into workspaces and tabs, and reports each pane's agent state (idle, working, blocked).
It does not decide what the agents do.

Firstmate is an agent distro.

- It is a git repo you run a coding agent from; the cloned repo is the distro.
- Running a primary harness (Pi) inside the checkout turns that agent into the first mate.
- The first mate spawns a visible crew, gives each crewmate a clean git worktree, supervises it to completion, and hands you finished PRs, approved local merges, or standalone reports.
- It is read-only over your projects except for narrow, guarded, captain-approved operations.
- It uses herdr as its crew session backend: every crewmate runs in its own herdr tab or workspace.

## How this configuration provides them

- `herdr` is installed from its own flake (`github:herdrdev/herdr`, pinned to a release tag in `flake.nix`) and added to `home.packages` by `den.aspects.pkgs.herdr` in `modules/herdr.nix`.
- `firstmate` is fetched over git from a pinned `flake=false` input and copied writable into `~/firstmate` by `den.aspects.pkgs.firstmate` in `modules/firstmate.nix`.
- The firstmate aspect adds its missing toolchain dependency (`gh`, the GitHub CLI) to `home.packages`.
- The firstmate aspect sets `FM_BACKEND=herdr` and writes `~/firstmate/config/backend = herdr`, so the crew uses herdr rather than the tmux default.
- Both aspects are wired into the `philipp` home in `modules/homes.nix`.

## Using them together

Open herdr so a session and server exist:

```text
herdr
herdr status server
```

Launch pi as the first mate:

```text
cd ~/firstmate
pi
```

Approve the project-trust prompt once so firstmate's tracked `.pi` extensions load.

Ask for parallel work:
> Run these as parallel tasks: (1) fix the flaky login test, (2) draft a migration plan for the orders table, (3) audit the S3 permission boundaries.
> Ship PRs for 1 and 3; leave 2 as a report.

The first mate assigns each task a clean worktree and spawns a crewmate into herdr.

Watch the crew in herdr: the TUI shows a `firstmate` workspace with one tab per task (`fm-<id>`), each a real pane you can watch or type into.

Supervise without attaching:

```text
~/firstmate/bin/fm-peek.sh <task-id>
FM_HOME=... ~/firstmate/bin/fm-send.sh <task-id> 'text'
```

Ship tasks end in a finished PR or approved local merge under the project's merge authority.
Scout tasks leave a standalone report.
The first mate reports plain outcomes and escalates only real decisions.

## Notes

- `FM_BACKEND=herdr` selects herdr for a single launch; the config file makes it the persistent preference.
- The Nix fetch keeps firstmate pinned and reproducible; the writable copy preserves its own-config and git operations.
- Firstmate runs on tmux by default, so herdr must be reachable for the herdr backend; a tmux pane nested inside herdr resolves to tmux because the innermost multiplexer wins.
