原典: Configure permissions / 日本語版
一行要約
ルールは deny → ask → allow の順に評価され、最初に一致したものが結果を決める(具体性は順序を変えない)。したがって広い deny ルールに狭い allow の例外を持たせることはできない —— 例外を切れるのは、パスのルール(Read / Edit)で、同じ設定ファイルの deny / ask リストの中に ! を並べるときだけである(Bash のルールには効かない)。
要点
3階層の権限システム
| ツール種別 | 例 | 承認が要るか | 「今後聞かない」の効果 |
|---|---|---|---|
| 読み取り専用 | ファイル読み取り、Grep | 不要(作業ディレクトリと追加ディレクトリ内) | — |
| Bash コマンド | シェル実行 | 必要(組み込みの読み取り専用コマンドを除く) | リポジトリとコマンドごとに永続 |
| ファイル変更 | Edit / Write | 必要 | セッション終了まで |
| Web fetch | WebFetch | 必要(組み込みの事前承認ドメインを除く) | リポジトリとドメインごとに永続 |
| Web search | WebSearch | 必要 | リポジトリごとに永続 |
永続する承認の保存先(間違えやすい): 「Yes, and don’t ask again」で永続する承認は
.claude/settings.local.json に保存される。場所は git リポジトリのルートで、
worktree はメインのチェックアウトへ解決される。同じリポジトリ内なら、サブディレクトリで
始めたセッションや worktree でも効く。v2.1.211 より前は常に起動ディレクトリに保存していたので、
worktree やサブディレクトリで与えた承認はリポジトリの他の場所に効かなかった。
「今後聞かない」が出ないことがある。 Claude Code がこの選択肢を出すのは、
その選択肢が許すことを全部プロンプトに表示できるときだけ。1回限りの承認しか出ないときは、
1回だけ承認するか、/permissions で自分でルールを足す。
Bash / PowerShell のプロンプトでは Ctrl+E でコマンドの説明(何をするか、なぜ走らせるか、
何が起こりうるか)を Low risk / Med risk / High risk のラベル付きで表示できる。
モデルへの送信は Ctrl+E を押したときだけで、毎回ではない。表示しても実行はされない。
切るには ~/.claude.json の permissionExplainerEnabled を false にする。
permission プロンプトにコメントを付ける
承認・拒否のときに Claude へ一言添えられる。 Bash / PowerShell / ファイル / MCP の
プロンプトで Yes か No に移動して Tab を押すとコメント欄が開く。
WebFetch とブラウザのプロンプトには無い。セッション中ずっと許可する選択肢や
ルールを保存する選択肢も受け付けない。
| キー | 動作 |
|---|---|
Enter | コメントを付けて回答を送る。空ならコメントなしで送る |
Tab | 回答せずに欄を閉じる。打った文字は保持され、その選択肢で回答すれば送られる |
Shift+Tab | ファイルのプロンプトでは Tab と同じ。v2.1.235 より前は、欄の中で押すと「セッション中ずっと許可」が選ばれ、コメントは捨てられた |
届き方が Yes と No で違う:
- Yes — アクションを実行してから、結果の後にコメントが Claude へ送られる
- No — 拒否の理由としてコメントが送られ、Claude は作業を続ける。 本体の会話からのプロンプトでコメント無しに No を選ぶと、ターンが止まる
モードを禁じる設定: permissions.disableBypassPermissionsMode / permissions.disableAutoMode を任意の設定ファイルで "disable" にすると、そのモードを使えなくする(managed に置けば上書きされない)。default モードは CLI・VS Code・JetBrains・デスクトップアプリで Manual と表示され、manual は別名として受け付けられる(v2.1.200 以降)。
評価順序(最重要)
Rules are evaluated in order: deny, then ask, then allow. The first match in that order determines the outcome, and rule specificity doesn’t change the order.
ルールは deny → ask → allow の順で評価される。この順序で最初に一致したものが結果を決め、ルールの具体性は順序を変えない。
A broad deny rule like
Bash(aws *)blocks every matching call, including calls that also match a narrower allow rule likeBash(aws s3 ls). An allow rule can’t carve an exception out of a deny rule. The same precedence applies between ask and allow: a matching ask rule prompts even when a more specific allow rule also matches the same call.
Bash(aws *)のような広い deny ルールは、一致するすべての呼び出しをブロックする。Bash(aws s3 ls)のようなより狭い allow ルールにも一致する呼び出しを含めてである。allow ルールで deny ルールに例外を切ることはできない。 同じ優先順位は ask と allow の間にも成り立つ —— より具体的な allow が同じ呼び出しに一致していても、一致する ask ルールがあればプロンプトが出る。
deny ルールは2種類で挙動が違う:
- 裸のツール名(
Bash)— ツールを Claude の context から完全に取り除く。Claude はその存在を知らない - スコープ付き(
Bash(rm *))— ツールは使えるまま、一致する呼び出しをブロックする
Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or
CLAUDE.mdshape what Claude tries to do, but they don’t change what Claude Code allows.permission ルールを強制するのは Claude Code であって、モデルではない。プロンプトや
CLAUDE.mdの指示は Claude が何をしようとするかを形づくるが、Claude Code が何を許すかは変えない。
ルール構文
形式は Tool または Tool(specifier)。 specifier の中の括弧はリテラルなので、括弧を含むコマンドやパスをエスケープする必要はない。Bash(*) は裸の Bash と等価(deny に置けばどちらもツールを context から取り除く)。
入力パラメータでのマッチ(deny / ask 専用):
Agent(model:opus)/Agent(isolation:worktree)/Bash(run_in_background:true)- allow ルールでは使えない(1つのパラメータ値だけでは呼び出し全体の安全性を保証しないため)
- パラメータ名はツール入力の直下フィールドでなければならない。オブジェクトや配列の中は不可
- 1ルールにつき1パラメータ。2つを条件にしたいなら2ルール書く
- 値には
*が使える —Agent(isolation:*)は明示された任意の isolation 値に一致する。*が無ければ完全一致。コロンの前後の空白は無視される - モデルが省略したパラメータは決してマッチしない —
Agent(model:*)はmodel未設定の呼び出しにマッチしない - 正規化前のリテラル入力と比較される —
Agent(model:opus)は別名opusにはマッチするが完全なモデル ID にはマッチしない。実際のパラメータ名と値は--verboseで確認する - MCP ツールのパラメータルールは
--disallowedToolsで渡すしかない —— 設定ファイルを読むとき、Claude Code は括弧つきのmcp__ルールを飛ばす。飛ばしたルールは対話セッション開始時の invalid-settings ダイアログとclaude doctorの出力に並ぶ
ツールの主要コンテンツフィールドはこの方法でマッチできない — Bash/PowerShell の
command、Read/Edit/Write のfile_path、Grep/Glob のpath、WebFetch のurl。Bash(command:rm *)は複合コマンドで迂回できてしまうので Claude Code は無視して起動時に警告を出す。
ツール名のワイルドカード: deny / ask はツール名の位置でも glob を受け付ける("*" は全ツール、"mcp__*" は全 MCP ツール)。allow のツール名 glob は mcp__<server>__ の literal な接頭辞の後でのみ許される — サーバ部分に glob は使えない。"*" や "mcp__*" のような anchor のない allow glob は警告付きでスキップされ、何も自動承認しない。
The label shown for a tool in the transcript and permission dialog can differ from its canonical name. For example, the tool labeled
Stop Taskin the transcript has the canonical nameTaskStop. Permission rules and hook matchers don’t match the label, so a rule written asStop Taskdoesn’t match. For deny and ask rules, the startup warning above catches the mismatch.トランスクリプトと permission ダイアログでツールに表示されるラベルは、正式名称と異なることがある。たとえばトランスクリプトで
Stop Taskと表示されるツールの正式名称はTaskStopである。permission ルールと hook のマッチャーはラベルに一致しないので、Stop Taskと書いたルールは一致しない。 deny と ask のルールなら、起動時の警告がこの食い違いを捕まえる。
Bash ルールの落とし穴
単一の * は空白を含む任意の文字列にマッチするので、1つのワイルドカードが複数の引数にまたがる。
末尾の * の前に空白があると単語境界を強制する:
Bash(ls *)はls -laにマッチするがlsofにはマッチしないBash(ls*)(空白なし)はlsofにもマッチする
複合コマンド:
Claude Code is aware of shell operators, so a rule like
Bash(safe-cmd *)won’t give it permission to run the commandsafe-cmd && other-cmd. The recognized command separators are&&,||,;,|,|&,&, and newlines. A rule must match each subcommand independently.Claude Code はシェルの演算子を認識するため、
Bash(safe-cmd *)というルールではsafe-cmd && other-cmdの実行は許可されない。認識される区切りは&&、||、;、|、|&、&、改行である。ルールは各サブコマンドに個別に一致しなければならない。
複合コマンドを「今後聞かない」で承認すると、サブコマンドごとに別々のルールが保存される(最大5つ)。
ラッパーの剥がし方(ここは知らないと事故る):
| 剥がされる | 剥がされない |
|---|---|
timeout, time, nice, nohup, stdbuf, シェル組み込みの command / builtin, zsh の noglob | command -v(照会形式)、zsh の nocorrect |
フラグなしの xargs | xargs -n1 ...(フラグ付き) |
既知の安全な環境変数の先頭代入(NODE_ENV=test npm test)。ただし allow ルールはそれ以外の変数代入を跨がない。deny / ask は任意の先頭代入を跨いでマッチする | — |
This wrapper list is built in and is not configurable. Development environment runners such as
direnv exec,devbox run,mise exec,npx, anddocker execare not in the list. Because these tools execute their arguments as a command, a rule likeBash(devbox run *)matches whatever comes afterrun, includingdevbox run rm -rf ..このラッパーの一覧は組み込みであり、設定で変更できない。
direnv exec、devbox run、mise exec、npx、docker execといった開発環境のランナーは一覧に含まれない。これらは引数をコマンドとして実行するため、Bash(devbox run *)のようなルールはrunの後に来るものすべてに一致してしまう。devbox run rm -rf .も含めてである。
watch / setsid / ionice / flock のような exec ラッパーは常に確認を求め、接頭辞ルールで自動承認できない。 find の -exec / -delete も同様。
組み込みの読み取り専用コマンド(設定不可): ls, cat, echo, pwd, head, tail, grep, find, wc, which, diff, stat, du, cd、および git の読み取り専用形式。プロンプトを出したければ ask か deny のルールを足す。 ただし PATH や IFS のような特殊なシェル変数を設定・解除・ループで回すコマンドは、残りが読み取り専用でも確認が出る。
出力リダイレクトは書き込みとして検査される。 > / >> / 2> の行き先に対して、
Edit の allow / deny ルール、protected paths、作業ディレクトリの検査がかかる。
A rule such as
Bash(git commit *)allows the command, not the target. A target that starts with~or contains a glob character needs your approval.
Bash(git commit *)のようなルールが許すのはコマンドであって行き先ではない。~で始まる行き先や glob 文字を含む行き先は承認が要る。
入力リダイレクト < file も検査される(v2.1.257 以降)—— Read の allow / deny と作業ディレクトリが対象。作業ディレクトリの外は allow ルールが無ければ承認が要る。glob を含む行き先、および同じコマンド内の cd の後に来る相対パスは、allow ルールがあっても承認が要る。
実体のない行き先は検査されない —— /dev/null、2>&1 や <&3 のようなファイル記述子の形、here-doc と here-string。
それでも確認を求めるケース:
- 書き込み可能フラグを持つコマンドでの unquoted glob(
find,sort,sed,git)— glob が-deleteのようなフラグに展開されうるため - 別デーモンを指す
docker(-H,--context, Podman の--url/--connection) fileの-m/-f(フラグの値に書かれたパスを開くため)- Windows のネットワーク(UNC)パス — Windows の認証情報が相手ホストに送られうるため
- 解析できないコマンド、および 10,000文字を超えるコマンド
cd+git(新しいディレクトリの hook が走りうる)、cd+ 出力リダイレクト(リダイレクト先の解決先が確定できない場合。/dev/nullだけなら確認なし)
Bash permission patterns that try to constrain command arguments are fragile. For example,
Bash(curl http://github.com/ *)intends to restrict curl to GitHub URLs, but won’t match variations like:コマンドの引数を制約しようとする Bash の permission パターンは脆い。たとえば
Bash(curl http://github.com/ *)は curl を GitHub の URL に絞るつもりのルールだが、次のような変種には一致しない。
- URL の前のオプション:
curl -X GET http://github.com/... - 別のプロトコル:
curl https://github.com/... - リダイレクト:
curl -L http://short.example.com/xyz(GitHub へ転送される) - 変数:
URL=http://github.com && curl $URL
URL を絞りたいなら: curl / wget を deny し、WebFetch の WebFetch(domain:...) を使う(deny ルールは、パスで指定した同じプログラムにも sh -c の中にも一致しないので、確実に効かせたいなら sandbox のネットワーク allowlist と組む)/ PreToolUse hook で検証する / CLAUDE.md は補助にとどめる。WebFetch だけではネットワークアクセスを防げない — Bash が許可されていれば curl で任意の URL に届く。
PowerShell ルール
形は Bash と同じ(* は任意の位置、:* は末尾の * と等価、裸の PowerShell /
PowerShell(*) は全コマンド)。Bash と違うのは次の2点。
- 別名が正規化されてから照合される — cmdlet 名で書いたルールは別名にも一致する。
PowerShell(Get-ChildItem *)はgci/ls/dirにも一致する。大文字小文字は区別しない - AST を解析して複合コマンドの各コマンドを個別に検査する — 区切りは
|、;、 PowerShell 7 以降では&&と||。全サブコマンドに一致しなければ複合コマンドは通らない
Read / Edit ルール
Editルールはファイルを編集する全組み込みツールに適用されるReadの deny ルールは同じパスの Edit(新規作成を含む)もブロックする。 ただし Write と NotebookEdit はカバーされないので、どのツールも変更してはいけないパスにはEditの deny ルールも足す.claudeignoreは効かない。 書いてあるなら中身をReadの deny ルールに移す- ファイル権限は
Edit(path)とRead(path)ルールだけで判定される。Write(...)/NotebookEdit(...)/Glob(...)にパスルールを書いても受理はされるが決して参照されず、起動時に警告が出る
パターンの anchor 4種(gitignore 構文):
| パターン | 意味 |
|---|---|
//path | ファイルシステムルートからの絶対パス |
~/path | ホームディレクトリから |
/path | 設定ファイルの出所からの相対 |
path / ./path | カレントディレクトリからの相対 |
A pattern like
/Users/alice/fileisn’t an absolute path. The single leading slash anchors at the settings source, not the filesystem root. Use//Users/alice/filefor absolute paths.
/Users/alice/fileというパターンは絶対パスではない。先頭のスラッシュ1つは、ファイルシステムのルートではなく設定ファイルの位置を基準にする。絶対パスには//Users/alice/fileを使え。
/path の解決先は設定の出所で変わる:
| 定義場所 | /path の解決先 |
|---|---|
.claude/settings.json | <project root>/path |
.claude/settings.local.json | <original cwd>/path |
~/.claude/settings.json | ~/.claude/path |
--settings <file> | <file のディレクトリ>/path |
CLI フラグ / /permissions / セッションルール | <original cwd>/path |
A deny rule such as
Read(/secrets/**)in user settings blocks~/.claude/secrets/**, not asecretsdirectory in your project.user 設定にある
Read(/secrets/**)のような deny ルールがブロックするのは~/.claude/secrets/**であって、プロジェクト内のsecretsディレクトリではない。
Read and Edit deny rules apply to Claude’s built-in file tools, to file commands Claude Code recognizes in Bash, such as
cat,head,tail,sed, andtee, and to the targets of Bash redirections such as> fileand< file. They don’t apply to a command that reads files without naming them, such asgrep -r pattern .run from the directory that holds the file, or to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that blocks all processes from accessing a path, enable the sandbox.Read と Edit の deny ルールは、Claude の組み込みファイルツール、Claude Code が Bash 内で認識するファイル操作コマンド(
cat、head、tail、sed、tee)、および> fileや< fileといった Bash のリダイレクト先に適用される。ファイル名を挙げずに読むコマンド(そのファイルがあるディレクトリで走らせたgrep -r pattern .など)には適用されない。Python や Node のスクリプトのように、自分でファイルを開いて間接的に読み書きするサブプロセスにも適用されない。すべてのプロセスからのアクセスを OS レベルで止めたいなら sandbox を有効にせよ。
! で deny から穴を開けられる(gitignore の否定。ここだけは「広い deny に例外を持たせられない」の例外にあたる):
A deny or ask pattern that starts with
!is a gitignore negation. It carves the paths it matches out of thepathor./pathrules listed before it. In one settings file’sdenylist,Read(*.env)followed byRead(!sample.env)blocks every file whose name ends in.envat any depth, except files namedsample.env. A!rule listed first carves nothing out.
!で始まる deny / ask のパターンは gitignore の否定である。一致したパスを、それより前に並んだpath/./pathのルールから切り抜く。 1つの設定ファイルのdenyにRead(*.env)、続けてRead(!sample.env)と書けば、深さを問わず.envで終わる全ファイルをブロックしつつsample.envだけ除外できる。!のルールを先に置いても何も切り抜かない。
- 切り抜きは同じ出所のルールにしか届かない — project 設定や
--disallowedToolsのRead(!.env)は、managed 設定など別の設定ファイルのRead(./.env)を打ち消さない !の後に/、~/、//を書いてもカレントディレクトリ基準で読まれるので、それらの anchor が付いたルールには届かない(Read(!~/notes/public/**)はRead(~/notes/**)から何も切り抜かない)- ディレクトリごとブロックしているルールの中のファイルは開け直せない —
Read(secrets/**)とRead(!secrets/public/**)があってもsecrets/publicはブロックされたまま
「今後聞かない」で生成されるルールは、パスの gitignore 特殊文字([、]、*)をエスケープするので、承認したそのパスにだけ一致する(自分で書くルールはエスケープされない。v2.1.202 より前はエスケープせずに保存していた)。括弧はエスケープ不要 —— Edit(./Finance (2024)/**) はそのまま一致する。gitignore パターンとして使えないパスでも、deny / ask ならそのパスちょうどを守る。allow なら何も承認しない。
symlink を経由するパスは「Claude が要求したパス」と「解決先」の2つが検査され、allow と deny で扱いが逆(macOS / Linux / Windows の symbolic link と、Windows の directory junction):
Allow rules: apply only when both the requested path and the file it resolves to match. Deny rules: apply when either the requested path or the file it resolves to matches.
allow ルールは、要求したパスと解決先の両方が一致したときにだけ効く。deny ルールは、どちらかが一致すれば効く。
- したがって、許可ディレクトリの中にある外を指す symlink を通した読み取りはルールに一致しない。deny されたファイルを指す symlink はそれ自体が deny される
- 書き込み先そのものが symlink なら、Edit / Write はその書き込みを拒否し、リンク先を使うよう Claude に伝える。途中のディレクトリが symlink のときや、Bash / PowerShell のコマンドが書くときは symlink を通って書けるので、解決先で判断が変わる —— 作業ディレクトリ内のパスが外へ解決するなら、
acceptEditsでも自動承認されず、auto mode でも(allow ルールが無ければ)分類器ではなく確認になる(確認には解決先のパスが出る)。要求したパスが名指ししていない protected path へ解決するなら、protected paths の表で分類器に回る場面も確認になる - 解決先が決められないパス(symlink がループしているなど)は、Read / Edit / Write が操作を拒否する
- macOS / Linux では、symlink を経由したディレクトリに
//、~/、/で書いた deny / ask ルールは、その実体の位置にも効く(/etcが/private/etcに解決される macOS で、Read(//etc/**)は/private/etc/hostsもブロックする。v2.1.268 以降) - Grep / Glob は
path引数の解決先ディレクトリを検索する。そのディレクトリにReadの deny ルールが適用される
WebFetch ルール
WebFetch(domain:example.com)— そのホストWebFetch(domain:*.example.com)— 任意の深さのサブドメイン。ただしexample.com自身にはマッチしない- 先頭の
*.と単独の*以外の位置では、ワイルドカードは2つのドットの間だけにマッチする —example.*はexample.orgにマッチするがexample.evil.comにはマッチしない(攻撃者が登録できるドメインに末尾ワイルドカードがマッチしないようにするため) - 照合は大文字小文字を区別せず、ルールとホスト名の末尾の
.を落とす(example.com.とexample.comは同じ) - ワイルドカードが fetch に効くのは v2.1.172 以降
裸の WebFetch と WebFetch(domain:*) は別物(どちらも全 URL を覆うが挙動が違う):
| ルール | allow に置くと | deny に置くと |
|---|---|---|
WebFetch | プロンプトなしで fetch する。sandbox のドメイン一覧は変えない | ツールごと取り除かれ、fetch 自体できなくなる。sandbox のドメイン一覧は変えない |
WebFetch(domain:*) | プロンプトなしで fetch し、sandbox 内のコマンドも任意のホストへ届く | ツールは残り毎回拒否される。sandbox 内のコマンドもどのホストへも届かない |
artifact(Artifact ツールが claude.ai に公開するページ)の読み取りでも2つの形は違う: 裸の WebFetch の deny / ask は artifact の読み取りに効かない。WebFetch(domain:claude.ai) や content ホストの *.claudeusercontent.com を覆う domain: ルール、あるいは Artifact ルールなら拒否・確認できる(v2.1.268 より前は、裸の deny が全 artifact 読み取りをブロックしていた)。
→ sandbox の allowlist をそのままにして fetch だけ自由にしたいなら、裸の形を使う。
domain: の形だけが sandbox の allowed / denied ドメイン一覧にも足される。
MCP ルール
mcp__<server> はそのサーバの全ツール、mcp__<server>__* も同じ、
mcp__<server>__<tool> は個別のツール。
If your organization has set a claude.ai connector tool to
askand that setting reaches Claude Code in your session, allow rules for that tool don’t take effect: Claude Code prompts on every call, even inautoandbypassPermissionsmodes. IndontAskmode, which never prompts, Claude Code denies the call instead.組織が claude.ai コネクタのツールを
askにしていて、その設定がセッションの Claude Code まで届いている場合、そのツールへの allow ルールは効かない。autoやbypassPermissionsのモードであっても毎回プロンプトが出る。決してプロンプトを出さないdontAskモードでは、代わりに呼び出しが拒否される。
コネクタのツールは mcp__claude_ai_<server>__<tool> として現れる。
Cowork(Claude Desktop)では Bash と WebFetch が MCP ツールになる —— シェルは mcp__workspace__bash、fetch は mcp__workspace__web_fetch。ツール全体を指す Bash / WebFetch の deny ルールはこれらにも適用される(managed の Bash deny は Cowork でもシェルを止める)。allow ルールは持ち越されない —— Bash の allow が mcp__workspace__bash に効くことはない。
Agent / Cd ルール
Agent(Explore)/Agent(Plan)/Agent(my-custom-agent)Cdはモデルが呼べるツールではない —/cdを自分で実行したときにだけ適用される。Cdallow ルールを1つでも足すと/cdが allowlist モードに切り替わる- 裸の
Cdの deny は/cdを丸ごと無効にする。 deny は目標のあらゆる綴り方(解決の途中で通る symlink のホップも含めて)を検査するので、1つの書き方で書いたルールが、そこへ解決する別の書き方も止める Cdのパスマッチはディレクトリパス全体に anchor される(gitignore 形式ではない)。*はちょうど1セグメント、**はセグメントを跨ぐ。末尾の/**はその root 自体にもマッチする
hook との関係
PreToolUse hook decisions don’t bypass permission rules. Claude Code evaluates deny and ask rules regardless of what a PreToolUse hook returns: a matching deny rule blocks the call, and a matching ask rule still prompts even when the hook returned
"allow"or"ask".PreToolUse hook の判断は permission ルールを迂回しない。PreToolUse hook が何を返そうと、Claude Code は deny と ask のルールを評価する。一致する deny ルールは呼び出しをブロックし、一致する ask ルールは hook が
"allow"や"ask"を返しても依然としてプロンプトを出す。
PreToolUse hook が走るのは EndConversation を除く全ツール。requiresUserInteraction の MCP ツールと、組織が ask にしたコネクタのツールは、hook が "allow" を返してもプロンプトが出る。
ただし exit code 2 のブロックは別:
A hook that exits with code 2 stops the tool call before permission rules are evaluated, so the block applies even when an allow rule would otherwise let the call proceed.
終了コード 2 で終わる hook は、permission ルールが評価される前にツール呼び出しを止める。そのため、allow ルールなら通していたはずの呼び出しでもブロックが効く。
→ 「Bash を全許可しつつ一部だけ止める」を実現するには、"Bash" を allow に入れて、PreToolUse hook で特定のコマンドを拒否する。
この優先順位が及ぶのは設定ファイルと plugin の hooks/hooks.json の hook まで。tool.check を扱う mod は、ルールと PreToolUse hook が決めた後に答え、その答えで置き換えられる(以前の取得で追加):
| 相手 | mod ができること |
|---|---|
| ask ルール | 確認が出るはずの呼び出しを承認できる |
PreToolUse hook のブロック | 承認できる(hook が managed settings にあれば別) |
| auto mode の分類器 | mod が承認した呼び出しは分類器を通らずに走る |
| deny ルール | managed settings のあるマシンか、Team / Enterprise でサインインしていれば、既定で deny が mod に勝つ(組織が変えられる)。それ以外では mod が deny を覆して承認できる |
作業ディレクトリと追加ディレクトリ
--add-dir / /add-dir からロードされる設定(permissions.additionalDirectories 設定からは何もロードされない):
| 設定 | --add-dir からロードされるか |
|---|---|
.claude/skills/ の skill | はい(live reload 付き) |
.claude/commands/ のコマンド | はい(live reload なし)。追加ディレクトリと project が同名のコマンドを持つときは project 側が走る |
.claude/agents/ の subagent | はい(live reload なし) |
.claude/settings.json | enabledPlugins と extraKnownMarketplaces キーのみ |
CLAUDE.md / .claude/rules/ / CLAUDE.local.md | CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 のときのみ |
主作業ディレクトリのサブディレクトリなら、/add-dir にそのパスを渡すだけで途中から skill・コマンド・subagent を読ませられる(すでに読めるディレクトリなので、作業ディレクトリは増えず確認も出ない。v2.1.257 以降)。
permissions.blockReadsOutsideWorkingDirectories を設定すると、どの permission モードでもファイルツールが囲った外のパスを拒む。auto モードでは、作業ディレクトリの外を初めて読んだときに有効化を提案してくる。組み込みの読み取り専用コマンドも、この設定が囲うパスだけは例外になる。
UNC などのネットワークパスは作業ディレクトリに追加できない(名前を引くだけで相手ホストに接触しうるため)。Windows ではドライブレターに割り当てて --add-dir で渡す。
/cd は /add-dir と違ってセッションを移動させる — 新しいディレクトリの CLAUDE.md がロードされ、--resume もそこから見つかる。移動した時点で、新しいディレクトリの project 設定(permission ルールと hook)・.mcp.json と local スコープの MCP サーバ・plugin・skill・subagent・env が適用され、前のディレクトリの project / local サーバは切断される(v2.1.246 より前は、resume するまで適用されなかった)。追加ディレクトリは新しいディレクトリの設定から取り直されるが、--add-dir / /add-dir で自分が足したものは残る。信頼していないディレクトリなら、その設定が有効化するものを一覧した trust プロンプトが出る。辞退すればセッションは動かない。
sandbox との関係
permission と sandbox は補い合う別の層である。permission はどのツールを使えるかを制御し、 sandbox は Bash・PowerShell・Monitor のコマンドとその子プロセスにだけ OS レベルの強制をかける。
- filesystem — sandbox の
sandbox.filesystem設定と Read / Edit の deny ルールが併合されて最終的な境界になる - network —
WebFetch(domain:...)と sandbox のallowedDomains/deniedDomainsが組み合わさる - deny や ask のルールは、他のツールが残っている限り
EndConversationをブロックできない
最も間違えやすいのは autoAllowBashIfSandboxed(既定 true):
When you enable sandboxing and leave
autoAllowBashIfSandboxedat its default oftrue, sandboxed Bash commands run without prompting even if your permissions include a bareBashask rule, or the equivalentBash(*)form: the sandbox boundary substitutes for that whole-tool prompt.sandbox を有効にして
autoAllowBashIfSandboxedを既定のtrueのままにすると、裸のBashask ルール(あるいは等価なBash(*))があっても、sandbox 内の Bash コマンドはプロンプトなしで走る。sandbox の境界がツール全体のプロンプトの代わりになる。
plan モードではこの置き換えをしない(v2.1.212 より前は plan モードでも置き換えていた)。
置き換えが効いても、次は依然として効く: 内容を絞った ask ルール(Bash(git push *) など)、
明示的な deny ルール、critical path を対象にした rm / rmdir。
設定の優先順位
Permission rules follow the same settings precedence as all other Claude Code settings, with managed settings highest: no other level, including command line arguments, can override a managed permission rule.
permission ルールは他の設定と同じ優先順位に従い、managed 設定が最上位に来る。コマンドライン引数を含め、他のどの階層も managed の permission ルールを上書きできない。
If a tool is denied at any level, no other level can allow it. For example, a managed settings deny can’t be overridden by
--allowedTools, and--disallowedToolscan add restrictions beyond what managed settings define.いずれかの階層でツールが拒否されていれば、他のどの階層もそれを許可できない。managed 設定の deny は
--allowedToolsで上書きできず、--disallowedToolsは managed が定めた以上の制限を足せる。
この優先順位は設定ファイルとコマンドライン引数の間の話で、入れた mod に deny が勝つかどうかは上の「hook との関係」の表による。
The same holds across settings scopes: if user settings allow a permission and project settings deny it, the deny rule blocks it. The reverse is also true: a user-level deny blocks a project-level allow, because deny rules from any scope are evaluated before allow rules.
同じことはスコープをまたいでも成り立つ。user 設定が許可し project 設定が拒否していれば deny が勝つ。逆も同じで、user 階層の deny は project 階層の allow をブロックする。どのスコープの deny も allow より先に評価されるからである。
project の allow ルールと workspace trust
permissions.allowrules andpermissions.additionalDirectoriesentries in a project’s.claude/settings.jsongrant capability, so Claude Code applies them only after you accept the workspace trust dialog for that folder. The dialog lists the rules and directories the folder would grant so you can review them first.denyandaskrules aren’t affected, since they only restrict.プロジェクトの
.claude/settings.jsonにあるpermissions.allowルールとpermissions.additionalDirectoriesの項目は権限を与えるものなので、Claude Code はその folder のワークスペース信頼ダイアログを承認した後にのみこれらを適用する。ダイアログは、その folder が与えることになるルールとディレクトリを先に確認できるよう一覧する。denyとaskのルールは制限するだけなので影響を受けない。
background セッションを起動・再起動する前にも、そのセッションが走るディレクトリの workspace trust を確かめる。信頼していないディレクトリで claude --bg を打つと、先に信頼ダイアログが出て、承諾してからセッションが始まる。スクリプトのようにダイアログを出せない場所では Workspace not trusted のエラーで終わる。
trust の保存キーは起動場所で決まる:
| 起動場所 | キー | 及ぶ範囲 |
|---|---|---|
| リポジトリ内 | git リポジトリのルート(worktree ではメインのチェックアウトのルート) | リポジトリ全体。ただし入れ子のリポジトリ(submodule など)は除く |
| リポジトリ外 | 起動したディレクトリ | その配下すべて。入れ子のリポジトリ(clone など)は除く |
| ホームディレクトリ | — | そのセッション限り。ディスクに書かれない |
Claude Code shows the trust dialog in interactive sessions only. A
claude -prun or an SDK session never shows it, and trusting a parent folder doesn’t count for these rules, so What runs before you trust a folder says which repository content Claude Code still uses in each of those two situations.信頼ダイアログが出るのは対話セッションだけである。
claude -pの実行や SDK のセッションでは決して出ず、親フォルダを信頼してもこれらのルールには効かない。だから「folder を信頼する前に何が動くか」が、その2つの状況それぞれで何が使われるかを示している。
.claude/settings.local.json が trust を要求する場合
通常これは自分のファイルなので、allow ルールと追加ディレクトリはtrust なしで適用される。
git で追跡されている場合、または .claude が symlink の場合は、リポジトリ由来として扱われ、
folder を信頼するまで保留される。
この判別のために git を走らせるが、git を走らせるのは folder を信頼した後である。 それまでは起動場所で決まる:
- 設定ホーム(ホームディレクトリ、または
CLAUDE_CONFIG_DIRに設定したディレクトリ)で起動 — git を走らせず即座に適用する - それ以外 — project 設定と同じように保留する。検査が済めば、追跡されていないファイルや git リポジトリの外にあるファイルのルールは、その folder を信頼していなくても適用される
~/.claude/settings.local.json は local スコープのまま —— 読まれるのは
ホームディレクトリ自体で始めたセッションだけで、全プロジェクトには効かない。
全プロジェクトに効かせたいなら user 設定(~/.claude/settings.json)に書く。
folder を信頼する前に何が動くか
「親フォルダだけ信頼した」場合と「claude -p / SDK で一度も信頼していない」場合の対比。
| リポジトリが与えるもの | 親だけ信頼 | claude -p / SDK |
|---|---|---|
設定ファイルの hook、env ブロック、apiKeyHelper などのヘルパ、project skill の hook と allowed-tools | 使われる | 使われる(skill の allowed-tools はどのセッションでも trust に阻まれない) |
.claude/settings.json の permissions.allow と additionalDirectories | 使われない(ダイアログが再度出て一覧される) | 使われない。stderr に this workspace has not been trusted 警告 |
project subagent の frontmatter hook、@skills-dir plugin、extraKnownMarketplaces | 使われない。ダイアログも出ない | 使われない |
subagent frontmatter のインライン mcpServers | 使われない。ダイアログも出ない | 使われない |
.mcp.json のサーバ | 接続前に聞かれる(リポジトリ自身の承認は数に入らない) | 承認の有無にかかわらず、聞かずに接続する |
.mcp.json サーバの headersHelper | 走らない(ダイアログが再度出る)。静的な headers だけで接続する | 走らない。静的な headers だけで接続し、stderr に警告 |
この folder ちょうどの信頼が要る行を、手で信頼する方法: ~/.claude.json の projects["<path>"].hasTrustDialogAccepted を true にする(<path> はリポジトリのルート、リポジトリ外ならその folder 自身)。入れ子のリポジトリには親の信頼が効かない —— 対話セッションではそこで trust ダイアログが出て、claude -p / SDK なら claude -p の列の挙動になる。
書いていないリポジトリで claude -p を走らせる前の手当て: --setting-sources user で
project 設定と .mcp.json を読ませない / --bare で hook・skill・コマンド・subagent・plugin・
.mcp.json を読ませない / --settings '{"disableAllHooks": true}' で hook を切る
(user 設定に書くだけでは足りない。project 設定が優先して false に戻せる)/
disabledMcpjsonServers で名前指定のサーバを拒否する。
managed 設定
組織向けの中央管理。user / project が上書きできない(security-sensitive な一部のキーを除く)。
配布方法・managed 階層内での優先順位・managed だけが設定できるキー(allowManagedPermissionRulesOnly
など)は、この原典から settings と managed settings の文書へ委ねられている。
disableBypassPermissionsMode は managed に置くのが典型だが、どのスコープでも効く。
ユーザーが自分の設定に書いて、自分を bypass モードから締め出すこともできる。
そのまま使える具体例
npm と git commit を許可し、git push を禁じる:
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)",
"Bash(git * main)",
"Bash(* --version)",
"Bash(* --help *)"
],
"deny": [
"Bash(git push *)"
]
}
}全 MCP ツールを禁じる:
{
"permissions": {
"deny": ["mcp__*"]
}
}Explore エージェントを無効化する:
{
"permissions": {
"deny": ["Agent(Explore)"]
}
}「Bash は全許可、一部だけ hook で止める」構成(この文書で最も実用的なパターン):
{
"permissions": {
"allow": ["Bash"]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous.sh" }
]
}
]
}
}user settings から全プロジェクトに効くパスルールを書く(/ ではなく // か ~/):
{
"permissions": {
"deny": [
"Read(//Users/alice/secrets/**)",
"Read(~/.ssh/**)"
]
}
}環境ランナーを許可するときは内側のコマンドまで書く:
- ❌
Bash(devbox run *)——devbox run rm -rf .まで通る - ✅
Bash(devbox run npm test)—— 許可したい内側のコマンドごとに1ルール
ワイルドカードの単語境界:
| ルール | マッチの仕方 |
|---|---|
Bash(ls *) | ls -la にマッチ、lsof にはマッチしない |
Bash(ls*) | lsof にもマッチしてしまう |
Bash(ls:*) | Bash(ls *) と同じ(:* は末尾でのみ有効) |
原典で言及されている関連文書
- mods-admin — 組織で deny ルールを mod に勝たせる設定
- mods-overview — mod が permission ルールの後に答える仕組み
- permission-modes — モードとルールの関係
- hooks-guide — exit code 2 のブロックが allow ルールより優先されること
- claude-code-sandboxing — OS レベルの強制(任意のサブプロセスまでカバーする唯一の手段)
- mcp — コネクタツールの
askとrequiresUserInteraction - sub-agents —
Agent(...)ルール - large-codebases —
Readdeny ルールによる読み取り削減 - settings — 設定の完全なリファレンスと優先順位