# How to Configure Firstmate Runtime Backends: Tmux, Herdr, Zellij, Orca, and Cmux

> Configure Firstmate runtime backends like Tmux, Herdr, Zellij, Orca, and Cmux. Learn the priority chain for backend selection to optimize your workflow.

- Repository: [Kun Chen/firstmate](https://github.com/kunchenguid/firstmate)
- Tags: how-to-guide
- Published: 2026-08-13

---

**Firstmate selects from five runtime backends—tmux, herdr, zellij, orca, and cmux—using a strict priority chain that checks the `--backend` flag, `FM_BACKEND` environment variable, and `config/backend` file before falling back to auto-detection or the tmux default.**

Firstmate is an open-source supervision system from kunchenguid/firstmate that manages worker panes across multiple terminal multiplexers. When you configure Firstmate runtime backends, you control whether tasks execute inside tmux, herdr, zellij, orca, or cmux sessions, with each backend offering unique capabilities for headless automation, cursor tracking, and distributed second-mate support.

## Supported Firstmate Runtime Backends

Firstmate supports five distinct backends, each defined in dedicated documentation under the `docs/` directory.

### Tmux (Default Reference)

**Tmux** is the verified reference backend and default choice. According to [`docs/tmux-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/tmux-backend.md), it provides full-featured terminal multiplexing for both primary harnesses and second-mate homes. It is the only backend that supports `--secondmate` launches.

### Herdr (Headless Editor Driver)

**Herdr** operates as an experimental "headless-editor-driver" backend that communicates directly with a Herdr server. As documented in [`docs/herdr-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/herdr-backend.md), Firstmate auto-detects this backend when the primary process runs under `HERDR_ENV=1`.

### Zellij (Secondary Multiplexer)

**Zellij** functions as a secondary multiplexer similar to tmux but lacks cursor-row information exposure. Per [`docs/zellij-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/zellij-backend.md), this backend is used only for pane capture, and the Firstmate *cursor* agent falls back to "cursor-less" mode when running under zellij.

### Orca (Experimental Session Provider)

**Orca** acts as a session-provider backend that also supplies the worktree. According to [`docs/orca-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/orca-backend.md), it is experimental and explicitly rejects second-mate launches until a dedicated design is implemented.

### Cmux (Experimental Workspace Backend)

**Cmux** serves as another experimental session-provider backend. As noted in [`docs/cmux-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/cmux-backend.md), it cannot host second-mates at this time and is detected via signals like `CMUX_WORKSPACE_ID`.

## Backend Selection Priority Chain

The backend resolution follows a strict five-step hierarchy defined in [`docs/configuration.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/configuration.md):

1. **Explicit `--backend` flag** on a task (authorized only by a concrete captain instruction)
2. **Environment variable `FM_BACKEND`**
3. **First non-empty line** in the local, git-ignored file `config/backend`
4. **Auto-detection** from the current process environment:
   - `$TMUX` → tmux
   - `HERDR_ENV=1` → herdr
   - `CMUX_WORKSPACE_ID` (or related cmux signals) → cmux
5. **Default** → tmux

When multiple detection signals are present, the *innermost-first* rule applies: `$TMUX` wins over `HERDR_ENV`, which wins over cmux signals. Any value other than `tmux`, `herdr`, `zellij`, `orca`, or `cmux` is rejected with an error.

## How to Configure Firstmate Runtime Backends Permanently

You can persist backend selection at the home-directory level or override it temporarily.

### Using the config/backend File

Create or edit `config/backend` in the Firstmate home directory and write the backend name on a single line:

```bash
printf "herdr\n" > config/backend

```

This sets herdr as the default for all subsequent spawns in this home, unless overridden by environment variables or flags.

### Using Environment Variables

Export the variable before invoking Firstmate for a temporary session-wide override:

```bash
export FM_BACKEND=orca
firstmate ship --brief "Add new feature"

```

This affects all Firstmate commands in the current shell session without modifying persistent configuration.

### Task-Specific Overrides with --backend

Use the `--backend` flag when spawning a task, as implemented in [`bin/fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-spawn.sh):

```bash
firstmate scout --backend zellij --brief "Investigate XYZ"

```

This override is permitted only when the captain explicitly authorizes backend switching for the specific task.

## Backend-Specific Limitations and Capabilities

Each backend imposes distinct constraints on Firstmate functionality:

- **tmux**: The only backend supporting second-mate homes. All other backends refuse `--secondmate` at launch time.
- **herdr** and **cmux**: Function solely as session providers; they do not provide worktree services.
- **zellij**: Cannot report cursor row data, forcing the cursor agent into cursor-less mode.
- **orca** and **cmux**: Experimental status means they reject second-mate launches with explicit errors until future design updates.

## Code Examples

### Set a Permanent Backend for the Current Firstmate Home

```bash
printf "herdr\n" > config/backend

```

*Result*: All subsequent spawns use the Herdr backend unless overridden by `FM_BACKEND` or `--backend`.

### Override the Backend for a Single Task

```bash
firstmate scout --backend zellij --brief "Investigate XYZ"

```

*Result*: Only this task runs under zellij; the home's default backend remains unchanged.

### Use the Environment Variable for a Temporary Session

```bash
export FM_BACKEND=orca
firstmate ship --brief "Add new feature"

```

*Result*: The ship task runs on orca for the duration of the shell session.

### Verify Which Backend a Task is Using

Task metadata records the chosen backend (except when it is the default `tmux`). Inspect it with:

```bash
cat state/<task-id>.meta | grep '^backend='

```

If the line is missing, the task ran on the default tmux backend.

## Key Source Files and Implementation Details

The backend selection logic is implemented across several critical files:

- [`docs/configuration.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/configuration.md): Central configuration reference documenting the runtime-backend priority chain and validation rules.
- [`docs/tmux-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/tmux-backend.md): Full description of the reference backend, installation steps, and runtime behavior.
- [`docs/herdr-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/herdr-backend.md): Details on auto-detection via `HERDR_ENV=1` and supervisor interaction.
- [`docs/zellij-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/zellij-backend.md): Information about cursor limitations and pane capture.
- [`docs/orca-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/orca-backend.md) and [`docs/cmux-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/cmux-backend.md): Experimental backend documentation and detection signals.
- [`bin/fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-spawn.sh): The launch script that consumes the backend selection and supports the `--backend` flag.
- [`bin/fm-tmux-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-tmux-lib.sh): Helper library for tmux-specific pane capture and liveness checks.

## Summary

- Firstmate supports five runtime backends: **tmux** (default), **herdr**, **zellij**, **orca**, and **cmux**.
- Backend selection follows a strict priority: `--backend` flag → `FM_BACKEND` env var → `config/backend` file → auto-detection → tmux default.
- Only **tmux** supports second-mate homes; **orca** and **cmux** explicitly reject these launches.
- **Herdr** auto-detects via `HERDR_ENV=1`, while **cmux** detects via `CMUX_WORKSPACE_ID`.
- **Zellij** lacks cursor-row reporting, forcing cursor-less mode for the cursor agent.

## Frequently Asked Questions

### What is the default backend if I don't configure anything?

If no `--backend` flag, `FM_BACKEND` variable, or `config/backend` file is present, and no auto-detection signals (like `$TMUX` or `HERDR_ENV`) are found, Firstmate defaults to **tmux**. This is the verified reference backend implemented in [`bin/fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-spawn.sh).

### Why does Firstmate reject my backend choice when launching a second-mate?

Only the **tmux** backend supports second-mate homes according to [`docs/tmux-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/tmux-backend.md). If you attempt to launch a second-mate using **herdr**, **zellij**, **orca**, or **cmux**, the system will reject the request because these backends cannot host secondary supervision instances.

### How can I verify which backend a running task is using?

Task metadata files stored in `state/<task-id>.meta` record the chosen backend in a `backend=` line. You can grep this file to confirm the runtime environment. If the line is absent, the task is using the default tmux backend.

### Can I use zellij if I need cursor position tracking?

No. As documented in [`docs/zellij-backend.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/zellij-backend.md), the zellij backend does not expose cursor-row information. When running under zellij, Firstmate's cursor agent automatically falls back to a "cursor-less" mode, which may limit functionality that depends on exact cursor positioning.