Yyatmita

git worktree でエージェントを並行実行する——5回失敗して動いた構成

Claude Code の isolation: worktree で並行リサーチを実行。origin/HEAD 問題、venv 独立問題、権限問題を1つずつ潰した記録

Claude Codeサブエージェント検証#claude-code#autoresearch#git#worktree

前回は autoresearch と git の関係を整理した。ブランチ設計、コミット管理、エージェントがベストの状態を壊す問題。

今回はその続き——git worktree を使ってエージェントを並行実行する話。5 回失敗して 6 回目で動いた。


git worktree とは

通常、git リポジトリは 1 つのディレクトリに 1 つのブランチしかチェックアウトできない。git checkout でブランチを切り替えると、ディレクトリ内のファイルが丸ごと入れ替わる。

git worktree は、同じリポジトリから別のディレクトリに別のブランチを同時にチェックアウトする機能だ。

# 通常: 1つのディレクトリに1つのブランチ
/my-project/ feature-a ブランチ
 
# worktree: 同じリポジトリから複数のディレクトリ
/my-project/ feature-a ブランチ
/my-project-b/ feature-b ブランチ(worktree)
/my-project-c/ feature-c ブランチ(worktree)

3 つのディレクトリは別々のファイルを持つが、.git(コミット履歴、リモート設定)は共有。各ディレクトリで独立にコミットできる。

いつ使うか

  • 並行作業: 2 つの機能を同時に開発するとき
  • 長時間タスク: テストを回している間に別ブランチで作業するとき
  • AI エージェント: 同じリポジトリで複数のエージェントを並行で走らせるとき

基本コマンド

# worktree を作成
git worktree add ../my-project-b feature-b
 
# 一覧
git worktree list
 
# 削除
git worktree remove ../my-project-b

なぜ worktree が必要になったか

autoresearch では、7 通貨ペアそれぞれのパラメータを最適化したい。1 ペアのリサーチに数時間かかるので、順番に回すと数日かかる。寝ている間に並行で回したい。

問題は、エージェントが同じファイル(entry_conditions.py)を書き換える設計だということ。2 つのエージェントが同時に動くとファイルが壊れる。worktree なら各ペアが独立したディレクトリで動けるので、ファイル競合は起きない——はずだった。

Claude Code の isolation: "worktree"

Claude Code の Agent ツールには isolation: "worktree" というオプションがある。指定すると、Claude Code が自動的に git worktree を作成し、その中でエージェントが作業する。

Agent tool:
  prompt: "BTCUSDT 向けにパラメータを最適化してください"
  isolation: worktree
  run_in_background: true

手動で git worktree add する必要がない。エージェントが完了したら、変更がなければ worktree は自動削除される。変更があれば worktree とブランチが残り、後からマージできる。

仕様

項目動作
チェックアウト元origin/HEAD(リモートのデフォルトブランチ)
ディレクトリ.claude/worktrees/agent-{id}/
ブランチ名worktree-agent-{id}
venv親と共有しない。新しく作られる
権限親セッションの settings.json に従う
変更なし時worktree 自動削除
変更あり時worktree とブランチが残る

便利そうに見える。実際に動かすまでに 5 回失敗した。

失敗 1: worktree が古いコードを使う

症状: worktree 内のコードに最近の修正が反映されていない。

原因: isolation: "worktree"origin/HEAD(リモートのデフォルトブランチ)からチェックアウトする。ローカルの HEAD でも、現在のブランチでもない

開発ブランチで作業していたが、origin/master は 168 コミット前のまま push していなかった。worktree は古い master のコードを使っていた。

対策: git push origin master でリモートを最新にする。ローカルで作業したら master にマージして push する習慣が必要

失敗 2: venv が独立して作られる

症状: ModuleNotFoundError: No module named 'xxx'

原因: worktree は新しいディレクトリなので、uv run が実行されると新しい .venv が作られる。親の venv は共有されない。pyproject.toml の依存に入っていない自作ライブラリ(別リポジトリのバックテスト環境)は、新しい venv にインストールされない。

試したこと 3 つ:

  1. pyproject.toml に editable dependency として追加 → 失敗。自作ライブラリの requires-python がプロジェクトと競合して依存解決エラー
  2. .worktreeinclude.venv を記載してコピー → 失敗。venv はコピーされたが uv run が依存チェックで上書き
  3. コード内に絶対パスのフォールバックを追加 → 部分的成功。import は通るがデータディレクトリのデフォルトパスが壊れる

最終的な対策: PYTHONPATH 環境変数で解決。原始的だが確実。

PYTHONPATH=/path/to/my-library/src uv run python main.py

.worktreeinclude について

Claude Code のドキュメントには .worktreeinclude ファイルが紹介されている。.gitignore されたファイルを worktree に自動コピーする機能だ。

# .worktreeinclude
.env
.env.local

.env のような設定ファイルには有効だが、.venv(Python 仮想環境)のコピーには使えなかった。uv run が依存解決で venv を上書きしてしまう。

失敗 3: エージェントが設定ファイルを書き換える

症状: requires-python が勝手に変わっている。依存リストに知らないパッケージが追加されている。

原因: エージェントが ModuleNotFoundError を見て「pyproject.toml を修正すれば解決する」と判断し、勝手に書き換えた。しかも requires-python を上げてしまい、現行の Python バージョンで venv が作れなくなった。

対策: プロンプトに「pyproject.toml は変更しないこと」を明示。

教訓: エージェントはエラーを見ると「直せそうなファイル」を探して修正しようとする。触ってほしくないファイルは明示的に禁止する必要がある。

失敗 4: worktree から脱出してメインを壊す

症状: 5 つのエージェントがメインディレクトリの同じファイルを同時に書き換えている。

原因: worktree 内でエラーが起きると、エージェントが「メインのリポジトリから実行すれば動くかも」と判断し、worktree を抜けてメインディレクトリで作業を始める。5 つのエージェントが全員同じことをやり、1 つのファイルが毎秒書き換わるカオスになった。

対策: プロンプトに「worktree 外のディレクトリで作業しないこと」を明示。ただし完全な防止策にはなっていない——エージェントは「指示に従いたい」気持ちと「問題を解決したい」気持ちの間で、後者が勝つことがある。

失敗 5: Bash の権限パターンが合わない

症状: Permission to use Bash has been denied

原因: グローバル設定で Bash(uv run*) は許可されていたが、PYTHONPATH=... uv run ... というコマンドは Bash(PYTHONPATH=*) というパターンにマッチし、許可リストになかった。

対策: ~/.claude/settings.jsonpermissions.allow に追加。

{
  "permissions": {
    "allow": [
      "Bash(uv run*)",
      "Bash(PYTHONPATH=*)"
    ]
  }
}

6 回目: 動いた

最終的に動いた構成:

  1. master を pushorigin/HEAD が最新コードを指すようにする
  2. PYTHONPATH — 外部ライブラリのパスを環境変数で渡す
  3. 権限設定Bash(PYTHONPATH=*) を allow に追加
  4. プロンプトの制約 — 設定ファイル変更禁止、worktree 外作業禁止を明示
  5. 並行数の制限 — CPU 負荷を考慮して同時 2〜3 まで

バックテストが worktree 隔離で実行され、メインのファイルに影響を与えずに回った。

CPU の話

5 ペアを並行で回したとき、CPU 使用率が 100% × 5 で load average 34 まで上がった。コンテナの通常使用に支障が出た。

Python のバックテストはシングルスレッドで、1 ペアでフルに 1 コアを使う。昼間は 1 ペア、寝る前に 2〜3 ペアに増やすという運用にした。

worktree は「もう 1 つのリポジトリ」

git worktree は「同じリポジトリの別ビュー」のように見えるが、実際には独立した作業環境に近い。

  • venv は共有されない
  • .gitignore されたファイルは存在しない
  • origin/HEAD からチェックアウトされる(ローカルの最新ではない)

この「独立性」は安全のためだが、セットアップコストが高い。外部ライブラリへの依存がある場合、その依存をどう解決するかが最大の課題になる。

最終的に PYTHONPATH という原始的な方法が一番確実だった。洗練された解決策ではないが、動く。


前回の記事: autoresearch と git

この記事は Claude Code(開発担当)への実際のインタビューをもとに構成しています。

本記事はバックテスト手法の技術的検証記録であり、特定の金融商品の売買を推奨するものではありません。投資判断はご自身の責任でお願いします。