https://github.com/kunchenguid/firstmate
Talk to one agent. Ship with a crew.
https://github.com/kunchenguid/firstmate
Last synced: 22 days ago
JSON representation
Talk to one agent. Ship with a crew.
- Host: GitHub
- URL: https://github.com/kunchenguid/firstmate
- Owner: kunchenguid
- License: mit
- Created: 2026-06-12T03:21:10.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-20T08:55:16.000Z (24 days ago)
- Last Synced: 2026-06-20T09:04:58.301Z (24 days ago)
- Language: Shell
- Homepage:
- Size: 1.02 MB
- Stars: 51
- Watchers: 0
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
- awesome - kunchenguid/firstmate - Talk to one agent. Ship with a crew. (Shell)
README
firstmate
Talk to one agent. Ship with a crew.
You can run one coding agent easily.
But the moment you want three project tasks done in parallel - fixes, investigations, plans, audits - you become a tab-juggler: babysitting sessions, copy-pasting context between repos, forgetting which terminal had the failing test.
firstmate flips the model.
You talk to a single agent - the first mate - and it runs the crew for you: spawning autonomous agents in tmux windows, giving each a clean git worktree, supervising them to completion, and handing you finished PRs, approved local merges, or standalone investigation reports.
There is no app to install; the whole orchestrator is an `AGENTS.md` file that any terminal coding agent can follow.
- **One liaison** - you never talk to a worker agent.
The first mate dispatches, supervises, escalates only real decisions, and reports plain outcomes about work that is ready, blocked, or needs your call.
- **A visible crew** - every crewmate lives in a tmux window.
Watch any of them work, or type into their window to intervene; the first mate reconciles.
- **Guarded by construction** - the first mate is read-only over your projects except for clean local default-branch refreshes, safe pruning of local branches whose remote is gone, and approved `local-only` fast-forward merges; crewmates work in disposable [treehouse](https://github.com/kunchenguid/treehouse) worktrees.
Ship tasks follow each project's delivery mode, and scout tasks produce local reports without pushing anything.
This is not an agent harness. This is not a skill. This is not a CLI.
This is.. a directory that turns any agent into your firstmate, and you the captain.
## Quick Start
```sh
$ git clone https://github.com/kunchenguid/firstmate && cd firstmate
$ claude # launch your agent harness here; AGENTS.md takes over
> ahoy! look at my github project xyz, then fix the flaky login test and add dark mode
# firstmate checks its toolchain (asking your consent before installing anything),
# clones the project under projects/, and spawns two crewmates in tmux windows
# fm-fix-login-k3 and fm-dark-mode-p7.
# Minutes later:
PR ready for review, captain: https://github.com/you/xyz/pull/42
(fix flaky login test - risk: low - CI green)
> alright merge it
```
## Install
**Prerequisites** (the first mate detects everything else and offers to install it):
```sh
# 1. a verified agent harness - claude, codex, opencode, or pi
# 2. git + GitHub auth
# 3. tmux - the crew lives in tmux windows (firstmate offers to install it if missing)
gh auth login
```
**Get firstmate:**
```sh
git clone https://github.com/kunchenguid/firstmate
cd firstmate && claude
```
That is the whole install.
On first launch the first mate detects what its toolchain is missing (tmux, treehouse, no-mistakes, gh-axi, chrome-devtools-axi, lavish-axi), lists it with the exact install commands, and installs only after you say go.
**Run it inside tmux for the best experience.**
firstmate works from any terminal - outside tmux, crewmates land in a detached `firstmate` session you can attach to - but launching your harness from inside tmux puts every crewmate window in your own session, one per task, where you can watch the crew work in real time or type into any window to intervene.
## How It Works
```
you (the captain)
│ chat: requests, decisions, "merge it"
▼
┌─────────────────────────────────────┐
│ firstmate (this repo) │
│ reads projects/; writes guarded │
│ backlog.md ── briefs ── watcher │
└──┬──────────────┬───────────────┬───┘
│ tmux send-keys / status files │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│fm-task1│ │fm-task2│ ... │fm-taskN│ tmux windows you can watch
│crewmate│ │crewmate│ │crewmate│ one autonomous agent each
└───┬────┘ └───┬────┘ └───┬────┘
▼ ▼ ▼
treehouse worktree (clean, disposable, parallel-safe)
│
├─ ship: project mode ► PR/local merge ► teardown
│
└─ scout: report at data//report.md ► relay findings ► teardown
```
- **Event-driven supervision** - a zero-token bash watcher (`bin/fm-watch.sh`) sleeps on the fleet and wakes the first mate only when a crewmate reports, stalls, a PR merges, or an internal heartbeat review is due.
Detected wakes are also written to a durable local queue (`state/.wake-queue`) before detector state advances, so a missed one-shot process exit can be recovered by draining the queue.
Routine watcher polling, restarts, elapsed waiting time, and unchanged heartbeat reviews stay silent; an idle crew costs you nothing.
A pull-based guard (`bin/fm-guard.sh`) warns through supervision tool output if tasks are in flight and that watcher stops running or queued wakes are waiting to be drained.
- **Worktrees, not branches in your checkout** - crewmates never touch your clone; treehouse pools clean worktrees so parallel tasks on one repo cannot collide.
- **Two task shapes** - ship tasks change projects and ship by project mode (`no-mistakes`, `direct-PR`, or `local-only`); scout tasks investigate, plan, reproduce bugs, or audit, then leave a report at `data//report.md` and never push.
- **Project modes are explicit** - `data/projects.md` records each project's delivery mode and optional `+yolo` autonomy flag.
`no-mistakes` projects run the full validation pipeline, `direct-PR` projects open PRs without that pipeline, and `local-only` projects stay local until firstmate performs an approved fast-forward merge.
- **Project memory belongs to projects** - durable project-intrinsic agent knowledge lives in each project's committed `AGENTS.md`, with `CLAUDE.md` as a symlink.
Ship briefs prompt crewmates to create or update those files through the normal delivery path; `data/projects.md` stays a thin private registry.
- **Local clones stay fresh** - bootstrap and PR-based teardown refresh remote-backed project clones with clean default-branch fast-forwards when the clone is on the default branch and has no local work, and prune local branches whose remote is gone and that no worktree still needs.
- **Restart-proof** - all state lives in tmux, status files, and local markdown under `data/`.
Kill the first mate session anytime; the next one reconciles and carries on.
## The bin/ toolbelt
The first mate drives these; you rarely need to, but they work by hand too.
| Script | Description |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `fm-bootstrap.sh` | Detect missing toolchain pieces; refresh clones best-effort; install tools only after consent |
| `fm-fleet-sync.sh` | Fetch clones, clean-fast-forward their checked-out default branches, and safely prune branches whose remote is gone |
| `fm-brief.sh` | Scaffold a ship brief, or a report-only scout brief with `--scout` |
| `fm-ensure-agents-md.sh` | Ensure project `AGENTS.md` is the real memory file and `CLAUDE.md` symlinks to it |
| `fm-guard.sh` | Warn when tasks are in flight but queued wakes are pending or the watcher liveness beacon is stale or missing |
| `fm-spawn.sh` | Spawn one task, or several `id=repo` pairs in one batch; records ship/scout task kind |
| `fm-project-mode.sh` | Resolve a project's delivery mode and `+yolo` flag from `data/projects.md` |
| `fm-merge-local.sh` | Fast-forward a `local-only` project's local default branch after approval |
| `fm-review-diff.sh` | Review a crewmate branch against the authoritative base, with optional `--stat` output |
| `fm-watch.sh` | Singleton-safe one-shot watcher; blocks until supervision work is due, queues it durably, then exits with one reason line |
| `fm-wake-drain.sh` | Atomically drain queued watcher wakes before handling supervision work |
| `fm-send.sh` | Send one literal line (or `--key Escape`) to a crewmate window |
| `fm-peek.sh` | Print a bounded tail of a crewmate pane |
| `fm-pr-check.sh` | Record a PR-ready task and arm the watcher's merge poll |
| `fm-promote.sh` | Promote a scout task in place so it becomes a protected ship task |
| `fm-teardown.sh` | Return the worktree and kill the window; protects ship work, requires scout reports, and reminds backlog refresh |
| `fm-harness.sh` | Detect the running harness; resolve the effective crewmate harness |
| `fm-lock.sh` | Single-firstmate session lock |
## Configuration
The shared orchestrator behavior lives in `AGENTS.md` - edit it like any prompt when the fleet is empty, or dispatch shared-repo edits to a crewmate while tasks are in flight.
Personal preferences for one captain's fleet live locally in `data/captain.md`; it is gitignored and read after `data/projects.md` during bootstrap.
Harness support is a table in section 4: claude, codex, opencode, and pi are all empirically verified; new harnesses get verified through a supervised trial task before joining the table.
Runtime tuning via environment variables (defaults shown):
```sh
FM_POLL=15 # seconds between watcher cycles
FM_HEARTBEAT=600 # base seconds between fleet reviews; backs off exponentially while idle
FM_HEARTBEAT_MAX=7200 # heartbeat backoff cap
FM_CHECK_INTERVAL=300 # seconds between slow checks (merged-PR polls)
FM_CHECK_TIMEOUT=30 # seconds allowed per slow check script
FM_GUARD_GRACE=300 # seconds a stale watcher beacon may age before guard warnings
FM_SIGNAL_GRACE=30 # seconds to coalesce nearby status and turn-end signals into one wake
FM_FLEET_SYNC_BOOTSTRAP_TIMEOUT=20 # seconds allowed for bootstrap's best-effort clone refresh
FM_FLEET_PRUNE=1 # set to 0 to skip pruning local branches whose upstream is gone
FM_BUSY_REGEX='esc (to )?interrupt|Working\.\.\.' # busy-pane signatures, extend per harness
```
## Development
Tracked changes to firstmate itself, including `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.github/workflows/`, `bin/`, and agent skill files, ship through the `no-mistakes` pipeline on a feature branch and require the captain's explicit merge approval.
When supervising live crewmates, keep long validation or build work in the background so watcher wakes can still be handled.
Human-authored pull requests targeting `main` must be raised through `git push no-mistakes`; see `CONTRIBUTING.md` for the enforced contributor workflow.
Local `.no-mistakes/` state and test evidence stay out of this repo; `.no-mistakes.yaml` keeps evidence in a temp directory instead.
The current watcher reliability work keeps the one-shot process model and adds a durable queue plus singleton lock.
The persistent detector daemon and blocking waiter split are deferred follow-up phases.
```sh
bash -n bin/*.sh # syntax-check the toolbelt
shellcheck bin/*.sh tests/*.sh # lint the toolbelt and behavior tests; CI enforces this
for test_script in tests/*.test.sh; do "$test_script"; done # behavior tests, matching CI
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ]
[ "$(readlink .claude/skills)" = "../.agents/skills" ]
FM_HEARTBEAT=2 FM_POLL=1 bin/fm-watch.sh # watcher smoke test (prints "heartbeat")
```