⚓ firstmate field guide
Using firstmate

Briefs & the status protocol

The anatomy of a crewmate brief, the status verbs workers write, the steering inbox, and the per-mode definition of done that firstmate independently verifies.

Crewmates are stateless strangers. Everything a worker knows comes from its brief, and everything the first mate knows about the worker comes from its status log, its pane, and the no-mistakes run. This page is the contract between them.

Anatomy of a brief#

bin/fm-brief.sh writes data/<id>/brief.md. The header comment of fm-brief.sh is the canonical spec. There is no separate doc. A ship brief looks like this:

You are a crewmate: an autonomous worker agent managed by firstmate.
Work on your own; do not wait for a human.

# Task
## Captain's intent
<the captain's ask, verbatim — no "Captain:" label>

## Firstmate spec
<only the build instructions the ask requires>

# Herdr lifecycle declaration - NOT ENABLED      (or the --herdr-lab isolation contract)

# Setup
Verify isolation before anything else: pwd -P and git rev-parse --show-toplevel
must resolve to the disposable task worktree ...
1. First action: create your branch: git checkout -b fm/<id> --

# Rules
1. <mode-specific "never push to X" rule>
2. Stay inside this worktree; modify nothing outside it.
3. Use gh-axi for GitHub operations and chrome-devtools-axi for browser operations.
4. Report status by appending one line: ...
5. If you hit the same obstacle twice, append `blocked [at=<epoch>]: {why}` ...
6. If a decision belongs to a human ... append `needs-decision [at=<epoch>]: {options}` ...
7. Never administer infrastructure that every lane shares.

# Firstmate instruction inbox
# Project memory
# Definition of done
# Home brief additions        (only if config/brief-include.md exists)

Key rules:

  • Intent is sacred. Only ## Captain's intent (plus later captain words) counts as intent for the no-mistakes --intent contract. The spec and the worker's own reasoning never do.
  • Project memory is correct-only. A worker may edit a project's AGENTS.md/CLAUDE.md only to correct wrong facts, never to add to it.
  • Rule 7 protects the shared no-mistakes daemon and the treehouse pool. One crewmate must not restart infrastructure every other lane depends on.
  • Scout briefs say "This is a SCOUT task: the deliverable is a written report, not a PR". Their rule 1 is "never push to any remote and never open a PR".
  • config/brief-include.md appends your standing worker instructions to every brief, e.g. "run make check before reporting done".

Status verbs#

A worker appends one line per event to state/<id>.status:

{verb} [at=<epoch>] [key=<slug>]: {one short line}
Verb Meaning First mate response
working A phase change worth knowing about. Not step-by-step narration. none (not captain-relevant)
needs-decision A human-owned choice; the worker stops and waits decide, or escalate to you
blocked Stuck; the first mate must act intervene
paused A known wait expected to clear itself: an external condition, or the worker's own background shell, pipeline run or long command (until <ISO> optional). A worker must declare it before ending a turn on such a wait. leave it; after one first-sight stale alert, recheck every 4h
done Mode-specific completion (below) verify, then report
failed Gave up report plainly
resolved [key=...] Closes a keyed needs-decision/blocked. Only an exact key match closes it. clears the open decision
note Informational (e.g. pipeline summary) none
captain-held The item was handed to a durable captain hold treated like paused

A later done or working never closes an open decision. Only a resolved line carrying the matching key does.

The steering inbox#

bin/fm-send.sh <id> '<text>' writes a sequenced record to state/<id>.inbox/NNN.msg and types a short "doorbell" line into the worker's pane. The worker processes messages in order and acknowledges each by moving it to handled/. The watcher re-rings an unacknowledged message (after 90s, up to 3 times), then escalates.

Lifecycle commands (interrupt, exit, relaunch) never go through the inbox. They use bin/fm-control.sh. See Troubleshooting.

Definition of done, per mode#

bin/fm-dod-lib.sh renders the # Definition of done section for each mode and forge. It also owns the gate that checks the claim:

Mode Worker reports Accepted when
local-only done: ready in branch <branch> the head is on the project's shared local branch
direct-PR done: PR <url> the worker's HEAD is what's pushed to the PR branch; the PR is not a draft
no-mistakes 1) done: <summary> → hands off to the pipeline (not gated)
2) done: PR <url> checks green
the named head is reachable outside the worktree, and gh-axi pr view confirms draft: no
gerrit done: PR <change url> published for review the change's current patch set carries the worktree's HEAD tree

a ship done: is never trusted merely because the worker said so — it must be proven reachable from outside the disposable worktree — fm-dod-lib.sh (paraphrased header)

If the gate fails, fm-crew-state.sh reports the task as blocked, not done. Nobody gets told "PR ready" for a commit that only exists in a worktree about to be deleted.

Reading state back: fm-crew-state.sh#

$ bin/fm-crew-state.sh fix-login-q3
state: working · source: run-step · no-mistakes review (round 2)

It resolves in this order:

  1. state/<id>.meta. A remote secondmate is probed remotely.
  2. A matching no-mistakes run for the branch and head. When one exists it is authoritative: running or fixing maps to working, awaiting_approval maps to parked, passed maps to done, failed maps to failed.
  3. The status log, reconciled so that open decisions survive unrelated later events.
  4. The pane's semantic busy state.
  5. unknown.

AGENTS.md is explicit: judge state by this line, "never by shell liveness, the last status event, or a raw run record."

Per-task files at a glance#

Path What
data/<id>/brief.md the contract
data/<id>/report.md scout deliverable (survives teardown)
state/<id>.meta worktree=, kind=, harness=, mode=, project=, pr=, pr_head=, backend=, remote_host= ...
state/<id>.status append-only wake events
state/<id>.inbox/ steering messages and handled/
state/<id>.busy-state semantic busy/idle from harness hooks
state/<id>.check.sh + .check-trust optional custom watcher check, SHA-256 pinned
state/<id>.git-hooks/ per-task hooksPath that strips AI commit trailers
Unofficial guide built 2026-09-26 from kunchenguid/firstmate, the AXI repos, and Kun Chen's public posts. The repo moves daily; when this guide and the repo disagree, the repo wins.