How to Set Up FM_HOME and Manage the Firstmate Operational Home Layout

FM_HOME is the environment variable that defines the operational home directory where Firstmate stores mutable data (state/, data/, config/, projects/) while executing scripts from the immutable repository root.

Setting up FM_HOME is essential for managing isolated operational environments in the kunchenguid/firstmate repository. This environment variable directs where the system stores mutable state, data, configuration, and project files, allowing you to separate active workspaces from the codebase. Understanding how to configure and switch between operational homes enables clean isolation for experiments, persistent second-mates, and reproducible sessions.

Understanding the FM_HOME Operational Home Layout

When FM_HOME is unset, Firstmate defaults to legacy "whole-root" behavior, storing mutable directories directly in the repository root. According to AGENTS.md (lines 50-52), this means state/, data/, config/, and projects/ subdirectories live alongside the source code.

When FM_HOME is explicitly set, the scripts in bin/ continue executing from the repository root, but all mutable data resolves under the custom path. As specified in docs/configuration.md (lines 191-200), this design keeps the codebase immutable while allowing flexible data placement.

Variable Precedence and Override Behavior

The Firstmate environment follows a strict hierarchy for resolving operational paths. The precedence flows from most specific to least specific:

  1. FM_HOME — The primary operational home directory
  2. FM_ROOT_OVERRIDE — Fallback override for the entire root
  3. Repository root — Default location when no overrides are set

Additionally, docs/turnend-guard.md (lines 46-47) documents two granular overrides: FM_STATE_OVERRIDE and FM_DATA_OVERRIDE can redirect specific subdirectories while maintaining other paths under FM_HOME.

Setting Up a Custom Firstmate Home

Creating an isolated operational home requires three steps:

  1. Create a writable directory for your private data
  2. Export the FM_HOME variable pointing to that directory
  3. Execute Firstmate commands—the system will automatically generate the required subdirectories
mkdir -p ~/firstmate-home
export FM_HOME=~/firstmate-home

echo "Home root: $FM_HOME"
ls "$FM_HOME"

# → Firstmate will create state/, data/, config/, projects/ as needed

Working with Second-Mate Homes

Each persistent second-mate requires its own isolated FM_HOME to maintain separate state, backlog, and session locks. As documented in AGENTS.md (lines 50-52), this isolation prevents conflicts between concurrent operational contexts. Switching between second-mates is accomplished by changing the FM_HOME value before invoking commands, requiring no code modifications.

Script-Specific Requirements and Bootstrap Handling

Certain scripts enforce stricter requirements for FM_HOME configuration. The bin/fm-send.sh script explicitly requires FM_HOME to be set before execution to prevent steering commands to the wrong operational context, as noted in docs/configuration.md (lines 197-199).

During bootstrap operations, Firstmate injects the FM_HOME value specifically into generated Relay poll shims, while transient consumers retain their shell-relative behavior (docs/configuration.md, lines 200-201).

Practical Examples

The following examples demonstrate common workflows using custom operational homes.

Setting up and verifying a new home:

mkdir -p ~/my-firstmate-home
export FM_HOME=~/my-firstmate-home

echo "Home root: $FM_HOME"
ls "$FM_HOME"

# → should show (or create) state/ data/ config/ projects/

Sending a command to a running task:


# Assume a task id 12345 exists

FM_HOME=~/my-firstmate-home bin/fm-send.sh 12345 'status?'

Starting a new worker with the current home:

FM_HOME=~/my-firstmate-home bin/fm-brief.sh \
   --task-id new-task \
   --description "Run diagnostics on repo X"

Inspecting task state:

FM_HOME=~/my-firstmate-home bin/fm-crew-state.sh new-task

Summary

  • FM_HOME controls where Firstmate stores mutable data, separating operational state from source code
  • When unset, mutable directories default to the repository root; when set, they resolve under the custom path
  • Variable precedence follows: FM_HOME → FM_ROOT_OVERRIDE → repository root
  • Specific subdirectories can be overridden using FM_STATE_OVERRIDE and FM_DATA_OVERRIDE
  • Persistent second-mates require isolated FM_HOME directories to prevent state conflicts
  • The bin/fm-send.sh script requires explicit FM_HOME configuration to ensure correct routing

Frequently Asked Questions

What happens if FM_HOME is not set?

When FM_HOME is unset, Firstmate falls back to legacy "whole-root" behavior, placing all mutable directories (state/, data/, config/, projects/) directly in the repository root alongside the source code. This behavior is documented in AGENTS.md (lines 50-52).

Can I override specific subdirectories while using FM_HOME?

Yes. While FM_HOME sets the base operational home, you can redirect specific subdirectories using FM_STATE_OVERRIDE and FM_DATA_OVERRIDE. These variables take precedence over the paths derived from FM_HOME, as explained in docs/turnend-guard.md (lines 46-47).

Why does fm-send.sh require explicit FM_HOME?

The bin/fm-send.sh script enforces explicit FM_HOME configuration to prevent accidentally steering commands to the wrong operational context. This safety mechanism ensures that messages route to the correct task home, avoiding cross-contamination between isolated environments (docs/configuration.md, lines 197-199).

How do I switch between different operational homes?

Change the FM_HOME environment variable to point to a different directory and re-export it. The same Firstmate scripts can then operate on a completely separate operational context without any code changes, enabling rapid switching between projects or experimental setups.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →