Claude Media
agent viewで.claude/worktreesが溜まる原因と掃除の手順

agent viewで.claude/worktreesが溜まる原因と掃除の手順

agent viewでセッションを削除しても.claude/worktrees/にディレクトリが残る原因と、git worktree listに出ない残骸も含めた掃除の手順を示します。

agent viewでセッションを削除しても、プロジェクトの.claude/worktrees/にディレクトリが残ることがあります。原因は、削除の操作によってはworktreeが意図的に残される、あるいはgitが認識しない状態でディスクに置き去りになるためです。

後者はgit worktree listにも出ません。git worktree removeだけでは片付かず、手で消す工程が要ります。

なぜ削除したのに残るのか

agent viewでセッションを削除すると、Claudeがそのセッション用に作ったworktreeは原則として一緒に消えます。ただし「原則として」であり、消えない条件が公式に列挙されています。残骸が生まれる場面は次の6つです。

場面worktreeの扱いセッション行
別のセッションがそのworktreeを使用中、またはロック中worktreeの扱い残る(再度削除しても変わらない)セッション行not deletedと表示
未pushのコミットがあるworktreeの扱い残る(もう一度削除すると破棄)セッション行残る
gitがworktreeを認識しない(git worktree prune後など)worktreeの扱いディレクトリだけディスクに残るセッション行削除される
gitまたはWorktreeRemove hookが削除に失敗worktreeの扱い残る(原因がメッセージに出る)セッション行残る
claude rmで未コミットの変更があるworktreeの扱い残るセッション行残る
自分で作ったworktreeの中でセッションを始めたworktreeの扱いそのまま残るセッション行削除される

3行目が今回の主題です。セッションの行は消えるのに、ディレクトリは.claude/worktrees/に居座ります。git worktree listには載らないので、一覧を見ても存在に気づけません。

agent viewの削除を通らない経路でも、.claude/worktrees/は溜まります。claude -p --worktreeのような非対話実行には終了時の確認がないため、Claudeはそのworktreeを片付けません。作成時にかけたロックも、あとのセッションによるロック掃除で解かれるまで残ります。消すにはgit worktree removeを使い、ロックで拒否されたら先にgit worktree unlockを実行します。作成の起点や通常セッションの片付けはClaude Code Worktree実践ガイドにあります。

agent view自体の仕組みはClaude Codeのagent viewで扱っています。ここでは、削除の後に何が残り、どう片付けるかに絞ります。

残骸を見つける — git worktree listと実ディレクトリの突き合わせ

まず、gitが把握しているworktreeを一覧します。プロジェクトのディレクトリで実行します。

git worktree list

出てくるのは、gitに登録済みのworktreeだけです。次に、実際に.claude/worktrees/にあるディレクトリと見比べます。

ls -1 .claude/worktrees/

lsにあってgit worktree listにない名前が、gitの認識から外れた残骸です。数が多いときは、次のように未登録のものだけを拾うと手間が減ります。

for d in .claude/worktrees/*/; do
  p="$(cd "$d" && pwd -P)"
  git worktree list --porcelain | grep -qxF "worktree $p" \
    || echo "未登録: $p"
done

これは公式の手順ではなく、上の突き合わせを自動化した例です。macOSで/tmp配下など、シンボリックリンク越しのパスを使っている場合は、gitが出す実パスと文字列が合わず、登録済みなのに「未登録」と出ることがあります。削除の前にgit worktree listの出力と目視で照合してください。

掃除の手順 — 登録済みと未登録で分ける

登録済みのworktree

git worktree listに出るものは、gitの標準コマンドで消せます。

git worktree remove .claude/worktrees/<name>

未コミットの変更や未追跡ファイルがあるとgitが拒否します。中身を捨ててよいと確認できたときだけ、--forceを付けます。

git worktree remove --force .claude/worktrees/<name>

worktreeがロックされていて拒否されたら、先にgit worktree unlockを実行します。バックグラウンドで動作中のセッションが持つロックは実行中だけ保持されるため、中のセッションが生きていないかを先に確かめてください。

git worktree unlock .claude/worktrees/<name>
git worktree remove .claude/worktrees/<name>

gitが認識しないディレクトリ

git worktree listに出ないディレクトリには、git worktree removeは使えません。公式は「手で消す」としています。消す前に次を確認します。

  • 中に、まだ必要な未コミットの作業がない
  • 実行中のセッションが、そのディレクトリを作業場所にしていない
  • パスが.claude/worktrees/の直下である

確認できたら、通常のファイル削除で消します。

rm -rf .claude/worktrees/<name>

rm -rfは取り消せません。未登録の判定を誤ると、登録済みworktreeの中身を消しかねないので、直前の突き合わせを飛ばさないでください。

Windowsでは、もう一つ確かめておく点があります。worktreeの中にNTFSのジャンクションやディレクトリのシンボリックリンクがあると、リンク先のフォルダーは別の場所にある実体です。Claude Codeによる削除はリンクだけを消し、リンク先は残します(v2.1.205より前は、サブディレクトリの中にあるリンクでリンク先まで消えることがありました)。手動削除でリンクをどう扱うかは、ドキュメントに書かれていません。消す前にエクスプローラーなどで、中にリンクがないかを確かめてください。

ブランチは別に残る

worktreeを消しても、そのworktreeで作業していたブランチが自動で消えるとは限りません。公式も、claude rm --force-remove-worktreeはディレクトリだけを消し、ブランチはリポジトリに残ると説明しています。不要なブランチはgit branchで確認し、マージ済みかを見てからgit branch -dで削除します。

claude rmが返す拒否メッセージから逆引きする

claude rm <id>が拒否されたときは、メッセージの中に次の一手がコマンド付きで出ます。値はメッセージが表示したものをそのまま渡します。

拒否の理由出るコマンド消えるもの必要なバージョン
未pushのコミットがある出るコマンドclaude rm <id> --discard-unpushed消えるものworktree、ブランチ、コミット、未コミットの変更必要なバージョンv2.1.260以降
gitまたはhookがworktreeを消せない出るコマンドclaude rm <id> --force-remove-worktree <worktree-id>消えるものディレクトリだけ(ブランチは残る)必要なバージョンv2.1.268以降

--discard-unpushedは、拒否時に見せたコミットだけを破棄する仕組みです。その後にworktreeへコミットが増えていれば、再びworktreeを残して最新の状態を示します。--force-remove-worktreeは、次の3つを確認できたときにだけ提案されます。

  • .claude/worktrees/配下にある、リポジトリのリンク済みworktreeである
  • worktreeにも、チェックアウト済みのサブモジュールにも、追跡ファイルの未コミット変更がない
  • ほかのセッションの記録が、そのworktreeを指していない

サブモジュールの状態を確認できないとき(別のgitリポジトリに置き換わっているなど)は、この提案も出ません。サブモジュールの確認はv2.1.274以降の挙動です。提案されなければ、変更をコミットまたはstashする、ディレクトリを自分で消してからもう一度削除する、のどちらかになります。

待てば消えるのか — 定期スイープの対象と限界

Claude Codeには、Claudeがサブエージェントやバックグラウンドセッション向けに作ったworktreeを定期的に掃除する仕組みがあります。cleanupPeriodDaysより古いものが対象で、既定は30日、最小は1です。

ただし、スイープは次のworktreeを残します。

  • 変更・未追跡ファイル・未pushコミットが残っている
  • サブモジュールに変更・未追跡ファイルがある、または検査できない
  • --worktreeセッションで、バックグラウンドに移していないもの(経過日数を問わない)
  • 自分でgit worktree addしたもの

Claude Codeは、gitで作ったworktreeのメタデータに印を書き込み、印のないworktreeはスイープの対象にしません。hookで作られたworktreeも同じです。そのため「そのうち消える」は、作業が残っておらず、Claudeが作ったもので、30日を過ぎたものにしか当てはまりません。未登録の残骸や、作業内容の入ったworktreeは、待っても減りません。

保持期間を短くしたい場合は、settings.jsonに書きます。

{
  "cleanupPeriodDays": 7
}

この値はトランスクリプトの保持期間も兼ねます。worktreeを早く消すために値を下げると、古いセッションが/resumeの一覧から消えるのが早まります。孤立したworktreeの自動削除にも同じ日数が使われますが、上の「残されるworktree」の条件は変わりません。

溜めないための運用

溜まる量を減らすには、削除の前後で次を習慣にします。

  1. 消すセッションの成果を先にpushする。agent viewの削除はコミットしていない変更ごとworktreeを消す一方、未pushのコミットがあるときは削除が止まる
  2. 削除の警告メッセージを読み、not deletedの行があれば理由を見る。使用中のロックは、相手のセッションを閉じてからもう一度削除する
  3. 週に一度、git worktree listとls .claude/worktrees/を突き合わせる

worktreeを使いたくないリポジトリでは、worktree.bgIsolationを"none"にする選択肢もあります。バックグラウンドセッションが作業ツリーを直接編集するようになり、worktreeが作られません。並列で同じファイルを触るリスクを引き受ける設定なので、詳しくはworktree.bgIsolationの記事を参照してください。

Claudeに一覧の作成だけを任せる手もあります。CLAUDE.mdやプロンプトに次のように書くと、削除の実行と分けて確認できます。

.claude/worktrees/ の未登録ディレクトリを、git worktree list と突き合わせて
一覧にしてください。削除はせず、各ディレクトリの中身(git status 相当)も
報告してください。

削除そのものは、一覧を見た自分が実行します。rm -rfをClaudeの自動実行に任せると、突き合わせの誤りがそのまま消失につながります。

よくある質問

git worktree pruneを実行すれば解決しますか

git worktree pruneは、gitの管理情報から、ディレクトリがすでに存在しないworktreeの記録を消すコマンドです。ディレクトリ自体は消しません。公式が示すとおり、pruneの後にagent viewでセッションを削除すると、ディレクトリだけが残る典型例になります。

削除したセッションの会話は失われますか

失われません。セッションの会話のトランスクリプトは、削除しても手元に残り、claude --resumeから再開できます。agent viewでは/resumeと入力すると、削除したセッションも含む一覧から呼び戻せます(v2.1.212以降)。

worktreeの作成や削除をhookで差し替えている場合は

WorktreeRemove hookが失敗すると、worktreeとセッションが残り、hookの終了状況と標準エラー出力の冒頭がメッセージに出ます。hookの設計はWorktreeCreate/WorktreeRemove hookにまとめています。

worktreeそのものの基礎(作成の起点、共有されるもの、通常セッションの終了時の片付け)はClaude Code Worktree実践ガイドにあります。

この記事を共有:XはてブLinkedIn