「is not matched by file permission checks」の対処法(Claude Code)
Write・NotebookEdit・Glob宛てのpermissionルールが効かないis not matched by file permission checks警告の直し方を解説します。書き換え先はEditとReadの2つです。
このTipsでできること
起動時のstderrにis not matched by file permission checksという警告が出て、.claude/settings.jsonに書いたWriteやNotebookEdit宛てのパスルールが実は一度も参照されていないことがあります。この記事では、なぜこの警告が出るのか、EditとReadのどちらに書き換えればよいのか、書き換えなくてよいケースの見分け方を解説します。
なぜ「is not matched by file permission checks」が出るか
Claude Codeがファイルへのアクセスを許可・拒否・確認するかどうかを判定する際、ファイルを対象にした権限ルールはEdit(path)とRead(path)の2種類しか実際には参照しません。設定ファイルや--allowedTools・--disallowedTools・--settingsフラグにWrite(path)・NotebookEdit(path)・MultiEdit(path)(廃止済みツール)・Glob(path)のようなパス付きルールを書いても、Claude Codeはそのルール自体は保持しますが、ファイル権限の判定には一切使いません。ルールを書いた側の意図と、実際の判定ロジックがずれているケースを検出するための警告です。
Permission deny rule (.claude/settings.json): Write(docs/**) is not matched by file permission checks — only Edit(path) rules are. Use Edit(docs/**) instead (Edit rules cover all file-editing tools).警告にはルールの内容・出典(どの設定ファイルか)・書き換え先が具体的に示されます。この機能自体はv2.1.210以降で有効です。それより前のバージョンでは、こうした無効なルールは警告なしにそのまま受理されていました。
この経緯は、チームで長く使い回しているsettings.jsonほど影響が大きくなります。「ドキュメントは書き換え禁止にしたい」という意図で数年前にWrite(docs/**)のdenyルールを追加し、以後誰も見直していない設定ファイルは珍しくありません。v2.1.210より前はこのルールが実は一度も機能していなくても警告が出ないため、docs/配下が実際には無防備なまま運用され続けていた可能性があります。アップグレード後にこの警告が出た場合は、単なる表記ゆれの指摘ではなく、これまで効いていなかった保護ルールが初めて可視化されたという意味で受け止め、優先度を上げて直すのが安全です。
書き換え先の対応表
ファイルを対象にした権限ルールは、ツール名にかかわらず次の2つに集約して書きます。
| 書いてしまいがちなルール | 書き換え先 | 理由 |
|---|---|---|
Write(path) | 書き換え先Edit(path) | 理由Editルールはファイルを編集するすべての組み込みツールをカバーする |
NotebookEdit(path) | 書き換え先Edit(path) | 理由同上 |
MultiEdit(path)(廃止済みツール) | 書き換え先Edit(path) | 理由同上 |
Glob(path) | 書き換え先Read(path) | 理由ファイル読み取り系のルールはReadに統一されている |
# .claude/settings.jsonの該当箇所を書き換える例{
"permissions": {
"deny": [
"Edit(docs/**)"
]
}
}--allowedToolsに渡すGlobルールだけは例外で、警告が出ません。それ以外の組み合わせはすべてEditまたはReadへの書き換えが必要です。
書き換えなくてよいケース
この警告はパス付きのルールが対象で、パスを持たない裸のツール名ルールには出ません。たとえばWriteという名前だけのdenyルールは、ツールレベルでそのまま一致判定されるため書き換え不要です。
- ✅ 書き換え不要:
"Write"(パスなし、ツール全体を対象にする裸のルール) - ❌ 書き換えが必要:
"Write(docs/**)"(特定パスを対象にしたルール)
パスを持つルールだけが、実際には参照されない無効なルールになります。
EditとReadが実際にカバーする範囲
書き換え先のEditとReadは、単に判定ロジックが参照するというだけでなく、対象範囲もツール名から想像するより広くなっています。Editルールはファイルを編集する組み込みツールすべてに適用され、ReadルールはClaudeの組み込みファイル読み取りツールに加えて、GrepやGlobでの検索、プロンプト中の@fileメンション、接続したIDEが共有する選択範囲・開いているファイルのコンテキストにもベストエフォートで適用されます。Write(path)やGlob(path)を個別に書いていた設定は、この2つのルールへ集約したほうが、実際の挙動と設定ファイルの見た目が一致します。
もう一つ覚えておく価値があるのが、ReadのdenyルールがEdit・Writeツールも道連れでブロックするという副作用です。あるパスに対してReadのdenyルールを設定すると、新規ファイルの作成も含めてそのパスへのEdit・Writeが同時に止まります。ただしNotebookEditはこの副作用の対象外なので、ノートブックファイルも含めて書き込みを一切禁止したいパスには、Readのdenyルールとは別にEditのdenyルールも用意する必要があります。この副作用はEdit側がv2.1.208以降、Write側がv2.1.228以降で有効になった機能なので、これより古いバージョンではReadのdenyルールだけを設定していても、期待した保護は働きません。
command:パラメータの類似警告と混同しない
似た性質の別の警告として、ツールの主要な入力フィールドをparam:value形式で直接指定しようとしたときのものがあります。Bash(command:rm *)のような書き方は、複合コマンドで回避可能なため無視され、これも起動時警告の対象です。対象になる主要フィールドはツールごとに決まっています。
| ツール | マッチできない主要フィールド |
|---|---|
| Bash / PowerShell | マッチできない主要フィールドcommand |
| Read / Edit / Write | マッチできない主要フィールドfile_path |
| Grep / Glob | マッチできない主要フィールドpath |
| NotebookEdit | マッチできない主要フィールドnotebook_path |
| WebFetch | マッチできない主要フィールドurl |
これらのフィールドを狙ったparam:valueルールを書いた場合の直し方は、Bash(rm *)やRead(./path)、WebFetch(domain:host)のような、各ツールが本来持つ指定子構文に書き直すことです。ファイル系ツール名そのものが実際の判定に使われない今回の警告とは原因が別なので、警告文がどちらのパターンかを読み分けてから対処します。
--allowedTools・--disallowedToolsフラグでも同じ警告が出る
この警告は設定ファイルだけでなく、コマンドラインの--allowedTools・--disallowedToolsフラグにパス付きルールを直接渡した場合にも出ます。CIの実行スクリプトにルールをインラインで書いているケースでは、設定ファイルを探しても見つからず戸惑いがちですが、原因は同じです。
claude -p "docs/READMEを更新して" \
--disallowedTools "Write(docs/**)"このように--disallowedToolsへ渡したWrite(path)ルールも、設定ファイルに書いた場合とまったく同じ理由で無視されます。警告の出典欄にはフラグ名がそのまま表示されるため、設定ファイルではなくコマンドラインの引数自体をEdit(path)へ書き換えます。無人実行のスクリプトに埋め込んだフラグほど普段は目に入りにくく、--debugを付けて実行しない限りこの種の警告に気づけないまま運用が続いてしまうことがあります。CIのビルドログにstderrをそのまま残す設定にしておくと、こうした無効なルールを早期に見つけやすくなります。
is not matchedとわかったら設定ファイル側から直す
警告は出典を丸括弧内に示します。.claude/settings.jsonのような通常のファイルパスであればそのまま編集すれば済みますが、claude-settings-<hash>.jsonという見慣れないパスが出た場合は、ディスク上に実在しないファイル名で、--settingsフラグにインラインで渡したJSON値を指しています。この場合は設定ファイルではなく、コマンドラインに渡しているJSON文字列そのものを直します。
出典がmanaged policy settingsとなっている場合は、組織の管理者が配布した設定なので、自分では直せません。管理者側へルールの修正を依頼します。組織全体に配布される設定であるぶん、同じ無効なルールが多数のメンバーの環境で同時に警告として出ている可能性が高く、個別に直すよりも配布元の設定ファイル1箇所を直すほうが早く解決します。
出力形式によっては、この警告はstderrではなく~/.claude/debug/<session-id>.txtのデバッグログに回されます。バックグラウンドセッションや--output-format json・stream-jsonで実行している場合は、機械可読な出力を汚さないための挙動なので、--debugフラグを付けて実行すればログとして確認できます。
設定例で書き換えを確認する
先ほどの警告文が示すdocs/書き換え禁止の例を、実際の.claude/settings.jsonで見比べます。書き換え前はWriteとGlobの2種類のツール名でパスを指定していますが、どちらも実際の判定には使われていません。
{
"permissions": {
"deny": ["Write(docs/**)"],
"allow": ["Glob(scripts/**)"]
}
}書き換え後は、編集の禁止をEdit、読み取りの許可をReadに集約します。ツールの種類で分けていた発想を、「読むか・編集するか」という操作の種類で分ける発想に置き換える形です。
{
"permissions": {
"deny": ["Edit(docs/**)"],
"allow": ["Read(scripts/**)"]
}
}書き換えたあとにClaude Codeを起動し直し、同じ警告が出なくなっていることを確認すれば作業は完了です。/permissionsを開いて、書き換えたルールが一覧に反映されているかもあわせて確認しておくと確実です。
権限ルールの設計を見直す機会にする
この警告に当たった場合、単に文言どおり書き換えるだけでなく、権限ルール全体をEdit/Readの2軸で設計し直す機会にもなります。ファイルの読み書きを制御したいときは、ツール名ではなく「読むか・編集するか」という操作の種類で考えると、WriteやNotebookEditのような個別ツール名に引きずられずに済みます。settings.json完全ガイドではpermissionsブロック全体の設計を扱っているので、あわせて見直すと同種のずれを他の項目でも発見しやすくなります。
よくある質問
BashやWebFetchのようなパス以外のツールにもこの警告は出ますか
出ません。この警告はファイルパスを対象にした権限ルール(Write・NotebookEdit・MultiEdit・Glob)に限定されています。BashのコマンドパターンやWebFetch(domain:...)のようなドメイン指定ルールは別の判定ロジックで、この警告の対象外です。
警告を無視してそのまま運用するとどうなりますか
該当のルールは今後も一切参照されません。denyルールのつもりで書いていた場合、意図した対象への書き込みや編集を防げていない状態が続くことになるため、セキュリティ上のギャップとして扱うのが安全です。
v2.1.210より前のバージョンで書いた無効なルールはどうなっていましたか
警告なしにそのまま受理されていました。ルールの内容自体は保存されますが、ファイル権限の判定には使われないという実態は当時から変わっていません。v2.1.210以降で初めて、このずれが警告として可視化されるようになりました。古いバージョンのまま運用している環境ほど、この種の無効なルールが手つかずで残っている可能性が高くなります。
まとめ
is not matched by file permission checksは、ファイルを対象にした権限ルールのうち、実際の判定に使われない書き方(Write・NotebookEdit・MultiEdit・Globへのパス付きルール)を検出する警告です。書き換え先はEdit(path)とRead(path)の2つに集約されており、警告文に示された出典を直せば解消します。パスを持たない裸のツール名ルールは対象外で、混同しやすいBashのcommand:パラメータ警告とは書き換え先が異なる点にも注意が必要です。v2.1.210以降で新設された警告なので、それより前のバージョンで書かれた設定ほど見直す価値があります。