Claude Codeで依存ライブラリのソースを読む — add-dirで足しdenyで書込を止める
依存ライブラリの実装を読ませて挙動を確かめるとき、--add-dirで実体ディレクトリを足し、Edit denyで書き込みだけ止める設定と、答えにファイル:行を付けさせる検証を示します。
ライブラリのドキュメントに書かれていない挙動は、ソースを読めば分かります。Claude Codeにその実装を読ませるなら、--add-dirで実体のディレクトリを足すのが近道です。ただし--add-dirが与えるのは読み取りだけではありません。
Claude Codeの--add-dirは「ファイルを読んで編集するための作業ディレクトリを足す」フラグです。足した先は編集も許可の対象になります。site-packagesやnode_modulesを足したまま作業を任せると、ライブラリ本体を書き換えられる状態になります。
この記事では、足す手順、permissions.denyのEditルールで書き込みだけを止める設定、答えに「ファイル:行」を付けさせて検証する流れを順に示します。
ライブラリを読むのに --add-dirが要る場面
プロジェクト直下のnode_modulesは、すでに作業ディレクトリの中にあります。追加の指定なしで読めるので、--add-dirは要りません。
足す必要があるのは、作業ディレクトリの外にあるソースです。
- 仮想環境が別の場所にあり、
site-packagesが作業ディレクトリの外にある - グローバルにインストールしたパッケージの実体を読みたい
- ライブラリのリポジトリを隣のディレクトリに
git cloneしてある - モノレポの別パッケージを、別セッションで開かずに参照したい
足す書式は、フラグに複数のパスを並べるだけです。存在するディレクトリでなければ、追加は検証で止まります。
claude --add-dir ~/work/.venv/lib/python3.12/site-packages \
../some-libraryセッション中に足すなら/add-dir、毎回足すなら設定ファイルのpermissions.additionalDirectoriesです。実体のパスを解決できない場合の対処は、add-dirで「couldn't be resolved」と出る原因にまとめています。UNCパスのようなネットワークパスが足せない制約は別の記事の領分です。
足した先は書き込みも許可の対象になる
追加ディレクトリのファイルには、元の作業ディレクトリと同じ権限規則が適用されます。読み取りはプロンプトなしで通り、編集は現在の権限モードに従います。
この「現在の権限モードに従う」が落とし穴です。
| 権限モード | 追加ディレクトリへの編集 |
|---|---|
default | 追加ディレクトリへの編集確認が出る |
acceptEdits | 追加ディレクトリへの編集作業ディレクトリとadditionalDirectoriesのパスは自動で通る |
bypassPermissions | 追加ディレクトリへの編集確認なしで通る |
acceptEditsは、作業ディレクトリとadditionalDirectoriesのパスについて、ファイル編集とmkdir・touch・mv・cpのような基本的なファイル操作を自動承認します。ライブラリを読むだけのつもりで足したディレクトリが、承認なしで書き換えられる対象に入ります。
だから、足すときは書き込みを止めるルールをセットで置きます。
Editのdenyで書き込みだけを止める
止めるのはEditのdenyルールです。Editルールは、ファイルを編集する組み込みツール全般に効きます。読み取りはReadルールの担当なので、Editを止めても読み取りには影響しません。
パスの書き方は、アンカーで決まります。
| 書き出し | 意味 |
|---|---|
//path | 意味ファイルシステムのルートからの絶対パス |
~/path | 意味ホームからのパス |
/path | 意味設定ファイルの置き場所を基準にしたパス |
path・./path | 意味カレントディレクトリからのパス |
作業ディレクトリの外を指すので、//の絶対パスか~/を使います。設定にはこう書きます。
{
"permissions": {
"additionalDirectories": [
"/Users/alice/work/.venv/lib/python3.12/site-packages"
],
"deny": [
"Edit(//Users/alice/work/.venv/lib/python3.12/site-packages/**)"
]
}
}additionalDirectoriesの方は通常の絶対パス、denyの方は//で始まる点が違います。/Users/...と一本スラッシュで書くと、設定ファイルの置き場所を基準にしたパスとして読まれます。
置く場所は、個人用の.claude/settings.local.jsonが向いています。プロジェクトの.claude/settings.jsonに書いたadditionalDirectoriesは、フォルダーを信頼するダイアログを承認するまで有効になりません。denyは制限を足すだけなので、この待ちの対象外です。
denyルールが警告で空振りしていないかは、matches no toolの警告の読み方で確かめられます。設定ファイル全体の構造はsettings.jsonの解説にあります。
denyが止めるものと止めないもの
Editのdenyは、Claude Codeが組み込みで扱う編集に効きます。Bashで書き込む場合も、sedやteeのようにClaude Codeが認識するファイルコマンドと、> fileのようなリダイレクト先には適用されます。
一方、ファイル名を明示しない操作は対象外です。たとえばPythonやNodeのスクリプトが自分でファイルを開いて書き込む場合は、denyルールをすり抜けます。
読み取り専用を確実にしたいなら、OSレベルで強制するサンドボックスを併用します。選び方はサンドボックスの早見表で比べられます。
シンボリックリンクについては、denyルールは要求されたパスと、その解決先のどちらかが一致すれば適用されます。仮想環境やpnpmのようにリンクで実体へ飛ぶ構成でも、実体側のパスで書いておけば守れます。
編集ツール自体を外す方法との違い
--disallowedTools "Edit"のように、ツール名だけを指定する方法もあります。この場合はEditツールそのものがClaudeのコンテキストから消えます。ライブラリを読むだけのセッションなら成立しますが、手元のコードも直せなくなります。
パス付きのEdit(...)ルールなら、ツールは残ったままライブラリ側だけを止められます。読み取りと自分のコードの修正を同じセッションで回すなら、こちらを使います。
読ませて、答えに「ファイル:行」を付けさせる
足して守ったら、読ませる番です。ここで大事なのは、推測で答えさせないことです。ライブラリの挙動を訊くと、モデルは訓練時に見た別バージョンの記憶で答えることがあります。ソースを読ませたことを、答えの形で確かめられるようにします。
プロンプトの例です。
requests のリトライの挙動を知りたい。
site-packages の実装を読んで答えて。
根拠は「ファイル:行」の形で全部付けて。
読んでいない推測は「推測」と明記して。もう一つ、CLAUDE.mdに常設しておく方法もあります。
## ライブラリの挙動を答えるとき
- 追加ディレクトリのソースを先に読む
- 結論ごとに「パス:行番号」を付ける
- 該当箇所が見つからなければ、見つからなかったと答える返ってきた答えは、そのまま信じずに数行だけ開いて突き合わせます。
sed -n '120,140p' \
~/work/.venv/lib/python3.12/site-packages/requests/adapters.py引用された行が実在し、主張と一致していれば、その答えはソース由来だと言えます。行番号がずれていたり、そのファイルが存在しなかったりした場合は、記憶で答えた可能性があります。読み直させる合図になります。
「ファイル:行」を付けさせる運用には、副次的な効果もあります。バージョンの食い違いに気づきやすくなります。付いたパスの中にあるバージョン番号や、.dist-infoの名前から、今のプロジェクトが使っている版を読んだのか確かめられます。
質問の立て方で、読む範囲が決まる
追加したディレクトリは広大です。site-packagesには何十ものパッケージが入っているので、「このライブラリの挙動は?」と漠然と訊くと、関係のないファイルまで開きにいきます。入口を指定して絞ります。
- 対象のパッケージ名を明示する(例:
requests、urllib3) - 挙動を確かめたい関数かオプションの名前を挙げる
- 呼び出しの入口から、実際に分岐する箇所まで辿るよう頼む
- 辿ったファイルと行を、順番に並べさせる
たとえば「Retryのbackoff_factorが待ち時間にどう効くか、urllib3の実装を呼び出しの入口から順に辿って」と頼めば、答えは辿った経路の形で返ります。経路が長いほど、途中の1行を自分で開いて確かめやすくなります。
Node.jsの場合は、手元のnode_modulesをそのまま読ませれば足ります。グローバルにインストールしたツールの実体を読みたいときだけ、そのnode_modulesを足します。pnpmのようにリンクで実体へ飛ぶ構成では、リンクの先にあるストア側のパスでdenyを書いておきます。
同じ設定を複数のライブラリに使い回す
読みたいライブラリが増えると、additionalDirectoriesとdenyの組が増えます。ディレクトリを1つ決めて、そこに読みたいリポジトリをgit cloneでまとめる運用にすると、additionalDirectoriesとEdit(//.../**)が1組で済みます。denyの**は配下全部に及ぶので、クローンを足しても設定を書き足す必要がありません。
ライブラリのバージョンを揃えたいなら、読む前にgit checkoutでプロジェクトが使っているタグへ切り替えておきます。これも編集ではなく読み取りの準備なので、Claudeに頼まず自分で行うのが確実です。
書き込みが止まっているかを先に試す
設定したら、本番の質問の前に一度だけ試します。
- 足したディレクトリ内の適当なファイルに、コメント行を1行足すよう頼む
- 編集が拒否されることを確認する
- 同じファイルを読んで要約するよう頼み、読み取りは通ることを確認する
拒否されたのに、後からsed -iやスクリプトで回避しようとする動きが出たら、サンドボックスの出番です。読むだけのセッションはacceptEditsにせず、defaultかplanで回す手もあります。planは--permission-mode planで始められます。
追加ディレクトリ側の .claudeは何が読み込まれるか
ライブラリのリポジトリを丸ごと足すと、そこに.claude/があることがあります。--add-dirで足した場合は、.claude/skills/のスキル、.claude/commands/のコマンド、.claude/agents/のサブエージェントが読み込まれます。設定ファイルからはenabledPluginsとextraKnownMarketplacesだけが対象です。
CLAUDE.mdは、環境変数CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1を設定したときだけ読まれます。
permissions.additionalDirectoriesで足したディレクトリは、ファイルアクセスだけを与え、上の設定類は読み込みません。他人のリポジトリのソースを読むだけなら、設定ファイル経由の追加の方が余計なものを取り込みません。
読めない・止まらないときの切り分け
足したのに読めない場合は、まずパスの綴りと、そのディレクトリが実在するかを見ます。--add-dirは存在するディレクトリかどうかを検証するため、存在しない場所は足せません。
denyが効かない場合は、書き出しのスラッシュの数を疑います。//が絶対パス、/が設定ファイルの置き場所基準です。ここを取り違えると、ルールは別の場所を指します。読み取り専用のつもりが編集できてしまうのは、たいていこの取り違えか、additionalDirectoriesとdenyで別のパスを書いたときです。パスはコピーして揃えます。
使い分けの早見表
| 状況 | 足し方 | 守り方 |
|---|---|---|
| 一度だけ読む | 足し方claude --add-dir <path> | 守り方Edit(//...)のdeny |
| 同じライブラリを繰り返し読む | 足し方permissions.additionalDirectories | 守り方同じ設定ファイルにdenyを併記 |
| 他人のリポジトリを丸ごと参照 | 足し方設定ファイル経由 | 守り方deny + サンドボックス |
| 書き込みを絶対に許したくない | 足し方どちらでも | 守り方サンドボックスで強制 |
まとめ
--add-dirは読み取り専用の機能ではないので、ライブラリの実体を足すならEditのdenyを同じ設定に置きます。denyはClaude Codeが認識する編集に効く一方、スクリプト経由の書き込みは止められません。確実に止めたいときはサンドボックスが担当です。
答えの信頼性は、「ファイル:行」を付けさせ、数行だけ自分で開いて突き合わせることで担保できます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。