Claude Codeで「リファクタリングと新機能実装を同時に進めたい」「複数のバグ修正を並列で試したい」と思ったことはないだろうか。通常のエージェント実行では作業ディレクトリが共有されるため、ファイルの競合やテスト結果の混線が避けられない。そこで登場するのが Git Worktree とサブエージェントを組み合わせた並列開発パターン だ。

この記事で学べることは以下の3点である。

  • Claude Codeのサブエージェントにおける isolation: "worktree" オプションの仕組みと内部挙動
  • 複数エージェントを安全に並列起動するためのプロンプト設計
  • 並列作業をマージ・破棄するときの実践的ワークフロー

なぜWorktreeが必要なのか

Claude Codeのサブエージェント(Agent ツール)は、デフォルトでは親プロセスと同じワーキングディレクトリで動作する。これは単発タスクには効率的だが、以下のような問題が起きやすい。

  • エージェントAがpackage.jsonを編集中に、エージェントBも同じファイルを書き換えてしまう
  • テストランナーが他エージェントの未コミット変更を拾ってfalse positiveを起こす
  • 失敗したエージェントの中途半端な変更がワーキングツリーに残り、後続作業を汚染する

Git Worktreeは1つのリポジトリから複数の作業ツリーを生やせる機能で、git worktree add ../feature-x feature/x のように使う。各ツリーは独立したファイルシステム空間を持ちつつ、.gitディレクトリは共有されるため軽量だ。

isolation: "worktree" オプションの基本

Claude CodeのAgentツールには isolation パラメータがあり、"worktree" を指定すると、エージェント起動時に自動で一時worktreeが作成される。

Agent({
  description: "認証ミドルウェアのリファクタ",
  subagent_type: "general-purpose",
  isolation: "worktree",
  prompt: `lib/auth/middleware.ts のセッション検証ロジックを
  リファクタしてほしい。背景: legal要件で
  セッショントークンの保存方法を変更する必要がある。
  対象ファイル: lib/auth/middleware.ts:42-118
  完了条件: npm test が通ること。`
})

この呼び出しが行われると、ランタイムは内部的に次の処理を実行する。

  1. 一時ブランチ(例: claude/agent-abc123)を作成
  2. git worktree add で隔離ツリーを生成
  3. エージェントをそのツリーで起動
  4. エージェント終了後、変更があればパスとブランチ名を結果として返却
  5. 変更がなければworktreeを自動クリーンアップ

親エージェント(あなた)の作業ツリーは一切影響を受けない。

複数エージェントの並列起動パターン

本領を発揮するのは、独立した複数タスクを 同時並列 で投げるケースだ。1つのアシスタントメッセージ内に複数の Agent ツール呼び出しを含めると、Claude Codeはそれらを並列実行する。

// 1メッセージ内で3つのworktreeエージェントを並列起動
[
  Agent({
    description: "記事フェッチャーのRSS対応強化",
    isolation: "worktree",
    prompt: "lib/fetchers/rss.ts でAtom 1.0の\n名前空間バリエーションを処理できるよう修正。\nテスト: lib/fetchers/rss.test.ts を追加。"
  }),
  Agent({
    description: "AI分析のプロンプトキャッシュ導入",
    isolation: "worktree",
    prompt: "lib/ai/analyze.ts にAnthropic SDKの\nprompt caching を導入。system promptを\ncache_control: ephemeral でマーク。"
  }),
  Agent({
    description: "X投稿スケジューラのリトライ実装",
    isolation: "worktree",
    prompt: "lib/social/x.ts に exponential backoff\nでのリトライを追加。最大3回、初回1秒。"
  })
]

この3エージェントはそれぞれ別worktreeで動くため、package.jsonを3つとも触ってもマージは後段で個別に処理できる。所要時間は逐次実行の約1/3になる。

マージワークフローの設計

並列実行が終わると、各エージェントは「ブランチ名」と「worktreeパス」を返してくる。これらをどう統合するかが運用上の鍵だ。一般的なパターンは以下の3種類である。

パターン1: 個別PR化

各worktreeをそのままpushしてPR化する。レビュー単位を小さく保てるため、/shipスキルや gh pr create と相性が良い。

cd ../claude-agent-abc123
git push -u origin claude/agent-abc123
gh pr create --title "feat: RSS Atom 1.0対応" --body "..."

パターン2: 統合ブランチへのcherry-pick

複数エージェントの成果を1つの統合ブランチに集約する。依存関係のあるタスクをまとめてリリースしたいときに使う。

git checkout -b feature/sprint-42
git cherry-pick claude/agent-abc123
git cherry-pick claude/agent-def456
npm test  # 統合後のテスト

パターン3: 破棄

試行錯誤的な実験では、結果を見て採用しないという判断もある。

git worktree remove ../claude-agent-abc123
git branch -D claude/agent-abc123

git worktree list で現存するworktreeを確認できる。放置するとディスクを圧迫するので、定期的なクリーンアップが推奨されている。

競合回避と運用上の注意点

Worktree並列化には固有の注意点がいくつかある。

マイグレーション系タスクは並列化しない

Supabaseのマイグレーションファイル(supabase/migrations/)はタイムスタンプ順に依存するため、並列で生成すると番号衝突が起きる。マイグレーション関連は逐次実行が安全だ。

node_modulesの扱い

worktreeは.gitを共有するがnode_modulesは共有しない。各worktreeで npm install が必要になる場合があり、初回起動が遅い。pnpmのcontent-addressable storeや、node_modulesをシンボリックリンクで共有する運用が一般的になってきている。

機密情報の漏洩防止

.env.local はworktreeにコピーされないことが多い。エージェントがDB接続を必要とする場合、明示的にコピーするか、テスト用の環境変数を渡す。.gitignoreされた機密ファイルの扱いは事前に確認しておくのが推奨されている。

親エージェントの責務

並列エージェントを起動した親(あなた)は、結果を集約して 理解した上で 次のアクションを決める必要がある。「3つのエージェントの結果を見て良しなにマージしておいて」というような丸投げはアンチパターンだ。各エージェントが何をしたか、テストが通ったか、副作用がないかを親が確認する責任を持つ。

実際のプロジェクトでの適用例

本メディア「Claude Works」では、以下のようにworktree並列化を活用している。

  • fetcher追加タスク: RSS / GitHub / HN / Qiita / DevTo の5ソース対応を、当初は5つのworktreeエージェントで並列開発した
  • AI分析の改善実験: プロンプトのバリエーションを3つworktreeで並列に試し、結果を比較してから本流に取り込んだ
  • デザイン微調整: 配色案A/B/Cをworktreeで並走させ、スクリーンショットを見比べて採用案を決めた

特に「捨てる前提の試行」と「並列でPR化する独立タスク」に対する効果が大きい。

まとめ

Claude Codeの isolation: "worktree" オプションは、サブエージェント並列化の現実的な解だ。Git Worktreeの独立した作業空間を活用することで、ファイル競合を恐れず複数タスクを同時進行できる。

運用のコツは、(1) 並列化に向くタスク(独立した実装、試行錯誤)と向かないタスク(マイグレーション、依存関係のある変更)を見極めること、(2) マージ戦略を事前に決めておくこと、(3) 親エージェントが結果を理解する責任を放棄しないこと、の3点である。並列エージェントは強力だが、最終的な判断は人間とその代理である親エージェントが担うという原則を忘れずに活用したい。