Claude CodeのWorktreeCreate hookで作ったworktreeが終了時に毎回確認される
v2.1.301以降、WorktreeCreate hookで作ったworktreeは、変更が無くても終了時に保持か削除かを毎回尋ねられます。報告の内容と、公式docsから組める暫定の対処を紹介します。
WorktreeCreate hookでworktreeを作っている環境では、v2.1.301からclaude --worktreeを終了するたびに「保持するか削除するか」を尋ねられます。変更を1行も加えていなくても同じです。GitHubのissue #102775が、この挙動を回帰として報告しています。issueは2026年10月17日時点でopenで、コメントはまだありません。
この確認は不具合として入ったのではなく、v2.1.301の修正項目に由来します。ただし作り方によっては確認が不要な環境も多く、そこが争点です。
何が起きているか
報告者のhookは、git worktree addで普通のworktreeを作ったうえで、次の3つを足しています。
- 用意済みの
node_modulesを移し、npm installを省く - ローカルの
.envをメインのチェックアウトからシンボリックリンクする - バックグラウンドでビルドを始める
WorktreeRemove側はgit worktree removeを呼ぶだけです。この構成で、v2.1.300までは「何も変えずに終了するとworktreeが確認なしで消える」動きでした。Claude Code自身が作ったworktreeと同じ扱いです。v2.1.301からは、終了のたびに次の文言つきの確認が出ます。
A WorktreeCreate hook made this worktree, so Claude Code can't tell whether it has unpushed commits.
終了時の挙動の違い(報告者の環境)
v2.1.300まで
変更の無いworktreeは、終了するとWorktreeRemoveが動いて消える。
v2.1.301
変更の有無に関係なく、保持するか削除するかを尋ねられる。
再現手順はissueに書かれたとおりです。git worktree addを実行してパスをprintするWorktreeCreate hookを設定し、claude --worktreeで起動して何も変えずに終了します。報告者はmacOSで確認しています。issueにはregression・has repro・area:hooks・platform:macosのラベルが付いています。
確認が入った理由は公式の修正項目にある
v2.1.301のchangelogには、バグ修正の1行として次の項目があります。
Fixed quitting removing a worktree made by a
WorktreeCreatehook without asking when it may hold unpushed commits
つまり直された側の問題は「hookで作ったworktreeが、未pushのコミットを抱えていても確認なしで消える」ことでした。Claude Codeはhookが返したパスしか知らないので、そこが何で、何を失うのかを判断できません。そこで保守的に、毎回尋ねる設計にしたと読めます。
issueの報告者もこの意図は理解しています。そのうえで「自分のworktreeは普通のgit worktreeだから、Claude Codeが自作のworktreeに対して行う未push確認と同じ検査をかけられるはずだ」と主張しています。提案は2つです。
- hookが作ったworktreeがgitのworktreeなら、通常の未pushコミット検査を走らせる
- 旧来の自動削除に戻す設定を用意する
どちらも、issueの時点ではClaude Code側の反応が出ていません。実装されるかどうかは、今のところ分かりません。
公式docsの記述とのずれ
ずれがあるのは、v2.1.301の挙動と、hooksリファレンスのWorktreeRemoveの節です。この節は、WorktreeRemoveが動く場面の1つとして「名前を付けていないインタラクティブなセッションを終了し、変更ファイルも未追跡ファイルも見つからず、確認なしでworktreeを削除するとき」を挙げています。issueの報告と食い違うのは、記述が更新前のままだからと考えるのが自然ですが、どちらが最終形かはissueの結論待ちです。
同じ節には、Claude Codeが変更ファイルや未追跡ファイルを調べるのにgitを使うこと、そのためgitのチェックアウトでないディレクトリでは、未コミットの作業があっても何も見つからないことも書かれています。作業の有無の確認はWorktreeRemoveに任せる設計が、元々のdocsにあります。
影響を受ける人と受けない人
hookの中身で、影響は分かれます。
| 状況 | 終了時の確認 |
|---|---|
WorktreeCreate hookでworktreeを作っている | 終了時の確認v2.1.301から毎回出る |
claude --worktreeでClaude Code自身がgitで作ったworktree | 終了時の確認公式docsどおり(変更が無い無名セッションは確認なしで削除、名前付きは確認) |
-pで起動した非対話実行 | 終了時の確認確認自体が無い(worktreeも自動では消えない) |
Sub-agentやclaude remote-controlが使うworktree | 終了時の確認別の経路。issueの報告範囲外 |
hookを使わない大半のユーザーは関係しません。影響が大きいのは、報告者のように依存の用意や環境変数ファイルの配置のためにhookでgit worktreeを作っているチームです。確認が毎回出ると、並列セッションを何本も回す運用では、終了のたびに入力待ちが挟まります。
自分の環境が当たるかを確かめる
確認の原因がhookにあるのか、別の要因なのかは、次の手順で切り分けられます。判断の軸は「worktreeを作ったのがhookかどうか」と「バージョン」の2つです。
終了時の確認が出る原因の切り分け
- Qclaude --versionがv2.1.301以降か?答えがv2.1.300以前答えがはい
この確認とは別の要因です。名前付きセッション(
--worktreeに名前を渡した場合)は、公式docsでも変更が無くても確認が出ます。 - Qsettings.jsonにWorktreeCreate hookを設定しているか?答えが設定していない答えがはい
Claude Code自身が作ったworktreeなので、今回の件は当たりません。変更や新しいコミットがあれば確認が出るのは通常の動作です。
今回の件に当たる
hookが作ったworktreeで、変更が無いのに確認が出ています。次の節の暫定対処1と2を検討してください。
バージョンは次のコマンドで見られます。hookの設定は、プロジェクトの.claude/settings.jsonと、ユーザーの~/.claude/settings.jsonの両方に書ける場所です。チームで共有しているリポジトリでは、自分が書いていないhookが入っていることもあります。
claude --version
grep -n "WorktreeCreate" .claude/settings.json ~/.claude/settings.json2行目は、どちらかのファイルにWorktreeCreateの記述があるかを行番号つきで返します。片方のファイルが無いときは、そのファイルについてのエラーが出ますが、もう片方の結果には影響しません。
暫定の対処
設定リファレンスのworktree系のキー(baseRef・bgIsolation・location・sparsePaths・symlinkDirectories)に、終了時の確認を切るものは載っていません。報告者が挙げるSessionEnd hookも、確認より後に動くので回避になりません。公式docsの記述から組める手は、次の3つです。
1. 確認に「削除」と答える
確認で削除を選ぶと、WorktreeRemove hookが動いてworktreeが消えます。挙動は変わらず手間が1回増えるだけで、未pushかどうかの判断は人が持ちます。
2. WorktreeRemoveに未push検査を持たせる
どうせ確認が出るなら、WorktreeRemoveの側で「失ってよい状態か」をスクリプトに検査させ、危ないときは削除を中止する構成にできます。非ゼロで終わった場合、そのパスのディレクトリがまだ存在していれば削除は失敗扱いになり、worktreeはディスクに残ります。この仕様を安全弁に使えます。
次は、公式の説明を踏まえた設計例です(実機で動作を確認したものではありません)。
#!/bin/bash
# WorktreeRemove: 変更や未pushのコミットがあれば削除せず終了する
path=$(jq -r '.worktree_path')
if [ -n "$(git -C "$path" status --porcelain 2>/dev/null)" ]; then
echo "未コミットの変更があるため削除しません: $path" >&2
exit 1
fi
if [ -n "$(git -C "$path" log HEAD --not --remotes --oneline 2>/dev/null)" ]; then
echo "未pushのコミットがあるため削除しません: $path" >&2
exit 1
fi
git worktree remove "$path"status --porcelainは変更ファイルと未追跡ファイルを、log HEAD --not --remotesは、そのworktreeのHEADから届くコミットのうち、どのリモートにも無いものを拾います。他のブランチの未pushコミットには反応しません。この構成は確認そのものは消しません。確認で「削除」を選んだときの取りこぼしを防ぐためのものです。
3. ExitWorktreeで抜けてから終了する
hooksリファレンスによると、セッション中にClaudeへworktreeからの退出と削除を頼み、ClaudeがExitWorktreeツールで削除する経路では、Claude CodeはWorktreeRemoveの前に確認を出しません。ExitWorktreeはhookで作られたworktreeを、discard_changes: trueが渡されない限り削除しないとも書かれていて、その場合はWorktreeRemove hookが最後の検査になります。したがって2の検査スクリプトとの併用が前提です。
この経路の後で通常の終了操作を行ったとき、確認が出るかどうかは、公式docsに記載がありません。試すなら、捨てても困らないworktreeからにしてください。
暫定対処を選ぶ目安
どれを選ぶか
1だけ
hookは変えず、確認のたびに自分で判断する。人数が少ない環境向きです。
1と2
確認は残るが、誤って「削除」を選んでも未pushのコミットは守られる。チームで共有するhookに向きます。
3は、確認を減らしたい人が試す余地のある手段で、効果は未確認です。設定リファレンスのworktree系キーにも、issue #102775の提案にも、確認を切る設定はまだありません。進捗はissueで追えます。
v2.1.300に戻す前に確認すること
確認が煩わしいからと、v2.1.300へ戻す選択肢もあります。戻すと、今回の修正の対象だった「未pushのコミットが確認なしで消える」状態にも戻ることになります。v2.1.301には、確認の変更のほかに、fableエイリアスが使えないモデルを指してエラーになる問題の修正などが入っています。
戻す場合は、先にWorktreeRemoveへ2の検査を入れておくと、未pushのコミットが消える経路を塞げます。この検査は、修正が入った後も保険として残せます。
今後の注目点
issueは、hookが作ったworktreeに対しても、gitのworktreeなら通常の検査を使うか、旧挙動に戻す設定を用意するかの選択を、Claude Code側に求めています。どちらになるかで、WorktreeRemoveに持たせる検査の量が変わります。WorktreeCreateの仕組み自体はWorktreeCreate/WorktreeRemove hookの解説記事に、worktree隔離の全体像はWorktree実践ガイドにあります。v2.1.301の他の変更はv2.1.301のリリースノートで確認できます。