← 기사 목록
日本語https://zenn.dev/topics/ai/feed

worktree の『バトンタッチ』問題を、自前 skill・Codex・Augment で比べて反省した

추출된 키워드

27
バトンタッチ·5Codex app·5Augment·5Handoff·5Living Spec·5grill-with-docs·5worktree·51 ターミナル依存·4ADR·4CONTEXT.md·4subagent·4git worktree·4Claude Code·4三層アーキテクチャ·4Verifier·3HANDOFF.md·3Matt Pocock·3Specialist·3Coordinator·3detached HEAD·3skill·3Spaces·2Local チェックアウト·2Worktree チェックアウト·2.gitignore·2pnpm test·2Vottia·1

원문

11,211
worktree の『バトンタッチ』問題を、自前 skill・Codex・Augment で比べて反省した

worktree の『バトンタッチ』問題を、自前 skill・Codex・Augment で比べて反省した

TL;DR

  • 前回、Claude Code の
    git worktree
    + skill + subagent で並行開発フローを自前で組んだ
  • だがその後 Codex app の「Handoff」Augment の三層アーキテクチャを読んで、自分が欲しかった「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
  ▼
メインの Claude(skill = オーケストレーター)
  ├─ git worktree add .worktrees/1234 feat/1234
  └─ Agent ツールで subagent を起動
          ▼
       subagent(worktree 内で実装まで完走)

skill が worktree を切って subagent を送り込み、メインの Claude は別の会話を続けられる。「Claude が checkout してユーザーの作業を壊す」問題は原理的に消えるし、並行作業もできる。これで完成、と思っていた。

しかし、運用してみると引っかかる点が残っていた。

subagent が完走しなかったとき、その作業を別のセッションや別の端末からどう引き継ぐのか?

subagent はメインのコンテキスト内でしか生きていない。メインの会話を閉じたら、worktree というディレクトリは残っても「どこまで何をやっていたか」という文脈は失われる。結局、最初に上げた skill を動かした その 1 ターミナルに張り付く ことになっていた。

この「1 ターミナル依存」をどう外すか、というのが本当に解きたかった問題だった。そしてそれを、Codex app と Augment はすでに製品として解いていた。これが今回の反省の出発点だ。

反省①:Codex app の「Handoff」は Git の制約を正面から解いていた

Codex app には Handoff という機能がある(公式ドキュメント)。

これが解いているのは、Git のこの根本制約だ。

同じブランチは、同時に 1 箇所でしか 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 の三層 + Living Spec は「まとめてから渡す」を常駐化していた

もうひとつ見落としていたのが Augment の構成(公式ガイド)。

Augment は Spaces という単位で「1 タスク = 1 ブランチ = 1 worktree」をマッピングし、複数の specialist エージェントを隔離ディレクトリで並列実行する。

.git
のオブジェクトストアは共有しつつ、ファイルシステムは完全分離する。

問題の解き方が明快だった:

課題Augment の解き方
ファイル衝突 衝突を実行時ではなく merge 時 に寄せ、標準の git ツールで検出させる
コンテキスト汚染 各エージェントが自分の作業ディレクトリと index を持ち、互いの前提を壊さない
ロック競合 worktree ごとに index ファイルが分かれ、
.git/index.lock
の取り合いが起きない

そして肝が 三層アーキテクチャLiving Spec だ。

Coordinator(計画を立てる)
   ├─ Specialist A ─┐
   ├─ Specialist B ─┼─ 並列実装(各 worktree)
   └─ Specialist C ─┘
            ▼
        Verifier(出力を検証)

   ※ 全エージェントが共有の「Living Spec」を参照する

Living Spec は、全エージェントが参照する自己更新の共有仕様書だ。これを見たとき、自分が別ルートで欲しがっていたものと同じだと気づいた。Coordinator が計画し、その文脈を Living Spec に書き出し、Specialist がそれを見て並列実装する——文脈が 1 枚の生きたドキュメント に集約され、全員がそこを参照する構造だ。

反省③:grill-with-docs は「バトンタッチの中身」を作る工程だった

ここまで来て、自分が当初イメージしていた「

grill-with-docs
でまとめてから
handoff
でバトンタッチ」というフローを、根本的に誤解していたことに気づいた。

Matt Pocock の

grill-with-docs
SKILL.md)は「まとめる」スキルではない。計画を既存のドメインモデルに対して容赦なく問い詰める スキルだ。
  • 質問を 1 つずつ投げ、ユーザーの回答を待ってから次へ進む(コードで答えが出るものはコードを探索して確認する)
  • 曖昧・多義的な用語が出たら、正準的な用語を提案して研ぐ。「あなたは "account" と言ったが Customer か User か。別物だ」
  • グロッサリー(
    CONTEXT.md
    )と矛盾する用語の使い方は即座に指摘する
  • コードと食い違う主張が出たら矛盾を表に出す
  • そして決定が固まった その場でする
    CONTEXT.md
    (用語集)と ADR を更新

重要なのは出力だ。

CONTEXT.md
は実装詳細を一切持たない 用語集に徹する。ADR は「後戻りしにくい・文脈なしだと驚かれる・本物のトレードオフがある」の 3 条件が揃ったときだけ、慎重に切る。

つまり grill-with-docs は「会話をまとめる」のではなく、問い詰めながら『持ち運べる文脈の実体』を結晶化させる工程 だった。そしてここまでの議論を踏まえると、その位置づけははっきりする。

  • grill-with-docs
    CONTEXT.md
    / ADR という文脈の実体を作る
  • handoffがそれを圧縮して次のエージェントに渡す
  • Augment の Living Specは、この
    CONTEXT.md
    を全エージェント常駐参照の形にした版

自分は「まとめてから渡す」と雑に捉えていたが、正しくは「問い詰めて文脈を結晶化させてから渡す」だった。バトンタッチの質は、渡し方ではなく 渡す中身をどれだけ研いだか で決まる——grill-with-docs はその「中身を研ぐ」ための工程だったわけだ。

3 つのアプローチを並べる

同じ「worktree のバトンタッチ問題」に対して、3 系統の解き方がある。

自前 skill + subagentCodex HandoffAugment 三層 + Living Spec
分離
git worktree
を skill で生成
detached HEAD の worktreeSpace = 1 タスク 1 worktree
バトンタッチの実体 (弱い)メインのコンテキスト依存スレッドを Local ⇄ Worktree で移送Living Spec(共有仕様書)
並列性 subagent を起動した分だけ前景 + 背景 worktreeSpecialist を並列実行
検証 各 subagent 内で
pnpm test
(ユーザー側)専任の Verifier 層
1 ターミナル依存 残る 外れる(作業を移送できる) 外れる(Spec が文脈を保持)
文脈の結晶化 (なし)(ユーザー側)Coordinator → Living Spec
導入コスト 自分で書く必要あり製品機能製品機能

ポイントは、自前 skill は「分離」までは解けていたが「移送(バトンタッチ)」が弱かったということ。Codex は移送そのものを、Augment は移送の中身(共有される文脈)を、それぞれ製品として実装していた。

そして「移送の中身」をどう作るかを担うのが、第 4 の系統である Matt Pocock の skill 群だ。

grill-with-docs
が文脈を結晶化(
CONTEXT.md
/ ADR)し、
handoff
がそれを渡す。製品(Codex / Augment)が「移送の仕組み」を作ったのに対し、こちらは「移送する中身の質」を作る道具立てになっている。両者は競合ではなく補完関係だ。

自前フローに持ち帰る:何を足すか

製品に乗り換える話ではなく、自前の Claude Code フローに「反省」を反映するなら、足すべきは 2 つだ。

1. worktree に「持ち運べる文脈」を結びつける

subagent のコンテキスト任せにせず、worktree の中に進捗を書き残す。これが Codex Handoff / Augment Living Spec の自前版になる。

# .worktrees/1234/HANDOFF.md(worktree 内に置く)

## タスク
Issue #1234 の実装

## 状態
- [x] スキーマ定義
- [x] API ハンドラ
- [ ] フロント結線 ← ここから
- [ ] テスト

## 次のセッションへの申し送り
- `lib/foo.ts` の型が暫定。本実装で差し替える
- マイグレーションは未適用

worktree というディレクトリ自体は端末をまたいで残る。そこに

HANDOFF.md
を置けば、別セッション・別端末の Claude が
cd .worktrees/1234 && cat HANDOFF.md
から再開できる。「1 ターミナル依存」が外れる。

2. skill を「再開」に対応させる

これまでの skill は worktree を「作る」だけだった。「既存の worktree を拾って続きをやる」入口を足す。

# .claude/skills/worktree-resume.md

引数の Issue 番号から既存 worktree を特定し、
HANDOFF.md を読んでから subagent に続きを委任する。

## 手順
1. `.worktrees/<id>` の存在を確認
2. `HANDOFF.md` を読んで現在地を把握
3. 「次のセッションへの申し送り」から再開点を決定
4. subagent に続きを委任、完了後 HANDOFF.md を更新

3. 着手前に
grill-with-docs
で中身を研ぐ

HANDOFF.md
を置くだけだと、書く中身が薄ければバトンタッチも薄くなる。worktree を切る前に grill-with-docs 的に計画を問い詰め、用語と決定を
CONTEXT.md
/ ADR として結晶化させておく。subagent はそれを参照して実装し、
HANDOFF.md
には差分だけ書けばよくなる。文脈の質を上流で作っておくほど、下流の引き継ぎは軽くなる。

まとめ

学び内容
本当の難所worktree の「分離」ではなく「バトンタッチ(移送)
Codex の解スレッドを Local ⇄ Worktree で移送し、Git の「1 ブランチ 1 checkout」制約を越える
Augment の解Living Spec(常駐の共有仕様書)で文脈を全エージェントに行き渡らせる
grill-with-docs の役割問い詰めて
CONTEXT.md
/ ADR に文脈を結晶化=移送する中身を研ぐ
自前への反映着手前に文脈を結晶化し、worktree 内に
HANDOFF.md
を置き、skill に「再開」入口を足す

前回は「自分で組めた」ことに満足して、製品側がどう解いているかを見ていなかった。Codex の Handoff と Augment の三層を読んで、バトンタッチには『持ち運べる文脈の実体』が要るという当たり前の核心にやっと辿り着いた。そして grill-with-docs を読み直して、その実体は黙っていても湧いてこない——問い詰めて研いではじめて文脈になるとわかった。worktree はディレクトリとして端末に残る。あとは、研いだ文脈をそこに残せばいいだけだった。

参考

この記事は Vottia のプロダクト開発の中で得た知見をまとめたものです。