Claude Media
worktree.symlinkDirectoriesでnode_modulesを共有(Claude Code)

worktree.symlinkDirectoriesでnode_modulesを共有(Claude Code)

Claude Codeのworktree.symlinkDirectoriesで、node_modulesなど大きなディレクトリを複製せず各worktreeへシンボリックリンク共有する設定方法と注意点。

worktree.symlinkDirectoriesとは

worktree.symlinkDirectories は、Claude Codeが新しいgit worktreeを作るたびに、指定したディレクトリを複製せずメインリポジトリからシンボリックリンク(symlink)で共有する設定です。対象は --worktreeEnterWorktree ツールで作るworktree全般です。settings.jsonの worktree オブジェクトに配列で書きます。狙いは大きなディレクトリをworktreeの数だけ増やさないことの1点です。

worktreeは新規のチェックアウトです。git worktreeはブランチごとに独立した作業ディレクトリを持ちますが、実体はメインリポジトリの .git を共有する軽量な仕組みです。node_modules のようなgit管理外のディレクトリは、作成直後のworktreeにはそもそも存在しません。放っておくとworktreeごとに npm install を回すことになり、同じ依存関係のファイルが並列セッションの数だけディスクに重複して書き込まれます。symlinkDirectories を設定しておけば、この初期セットアップ自体をスキップできます。新しいworktreeの node_modules はメインリポジトリの実体を指すリンクになり、追加の書き込みもインストール待ちも発生しません。

Claude Codeは --worktree セッションだけでなく、サブエージェントの隔離実行やバックグラウンドセッション用のworktreeも同じ仕組みで作ります。並列で走らせるセッションが増えるほど、このディレクトリ共有の効果は大きくなります。

設定しなくても共有されるものとの違い

worktreeはメインリポジトリと .git ディレクトリを共有します。この共有は symlinkDirectories を書かなくても自動で起きるので、worktree内で git commit を実行すれば、その結果はメインリポジトリの履歴にそのまま残ります。プロジェクトスコープでインストールしたプラグインや、Bashコマンドで「Yes, and don't ask again」を選んで保存した権限ルールも、同じ理由で全worktreeに自動的に及びます。設定ファイルを介さない、gitの構造そのものに根ざした共有です。

一方、node_modules.cache はgitの管理対象ではないため、この自動共有の恩恵を受けません。git管理外のディレクトリをworktree間で共有するには、symlinkDirectories のように明示的に指定する必要があります。gitが追跡しているものは自動で共有され、追跡していない大容量ディレクトリだけ自分で共有先を指定する。この線引きを押さえておくと、他の worktree 設定との役割分担も見通しやすくなります。

設定方法 — settings.jsonの書き方

書く場所はプロジェクトの .claude/settings.json でもユーザー設定でも構いません。スコープは「Any file」で、どの設定ファイルに置いても有効になります。

{
  "worktree": {
    "symlinkDirectories": ["node_modules", ".cache"]
  }
}
  • : 文字列の配列。リポジトリルートからの相対パス
  • 既定値: unset(何も指定しなければ、どのディレクトリもシンボリックリンクされません)
  • 対象: 公式ドキュメントが明記しているのは --worktree セッションと EnterWorktree で作るworktree。サブエージェントの隔離実行やバックグラウンドセッション用のworktreeも同じ作成処理を経由するため同様に対象になると考えられますが、この2ケースへの適用を名指しした記述はありません

配列に複数のパスを並べれば、node_modules 以外のビルドキャッシュや一時ディレクトリも同時に共有できます。パスはリポジトリルートからの相対パスで指定するため、モノレポで対象ディレクトリが深い階層にある場合はそこまでのパスを正確に書く必要があります。

worktree設定の使い分け早見表

worktree オブジェクトには symlinkDirectories の他にも似た役割の設定があります。何を止めたいか・何を引き継ぎたいかで選ぶ設定が変わります。

設定何をするか向いている場面
symlinkDirectories何をするか指定ディレクトリをメインリポジトリへのリンクに置き換える向いている場面node_modules など、branchが変わっても中身がほぼ同じ大容量ディレクトリ
sparsePaths何をするか指定ディレクトリ以外をチェックアウトしない(sparse-checkout)向いている場面巨大モノレポで、1 worktreeが触るのは特定パッケージだけの場合
baseRef何をするか新しいworktreeの分岐元を選ぶ(既定は origin/<default-branch>)向いている場面未pushのローカルコミットを新しいworktreeに引き継ぎたい場合
bgIsolation何をするかバックグラウンドセッションがworktree経由でしかメインリポジトリを編集できないようにする向いている場面チームでメインリポジトリへの直接編集を避けたい場合。"none" にすると隔離を止められる

sparsePaths はチェックアウトそのものを絞る設定なので、symlinkDirectories と組み合わせて使えます。モノレポで対象パッケージだけをsparse-checkoutし、そのパッケージの node_modules だけをsymlinkする、という併用が現実的です。

{
  "worktree": {
    "sparsePaths": ["packages/my-app", "shared/utils"],
    "symlinkDirectories": ["packages/my-app/node_modules"]
  }
}

baseRef は既定で "fresh" です。新しいworktreeは常に origin/<default-branch> から分岐し、リモートの最新状態と同じ内容になります。ローカルにしかない未pushのコミットを新しいworktreeへ引き継ぎたい場合だけ "head" に変更します。symlinkDirectories はどちらの baseRef とも独立して効くので、分岐元の選択とディレクトリ共有は別々に決めて構いません。

gitignoreされたファイルをworktreeに持ち込みたいときは、設定ではなくプロジェクトルートの .worktreeinclude ファイルを使います。.env のような環境ファイルはコピーする対象で、node_modules のような大容量ディレクトリはコピーではなく共有する対象、と役割が分かれています。

symlinkDirectoriesを使うときの注意点

シンボリックリンクは「同じ実体を複数の場所から見せる」仕組みです。コピーではないので、あるworktreeでの変更は即座に他のすべてのworktreeへ反映されます。この性質を理解せずに使うと、並列開発のメリットを自分で消してしまいます。

向いているのは、並列で動く複数セッションの package.json がほとんど同じで、依存関係の差分が小さいケースです。逆に、依存関係を大きく変えるbranchを試すworktreeでは symlinkDirectories の対象から外し、そのworktreeだけ独立した node_modules を持たせるほうが安全です。

対象に選べるのは実質的にgit管理外のディレクトリだけです。node_modules.cache が例に挙がるのは、どちらも通常 .gitignore に含まれるディレクトリだからです。gitが追跡しているファイルを含むディレクトリをsymlink先にすると、worktreeごとに独立しているはずの差分がメインリポジトリの実体へ流れ込み、想定しないコミットや差分が発生します。

ビルドキャッシュを共有する場合はさらに注意が必要です。.next.turbo のような、ソースコードの内容に依存するキャッシュディレクトリを複数のブランチ間でsymlink共有すると、あるworktreeでのビルドが別のworktreeのキャッシュを上書きし、古いキャッシュを参照した不整合なビルド結果を招くことがあります。symlinkDirectories に向くのは、node_modules のようにブランチが変わっても中身がほぼ同じディレクトリに絞るのが安全です。

もう1点、WorktreeCreate フックで作成ロジックそのものを置き換えている場合は要注意です。フックはgitのデフォルト挙動を丸ごと置き換えるため、SVNやPerforceなど非gitのバージョン管理と組み合わせているプロジェクトでは、公式ドキュメントが明記しているとおり .worktreeinclude が処理されなくなります。symlinkDirectories も同じ作成処理の中で実行される設定なので、同様に自動では効かないと考えられます(この点は .worktreeinclude ほど明示的な記述はなく、処理の共通性からの推論です)。ローカル設定のコピーやリンクの作成は、フックスクリプト側で自分で実装する必要があります。

lsコマンドでシンボリックリンクを確認する

設定が効いているかは、worktree内で対象ディレクトリを見れば分かります。

ls -la .claude/worktrees/<worktree>/node_modules

symlinkが効いていれば、出力の該当行が node_modules -> /path/to/main-repo/node_modules のようにリンク先を示す形式になります。-> が出ずに通常のディレクトリとして表示される場合は、設定ファイルの置き場所(プロジェクト直下の .claude/settings.json か、ユーザー設定か)か、配列に書いたパスの綴りを見直します。相対パスはリポジトリルート基準なので、モノレポでサブディレクトリの node_modules を指定する場合はそこまでのパスを正確に書く必要があります。

よくある質問

設定後、既存worktreeにも反映されますか

反映されません。設定はworktreeを新規作成するタイミングで参照されるため、既存のworktreeにあるディレクトリは複製されたままです。既存worktreeにも共有を効かせたい場合は、対象ディレクトリを手動で削除してからメインリポジトリの実体へシンボリックリンクを張り直すか、worktreeを作り直します。

メインリポジトリで対象ディレクトリを削除するとどうなるか

すべてのworktreeが同じ実体を参照しているため、メインリポジトリの node_modules を削除すると、symlink経由で参照しているworktreeも同時に依存関係を失います。共有ディレクトリの再インストール・再ビルドはメインリポジトリ側で行い、その結果を全worktreeに波及させる運用だと考えると扱いやすくなります。

gitコマンドで直接作ったworktreeにも効くか

効かないと考えられます。symlinkDirectories はClaude Codeがworktreeを作成する処理の一部として実行される仕組みのため、git worktree add のようにgitコマンドで直接作成した場合は同じ処理を経由しません(公式ドキュメントにこのケースを名指しした記述はなく、ここは処理の仕組みからの推論です)。手動で作ったworktreeで同様に共有したい場合は、自分でシンボリックリンクを張るか、そのworktree内で改めて npm install を実行することになります。

worktreeの並列運用そのもの(隔離の仕組み・サブエージェントでの使い方・掃除の挙動)はClaude Code Worktree実践ガイドにまとめています。settings.json の他のキーで起動時の挙動を絞り込みたい場合は、allowedTools/disallowedToolsで権限を絞る設定--mcp-configと--strict-mcp-configの使い分けも同じ settings.json 上で組み合わせられる設定です。

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