WorktreeCreate / WorktreeRemove(ワークツリークリエイト・ワークツリーリムーブ)

フック
WorktreeCreate / WorktreeRemove
ワークツリークリエイト・ワークツリーリムーブ
Claude Code が並列セッション機能のために作業フォルダを切ったり消したりする処理を、自分のスクリプトに差し替えるための1対のフック。WorktreeCreate は作成処理を丸ごと置き換え、WorktreeRemove は削除タイミングで観察・掃除を走らせる

Claude Code を git 以外のバージョン管理(SVN / Mercurial)で使っていて並列セッション機能を自前で再現したい人、または git 環境でも worktree 作成・削除に独自処理を仕込みたい人向け

SVN や Mercurial で動いているプロジェクトに Claude Code を導入して --worktree を成立させたいとき、または git プロジェクトで作成時に依存関係インストールや認証ファイルのコピー、削除時にログ送信などの独自処理を1か所にまとめたいときに .claude/settings.json の hooks セクションに書いて仕込む

Claude Code は並列セッション機能を持っています。同じプロジェクトを別のフォルダにコピーして、同時に複数の作業を走らせる仕組みです。これを発動するとき、内部では git worktree add が自動で叩かれます。WorktreeCreate は、この「作成処理そのものを丸ごと自分のスクリプトに差し替える」ためのフックです。git の代わりに SVN や Mercurial で working copy を切り出したり、作成時に依存関係のインストールやログ送信を仕込みたいときに使います。

WorktreeRemove はその対になる削除フック。ただし役割は非対称で、こちらは観察専用です。セッション終了や subagent の完了で worktree が消されるタイミングで発火しますが、削除自体を止めることはできません。掃除処理・ログ送信・リソース解放を仕込む場所として割り切るのが正解です。

噛み砕くと

会社のオフィスを想像してください。普通は「会議室を取る予約システム」が決まったやり方で部屋を割り当てます。WorktreeCreate は、その予約システムごと「うちの会社独自のルールで部屋取りますんで」と差し替える仕組みです。Claude Code は本来 git で作業フォルダを切り出しますが、このフックを置くと git をすっ飛ばして、自分の書いた手順だけが走ります。

差し替えなので、git 環境でこのフックを置くと git worktree add が動かなくなります。Claude Code は「うちのスクリプトに任せたから git は呼ばない」と判断します。これが落とし穴になりやすいので頭に入れておきます。

もう1つ大事なこと。Claude Code のフックは普通「exit 2 だけが操作を止める特別な合図」です。それ以外の非ゼロ終了は警告扱いで操作は続行します。ところが WorktreeCreate はこの慣例から外れていて、非ゼロ終了が全部 blocking。1でも127でも、ゼロ以外で終わると worktree 作成は中止されます。これも頭に入れておきます。

大事な前提:git 以外で使うときと git 環境で使うときで意味が違う

このフックを置く動機は2パターンあります。1つ目は git 以外のバージョン管理を使っているケース。SVN や Mercurial で動いているプロジェクトに Claude Code を導入すると、デフォルトの git worktree は当然失敗します。そこで WorktreeCreate に「svn checkout してこい」と書いて、git の代わりを務めさせます。2つ目は git 環境のままで作成時の独自処理を足したいケース。並列セッション起動時に自動で npm install を走らせたり、社内ログサーバーに通知したりという用途です。

もう1つ、地味だけど重要な前提が .worktreeinclude の扱い。git デフォルトの worktree 作成では、本来コピーされない gitignore 対象ファイルを「これは新しい worktree にも持っていってほしい」と指定する仕組みがあります。たとえば .envnode_modules の一部設定がここで指定対象になります。WorktreeCreate を置いた瞬間、この自動コピーは止まります。差し替えなので当然です。必要なら自分のスクリプトの中で cp なりなんなりで明示的に運ぶ必要があります。

「会社のSVNで動いている古いウェブサービス」を例に、実際の手順を見る

題材として、会社の SVN サーバーで動いている古いウェブサービスを想定します。普段は1人で1つの feature を進めていますが、急なバグ修正が降ってきて、いま触っている feature とは別の場所で trunk から checkout し直して並行作業したい場面。claude --worktree fix-login-bug と叩けば、Claude Code が新しい作業フォルダを切ってくれて、いまのセッションを止めずに別件を進められるようにします。git なら標準機能で済みますが、SVN なのでフックで差し替えます。

ステップ1: フックを書く場所を決める

プロジェクトのルートに .claude/settings.json があるので、ここに hooks セクションを足します。チーム全員に配るなら .claude/settings.json(git 管理下)、自分だけなら .claude/settings.local.json(git 管理外)に書きます。

ステップ2: WorktreeCreate の中身を書く

公式が SVN 向けに出しているサンプルをそのまま使います。受け取った JSON から name(worktree の名前)を取り出し、$HOME/.claude/worktrees/<名前> に SVN の trunk を checkout し、最後に標準出力へ作業フォルダの絶対場所を1行で出す形です。

{
  "hooks": {
    "WorktreeCreate": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/.claude/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
          }
        ]
      }
    ]
  }
}

標準入力で受け取る JSON に含まれるのは session_id cwd hook_event_name、そして worktree の作成リクエスト名 name など。今回は jq -r .name で名前だけ取り出して使っています。svn checkout の進捗ログは >&2 という書き方で標準エラー側へ逃がします。標準出力は最後の echo "$DIR" 1行だけにします。ここが大事で、Claude Code は標準出力に出てきた文字列を「作成された作業フォルダの場所」として受け取ります。余計な出力が混ざると場所が壊れます。

ステップ3: WorktreeRemove で掃除する

セッションを閉じたとき、SVN の working copy が $HOME/.claude/worktrees/ に残り続けるとローカルが散らかります。WorktreeRemove で消すように仕込みます。

{
  "hooks": {
    "WorktreeRemove": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'DATA=$(cat); DIR=$(echo \"$DATA\" | jq -r .worktree_path); rm -rf \"$DIR\"'"
          }
        ]
      }
    ]
  }
}

受け取る JSON にはすでに削除対象の worktree_path が入っています(これは WorktreeRemove 固有のフィールドで、消そうとしているフォルダの絶対場所が文字列で渡ってきます)。これをそのまま rm -rf に渡すだけ。注意:このフックは観察用なので、ここで exit 1 しても削除自体は止められません。ログ送信や掃除の失敗があっても Claude Code は粛々と次に進みます。

ステップ4: 実際に並列セッションを切ってみる

ターミナルで以下を叩きます。

$ claude --worktree fix-login-bug

Claude Code は内部で WorktreeCreate フックを発火し、JSON を渡して結果を待ちます。フックが $HOME/.claude/worktrees/fix-login-bug を出力して終わると、Claude Code はそのフォルダで新しいセッションを開始します。これで元のセッションはそのまま、別のセッションでバグ修正を進められる状態になりました。

ステップ5: ここで初心者がよくやる勘違い

svn checkout の進捗ログを echo で出しちゃえばいいや」と書くと、Claude Code はその進捗ログを「作業フォルダの場所」として受け取ってしまい、存在しない場所を指して落ちます。SVN や git のコマンドが普通に出してくる進捗・ステータスは、全部 1>&2 で標準エラー側に逃がす。標準出力は 最後の絶対場所1行だけ。これがコマンド型フックの作法です。

ステップ6: セッションを閉じる

Claude Code を終了すると WorktreeRemove が発火し、$HOME/.claude/worktrees/fix-login-bugrm -rf で消えます。ローカルに散らかさず、必要なときだけ working copy を持つ運用が成立します。

つまり WorktreeCreate / WorktreeRemove は何をしてくれるのか

  • やってくれる: 並列セッションのために作業フォルダを作る処理(WorktreeCreate)と、消す処理(WorktreeRemove)をユーザー側のスクリプトに丸ごと差し替えること。git 以外のバージョン管理でも --worktree 機能を成立させられる
  • やってくれない: WorktreeRemove での削除中断。観察専用なので、ここで止めようとしても無視される。掃除や記録に限定して使う
  • 意味が薄い場面: 純粋な git プロジェクトで標準動作のままで満足できているとき。フックを置いた瞬間に .worktreeinclude も標準処理も全部止まるので、足したい処理が少しだけなら別フック(PostToolUse など)で済ませた方が安全

使いどころ3シナリオ(具体題材で再現)

シナリオ1: 会社の SVN で動く古い基幹システムで Claude Code を試したいとき

SVN は 2026年現在も金融・製造系の社内システムでは現役です。Claude Code を導入したくても git worktree が動かないので並列セッション機能が使えない、と諦める前に WorktreeCreate を置きます。1つの基幹システムに対して「経費精算画面の改修」と「ログイン周りの調査」を同時に走らせたい、みたいな並列ニーズが出てきたとき、本文サンプルの形で SVN checkout を差し込めば --worktree がそのまま使えます。チーム全員に配る場合は .claude/settings.json に置いて git で配布します。

シナリオ2: git プロジェクトだが worktree 作成時に npm install を自動で走らせたいとき

家計簿アプリのフロントエンドが Node.js 系で、新しい worktree を切るたびに node_modules を入れ直す必要がある状況。普通は人間が手で cd して npm install しますが、これを WorktreeCreate に書いておくと自動化できます。ただし注意:このフックを置くと git worktree add も自分のスクリプトで再現する必要が出てきます。「git の標準動作にちょい足ししたいだけ」なら、後述するように別の場所で npm install を走らせる方が無難です。本フックは「処理全体を差し替える」性質なので、軽い追加処理には重い選択肢になります。

シナリオ3: 並列セッション終了時に社内ログ基盤へ作業時間を送りたいとき

料理ブログ運営チームで Claude Code の利用時間を社内 Slack に通知したい、というような運用。WorktreeRemove はちょうど「セッションを閉じた瞬間」に発火するので、JSON から session_idworktree_path を拾って curl で Slack Webhook に投げれば、誰がどの作業を何分やったかが自動で記録できます。削除を止められない仕様は、こういう「観察と通知」用途とは相性が良い設計です。

初心者が踏みやすい落とし穴

  • git 環境で WorktreeCreate を置いた瞬間に git worktree add が動かなくなる。フックは「差し替え」なので、ちょい足し用途では使わない。標準動作に追加処理を足したいだけなら、別フックを検討する
  • 標準出力に絶対場所以外を1文字でも出すと作成失敗扱いになるsvn checkoutgit clone の進捗ログは必ず 1>&2 で標準エラーに逃がす。echo "$DIR" だけが標準出力に残る形が正解
  • WorktreeCreate だけ「非ゼロ終了が全部 blocking」という例外仕様。他のフックは exit 2 だけが特別だが、ここは違う。スクリプトの最後で意図せず exit 1 が走らないように set -e の挙動とエラーハンドリングを確認する
  • .worktreeinclude の自動コピーは止まる.env や認証ファイルを新しい worktree でも使いたい場合、フックスクリプト側で cp を仕込まないと参照できずに作業が止まる
  • WorktreeRemove で exit 1 しても削除は止められない。「失敗したから消さない」ロジックは書けない。観察と記録に徹する。掃除を止めたい場合は SessionEnd など別のフックを使う
  • Matcher が使えないので両フックとも常時発火する。特定の worktree 名や条件でだけ動かしたい場合は、スクリプトの中で JSON の name(作成時)や worktree_path(削除時)を見て自分で条件分岐する必要がある
  • システム本体の保存場所には絶対に作業フォルダを切らない$HOME/.claude/worktrees//tmp/ 配下に限定する。rm -rf が走るので、間違った場所を指すと取り返しがつかない

書き方

settings.json に hooks.WorktreeCreate / hooks.WorktreeRemove を定義(どちらも Matcher 指定なし、常時発火)

やってみるとこうなる

入力

{
  "hooks": {
    "WorktreeCreate": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/.claude/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
          }
        ]
      }
    ],
    "WorktreeRemove": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'DIR=$(jq -r .worktree_path); rm -rf \"$DIR\"'"
          }
        ]
      }
    ]
  }
}

出力例

WorktreeCreate の標準入力には {"session_id":"abc123","cwd":"/Users/me/projects/legacy-svn-app","hook_event_name":"WorktreeCreate","name":"fix-login-bug"} のような JSON が流れてくる(公式 SVN サンプルが jq -r .name で読み取るフィールド)。スクリプトは標準出力に作業フォルダの絶対場所1行だけを出して exit 0 で終わると成功。1文字でも余計な出力が混ざると場所が壊れる。他のフックと違い、ゼロ以外の終了コードはすべて作成中止(blocking)になる例外仕様。WorktreeRemove は {"session_id":"abc123","hook_event_name":"WorktreeRemove","worktree_path":"/Users/me/.claude/worktrees/fix-login-bug"} を受け取って掃除するだけで、終了コードは無視される(削除自体を止められない観察フック)

このページに出てきた言葉

worktree
同じプロジェクトを別フォルダにコピーして複数作業を同時に走らせる仕組み。Claude Code は <code>--worktree</code> を付けて起動すると <code>~/.claude/worktrees/</code> 配下に作業用コピーを切り出す
working copy
SVN や Mercurial で「サーバーから取ってきたファイル一式が置いてある作業用フォルダ」のこと
subagent
Claude Code がメインの会話とは別に裏で走らせる小さなセッション。完了すると WorktreeRemove が発火する場面もある
SVN
Subversion の略。git より古いバージョン管理の仕組みで、企業の昔からあるシステムでまだ現役
Mercurial
git と同時期に登場したバージョン管理。今は git に押されているが残っている現場がある
blocking
「処理を止めてその先に進ませない」という意味。WorktreeCreate ではゼロ以外の終了コードがすべて blocking 扱いになる例外仕様がある
.worktreeinclude
git の worktree 作成時に「gitignore 対象だけど新しい worktree にも持っていく」ファイルを指定する仕組み。WorktreeCreate を置くと自動処理は止まる
trunk
SVN でいう「メインの最新版」の置き場所。git でいう <code>main</code> ブランチに相当
標準出力 / 標準エラー
コマンドが結果を吐く出口が2つあり、片方が普通の結果用、もう片方が進捗・エラー用。<code>1>&2</code> は普通の結果用に出そうとしたものをエラー側に流す書き方

関連項目

公式ドキュメント

https://code.claude.com/docs/en/hooks

-

← 戻る