엉클 밥과 에이전트 Part 2: swarm-forge
이 글은 Claude Opus 5.5 를 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.
./swarm 을 실행하자 터미널에 “Disciplined agents build better software” 라는 문구가 찍히고, 몇 초 뒤 “SwarmForge is ready.” 가 떴습니다. 대시보드 주소도 하나 나왔습니다. 그런데 tmux 세션을 열어 보니 두 에이전트 모두 아무 일도 하지 않고 있었습니다. 새 폴더에서 처음 뜬 Claude Code 가 똑같은 질문을 띄워 두고 기다리고 있었기 때문입니다. “Quick safety check: Is this a project you created or one you trust?” 커서는 기본값인 “No, exit” 에 놓여 있었습니다.
권한 확인을 전부 건너뛰도록 띄운 에이전트가 폴더를 믿어도 되느냐는 질문 앞에서 멈춘 장면이, 이 도구의 성격을 잘 보여 줬습니다. 1편에서 본 엉클 밥의 역할 분담을 그대로 코드로 옮긴 도구인데, 사람이 옆에서 지켜보며 쓰는 걸 전제로 만들어져 있습니다. 이번 편은 swarm-forge 를 코드로 읽고, Go 예제로 한 번 돌려 보고, 팀에 들일 만한지를 따져 봅니다. 엉클 밥 자신은 10월 16일에 이 하네스에서 한발 물러섰지만, 그가 반년 동안 다듬은 생각이 가장 구체적으로 남아 있는 곳이 여기라 볼 가치는 충분했습니다.
무엇을 하는 도구인가#
저장소 설명은 “A simple tool for coordinating several AI agents.” 한 줄입니다. 4월 17일에 GitHub 에 올라왔고, 첫 커밋은 그보다 앞선 3월 31일 Justin Martin 이 쓴 초안입니다. tmux 화면 네 개로 에이전트를 돌리던 초안을 4월 중순부터 엉클 밥이 이어받았고, 지금의 런타임은 6월에 Babashka(Clojure 스크립트 런타임)로 옮긴 것입니다. 셸 스크립트 23개는 모두 zsh 입니다. 10월 24일 기준으로 별 4,037개, 모든 브랜치를 합친 커밋 723개 가운데 716개가 그의 커밋입니다.
설치하면 두 종류의 물건이 나옵니다. 이미 있는 저장소에 덧씌우는 팩(pack)과, 빈 디렉터리에 깔아 여러 프로젝트를 관리하는 포지(forge)입니다. 팩은 역할 수에 따라 셋입니다. two-pack 은 구현 담당(coder)과 정리 담당(cleaner), four-pack 은 명세·구현·리팩터링·구조, six-pack 은 1편에서 본 여섯 역할입니다. 필요한 건 zsh, git, tmux, Babashka, 그리고 로그인된 에이전트 CLI 하나 이상(grok, codex, claude, copilot)입니다.
역할 배치는 swarmforge/swarmforge.conf 한 파일로 정합니다. 한 줄이 한 역할이고, 줄 순서가 곧 파이프라인 순서입니다.
window-invisible coder claude master
window-invisible cleaner claude cleaner batch back-one
역할마다 tmux 세션이 하나씩 뜨고, master 로 지정한 역할 하나만 사용자의 원래 체크아웃에서 일하고 나머지는 .worktrees/<이름> 의 git worktree 에서 일합니다. 기본 설정은 coder 를 grok, cleaner 를 codex 로 띄우는데, 저는 둘 다 claude 로 바꿨습니다.
일이 넘어가는 방식#
역할 사이에 오가는 건 메시지가 아니라 커밋입니다. coder 가 작업을 커밋하고 swarm_handoff.sh 에 헤더 네 줄(type, to, priority, task)만 적은 초안을 넘기면, 도우미 스크립트가 커밋 SHA 를 채우고 그 커밋이 정말 존재하는지, 비어 있지 않은지, 작업의 출발점에서 이어지는지 검사한 뒤 큐 파일로 내보냅니다. 처음 호출하면 일부러 AUDIT_REQUIRED 와 자기 점검 목록만 출력하고, 같은 요청을 한 번 더 해야 큐에 들어갑니다. 에이전트에게 한 번 더 돌아보게 만드는 장치입니다.
큐는 각 worktree 의 .swarmforge/handoffs/ 아래 outbox·inbox·completed 같은 디렉터리이고, 1초마다 도는 데몬이 파일을 받는 쪽 inbox 로 옮긴 다음 tmux 의 send-keys 로 그 에이전트 화면에 깨우는 문장을 타이핑해 넣습니다. 깨어난 에이전트는 ready_for_next.sh 로 받은 커밋을 git merge 하고 자기 일을 시작합니다. 명세 담당이 있는 four-pack·six-pack 에서는 명세 커밋이 사람의 승인을 기다리고, two-pack 에는 그런 관문이 없습니다.
flowchart TD
H[사람: 대시보드에서 작업 등록] --> S[specifier: Gherkin 과 QA 절차]
S --> A{사람 승인}
A --> C[coder: TDD 로 구현]
C --> CL[cleaner: CRAP 과 중복 정리]
CL --> AR[architect: 모듈 구조]
AR --> HD[hardener: 뮤테이션 테스트]
HD --> Q[QA: UI 수준 확인]
Q --> D[완료]
style A fill:#FFD700,color:#000000
style H fill:#87CEEB,color:#000000
style D fill:#90EE90,color:#000000
six-pack 의 흐름이 이렇고, two-pack 은 이 가운데 coder 와 cleaner 만 남은 모양입니다. 사람이 쓰는 화면은 localhost 의 임의 포트에 뜨는 웹 대시보드입니다. 작업 카드를 만들고, 역할별 레인으로 카드가 옮겨 가는 걸 보고, 승인과 질문에 답하고, 각 에이전트의 tmux 화면을 들여다볼 수 있습니다.
헌법과 역할 프롬프트#
swarm-forge 는 에이전트에게 주는 지시를 “constitution” 이라고 부릅니다. 모든 팩이 공유하는 조문이 셋입니다. 언어별 도구와 검증 규칙을 담은 engineering.prompt 가 810단어, worktree 와 커밋 규칙의 workflow.prompt 가 235단어, 넘겨주기 절차의 handoffs.prompt 가 733단어입니다. 여기에 팩마다 project.prompt 와 역할 프롬프트가 붙습니다. two-pack 의 coder 프롬프트는 221단어, cleaner 는 433단어라, 에이전트 하나가 읽는 지시는 모두 합쳐 2,200~2,400단어쯤 됩니다. 1편에서 본 “긴 규칙 문서는 무시된다” 는 이야기와 견주면 결코 짧지 않습니다. 다만 대부분이 넘겨주기 절차와 도구 사용법 같은 절차서이고, 코드 스타일에 대한 조언은 적습니다.
역할 프롬프트는 늘 같은 틀을 씁니다. 무엇을 소유하는가(Owns), 무엇을 소유하지 않는가(Does Not Own), 일이 끝나면 누구에게 넘기는가(Handoff). coder 는 TDD 로 구현하되 CRAP·중복·뮤테이션은 건드리지 않고, cleaner 는 새 동작을 넣지 않되 커버리지·CRAP(10 이하)·중복·구조·뮤테이션을 차례로 정리합니다. 역할 사이의 경계를 문장으로 그어 두는 이 형식은 사람 팀의 업무 분장표로 써도 될 만큼 깔끔합니다.
흥미로운 건 무엇이 코드로 강제되고 무엇이 문장으로만 요구되는지입니다. 넘겨주기의 형식 검사, 두 번 확인하는 감사 관문, 명세 승인 대기, 커밋 메시지 끝에 역할 이름을 붙이는 git 훅, 뮤테이션 도구의 worker 수 같은 건 스크립트가 강제합니다. 반면 CRAP·중복·뮤테이션 도구를 실제로 돌리는지, 그 점수가 문턱을 넘는지는 프롬프트에 적혀 있을 뿐 어떤 스크립트도 확인하지 않습니다. 결정론적 도구를 강조해 온 그의 하네스에서 정작 품질 문턱은 에이전트의 성실함에 맡겨져 있는 셈입니다. 저장소의 README 에는 이런 원칙도 있습니다. “Do not pin prompt prose with automated tests.” 프롬프트 문장을 테스트로 고정하지 말고 런타임 동작을 테스트하라는 뜻인데, 실제로 테스트 246개는 명령 문자열과 파일 상태만 검사합니다.
Go 예제로 돌려 본 결과#
3편의 실험과 같은 과제를 줬습니다. Emily Bache 가 관리하는 리팩터링 카타 Gilded Rose 의 Go 판에, 요구사항 문서를 읽고 Conjured 아이템을 추가하라는 요청입니다. 원본 UpdateQuality 는 순환 복잡도 19 의 중첩 if 덩어리입니다. two-pack 을 설치하고, 두 역할을 claude(Opus 5.5)로 바꾸고, project.prompt 의 “Project language: Babashka.” 를 Go 로 고친 뒤 대시보드 API 로 작업을 등록했습니다.
신뢰 확인 창을 넘긴 뒤로는 빨랐습니다. 09:31 에 작업을 넣자 coder 가 기존 동작을 고정하는 테스트부터 쓰고 1분 남짓 뒤 “Add Conjured item support” 를 커밋해 넘겼습니다. cleaner 는 Go 용 CRAP·중복·뮤테이션 도구(crap4go, dry4go, mutate4go)를 GitHub 에서 받아 worktree 안의 tmp/bin 에 설치하고, CRAP 19 짜리 함수를 아이템 종류별 작은 함수로 나눈 커밋을 돌려보냈습니다. 09:36 에 카드가 Done 으로 옮겨 갔습니다. 도중에 cleaner 가 같은 커밋으로 넘겨주기를 두 번 보냈다가 스스로 중복을 확인하고 넘어가는 장면이 한 번 있었습니다. 커밋 메시지 끝에는 훅이 붙인 “By coder.” “By cleaner.” 가 남았습니다.
결과를 같은 과제의 단일 에이전트 실행과 나란히 놓으면 이렇습니다. 단일 에이전트는 3편의 실험 가운데 짧은 규칙과 Stop 훅 게이트를 쓴 Claude Code 실행입니다. 품질 지표는 두 결과물을 같은 측정 스크립트로 잰 값이고, 숨은 인수 테스트는 제가 따로 만든 참조 구현과 30일치 상태를 비교하는 테스트입니다.
| swarm-forge two-pack | 단일 에이전트 + 게이트 | |
|---|---|---|
| 숨은 인수 테스트 | 통과 | 통과 |
| 걸린 시간 | 약 6분 (신뢰 확인 대기 포함) | 약 2분 |
| 모델 요청 / 입력 토큰 | 62회 / 약 399만 | 14회 / 약 49만 |
| 정가 환산 | 약 2.3달러 | 약 0.57달러 |
| 함수 수 / 제품 코드 줄 수 | 7 / 69 | 7 / 71 |
| 최대 순환 복잡도 / 최대 CRAP | 4 / 4 | 5 / 5 |
| 뮤테이션 효율 (gremlins) | 88% | 100% |
과제가 작긴 하지만 결과는 분명했습니다. 같은 모델 둘이 역할을 나눠 일한 결과물은 혼자 일한 결과물과 품질이 거의 같았고, 토큰은 여덟 배쯤 들었습니다. 역할마다 2천 단어 넘는 헌법을 새로 읽고, 도구를 설치하고, 넘겨주기 절차를 밟는 비용입니다. 엉클 밥이 7화에서 “A single disciplined agent” 를 말한 배경이 이런 것 아닐까 싶었습니다. 모델이 혼자서도 이 정도를 해내면 역할을 나누는 데 드는 비용이 이득보다 커집니다.
팀에 들일 수 있나#
현업 도입을 기준으로 따져 보면 지금의 swarm-forge 는 막히는 데가 많습니다.
| 기준 | 2026년 10월 24일 현재 |
|---|---|
| 라이선스 | 9개 브랜치 어디에도 LICENSE 파일이 없고, 라이선스를 묻는 이슈 #64·#70 에 답이 없음 |
| 권한과 보안 | 8월 21일 이후 모든 백엔드를 권한 확인 없이 실행(claude 는 bypassPermissions, codex 는 --yolo)하고 테스트로 고정. codex 백엔드를 쓰면 사용자 홈의 .codex/config.toml 에 worktree 마다 trusted 항목을 써 넣음. 대시보드는 인증 없는 localhost 웹 서버. 검사 도구는 실행할 때마다 GitHub 기본 브랜치에서 받음 |
| 플랫폼 | macOS 가 1순위, Linux 는 일부 기능 저하, Windows 는 WSL 에서만 동작. 셸 스크립트가 모두 zsh |
| 유지보수 | 마지막 커밋 9월 7일. PR 49개 가운데 머지 2개, 기여는 본인이 main 에서 다시 구현하고 닫는 방식. 6월 17일 이후 이슈 댓글 없음 |
| 팀 작업 흐름 | push·PR·CI 연동 없음. master 역할이 사용자의 현재 브랜치에 직접 커밋. 커밋 작성자 대신 역할 이름이 남음 |
| 비용 | 팩에 따라 동시 세션 2~6개, 포지는 프로젝트마다 더 늘어남 |
라이선스가 없다는 건 저작권자가 모든 권리를 갖는다는 뜻이라, 회사 저장소에 들여와 쓰거나 고치는 것 자체가 법무 검토 대상이 됩니다(제 해석이고 법률 자문은 아닙니다). 보안 쪽은 더 직접적입니다. 권한 확인 없이 도는 에이전트 여러 개가 개발자의 자격 증명을 그대로 가진 채 사용자의 체크아웃에서 일하고, 그 에이전트들에게 키 입력을 넣을 수 있는 웹 서버가 인증 없이 떠 있습니다. 개인 실험 환경이 아니라면 컨테이너나 별도 계정 안에 가두지 않고는 쓰기 어렵습니다.
그러니 코드를 들이는 건 권하기 어렵지만, 아이디어는 가져올 게 많습니다. 역할마다 Owns 와 Does Not Own 을 적는 프롬프트 형식, 일을 말이 아니라 커밋으로 넘기는 방식, 도우미 스크립트만 고칠 수 있는 큐, 한 번 더 돌아보게 만드는 감사 관문, 도구 옵션을 프롬프트가 아니라 코드에서 강제하는 습관. 그리고 명세가 확정되는 지점에서만 사람의 승인을 받는다는 설계까지 그렇습니다. 이 중 상당수는 Claude Code 나 Codex 하나만으로도 흉내 낼 수 있고, 그게 3편의 주제입니다.
자료에 대해#
구조와 동작은 10월 24일에 받은 저장소 클론(main 은 9월 4일 f4f5fbc)의 코드와 README 로 확인했고, 커밋·이슈·PR 수는 GitHub API 기준입니다. 실행은 제 노트북(macOS)에서 two-pack 을 claude 백엔드 둘로 바꿔 한 번 돌린 것이고, 신뢰 확인 창은 제가 만든 실험용 폴더라 직접 “Yes” 를 골라 넘겼습니다. 토큰 수는 두 Claude Code 세션 기록을 메시지 단위로 합친 값이고, 정가 환산은 Opus 5.5 의 정가(입력 100만 토큰당 4달러, 캐시 읽기 0.2달러, 1시간 캐시 쓰기 8달러, 출력 20달러)로 계산한 어림값입니다. 실제로는 구독 한도에서 차감됐습니다. 한 번씩만 돌린 결과라 반복하면 숫자가 달라질 수 있고, 과제가 작아 역할 분담의 이점이 드러나기 어려운 조건이라는 점도 감안해야 합니다. 대시보드가 인증 없이 떠 있다는 건 코드로 확인했지만, 외부 웹 페이지에서 실제로 요청을 보낼 수 있는지는 시험하지 않았습니다.
| 편 | 주제 |
|---|---|
| Part 1 | 코드를 읽지 않는 이유 |
| Part 2 (이 글) | swarm-forge |
| Part 3 | 규칙 파일 대신 게이트 |
References#
최신 자료 (2026)
- Robert C. Martin, unclebob/swarm-forge README·
swarmforge/·test/, mainf4f5fbc(2026-09-04), two-pack·four-pack·six-pack 브랜치 (조회 2026-10-24) [본인 저장소] - GitHub, swarm-forge 이슈·PR 목록 (#64, #70 등, 조회 2026-10-24) [저장소]
- Justin Martin · Robert C. Martin, 「Agentic Discipline 6: Swarm Forge Demonstration」 · 「Agentic Discipline 7」, cleancoders.com (7화 2026-10-16) [본인 영상 소개]
- 직접 실행: swarm-forge two-pack(claude 백엔드 2개)과 Claude Code 단일 실행, Gilded Rose Go, 측정 스크립트(gocyclo 0.6.0, gremlins 0.6.0, go test 커버리지) (2026-10-24)
비교·배경 자료
- Emily Bache, GildedRose-Refactoring-Kata Go 판 (MIT) [저장소]