カテゴリー / 連携・活用

Claude Codeのworktreeで並列作業する方法|編集の衝突を避ける始め方・片付け方・限界

この記事の目次

生成AIのコーディング支援を使っていると、Claude Codeを2本以上同時に走らせたくなる場面が出てきます。同じ作業ディレクトリで動かすと、片方の編集がもう片方の作業に混ざります。この記事では、Claude Code CLIの --worktree で作業ディレクトリを分け、並列セッションを始めて片付けるまでを扱います。内容は公式ドキュメント(https://code.claude.com/docs/en/worktrees)の記述に基づいており、筆者が実機で動かした結果ではありません。

読み終えるころには、次の3点を自分で判断できる状態を目指します。

  • 並列セッションで編集が衝突する理由を、自分の言葉で説明できる
  • claude --worktree <名前> で別々のセッションを起動できる
  • .worktreeinclude が必要かどうかと、終了時にworktreeが残るか消えるかを判断できる

前提条件

  • 対象はCLI(claude)です。git リポジトリが必要で、git 以外のバージョン管理を使う場合は WorktreeCreate フックで代替します(詳細は公式の「Non-git version control」の節にあります)。
  • 対話実行ではワークスペースの信頼確認が必要です。-p による非対話実行では信頼チェックは行われません。
  • 画面表示の文言、コマンドの出力例、対応プラン、地域、提供段階、依存関係ごとの導入手順は、公式ドキュメントに記載が無いため、この記事では補いません。
  • 本文に出てくる版番号は、いずれも公式本文のものです。お使いの版で挙動を確かめてから使ってください。

同じリポジトリで複数のClaude Codeセッションを動かすと何が困り、worktreeは何を解決するのか?

困りごとは、複数のセッションが同じ作業ディレクトリのファイルを編集することです。worktreeは、セッションごとに別のファイルとブランチを用意して、その編集を分けます。解決するのはファイル編集の隔離です。どの作業を並べて走らせ、結果をどう突き合わせるかという設計は、Claude Codeのエージェントチームの解説のような別の話題になります。

課題を一文にしてみる

次のように言い換えられれば、課題は掴めています。「同じ作業ディレクトリを2つのセッションが共有していると、片方が書き換えているファイルをもう片方も読み書きしてしまう」。たとえば、認証まわりの機能追加と別のバグ修正を同時に走らせる場面を想像してください。どちらも同じファイルに触れる可能性があり、編集が入り混じります。これは説明のための仮定であり、再現手順や体験談ではありません。

worktreeとは何か

公式の説明では、git worktree は「独自のファイルとブランチを持つ別の作業ディレクトリ」で、リポジトリの履歴とリモートはメインのチェックアウトと共有します。セッションごとにworktreeを持たせると、編集対象のファイルが別々になります。たとえば一方のセッションで機能を作りながら、もう一方でバグを直せます。

並列セッションの始め方: コマンドと起動後の確認

1本目は claude --worktree <名前>(短縮形は -w)で起動し、2本目は別のターミナルで別の名前を指定して同じコマンドを実行します。名前を省略すると自動で名前が付きます。既定では、リポジトリ直下の .claude/worktrees/<名前>/ に作られ、ブランチ名は worktree-<名前> です。

1本目: 名前を付けて起動する

claude --worktree feature-auth

この場合、作成先は .claude/worktrees/feature-auth/、ブランチは worktree-feature-auth になります。

2本目: 別のターミナルで別の名前を指定する

claude --worktree bugfix-login

公式の説明は「別のターミナルで違う名前を指定してもう一度実行すると、2つ目の隔離セッションが始まる」というものです。名前を省くと bright-running-fox のような名前が自動で付きます。

起動できたかを確認する

リポジトリ内の別のターミナルで次のコマンドを実行し、作成先のパスとブランチ名が上記の規則どおりかを照合します。

git worktree list

これは公式が起動後の確認として示している方法ではなく、gitの一般的なコマンドを使った、この記事独自の確認です。出力の見た目には公式の例が無いので、「パスとブランチ名が規則どおりに並んでいるか」だけを見てください。

初回の信頼確認

そのディレクトリで一度も claude を実行したことがない場合、対話実行の --worktree は信頼確認の未了を知らせるエラーで終了します。先にそのディレクトリで claude を一度実行して、信頼ダイアログを承認してください。claude -p --worktree のような非対話実行では、この確認は省かれます。

起動後の環境構築

worktreeは新しいチェックアウトです。依存関係の導入などの初期化は、Claudeに頼むか、.claude/worktrees/ 以下のそのディレクトリで自分で実行します。

.gitignore への追記

公式のTipとして、.claude/worktrees/ を .gitignore に追加しておくと、worktreeの中身がメインのチェックアウトで未追跡ファイルとして現れずに済みます。

セッション中に頼む方法

起動後でも、Claudeに「worktreeで作業して」と頼めば EnterWorktree ツールで作成されます。.claude/worktrees/ の外のパスに入る場合は、事前に承認を求められます。

.env など git に入っていないファイルを新しいworktreeに持ち込む

プロジェクトルートに .worktreeinclude を置き、.gitignore と同じ構文で持ち込みたいファイルを書きます。パターンに一致し、かつ gitignore の対象になっているファイルだけが、新しいworktreeにコピーされます。tracked なファイルは複製されません。

なぜ新しいworktreeに .env が無いのか

worktreeは新しいチェックアウトなので、git の管理外にある .env や .env.local はそこに存在しません。無いのは異常ではなく、仕様どおりです。

.worktreeinclude の書き方

公式の例を言い換えると、次のように書きます。

.env
.env.local
config/secrets.json

この設定は、--worktree で作られるworktree、デスクトップアプリの並列セッションなど、Claude Codeが git で作るすべてのworktreeに適用されます。

**/ で始まるパターンの注意

**/ で始まるパターンは、ディレクトリ全体が gitignore されている場合に扱いが変わります。コピーされるのは、そのディレクトリ自体がパターンに一致する場合か、**/ の次の名前がディレクトリのパスに含まれる名前の1つである場合です。たとえば **/.claude/skills/*.md は、先頭の名前が .claude なので、無視されている .claude/ の中から一致するファイルをコピーします。**/ のパターンが届かないときは、ディレクトリ名を明示して vendor/**/config.json のように書きます。この挙動は v2.1.239 で変わっており、それ以前はディレクトリ自体がパターンに一致する場合に限られていました。

WorktreeCreate フックを使う場合

WorktreeCreate フックを使うと .worktreeinclude は処理されません。必要な設定ファイルは、フックのスクリプト内でコピーします。

複製するファイルは自分で選ぶ

ここは公式本文の記述ではなく、編集上の注意です。.env 系には秘密情報が含まれることがあります。.worktreeinclude に書くファイルは、読者自身が必要なものだけに絞ってください。

分岐元のブランチと、同じ名前で起動し直したときの挙動

既定ではリモートの既定ブランチ(多くは main)から分岐します。手元の未pushの作業から始めたいときは worktree.baseRef を "head" にします。同じ名前で起動し直すと既存のworktreeが開き、条件がそろうと既定ブランチへリセットされます。

分岐元の2つの値

値 分岐元 向いている場面
"fresh"(既定) リモートの既定ブランチ リモートと一致するきれいな状態から始めたいとき
"head" 現在のローカル HEAD 未pushのコミットや、作業中のブランチ状態を持ち込みたいとき

"head" をworktree内で使うと、メインのチェックアウトではなく、そのworktreeの HEAD が基準になります。ブランチ名を worktree.baseRef に指定することはできません。

"fresh" では、Claude Code は origin/HEAD を最新に保とうとします。直近24時間以内に取得していなければ既定ブランチを fetch し、待つのは最大5秒です。失敗した場合はローカルにキャッシュされた参照を使います。パスワードや鍵のパスフレーズの入力待ちが必要になった場合も、失敗として扱われます。リモートが無い、または origin/HEAD がキャッシュに無く取得もできない場合は、ローカルの HEAD が使われます。v2.1.208 より前は、ローカルにキャッシュ済みの origin/HEAD をそのまま使っていました。

Claude Codeのsettings(settings.json)に、次のキーを追加します。

{
  "worktree": {
    "baseRef": "head"
  }
}

どのスコープのsettingsファイルに書くかは、公式のsettingsリファレンスで確認してください。

同じ名前で起動し直したとき

既にディレクトリがある名前を --worktree に渡すと、新規作成ではなく既存のworktreeが開きます。"fresh" のとき、次の3つがすべて当てはまると、開き直したworktreeは既定ブランチへリセットされます。

  • 未コミットの変更も未追跡ファイルも無い
  • Claude Codeが作ったブランチのままである
  • 自分のコミットが無い、またはプルリクエスト(マージリクエスト)がマージ済みでリモートブランチが削除されている

状態ごとの結果と、読者が取れる行動は次のとおりです。

状態 結果 読者の行動
"fresh" で、上の3つがすべて当てはまる 既定ブランチへリセットされて開く 前回の位置から続けたいなら、先に変更やコミットを残しておくか、worktree.baseRef を "head" にする
"fresh" で、3つのどれかを満たさない 元の先頭のまま開き直される そのまま作業を続ける
worktreeの状態を確認できない 元の先頭のまま開き直される そのまま作業を続ける
worktree.baseRef が "head" 元の先頭のまま開き直される そのまま作業を続ける
名前をPR/MR参照(例: --worktree "#1234")で指定した 元の先頭のまま開き直される そのまま作業を続ける

v2.1.208 より前は、どの場合も常に元の先頭で開き直されていました。PR/MR参照で始める手順そのものは、この記事では扱いません。

特定の既存ブランチから始めたい場合

その場合は git で直接worktreeを作ります。fix-issue-456 は、自分のリポジトリに既にあるブランチ名に置き換えてください。

git worktree add ../project-bugfix fix-issue-456
cd ../project-bugfix
claude

不要になったら git worktree remove ../project-bugfix で消せます。ただし、この手動作成のworktreeに、次節の隔離チェックや、その次の節の終了時の自動cleanupが同じ規則で働くかは、公式ドキュメントに明記が無く、確認できていません。公式が隔離の対象に挙げているのは、--worktree で始めた場合、EnterWorktree で入った場合、worktreeセッションを再開した場合です。なお公式には、手動で作ったworktreeはサブエージェントやバックグラウンドセッション向けの定期的な片付けの対象外になる、という記述があります。

隔離の範囲: 4つのチェックで止まる操作と止まらない操作

隔離されたセッション中は、次の4つのチェックで、メインのチェックアウトに向かう特定のツール呼び出しが止まります。--worktree で始めた場合も、EnterWorktree で入った場合も、worktreeセッションを再開した場合も同じ規則です。

チェックごとの対象と対処

操作 隔離で止まるか 読者が取るべき対処
Edit / Write / NotebookEdit でメインのチェックアウトのパスを指す 止まる 通常は不要
Bash / PowerShell / Monitor の作業ディレクトリがメインのチェックアウトになる 止まる 通常は不要
Bash / Monitor で git -C、--git-dir、GIT_DIR / GIT_WORK_TREE、メインへの cd により git の向き先を変える(PowerShell にはこのチェックは適用されない) 止まる 通常は不要
実行内容がコマンドのテキストから確認できない Bash / Monitor のコマンド 止まる(このチェックは無効化できない) 拒否されたら、単純なコマンドに分けて書き直す(Claudeに書き直し方が示される)
git を介さずに cp やシェルのリダイレクトでメインに書き込む 止まらない permissions と sandbox の設定で制御する

最後の行は、チェックが編集対象のパス、コマンドの実行ディレクトリ、コマンドのテキストだけを読んでいて、シェルコマンドがどのファイルに書くかまでは追跡しないために生じます。そうした書き込みは、通常のシェルコマンドと同じく、permissions と sandboxing の設定に従います。

同じ規則は、隔離されたセッションが起動するサブエージェントにも及びます。チェックの対象は、起動したリポジトリと、リンク元のメインのチェックアウトです。

フックを使う場合

worktreeに入っても、フック内の ${CLAUDE_PROJECT_DIR} はセッションを始めたプロジェクトルートのままです。worktreeのパスが必要なときは、フックに渡される入力JSONの cwd を読みます。cwd はClaudeの移動に追随します。

worktreeを分けても共有されるもの

公式に記載がある共有物は4つです。リポジトリの .git ディレクトリ、プロジェクトスコープのプラグイン、Bashコマンドの権限承認、未追跡のスキル・エージェント・コマンドです。特に権限承認は、worktreeをまたいで効く点に注意が必要です。

  • .git ディレクトリ: worktree内のgit操作は、メインのリポジトリの .git に書き込まれます。サンドボックスが有効でも、この書き込みは許可されます。
  • プラグイン: プロジェクトスコープで入れたプラグインは、同じリポジトリのworktreeでも読み込まれます。worktreeごとに入れ直す必要はありません(v2.1.200 以降)。
  • 権限の承認: Bashコマンドで「Yes, and don’t ask again」を選ぶと、そのルールはメインのチェックアウトの .claude/settings.local.json に保存されます。メインと、同じリポジトリの他のworktreeのすべてに効き、worktreeを消しても残ります(v2.1.211 以降)。Windowsなど、保存先がリポジトリルートにならない場合は、そのworktreeに留まります。
  • 未追跡のスキル・エージェント・コマンド: worktree側にルートの .claude/skills が無い場合(たとえば gitignore している場合)は、メインのチェックアウトのプロジェクトスキルが読み込まれます。worktree側に .claude/skills があれば、そのコピーだけが読み込まれます。.claude/agents と .claude/commands も同様です。スキルについては v2.1.277 以降が必要です。

データベース、ポート、node_modules のようにファイルの外にある共有資源は、公式ドキュメントでは扱われていません。この記事でも助言は作りません。

セッション終了時のworktreeとブランチの扱い

クリーンで名前なしのセッションなら、worktreeとブランチは自動で削除されます。作業が残っていれば、残すか消すかを聞かれます。-p の非対話実行では自動の片付けは行われません。

終了時の状態と結果の対応表

対話セッションを終了するとき、Claudeは削除で失われる作業の有無を調べます。見るのは、変更済みや未追跡のファイル、チェックアウト済みサブモジュール内の未コミット作業、新しいコミットです。

worktreeの状態 終了時の結果 読者の行動
クリーン、名前なしのセッション worktreeとブランチが自動で削除される 対応不要
クリーン、名前付きのセッション 削除の前に確認される 後で使うなら残す
変更、未追跡ファイル、新しいコミットのいずれかがある 残すか削除するかを聞かれる。削除すると、ディレクトリ、ブランチ、中の作業がすべて消える 中の作業を確認してから選ぶ
状態を確認できない 自動では削除されず確認される。確認できなかった内容がプロンプトに示される 示された内容を読んで選ぶ
-p の非対話実行 終了時のプロンプトが無く、自動では片付かない。作成時のロックも残る git worktree remove で削除する。ロックで拒否されたら、先に git worktree unlock を実行する

状態を確認できないのは、変更数を数えられない場合や、サブモジュールのチェックアウトを調べられない場合です。この表は、Claudeが git で作ったworktreeに当てはまります。WorktreeCreate フックで作ったworktreeは、公式の WorktreeRemove フックの記述を参照してください。

残したworktreeに戻る

終了時にworktreeを残すと、再開用のコマンドが表示されます。そのコマンドを実行します。

claude --worktree <name> --resume

サブエージェントやバックグラウンドセッションが作ったworktreeの定期的な片付けは、この記事の範囲外です。

worktreeが作れない・拒否されたときの確認先

メッセージで原因が分かれます。ここでは、起動時にworktreeへ入れない場合、シンボリックリンクで拒否される場合、Git LFS のファイルがポインタのままの場合、Refusing to use <path> as an isolation worktree が出る場合に絞ります。

起動時にworktreeへ入れない

パスを示すエラーが出て、終了コード1で終わります。WorktreeCreate フックが作成したディレクトリ以外のものを出力した場合や、設定後にディレクトリが削除された場合に起こりえます。

シンボリックリンクで作成が拒否される

.claude、.claude/worktrees、worktreeのディレクトリ自体のどれかがシンボリックリンクだと、作成は拒否されます。エラーはリンクのパスを示すので、リンクを外して再試行してください。

Git LFS のファイルがポインタのまま

git lfs install --local で設定していると、Claude Codeが作るworktreeでは、実体ではなく LFS のポインタファイルになります。リポジトリ自身の設定にあるフィルタドライバは、作成時にスキップされるためです(v2.1.247 より前は実行されていました)。実体は、worktree内で次のコマンドを実行すると取得できます。

git lfs pull

まれに、フィルタドライバを判別できない場合などで、worktree自体が作られないことがあります。メッセージごとの対処は、公式の該当節にあります。

Refusing to use <path> as an isolation worktree

Claude Codeがそのディレクトリのgit上の素性を確認し、隔離用のチェックアウトとして採用しないと判断したときのメッセージです。拒否されたディレクトリは、作業が入っている可能性があるため、そのまま残されます。メッセージの末尾の文言で、次のように対処が分かれます。

メッセージの末尾 対処
launch from the parent checkout(再開時は Run the resume from the project checkout) worktreeの中から起動したのが原因です。メインのチェックアウトから起動し直します。worktreeを作り直す必要はありません
it contains the protected checkout 拒否されたディレクトリが、メインのチェックアウトの親(たとえばホームディレクトリ)になっています。削除はせず、worktreeのパスを変えます
its recorded path has a network spelling ネットワークパス上のworktreeへは再開されません。ローカルのパスで作り直します
上記以外 メッセージが問題と対処を示しているので、その指示に従います

it cannot be resumed or re-entered や、メインのチェックアウトのgitメタデータが調べられないという趣旨の終わり方もあります。それらの対処は、公式の該当節で確認してください。

まとめ: 最初の1回の試し方

最初は、小さな作業を2つ用意して、別々のターミナルから claude --worktree <名前> を2回実行します。隔離の範囲は、編集ツール・作業ディレクトリ・gitの向きのチェックまでです。終了時の分岐を表で確かめてから、並列の数を増やしてください。

次に読む記事は2本に絞れます。並列で作った変更のコミットやコンフリクトの扱いはClaude Codeのgit操作の解説が詳しく、作業をどう分けるかはエージェントチームの解説が扱います。

ここまでの内容は、公式ドキュメントだけでも試せます。そのうえで、自分の手で並列作業を使えるようになるために学べる場として、月額1,980円からの学習コミュニティ「AI駆動ラボ」があります。