OpenSource-Hub

firstmate

프레임워크

kunchenguid/firstmate

단일 진입점으로 멀티 에이전트 협업을 관리하는 에이전트 배포판.

개요

firstmate는 하나의 메인 코딩 에이전트가 자율 협업 에이전트 그룹을 통합적으로 스케줄링할 수 있게 해주는 에이전트 배포판입니다. 독립적인 git worktree, tmux 세션 시각화, 재시작 후에도 유지되는 상태 관리를 제공하며 Claude Code, Grok, Pi 등 다양한 터미널 에이전트를 지원합니다.

README 미리보기

firstmate\n\n  \n  \n  \n\n\nTalk to one agent. Ship with a crew.\n\n\n  \n\n\n## What it is\n\nYou can run one coding agent easily.\nBut 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.\n\nfirstmate flips the model.\nYou talk to a single agent - the first mate - and it runs the crew for you: spawning autonomous agents in a visible session backend, giving each a clean git worktree, supervising them to completion, and handing you finished PRs, approved local merges, or standalone investigation reports.\nFor larger fleets, you can opt in to persistent secondmates: second mates that are still ordinary direct reports, but run from their own isolated firstmate homes on this machine or another SSH-reachable host.\n\nfirstmate is not a model, not a harness, not a skill, not an MCP server, and not a CLI.\nfirstmate is an agent distro for running a crew of agents.\nAn agent distro is a portable directory of instructions, skills, tooling, policies, and state conventions that turns a general-purpose agent into a specialized one.\nThere is no app to install: the cloned repo is the distro - `AGENTS.md`, bundled firstmate skills, and helper scripts that any terminal coding agent can follow.\nLaunching a supported harness inside it instantiates your first mate - and makes you the captain.\n\n## Features\n\n- **One liaison** - you talk only to the first mate; it dispatches, supervises, escalates only real decisions, and reports plain outcomes.\n- **A visible crew** - every crewmate works in its own tmux window, experimental herdr/zellij tab, cmux workspace, or Orca terminal you can watch or type into; the first mate reconciles.\n- **Disposable worktrees** - each task runs in a clean [treehouse](https://github.com/kunchenguid/treehouse) git worktree, or an Orca-managed worktree when `backend=orca`, so par

FAQ (5)

문제 해결
두 번째 Linux 또는 macOS 사용자가 fm-teardown을 실행할 때 'herdr session presentation lock could not be resolved' 오류를 해결하는 방법

이 오류는 Firstmate가 머신 전역 디렉터리 /tmp/firstmate-herdr-presentation을 사용하고, 해당 디렉터리가 현재 UID 소유에 모드 700이어야 하며, presentation이 비활성화된 경우에도 fm-teardown.sh가 이 락을 확인하기 때문에 발생합니다. --force로도 이를 우회할 수 없습니다. 즉시 적용 가능한 해결 방법: 활성화된 Herdr presentation 세션이 없을 때 디렉터리 소유자가 rm -rf /tmp/firstmate-herdr-presentation으로 디렉터리를 제거한 다음, 차단된 사용자로 즉시 bin/fm-teardown.sh <task>를 다시 실행하세요. 이후 디렉터리를 다시 제거해야 할 수도 있습니다. 또는 sudo chown <blocked-user>:<blocked-group> /tmp/firstmate-herdr-presentation으로 한 번 소유권을 넘기는 방법도 있습니다. 공유 호스트에서 반복되는 충돌을 방지하려면 프라이머리에서 config/backend를 tmux로 설정하여 원격 홈이 이를 상속받도록 하거나, /tmp/firstmate-herdr-presentation-$UID 또는 $XDG_RUNTIME_DIR/firstmate-herdr-presentation과 같은 계정별 네임스페이스를 적용/패치하세요. 이 문제는 Firstmate 8b10b61e와 Herdr 0.7.4에서 관찰되었으며, 관련 수정 사항은 PR #2730, #2530, #5804에서 추적되고 있습니다.

원본 Issue #4716
문제 해결
간헐적인 fm-watcher-lock stale-steal 실패를 어떻게 해결하나요: 'expected exactly one stale-lock stealer, got 0' 및 'reap race hook never fired'?

이는 락 구현 버그가 아니라 테스트 픽스처 경합 상태입니다. tests/fm-watcher-lock.test.sh를 패치하세요:

1. test_lock_stale_steal_single_winner_under_concurrency에서, 40번의 일회성 fm_lock_try_acquire 호출이 승자를 만들어 낸다고 가정하지 마세요. 부하 상황에서는 모든 논블로킹 경쟁자가 점유 중인 .steal 뮤텍스를 보고 종료될 수 있습니다. 39개의 논블로킹 경쟁자와 하나의 fm_lock_acquire_wait 경쟁자를 사용하세요. 대기 중인 경쟁자가 FIFO를 통해 자신의 승리를 보고하게 한 다음, 정확히 하나의 FIFO 승자가 있음을 단언하세요.
2. test_lock_steal_reap_cannot_remove_successor에서, OS가 해당 PID를 재사용할 수 있으므로 픽스처 프로세스를 죽이고 그 PID를 락에 남겨두지 마세요. 전용 프로세스를 생성하고, 종료되었는지 확인한 다음, 종료가 확인된 그 PID를 락 픽스처에 기록하여 reap 경로가 반드시 실행되도록 하세요.

락 구현 자체는 변경할 필요가 없습니다. 이 안정화는 PR "test: stabilize watcher lock race fixtures"에서 다뤄지며, 다운스트림 증명은 ironerumi/firstmate#69에서 확인할 수 있습니다.

원본 Issue #6455
문제 해결
왜 fm-send.sh --help가 사용법을 출력하는 대신 "target '--help' is not resolvable" 오류로 실패하나요?

bin/fm-send.sh에는 -h|--help 핸들러가 없습니다: FM_HOME 검사가 먼저 실행되고(약 231행) 옵션 파싱(약 486행)은 --resolve-key / --fire-and-forget만 처리하므로, --help가 타겟 해석 단계로 전달되어 fm---help를 사용하라는 오해를 일으키는 제안과 함께 실패합니다. 수정: 스크립트 헤더의 Usage: 블록을 출력한 후 FM_HOME 검사와 타겟 해석 전에 0으로 종료하는 초기 -h|--help 분기를 추가하는 PR #6402가 포함된 버전으로 업데이트하십시오. 영향을 받는 버전에서의 우회 방법: 헤더가 steering, --resolve-key 및 pending-reply 계약의 문서화된 출처이므로, sed -n '1,40p' bin/fm-send.sh와 같이 헤더 주석에서 사용법 계약을 직접 읽으십시오.

원본 Issue #6398
문제 해결
대상 세션이 유효하지 않거나 비활성 상태일 때 Herdr composer probe로 인해 Bash 파이프라인이 멈추는(hang) 문제를 어떻게 해결하나요?

issue #6915(fix(bin): keep herdr composer probes observable-only without autostarting server)에 대한 수정이 포함된 빌드로 업그레이드하세요. 이 멈춤 현상은 fm_backend_composer_state가 herdr server를 시작하는 fm_backend_herdr_target_ready를 호출하기 때문에 발생합니다. 백그라운드 헬퍼가 파이프 디스크립터 10을 상속받으므로 ... | head -20과 같은 명령은 EOF를 받지 못합니다.

bin/backends/herdr.sh에 코드 수정을 적용하세요:
1. fm_backend_composer_state에서 준비 상태(readiness)/자동 시작 확인을 수동적인 observable/status 확인으로 교체하세요.
2. 세션이 비활성 상태이거나 존재하지 않거나, 대상이 wPW:p2와 같은 bare pane ID인 경우 fm_backend_herdr_server_ensure를 호출하지 않고 즉시 unknown을 반환하세요.
3. 심층 방어(defense in depth)를 위해 백그라운드 서버 프로세스를 상속된 디스크립터에서 분리하세요. 예:
( exec herdr server --session "$session" ) </dev/null >/dev/null 2>&1 10>&- &

즉각적인 해결 방법은 이미 실행 중인 세션의 대상만 프로브하고, 신뢰할 수 없는 대상에 대해서는 프로브를 파이프로 연결하지 않으며, timeout으로 감싸서 실행하고, 다음 명령으로 rogue 서버를 제거하는 것입니다:
pkill -f 'herdr server --session nonexistent-session'

원본 Issue #6915
문제 해결
Claude Code 백그라운드 세션에서 /clear를 실행한 후 "another live firstmate session holds the lock" 오류를 해결하는 방법은?

Claude Code 백그라운드 세션(claude --bg-pty-host)은 /clear 이후 자신의 fleet lock을 외부 소유로 잘못 감지하여 읽기 전용 상태가 되고 모든 fleet 변경 작업(drain, spawn, steer, merge)이 차단될 수 있습니다. 원인: /clear는 프로세스 pid(CLAUDE_PID)가 변경되지 않은 상태에서 새로운 CLAUDE_CODE_SESSION_ID를 발급하므로, state/.lock의 1행이 모델 루프 pid 대신 오래된 비조상 pid(예: 터미널 프론트엔드 pid)를 가지고 있으면 소유권 검사가 실패합니다.

즉각적인 해결 방법: 오래된 lock을 제거하고 다시 획득합니다:
rm state/.lock && bin/fm-lock.sh
다시 획득한 후에는 1행이 모델 루프 pid가 되어 세션이 정상적으로 동작합니다.

영구적인 수정: bin/fm-lock.sh의 confirm_own_lock을 패치하여, 신뢰할 수 있는 동일 세션 ID 경로를 통해 소유권이 확인되고 CLAUDE_PID가 기록된 활성 pid와 다를 경우 1행을 CLAUDE_PID(세션의 앵커)로 다시 쓰도록 합니다. 이렇게 하면 조상 멤버십 검사가 세션 ID 변경과 관계없이 통과하므로 /clear 이후에도 lock이 유효하게 유지됩니다. 선택적으로, 동일한 CLAUDE_PID에서 발생한 source: "clear"를 가진 SessionStart 훅 이벤트도 동일 세션으로 처리할 수 있습니다.

예방: state/.lock의 1행이 항상 생성한 프론트엔드 pid가 아닌 세션 자신의 CLAUDE_PID로 갱신되도록 합니다. 오래된 비조상 pid는 프론트엔드 프로세스가 살아 있는 동안 무기한 남아 있기 때문입니다.

원본 Issue #6820