Claude CodeのallowedTools/disallowedToolsで起動時に権限を絞る
起動時のallowedTools/disallowedToolsは初回プロンプトを省略するだけで、使えるツールの集合を絞るのは--toolsの役割です。CIでの使い分けと落とし穴をまとめます。
Claude Codeを起動するとき、--allowedToolsと--disallowedTools(短縮形は--allowed-tools/--disallowed-tools)を渡すと、対話中の許可プロンプトを介さずにツールの可否を一括で指定できます。CIパイプラインやスクリプトからの非対話実行で、毎回のyes/noを止めたいときに使うフラグです。ただし両者は名前が似ているぶん、「ツールの利用可否」を決めているのか「利用できるツールの集合そのもの」を決めているのかを混同しやすく、これは--toolsフラグとの役割分担を理解して初めて避けられます。
allowedTools/disallowedToolsでできること
--allowedToolsはClaude Codeが自分でツールを呼び出す際に、プロンプトなしで実行してよい対象を宣言するフラグです。--disallowedToolsはその逆で、呼び出しを拒否する対象を宣言します。どちらも値はダブルクォートで囲んだ文字列を複数個、スペース区切りで渡します。
claude --allowedTools "Bash(git log *)" "Bash(git diff *)" "Read"この例ではgit logとgit diff系のBashコマンドと、ファイル読み取り(Read)がプロンプトなしで実行されます。ルールの書式はTool(全呼び出しにマッチ)かTool(specifier)(特定の呼び出しにマッチ)のどちらかで、settings.jsonのpermissions.allow/permissions.denyと同じ構文です。
allowedToolsは「許可」であって「制限」ではない
--allowedToolsに書いたツールだけが使える、と誤解しがちですが違います。公式ドキュメントは--allowedToolsの説明で「利用できるツールを絞りたいなら--toolsを使うこと」と明記しています。--allowedToolsはあくまでプロンプトをスキップするための許可リストで、そこに書かれていないツールも、通常の権限確認を経れば呼び出されます。逆に「Claudeに見えるツールの集合」そのものを縮小したいなら--toolsが必要です。
| フラグ | 何を決めるか | 効果が及ぶ範囲 |
|---|---|---|
--allowedTools | 何を決めるかプロンプトを省略してよい呼び出し | 効果が及ぶ範囲該当ツール・該当パターンのみ。他のツールは通常どおりプロンプトされる |
--disallowedTools | 何を決めるかプロンプトなしで拒否する呼び出し、または存在ごと消すツール | 効果が及ぶ範囲裸のツール名は完全除去、スコープ付きルールは該当呼び出しのみ拒否 |
--tools | 何を決めるかClaudeに見せる組み込みツールの集合そのもの | 効果が及ぶ範囲挙げなかった組み込みツールは呼び出し自体が不可能。MCPツールには影響しない |
--toolsで絞る場合もMCPツールは対象外である点が、実運用でつまずきやすいポイントです。MCP経由のツールをまとめて塞ぎたいときは、--toolsではなく--disallowedTools "mcp__*"を使います。
disallowedToolsの2つの効き方
--disallowedToolsは書き方によって効果が変わります。"Edit"のような裸のツール名を渡すと、そのツールはClaudeのコンテキストから完全に取り除かれ、Claude自身がそのツールの存在を認識しなくなります。"*"はすべてのツールを、"mcp__*"はすべてのMCPツールを同じ扱いで除去します。
一方"Bash(rm *)"のようにスコープを指定した拒否ルールは、Bashツール自体は残したまま、パターンに一致する呼び出しだけを拒否します。ClaudeはBashが使えることを認識したうえで、rmから始まるコマンドだけ実行できません。この違いは、Bash権限ルールが複合コマンドをどう評価するかで扱った評価順序(deny → ask → allow)とも関わり、広いdenyルールは狭いallowルールより常に優先されます。
なおEndConversationツールだけは例外で、他に残っているツールがある限り、disallowedToolsの裸のツール名指定では除去できません。
実践例 — CIでBashを読み取り専用に絞る
非対話実行(-p)と組み合わせると、CI上でリポジトリの調査だけをプロンプトなしで許可し、変更系コマンドは常に拒否する構成が作れます。
claude -p "このPRの変更点をレビューして" \
--allowedTools "Bash(git log *)" "Bash(git diff *)" "Bash(git show *)" "Read" "Grep" \
--disallowedTools "Bash(git push *)" "Bash(rm *)" "Edit" \
--permission-prompts none--permission-prompts none(Claude Code v2.1.259以降)を足すと、allowedTools/disallowedToolsのどちらにも該当しない呼び出しは黙って拒否され、誰も答えられない環境でプロンプトが宙に浮くことがなくなります。無人実行のパイプラインでは、許可リストと拒否リストに加えてこのフラグまでセットで考えておくと安全です。
パラメータ単位でマッチさせる
--disallowedToolsのスコープ構文だけでは足りない場面もあります。ツールの入力パラメータ単位でマッチさせたいときは、Tool(param:value)という書き方が使えます。たとえばAgent(model:opus)はOpusモデルを指定したAgent呼び出しにマッチし、Bash(run_in_background:true)はバックグラウンド実行を指定したBash呼び出しにマッチします。パラメータ名はツール入力の直下フィールドに限られ、ネストしたオブジェクトやリストの中身は対象外です。値には*をワイルドカードとして使えますが、モデルが省略したパラメータには決してマッチしません。
MCPツールに対してこのパラメータマッチを使う場合、--disallowedToolsが唯一の経路になります。settings.json側は括弧付きのmcp__ルールを読み込み時にスキップするため、MCPツールのパラメータをピンポイントで拒否したいときは起動フラグで渡す必要があります。
claude --disallowedTools "Agent(model:opus)" "Bash(run_in_background:true)"command(Bash/PowerShell)やfile_path(Read/Edit/Write)、path(Grep/Glob)、url(WebFetch)といった各ツールの主要な入力フィールドは、このパラメータマッチでは狙えません。Bash(command:rm *)のようなルールは複合コマンドで簡単にバイパスされるため、Claude Codeは起動時に警告を出してこのルールを無視します。こうした主要引数を絞るときは、前述のスコープ付きルール(Bash(rm *)のような形)を使います。
サブエージェントの利用を絞る
--disallowedToolsは組み込みのBashやReadだけでなく、Agent(AgentName)という形でサブエージェントの利用も制御できます。特定のサブエージェントを使わせたくない場合に、名前を指定して拒否します。
claude --disallowedTools "Agent(Explore)"CIで探索用のサブエージェントを自動起動させたくない、社内で認可したカスタムサブエージェントだけを使わせたい、といった場面でこの形が使えます。
よくあるつまずき
- ワイルドカードで抜け道ができる:
Bash(curl http://github.com/ *)のようにURLを制限したつもりでも、curl -X GET http://github.com/...のようにオプションが先に来る形や、URL=http://github.com && curl $URLのような変数展開はマッチしません。ネットワーク先を確実に絞るなら、Bash側のcurl自体をdisallowedToolsで塞ぎ、WebFetchツールをWebFetch(domain:github.com)で許可する構成に寄せたほうが確実です。 - ルールはClaudeが書いたコマンド文字列にしかマッチしない:
"Bash(rm *)"を拒否しても、/bin/rm -rf build/やbash -c 'rm -rf build/'のような別形での呼び出しは文字列が一致せず、そのまま実行されます。コマンド文字列に依存しない強制力が必要なら、OSレベルで実行を止めるサンドボックス機能と組み合わせます。 - 一括許可のワイルドカードは無効化される:
--allowedTools "*"のようにツール名部分をワイルドカードにした許可ルールは、起動時の警告つきでスキップされ、何も許可されません。ツール名のワイルドカードが使えるのはmcp__<server>__*のように、サーバー名部分がリテラルなMCPルールに限られます。 *をサブコマンドより前に置くと意図より広く許可される:Bash(git * main)と書くと、*はサブコマンドとその前のオプション全体に対応するため、git merge mainやgit push origin mainまで許可対象に含まれます。git logだけを許可したいなら、サブコマンドの後ろに*を置いたBash(git log * main)のように書く必要があります。Claude Codeはサブコマンドより前に*がある許可ルールに対して起動時に警告を出しますが、書き方自体は防げません。--restrictedモードでは--toolsしか通らない:--restrictedはコマンド実行・コード実行系のツールとWebFetchを丸ごと外し、個別に戻すには--toolsで名指しする必要があります(defaultプリセット経由では戻せません)。この制約下で--allowedToolsに同じツール名を書いても、除去されたツール自体は復活しません。
MCPサーバーの権限と組み合わせる
MCP経由でツールを提供するサーバーを本番環境に接続する場合、--allowedTools/--disallowedToolsだけでなく、サーバー側の認可設計も合わせて検討する必要があります。読み取り専用ロールと承認フローの組み方はMCPで本番環境に接続する権限設計で扱っています。
またシンボリックリンクを経由した権限すり抜けは、Read/Editのdenyルールがシンボリックリンク自体とその参照先の両方をチェックする形で対策されており、Claude Code v2.1.268ではこのすり抜け経路の一つが修正されています。詳細はClaude Code v2.1.268のリリースノートにまとめています。CLIフラグでの権限設計は、こうしたシンボリックリンクや複合コマンドの評価ルールとセットで理解しておくと、想定外の抜け道を減らせます。
追加のディレクトリを渡す--add-dirは、ここで扱った--allowedTools/--disallowedToolsとは別軸のフラグで、読み書き権限を広げるだけでSkillsやhooksは読み込まれません。詳しくはadditionalDirectoriesは権限だけ拡張するにまとめています。
設定ファイルとの関係
--allowedTools/--disallowedToolsはその起動だけに効くフラグで、settings.jsonを書き換えるわけではありません。同じルールを毎回のセッションで有効にしたいなら、permissions.allow/permissions.denyとして設定ファイル側に書きます。対話中に「Yes, and don't ask again」を選んだときに保存されるルールも同じpermissions.allowに追記され、保存先はgitリポジトリのルート(worktreeで作業している場合はメインの作業ツリー)にある.claude/settings.local.jsonです。CLIフラグでその場限りの検証をして、恒久化したいルールだけを設定ファイルへ書き写す、という使い分けが実務では扱いやすくなります。
まとめ
--allowedToolsはプロンプトを省略する許可リスト、--disallowedToolsは書き方次第でツールを完全除去するか特定呼び出しだけを拒否する拒否リストです。どちらも「使えるツールの集合」そのものを絞る機能ではなく、それを担うのは--toolsです。CIやスクリプトから非対話実行するときは、この3つのフラグの役割の違いを踏まえたうえで、--permission-prompts noneや--restrictedと組み合わせて設計すると、意図しない実行や宙に浮いたプロンプトを避けられます。