Thanks for wanting to contribute. One rule up front:
Human-authored pull requests targeting main must be raised through no-mistakes.
We require this to reduce the maintainer's burden of reviewing and merging contributions.
no-mistakes puts a local git proxy in front of your real remote.
Pushing through it runs an AI-driven review/test/lint pipeline in an isolated worktree, forwards the push upstream only after every check passes, and opens a clean PR automatically.
A GitHub Actions check (Require no-mistakes) runs on PRs targeting main and fails if the body is missing the deterministic signature that no-mistakes writes.
Dependency bots are exempt so their automation keeps working, but regular contributor PRs without the signature will not be reviewed or merged.
-
Fork the repo, then clone the parent repo or set your local
originback to the parent (git@github.com:kunchenguid/firstmate.git). -
Create a branch and make your changes.
-
Initialize the gate with your fork as the push target:
no-mistakes init --fork-url git@github.com:<you>/firstmate.git(firstmate expects no-mistakes v1.31.2+; without a fork, plainno-mistakes initstill works for maintainers with push access). -
Commit your changes.
-
Push through the gate instead of pushing to
origin:git push no-mistakes
-
Run
no-mistakesto attach to the pipeline, watch findings, authorize auto-fixes, and review ask-user findings as needed. Follow the installed no-mistakes version's SKILL.md and liveaxihelp for gate mechanics. -
Once the pipeline passes, it pushes the branch to your fork and opens the PR against the parent repo for you.
See the no-mistakes quick start for the full first-run walkthrough.
- This repo is a template for running a firstmate orchestrator agent.
AGENTS.mdis the agent's main job description and names when to load bundled firstmate skills;CLAUDE.mdis a symlink to it, and.claude/skillsis a symlink to.agents/skills. - Only shared material is tracked:
AGENTS.md,README.md,CONTRIBUTING.md,.tasks.toml,.github/workflows/,bin/,.agents/skills/, andskills/..agents/skills/holds agent-loaded skills that assume a live firstmate home and carrymetadata.internal: trueso installers such as skills.sh hide them from discovery;skills/holds standalone, installer-facing public skills with no firstmate dependency (see the README's "Two-tier skill layout"). Everything personal to one captain's fleet (.env,data/,state/,config/,projects/,.no-mistakes/) is gitignored; never commit it. The root.tasks.tomlis trackedtasks-axiconfig fordata/backlog.md; compatibletasks-axiis the default backend for routine backlog mutations, with the compatibility definition owned bydocs/configuration.md("Backlog backend"). A localconfig/backlog-backend=manualopt-out forces firstmate's routine backlog updates to hand-editing and stays gitignored; validated secondmate handoffs still delegate throughtasks-axi mv. A localconfig/backendfile explicitly overrides runtime auto-detection for new task endpoints and stays gitignored; spawn-supported values aretmuxplus experimentalherdr,zellij,orca, andcmux, whilecodex-appis documented only indocs/codex-app-backend.md. It does not makedata/tracked. - Helper scripts in
bin/are plain bash. Each starts with a usage header comment; keep it accurate when you change behavior. Test scripts and helpers intests/are plain bash too.bin/fm-lint.shmust pass: it is the single owner of the lint definition (the shellcheck file set, config, and pinned shellcheck version), and both CI and the no-mistakes pre-push gate run it, so local and CI can never diverge. It pins one exact shellcheck version and refuses to run under any other; print it withbin/fm-lint.sh --required-versionand install that build locally. - Changes to harness adapters (detection in
bin/fm-harness.sh, launch and hook mechanics inbin/fm-spawn.sh, busy signatures inbin/fm-watch.shandbin/fm-tmux-lib.sh, cleanup inbin/fm-teardown.sh, and facts in.agents/skills/harness-adapters/SKILL.md) must be verified empirically against the real harness, never written from documentation alone. - Changes to runtime session backends (
bin/fm-backend.sh,bin/backends/, and the scripts that dispatch through them) need empirical adapter notes in the relevant backend guide:docs/tmux-backend.md,docs/herdr-backend.md,docs/zellij-backend.md,docs/orca-backend.md,docs/cmux-backend.md, ordocs/codex-app-backend.mdfor blocked Codex App transport work. - In Markdown, put each full sentence on its own line.
README.mdstays a concise overview plus pointers: it never carries a wall of inline detail. Route detail to the most specificdocs/file (architecture, configuration, or a backend guide) and link to it instead.
Tracked changes to firstmate itself - AGENTS.md, README.md, CONTRIBUTING.md, .tasks.toml, .github/workflows/, bin/, .agents/skills/, and skills/ - ship through the no-mistakes pipeline on a feature branch and require an explicit merge approval.
Before making any such change, load the agent-only firstmate-coding-guidelines skill (.agents/skills/firstmate-coding-guidelines/SKILL.md).
It has the knowledge-placement rules that keep AGENTS.md from regrowing after each diet pass.
There is no reliable way for bin/fm-brief.sh's scaffold to detect that a task's repo is firstmate itself, so firstmate adds this skill's load line to firstmate-repo briefs by hand.
A crewmate picking up such a brief should load the skill even if the brief predates this instruction.
When supervising live crewmates, keep firstmate's own long validation or build commands in the background so watcher wakes can still be handled.
Crewmate validation follows the installed no-mistakes version's SKILL.md and live axi help instead of duplicating gate mechanics in firstmate docs.
Firstmate's wrapper still matters: ask-user findings route to the captain through firstmate, and crewmates avoid --yes because it silently resolves captain-owned decisions without escalation.
Local .no-mistakes/ state and test evidence stay out of this repo; .no-mistakes.yaml keeps evidence in a temp directory and pins the gate's lint and portable behavior commands to the Linux CI jobs, while .github/workflows/ci.yml owns additional platform-specific compatibility lanes.
That is firstmate-specific; do not commit .no-mistakes/evidence/ here even when another no-mistakes-managed target project keeps committed PR evidence.
Check and test the toolbelt before pushing:
for script in bin/*.sh bin/backends/*.sh; do bash -n "$script"; done # syntax-check the toolbelt
bin/fm-lint.sh # lint the toolbelt and behavior tests; the single owner CI and the no-mistakes gate both run
for test_script in tests/*.test.sh; do bash "$test_script"; done # behavior tests, matching CI and no-mistakes commands.test
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ]
[ "$(readlink .claude/skills)" = "../.agents/skills" ]
tmp=$(mktemp -d) && printf 'done: smoke\n' > "$tmp/smoke.status" && FM_STATE_OVERRIDE="$tmp" FM_SIGNAL_GRACE=1 FM_POLL=1 FM_HEARTBEAT=999999 bin/fm-watch-arm.sh # watcher re-arm smoke test (prints arm status, then an actionable signal)Discover tests by listing tests/*.test.sh: each is a self-contained bash script named <subject>.test.sh, and its header comment describes what it covers, so run one directly to focus on a subject.
Tests that need a real optional backend or an explicit opt-in (real herdr/zellij/cmux smoke tests, the live Pi regression) skip themselves and print the tool or environment gate needed to enable them, so the run-all loop above is always safe.
Open an issue, or talk to me on Discord.