Claude Codeの権限ルールをパラメータで書く — Agent(model:opus)の使い方
Tool(param:value)で、ツール呼び出しの入力パラメータの値に応じてdenyとaskを書けます。allowに使えない理由、Bashのcommandが無視される理由、MCPツールの扱いを確かめます。
Tool(param:value)は、ツール呼び出しの入力パラメータの値を見て一致を判定する権限ルールの書き方です。たとえばAgent(model:opus)と書くと、Opusのモデル階層を要求したサブエージェント呼び出しだけを止めたり、確認に回したりできます。使えるのはdenyとaskだけで、allowには使えません。
この記法はv2.1.178で追加されました。経緯はv2.1.178のリリースノートにあります。ここでは、書けるルールと書けないルールの境目、一致の条件、MCPツールの扱いを、設定例と一緒に確かめます。
Tool(param:value)で何を条件にできるか
従来の権限ルールは、Bash(npm run *)やRead(./.env)のように、各ツールが決めた書式(指定子)で書いてきました。パラメータ指定はそれとは別の軸です。ツールの入力に含まれる項目名と値を、そのまま条件にします。
ルールが当たるのは、Claudeがそのパラメータをその値で渡してツールを呼んだときです。ページに載っている例は次の3つです。
| ルール | 当たる呼び出し |
|---|---|
Agent(model:opus) | 当たる呼び出しOpusのモデル階層を要求するAgent呼び出し |
Agent(isolation:worktree) | 当たる呼び出しgitのworktreeを要求するAgent呼び出し |
Bash(run_in_background:true) | 当たる呼び出しバックグラウンドで実行するBash呼び出し |
「このコマンドか」ではなく「このツールにこの引数を渡したか」で止められるのが、新しい軸です。サブエージェントのモデルやworktree分離のように、コマンド文字列に現れない指定を条件にできます。サブエージェントのモデル配分そのものの考え方はサブエージェントのモデル配分設計にまとめています。
denyとaskだけで、allowには書けない
パラメータ指定が使えるのはdenyルールとaskルールです。組み込みツールなら、どのツールにも書けます。
allowに使えない理由は、ページに書かれています。あるパラメータの値を許可しても、その呼び出し全体が安全だとは言えないからです。allowルールは従来どおり、ツールごとの指定子で書きます。
設定ファイルに書くなら、次のようになります。ここでは例として、Opusを使うサブエージェントは確認を挟み、worktree分離つきの起動は止めています。
{
"permissions": {
"ask": ["Agent(model:opus)"],
"deny": ["Agent(isolation:worktree)"]
}
}評価の順序はdeny、ask、allowです。最初に一致したものが結果を決め、ルールの具体性では順序が変わりません。つまり、パラメータ指定のaskルールに一致した呼び出しは、より狭いallowルールが同時に一致していても確認に回ります。
一致の条件を表で確かめる
一致の判定には、いくつか癖があります。ページに書かれている規則を、「書き方」と「当たるか」の対応にまとめます。
| 書き方 | 当たるか |
|---|---|
Agent(model:opus) | 当たるか入力がopusのとき当たる。完全なモデルIDには当たらない |
Agent(isolation:*) | 当たるかisolationを明示した呼び出しなら、値に関係なく当たる |
Agent(model:*) | 当たるかmodelを省略した呼び出しには当たらない |
Agent(model : opus) | 当たるかコロンの前後の空白は無視されるので、Agent(model:opus)と同じ |
Agent(model:opus, isolation:worktree) | 当たるか書けない。1ルールにつき1パラメータ |
値は、Claudeが送ったそのままの入力と比べられます。正規化の前の文字列です。だからopusというエイリアスは捕まえても、opusが解決される先のバージョン付きモデルIDは捕まえません。opus・sonnet・haikuのエイリアスは、最新のバージョンに解決される仕組みです。解決後のIDで送られる運用なら、そのIDも別のルールとして足す必要があります。
省略の扱いも重要です。モデルがmodelを渡さなかった呼び出しは、Agent(model:*)でも捕まりません。「モデルを明示せずに起動されたサブエージェント」を止めたい場合に、このルールは使えないということです。
複数の条件を組み合わせたいときは、ルールを並べます。modelとisolationの両方を見たいなら、Agent(model:opus)とAgent(isolation:worktree)を別々に書きます。並べたルールは、どれか1つに一致すれば効きます。両方が揃ったときだけ止める、という書き方はできません。
条件にできる項目は、直下のスカラーだけ
パラメータ名は、ツール入力の直下にある項目に限られます。オブジェクトや配列の内側にある項目は対象外です。値として比べられるのもスカラー(文字列や真偽値など)です。
自分のツールにどんな項目があるかは、--verboseで起動すると確かめられます。ツール呼び出しごとに、実際のパラメータ名と値が表示されます。推測でパラメータ名を書くと、一致しないルールが静かに残ります。
claude --verbose表示された呼び出しの値をそのままルールに写すのが、確実な書き方です。Agent(model:opus)のように、名前と値の両方が出力に現れるはずです。
Bashのcommandは無視される
主要な内容フィールドは、パラメータ指定の対象になりません。ページが挙げているのは次の対応です。
| ツール | 対象外の項目 |
|---|---|
| BashとPowerShell | 対象外の項目command |
| Read・Edit・Write | 対象外の項目file_path |
| GrepとGlob | 対象外の項目path |
| NotebookEdit | 対象外の項目notebook_path |
| WebFetch | 対象外の項目url |
Bash(command:rm *)のようなルールは、複合コマンドで迂回できてしまいます。そのため、Claude Codeはこのルールを無視して、起動時に警告を出します。代わりにBash(rm *)、Read(./path)、WebFetch(domain:host)のように、従来の指定子で書きます。
Bash側の書式が複合コマンドをどう評価するかは、Bash権限ルールと複合コマンドで詳しく見ています。パラメータ指定を使う場面は、Bashならrun_in_backgroundのような、コマンド文字列以外の項目に限られます。
Skill(skill:<name>)のdenyルールだけは、例外的な扱いです。スキルが持つ別名や表示名のどれで呼ばれても一致します。
MCPツールは設定ファイルに書けない
MCPツールの入力パラメータで止めたいときは、書き方が変わります。ページの記述は次のとおりです。
- 組み込みツールのパラメータ指定は、設定ファイルにも書ける
- MCPツールのパラメータを指定するdenyルールは、
--disallowedToolsで渡す - 設定ファイルを読み込むとき、括弧つきの
mcp__ルールは読み飛ばされる
読み飛ばされたルールは、対話セッションの起動時に出る「無効な設定」のダイアログに並びます。claude doctorの出力にも現れます。設定ファイルに書いたはずのMCPのパラメータルールが効かないときは、この2か所を見ると原因が分かります。
ページにはMCPの具体例が載っていないので、実際の書式は手元で確かめてください。--verboseで出る名前と値を使い、Tool(param:value)の形をMCPのツール名に当てはめる形になると考えられます。
任意のパラメータを省略したMCPツールが拒否される現象は、別の仕組みです。原因と回避策はMCPツールが任意パラメータ省略で拒否される場合にあります。
起動時に渡す書き方と、運用での使いどころ
--disallowedToolsは、起動時にdenyルールを足すCLIフラグです。裸のツール名はそのツールをClaudeの文脈から取り除き、Bash(rm *)のような絞り込みつきのルールはツールを残したまま、一致した呼び出しだけを拒否します。パラメータ指定のルールは後者の側にあたります。
claude --disallowedTools "Agent(model:opus)" "Bash(run_in_background:true)"起動時のフラグと設定ファイルの使い分けは、allowedToolsとdisallowedToolsの記事で扱っています。一時的な実行なら起動時のフラグ、チーム全体で固定したいなら設定ファイルが基本です。
運用での使いどころとして、次の3つが考えられます。
- コストの上限を作る:
Agent(model:opus)をaskにして、Opusを使うサブエージェントだけ人の確認を挟む - 作業ツリーを汚さない:
Agent(isolation:worktree)をaskにして、worktreeを作る起動を把握する - バックグラウンド実行を見える化する:
Bash(run_in_background:true)をaskにして、裏で走るコマンドを確認する
どれも「denyで全面禁止」にしなくてよい点が使いやすいところです。askなら、必要なときは承認して進められます。
権限ルールはClaudeではなくClaude Code側が強制します。CLAUDE.mdに「Opusのサブエージェントは使わない」と書いても、Claudeが試みる内容に影響するだけで、許可の可否は変わりません。確実に止めたいなら、ルールとして書きます。
ルールを書いたあとの確認手順
書いたルールが効いているかは、次の順に確かめます。
パラメータ指定ルールの確認
- 1
起動時の警告を見る
対話セッションの起動時に、無効な設定のダイアログが出ないか確かめます。
mcp__ルールやBash(command:...)は、ここで指摘されます。 - 2
doctorで解決後の設定を見る
claude doctorの出力に、読み飛ばされたルールが載ります。 - 3
--verboseで実際の入力を見る
ルールに書いたパラメータ名と値が、ツール呼び出しの表示と一致しているかを比べます。
- 4
/permissionsで反映を見る
/permissionsのダイアログには、ルールと、そのルールを定義した設定ファイルが並びます。ルールの追加や削除は、同じターンの次のツール呼び出しから反映されます。
よくあるつまずき
効かないルールの原因は、ほとんどが次のどれかです。
- モデルIDで指定している: 比較は入力そのままなので、
opusのエイリアスで送られた呼び出しにはエイリアスで書く。IDで送られる運用ならIDも足す modelを省略した呼び出しを捕まえたい: 省略されたパラメータは一致しないので、このルールでは捕まえられない- allowに書いた: パラメータ指定はdenyとaskの専用。allowには従来の指定子を使う
- ネストした項目を指定した: 直下の項目だけが対象
- 1つのルールに2つの条件を詰めた: 1ルールにつき1パラメータ。ルールを分ける
最後の「省略された場合」は、サブエージェントの定義側でモデルを決めている構成で効いてきます。定義ファイル側のモデル指定が、このルールの比較対象になるかどうかは、権限のページに記載がありません。止めたいサブエージェントが実際にルールへ一致するかは、--verboseで入力を見て確認するのが確実です。
まとめ
Tool(param:value)は、コマンド文字列に現れない指定を、権限ルールの条件にするための記法です。denyとaskにだけ書け、一致はClaudeが送った入力との完全一致(*は任意の文字列)で決まります。BashのcommandやReadのfile_pathなどの主要フィールドは対象外で、MCPツールは--disallowedToolsで渡します。
まず--verboseで実際のパラメータ名と値を見て、それをそのままaskに書き、/permissionsで反映を確かめる。この順で進めると、効かないルールを書くことが減ります。