Run parallel sessions with worktrees
概要
git worktree ごとに Claude Code のセッションを分離し、並行して走るセッションのファイル編集が衝突しないようにする仕組み。--worktree / -w で作成・起動する。worktree は git リポジトリを前提とし、他の VCS では hook で置き換える。
仕様
起動
claude --worktree <name>(短縮形-w)で分離された worktree を作り、その中で Claude を起動する- 既定の作成先はリポジトリルートの
.claude/worktrees/<name>/、ブランチ名はworktree-<name> - 名前を省略すると
bright-running-foxのような名前が生成される - 対話実行には workspace trust が必要。そのディレクトリで Claude を実行したことがない場合、一度
claudeを実行して trust ダイアログを承認する。未承認なら--worktreeはエラー終了する -pの非対話実行は trust チェックを飛ばすため、claude -p --worktreeはそのまま進む- worktree は新しい checkout なので、依存関係のインストールなど開発環境の初期化が必要
セッション中に worktree へ入る
- Claude に worktree で作業するよう依頼すると
EnterWorktreeツールで作成する - worktree 内から
EnterWorktreeに対象パスを渡すと別の.claude/worktrees/配下の worktree へ直接切り替えられる。元の worktree はディスク上にそのまま残る - リポジトリの
.claude/worktrees/の外のパスに入る場合は必ず承認を求める。セッションの作業ディレクトリ・書き込み権限・CLAUDE.mdなどのプロジェクト設定がその場所へ移るため。EnterWorktreeの permission rule や「don't ask again」ではこのプロンプトは抑止できず、bypassPermissionsモードのみが飛ばす- v2.1.206 より前は、既存の worktree パスなら確認なしに入れた
後片付け
対話セッションを終了すると、削除で失われる作業(変更済み・未追跡ファイル、新しいコミット)があるかを検査する。
- worktree がクリーン: 名前なしセッションでは worktree とブランチを自動削除する。名前付きセッションでは先に確認する
- 作業が残っている: 保持か削除かを尋ねる。削除するとディレクトリ・ブランチと、その中の作業がすべて消える
-pの非対話実行には終了時のプロンプトが無いため後片付けされない。git worktree removeで削除する
セッションの resume
- worktree 内にあったセッションを resume すると、その worktree へ戻る。対話 resume、
-pでの--continue/--resume、Agent SDK のいずれでも同じ - 戻す前に、その worktree が main checkout とは別の checkout であることを検証し、失敗した場合は再入場を拒否する
- 起動ディレクトリと resume 方法で挙動が変わる
- 起動ディレクトリ: main checkout やリポジトリの別ディレクトリから resume する。git で
.claude/worktrees/配下に作った worktree は、その中から起動しても再入場する。それ以外の worktree の中から起動した場合、そこから保証できるときのみ再入場する(自身がリポジトリである worktree、git メタデータの無い worktree、git worktree addで作った worktree のサブディレクトリからの起動は拒否されるので main checkout から起動する) --fork-session: fork したセッションは Claude を起動したディレクトリで開始し、元セッションの worktree には手を付けない- worktree が削除済み: 起動したディレクトリで resume し、worktree が無いことを通知してセッションの worktree binding をクリアする
- 起動ディレクトリ: main checkout やリポジトリの別ディレクトリから resume する。git で
- Claude Code が git で作った worktree に出入りすると、トランスクリプトもセッションの新しい作業ディレクトリの下に記録される(
/cdと同じ扱い)。WorktreeCreatehook が作った worktree はトランスクリプトを起動ディレクトリに保つ。v2.1.198 以降が必要 - v2.1.212 より前は、非対話 resume は起動ディレクトリに留まり、
ExitWorktreeは「終了すべき worktree セッションが無い」と報告していた
分離の強制
worktree に分離されたセッション(--worktree 起動、EnterWorktree での入場、worktree セッションの resume のいずれでも)では、main checkout に到達するツール呼び出しをブロックする。分離セッションから起動したすべての subagent にも適用され、対話・バックグラウンドを問わない。
| チェック | 内容 |
|---|---|
| File edits | main checkout 内のパスを対象とする Edit / Write / NotebookEdit をブロックする |
| Command working directory | 作業ディレクトリが main checkout に解決される、または main checkout の外に留まることを検証できない Bash / PowerShell / Monitor コマンドをブロックする |
| Git redirects | git -C、--git-dir、GIT_DIR / GIT_WORK_TREE 変数、git 実行前の main checkout への cd などで git を main checkout に向ける Bash / Monitor コマンドをブロックする。worktree 内に留まることを検証できないコマンドもブロックする。PowerShell コマンドには working-directory チェックのみを適用する |
- チェック対象は Claude Code を起動したリポジトリ(linked worktree のリンク元である main checkout を含む)
subagent の worktree 分離
- カスタム subagent の frontmatter に
isolation: worktreeを追加すると常に自分の worktree で動く - 各 subagent には一時的な worktree が割り当てられ、変更なしで終了すると自動削除される。変更がある worktree は、後述の定期スイープが作業を失わずに削除できるようになるまでディスク上に残る
- subagent の worktree は
--worktreeと同じ base branch を使う(worktree.baseRefが"head"でない限りリポジトリの既定ブランチから分岐する)
定期スイープ
- Claude が subagent とバックグラウンドセッション用に作った worktree のうち、
cleanupPeriodDays設定より古いものを定期的に削除する - 作業(変更済み・未追跡ファイル、未 push のコミット)が残っている worktree はスキップする
--worktreeで自分が作った worktree は決して削除しない- agent の実行中は
git worktree lockをかけ、並行するクリーンアップが削除できないようにする。終了時に解除される - プロセスが終了したセッションのために Claude Code が設定したロックはスイープが解除する。自分で
git worktree lockしたロックは解除しない。v2.1.210 より前は kill されたセッションのロックがgit worktree unlockするまで残っていた - スイープが残した worktree を消すには
git worktree remove(未コミット変更や未追跡ファイルがある場合は--force)
作成のカスタマイズ
base branch
worktree.baseRef 設定(settings):
| 値 | 内容 |
|---|---|
"fresh"(既定) | リモートのリポジトリ既定ブランチ(通常 main)から分岐する |
"head" | ローカルの現在の HEAD から分岐し、未 push のコミットや feature ブランチの状態を引き継ぐ。worktree 内では、その worktree の HEAD に解決される |
worktree.baseRefにブランチ名は指定できない。特定の既存ブランチから始めるには git で直接作成する"fresh"の場合、24 時間以内に fetch していなければ既定ブランチを fetch してorigin/HEADを更新する(上限 5 秒、失敗時はローカルキャッシュの ref を使う)。remote が未設定、またはorigin/HEADがローカルに無く fetch もできない場合は現在のローカルHEADにフォールバックする- v2.1.208 より前は、fresh の worktree はローカルにキャッシュ済みの
origin/HEADをそのまま使っていた
pull request から分岐
--worktreeに#付きの PR 番号、または GitHub の pull request URL を渡すoriginからpull/<number>/headを fetch し、.claude/worktrees/pr-<number>に worktree を作る- シェルが
#をコメント開始と解釈しないよう引用符で囲む
gitignore されたファイルのコピー
- プロジェクトルートに
.worktreeincludeを置くと、worktree 作成時に自動コピーされる - 記法は
.gitignoreと同じ。パターンに一致し、かつ gitignore されているファイルだけがコピーされる(追跡済みファイルは複製されない) - Claude Code が git で作るすべての worktree に適用される(
--worktree、subagent の worktree、desktop アプリの並行セッション) WorktreeCreatehook を使う場合は hook スクリプト内でコピーする
同じ worktree 名の再利用
- 既にディレクトリが存在する名前を
--worktreeに渡すと、新規作成せずその worktree を開く - 既定の
"fresh"base では、次の条件をすべて満たす場合に再オープン時にリポジトリ既定ブランチへリセットされる- 未コミットの変更も未追跡ファイルも無い
- Claude Code が作ったブランチのまま
- 独自のコミットが無い、または pull request がマージ済みでリモートブランチが削除されている
- それ以外(条件を満たさない、状態を検証できない、
worktree.baseRefが"head"、名前が PR 番号)は古い tip で再オープンされる - v2.1.208 より前は、名前を再利用すると常に古い tip で再オープンされた
hook による置き換え
WorktreeCreatehook を設定すると、既定のgit worktreeロジックを完全に置き換えられる(.claude/worktrees/以外の場所への配置を含む)- 非 git の VCS(SVN / Perforce / Mercurial など)では
WorktreeCreateとWorktreeRemovehook を設定する - hook が既定の git 挙動を置き換えるため、
--worktree使用時に.worktreeincludeは処理されない
main checkout と共有されるもの
worktree は独自のファイルとブランチを持つが、次を main checkout と共有する。--worktree・git worktree add・desktop アプリのいずれで作った場合も同じ。
- リポジトリの
.gitディレクトリ: worktree 内の git コマンドは main リポジトリの共有.gitに書き込む。sandboxing はその書き込みを許可するため、sandbox 有効時も worktree 内からgit commitが動く - Plugins: main checkout から project scope でインストールした plugin は同じリポジトリの worktree でも読み込まれる。v2.1.200 以降が必要
- Permission approvals: worktree セッションで Bash コマンドに「Yes, don't ask again」を選ぶと、ルールは main checkout の
.claude/settings.local.jsonに保存され、main checkout と同リポジトリの全 worktree に適用され、worktree を削除しても残る。v2.1.211 より前はその worktree 内に保存され、他所には適用されず、worktree 削除で失われた
手動での管理
git worktree add ../project-feature-a -b feature-a
git worktree add ../project-bugfix fix-issue-456
git worktree list
git worktree remove ../project-feature-a
設定
{
"worktree": {
"baseRef": "head"
}
}
# .worktreeinclude
.env
.env.local
config/secrets.json
---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---
Apply the requested refactor across every affected file, then run the tests
and report the results.
制約・注意点
- worktree には git リポジトリが必要
.claude/worktrees/を.gitignoreに追加すると、main checkout で worktree の内容が未追跡ファイルとして現れない- Windows では worktree の削除がその外のファイルを消さない。worktree 内のフォルダが NTFS junction やディレクトリ symlink の場合はリンクだけを削除し、参照先のフォルダは残す。v2.1.205 より前は、サブディレクトリにネストしたリンクを持つ worktree の削除で参照先フォルダを消すことがあった
.claude、.claude/worktrees、worktree ディレクトリ自体が symlink の場合、worktree の作成を拒否する。symlink を削除して再試行する。v2.1.212 より前は、コミット済みの symlink があるとそれを辿ってリポジトリ外にファイルを作ることがあった- 起動時に worktree ディレクトリへ入れない場合、パスを示すエラーを出して終了コード 1 で終了する(
WorktreeCreatehook が作成したディレクトリ以外を出力した場合や、セットアップ後にディレクトリが削除された場合)。v2.1.205 より前はセッションがクラッシュし、-pでは約 30 秒停止した後に終了コード 0 で終了した Refusing to use <path> as an isolation worktreeは、ディレクトリの git identity 検査で拒否されたことを意味する。多くはディレクトリの git メタデータが main checkout に解決される場合(.gitファイルが main リポジトリの.gitを指す、core.worktreeリダイレクトで working tree が main checkout に解決されるなど)。読めない.gitエントリがある場合も拒否する。拒否されたディレクトリは作業が残っている可能性があるためそのまま残される- ネットワークパスに記録された worktree へは決して resume しない(
its recorded path has a network spelling)
resume が worktree の外で始まる場合のメッセージ
| メッセージの冒頭 | 意味 |
|---|---|
Your worktree <path> no longer exists | worktree ディレクトリが削除された。分離なしで現在のディレクトリで継続し、binding をクリアする。対処不要 |
Could not verify your worktree <path> this time | 検証できなかった(多くは一時的)。binding は保持され、分離なしで継続する。再度 resume して再試行する |
Did not re-enter your worktree <path> | binding が安全でないとして拒否された。binding をクリアし、分離なしで継続する |
Could not re-enter your worktree <path> | 起動場所からその worktree を保証できなかった(多くは worktree の中から起動したため)。binding は保持される |
-p の非対話モードと Agent SDK の resume では、worktree が消えている場合を除き、分離なしで継続せず stderr のエラーで resume を停止する。
関連
facts/claude-code/sub-agents.mdfacts/claude-code/cli-reference.mdfacts/claude-code/settings.mdfacts/claude-code/hooks.mdfacts/claude-code/permissions.mdfacts/claude-code/sandboxing.mdfacts/claude-code/tools-reference.mdfacts/claude-code/headless.md