
worktree의 '바톤터치(Handoff)' 문제를 자체 skill · Codex · Augment로 비교하며 반성하다
요약
Claude Code의 worktree 활용 시 발생하는 작업 문맥(context) 인계 문제를 Codex app의 Handoff 기능과 Augment의 아키텍처를 통해 분석하고 반성합니다. 단순한 디렉토리 분리를 넘어, 작업 세션을 다른 터미널이나 환경으로 어떻게 효율적으로 이송할 것인가에 대한 기술적 통찰을 다룹니다.
핵심 포인트
- worktree 활용의 핵심 난관은 작업 문맥의 '바톤터치(Handoff)' 문제임
- Codex app의 Handoff는 Local과 Worktree 간 작업 문맥을 자동 이송함
- 단순한 환경 분리를 넘어 작업의 지속성을 유지하는 설계가 중요함
- 문맥을 다듬는 과정(grill-with-docs)은 이송할 내용을 날카롭게 만드는 공정임
TL;DR
- 지난번, Claude Code의
git worktree+ skill + subagent를 사용하여 병행 개발 플로우를 직접 구축함 - 하지만 그 후 **Codex app의 「Handoff」**와 **Augment의 3층 아키텍처 (three-layer architecture)**를 읽고, 내가 원했던 「1개 터미널 의존성으로부터의 해방」을 제품 측에서 이미 정면으로 해결하고 있었다는 사실을 깨달음 - worktree의 진짜 난관은 분리 그 자체가 아니라 「작업을 어떻게 다음 세션/에이전트에게 넘길 것인가 (바톤터치)」였음 - 그리고 Matt Pocock의grill-with-docs는 '정리하는 것'이 아니라 질문하여 『이송할 문맥의 내용』을 날카롭게 다듬는 공정이었음 (당초 이해가 틀렸었음) - 동일한 과제에 대한 여러 접근 방식(자체 skill / Codex Handoff / Augment Living Spec / grill-with-docs)을 나란히 놓고 정리함
배경: 자체적으로 구축하고 만족하고 있었다
지난번(Claude Code의 worktree + skills + subagent로 팀 개발 플로우를 구축한 이야기), Claude Code를 사용하여 다음과 같은 구조를 구축했다.
사용자
│ /worktree 1234
▼
...
skill이 worktree를 생성하여 subagent를 투입하고, 메인 Claude는 다른 대화를 계속할 수 있다. 「Claude가 checkout 하여 사용자의 작업을 망가뜨리는」 문제는 원리적으로 사라지며, 병행 작업도 가능하다. 이것으로 완성되었다고 생각했다.
하지만 운용해 보니 걸리는 점이 남아 있었다.
subagent가 완주하지 못했을 때, 그 작업을 다른 세션이나 다른 터미널에서 어떻게 인계할 것인가?
subagent는 메인 컨텍스트(context) 내에서만 존재한다. 메인 대화를 닫으면, worktree라는 디렉토리는 남아 있어도 「어디까지 무엇을 하고 있었는지」에 대한 문맥(context)은 상실된다. 결국, 처음에 올린 skill을 실행했던 그 1개의 터미널에 매달려 있게 되었다.
이 「1개 터미널 의존성」을 어떻게 벗어날 것인가가 정말로 풀고 싶었던 문제였다. 그리고 그것을 Codex app과 Augment는 이미 제품으로서 해결하고 있었다. 이것이 이번 반성의 출발점이다.
반성 ①: Codex app의 「Handoff」는 Git의 제약을 정면으로 해결하고 있었다
Codex app에는 Handoff라는 기능이 있다 (공식 문서).
이것이 해결하고 있는 것은 Git의 다음과 같은 근본적인 제약이다.
동일한 브랜치는 동시에 한 곳에서만 checkout 할 수 있다.
내가 「메인으로 작업하면서 worktree에서도 동일한 작업을 계속하고 싶다」거나 「다른 단말로 가져가고 싶다」고 생각할 때 반드시 부딪히는 벽이 이것이었다. Codex의 Handoff는 스레드(작업 문맥)를 Local 체크아웃 ⇄ Worktree 체크아웃 사이에서 이송함으로써, 이 벽을 자동화된 Git 조작으로서 넘어선다.
설계 판단에서 참고가 된 점:
| 메커니즘 | 내용 |
|---|---|
| detached HEAD로 시작 | worktree는 기본적으로 detached HEAD 상태임. 브랜치를 더럽히지 않음 |
| 스레드 지속성 | Local ⇄ Worktree를 이동해도 작업 문맥(스레드)이 유지됨 |
| 자동 클린업 | 최근 15개의 worktree를 유지(설정 가능), 그 이전은 자동 청소 |
| 스냅샷 복원 | 삭제한 worktree의 작업도 저장되어 복원 가능 |
.gitignore 존중 | Handoff 시 .gitignore 대상 파일은 이동하지 않음 |
자체 skill에서는 worktree를 「만드는 것」만 있었고 「옮기는」 개념이 없었다. Handoff는 작업의 소재지 그 자체를 움직일 수 있게 만들어 두었으며, 이것이 「1개 터미널 의존성으로부터의 해방」의 정체였다. 바톤터치란 에이전트를 나열하는 것이 아니라 작업 문맥에 휴대 가능한 실체를 부여하는 것이었던 셈이다.
반성 ②: Augment의 3층 + Living Spec은 「정리해서 전달하기」를 상주화하고 있었다
또 하나 간과하고 있었던 것이 Augment의 구성(공식 가이드)이다.
Augment는 Spaces라는 단위로 「1 태스크 = 1 브랜치 (branch) = 1 worktree」를 매핑하며, 여러 specialist 에이전트 (agent)를 격리된 디렉토리에서 병렬 실행한다. .git의 오브젝트 스토어 (object store)는 공유하면서도, 파일 시스템 (file system)은 완전히 분리한다.
문제 해결 방식이 명쾌했다:
| 과제 | Augment의 해결 방식 |
|---|---|
| 파일 충돌 | 충돌을 실행 시점이 아닌 merge (병합) 시점으로 미루어, 표준 git 도구로 검출하게 함 |
| 컨텍스트 오염 (context contamination) | 각 에이전트가 자신만의 작업 디렉토리와 index를 가져서, 서로의 전제를 깨뜨리지 않음 |
| 락 경합 (lock contention) | worktree마다 index 파일이 분리되어, .git/index.lock을 차지하기 위한 다툼이 발생하지 않음 |
그리고 핵심은 **3층 아키텍처 (three-layer architecture)**와 Living Spec이다.
Coordinator (계획 수립)
├─ Specialist A ─┐
├─ Specialist B ─┼─ 병렬 구현 (각 worktree)
...
Living Spec은 모든 에이전트가 참조하는 자기 업데이트형 공유 명세서다. 이것을 보았을 때, 내가 다른 경로로 원했던 것과 동일하다는 것을 깨달았다. Coordinator가 계획을 세우고, 그 문맥 (context)을 Living Spec에 기록하며, Specialist가 그것을 보고 병렬 구현한다——문맥이 한 장의 살아있는 문서로 집약되어, 모두가 그곳을 참조하는 구조다.
반성③: grill-with-docs는 「바톤터치의 내용물」을 만드는 공정이었다
여기까지 오고 나서야, 내가 당초 이미지로 그렸던 「grill-with-docs로 정리한 뒤 handoff로 바톤터치한다」라는 흐름을 근본적으로 오해하고 있었다는 사실을 깨달았다.
Matt Pocock의 grill-with-docs (SKILL.md)는 「정리하는」 기술이 아니다. 기존의 도메인 모델 (domain model)에 대해 계획을 가차 없이 추궁하는 기술이다.
- 질문을 하나씩 던지고, 사용자의 답변을 기다린 후 다음으로 진행한다 (코드로 답이 나오는 것은 코드를 탐색하여 확인한다)
- 모호하거나 다의적인 용어가 나오면, 정전적인 (canonical) 용어를 제안하며 다듬는다. "당신은 'account'라고 말했지만 Customer인가 User인가. 별개의 것이다"
- 글로서리 (glossary,
CONTEXT.md)와 모순되는 용어 사용은 즉시 지적한다 - 코드와 어긋나는 주장이 나오면 모순을 겉으로 드러낸다
- 그리고 결정이 굳어지면 그 자리에서 수행한다
CONTEXT.md(용어집)와 ADR을 업데이트한다
중요한 것은 출력물이다. CONTEXT.md는 구현 상세를 일절 포함하지 않는 용어집 역할에 철저히 집중한다. ADR은 「되돌리기 어렵다·문맥 없이는 당혹스럽다·진정한 트레이드오프 (trade-off)가 존재한다」라는 3가지 조건이 갖춰졌을 때만 신중하게 결정한다.
즉, grill-with-docs는 「대화를 정리하는 것」이 아니라, 추궁하면서 『이동 가능한 문맥의 실체』를 결정화(crystallization)시키는 공정이었다. 그리고 지금까지의 논의를 바탕으로 하면 그 위치가 명확해진다.
- grill-with-docs가
CONTEXT.md/ ADR이라는 문맥의 실체를 만든다 - handoff가 그것을 압축하여 다음 에이전트에게 전달한다
- Augment의 Living Spec은 이
CONTEXT.md를 모든 에이전트가 상주하며 참조하는 형태로 만든 버전이다
나는 「정리해서 전달한다」라고 막연하게 파악하고 있었지만, 올바른 방식은 「추궁하여 문맥을 결정화시킨 뒤 전달한다」였다. 바톤터치의 질은 전달 방식이 아니라 전달하는 내용물을 얼마나 날카롭게 다듬었는가에 의해 결정된다——grill-with-docs는 바로 그 「내용물을 다듬기」 위한 공정이었던 것이다.
3가지 접근법을 나열하기
동일한 「worktree의 바톤터치 문제」에 대해, 3가지 계통의 해결 방식이 있다.
| 自전 skill + subagent | Codex Handoff | Augment 3층 + Living Spec | |
|---|---|---|---|
| 분리 (Separation) | git worktree를 skill로 생성 | detached HEAD의 worktree | Space = 1 태스크 1 worktree |
| 바톤터치(Handoff)의 실체 | (약한) 메인 컨텍스트 의존 | 스레드를 Local ⇄ Worktree로 이송 | Living Spec (공유 사양서) |
| 병렬성 (Parallelism) | subagent를 실행한 만큼 | 전경(Foreground) + 배경(Background) worktree | Specialist를 병렬 실행 |
| 검증 (Verification) | 각 subagent 내에서 pnpm test | (사용자 측) | 전담 Verifier 층 |
| 의존성 | 1 터미널 의존 | 벗어남 (작업을 이송할 수 있음) | 벗어남 (Spec이 문맥을 유지) |
| 문맥의 결정화 (Crystallization) | (없음) | (사용자 측) | Coordinator → Living Spec |
| 도입 비용 | 직접 작성할 필요 있음 | 제품 기능 | 제품 기능 |
포인트는, 자전 skill은 「분리」까지는 해결되었지만 「이송 (바톤터치)」이 약했다는 것이다. Codex는 이송 그 자체를, Augment는 이송의 내용(공유되는 문맥)을 각각 제품으로서 구현하고 있었다.
그리고 「이송의 내용」을 어떻게 만들지를 담당하는 것이, 제4의 계통인 Matt Pocock의 skill 군이다. grill-with-docs가 문맥을 결정화(CONTEXT.md / ADR)하고, handoff가 그것을 전달한다. 제품(Codex / Augment)이 「이송의 메커니즘」을 만들었다면, 이것은 「이송할 내용의 질」을 만드는 도구 세트가 된다. 양자는 경쟁 관계가 아니라 보완 관계다.
자전 플로우로 가져오기: 무엇을 추가할 것인가
제품으로 갈아타자는 이야기가 아니라, 자전 Claude Code 플로우에 「반성」을 반영한다면 추가해야 할 것은 두 가지다.
1. worktree에 「가지고 갈 수 있는 문맥」을 결합하기
subagent의 컨텍스트에만 맡기지 말고, worktree 안에 진행 상황을 기록해 둔다. 이것이 Codex Handoff / Augment Living Spec의 자전 버전이 된다.
# .worktrees/1234/HANDOFF.md (worktree 내에 배치)
## 태스크
Issue #1234 구현
...
worktree라는 디렉토리 자체는 터미널을 넘나들며 남는다. 그곳에 HANDOFF.md를 두면, 다른 세션이나 다른 터미널의 Claude가 cd .worktrees/1234 && cat HANDOFF.md를 통해 재개할 수 있다. 「1 터미널 의존」에서 벗어날 수 있다.
2. skill을 「재개 (Resume)」에 대응시키기
지금까지의 skill은 worktree를 「만드는」 것뿐이었다. 「기존 worktree를 집어서 이어서 하기」 입구를 추가한다.
# .claude/skills/worktree-resume.md
인수의 Issue 번호로부터 기존 worktree를 특정하고,
HANDOFF.md를 읽은 뒤 subagent에게 다음 작업을 위임한다.
...
3. grill-with-docs로 내용을 연마하기
착수 전에 HANDOFF.md를 두는 것만으로는, 쓰는 내용이 부실하면 바톤터치도 부실해진다. worktree를 생성하기 전에 grill-with-docs 방식으로 계획을 심문하여, 용어와 결정을 CONTEXT.md / ADR로서 결정화해 둔다. subagent는 그것을 참조하여 구현하고, HANDOFF.md에는 차이점(diff)만 적으면 된다. 문맥의 질을 상류에서 만들어 둘수록, 하류의 인수인계는 가벼워진다.
요약
| 학습 내용 | 상세 내용 |
|---|---|
| 진짜 난관 | worktree의 「분리」가 아니라 「바톤터치 (이송)」 |
| grill-with-docs의 역할 | 심문하여 CONTEXT.md / ADR에 문맥을 결정화 = 이송할 내용을 연마함 |
| 자전 플로우 반영 | 착수 전에 문맥을 결정화하고, worktree 내에 HANDOFF.md를 두며, skill에 「재개」 입구를 추가함 |
지난번에는 "스스로 구축할 수 있었다"는 사실에 만족하여, 제품 측에서는 이를 어떻게 해결하고 있는지 살펴보지 않았다. Codex의 Handoff와 Augment의 3개 계층을 읽으며, 바톤터치(Handoff)에는 『옮길 수 있는 문맥의 실체』가 필요하다는 당연한 핵심에 마침내 도달했다. 그리고 grill-with-docs를 다시 읽으며, 그 실체는 가만히 있는다고 해서 저절로 생겨나는 것이 아니라—집요하게 질문하며 갈고닦아야 비로소 문맥이 된다는 것을 깨달았다. worktree는 디렉터리로서 단말기에 남는다. 남은 것은, 갈고닦은 문맥을 그곳에 남기기만 하면 되는 것이었다.
참고
- Codex app — Worktrees & Handoff
- Augment — Git Worktrees for Parallel AI Agent Execution
- mattpocock/skills (grill-with-docs / handoff 등)
- Git worktree 공식 문서
이 기사는 Vottia의 제품 개발 과정에서 얻은 지식을 정리한 것입니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기