--disallowedTools(ディスアロウドツールズ)

起動オプション
--disallowedTools
ディスアロウドツールズ
Claude Codeに対して「これらの命令は最初から使わせない」というブラックリストを起動時に渡す追加スイッチ。指定した tool は Claude のコンテキストから消され、選択肢として存在しなくなる

Claude Codeを-pモードやCI/CDで動かす人向け

claude -p や GitHub Actions などで Claude を無人で走らせるとき、「git push だけは絶対にさせたくない」「本番DBに接続するコマンドを使わせたくない」「特定のMCPサーバーを1セッションだけ無効化したい」のように、特定の命令を確実に止めたい場面で起動時に書き足す

Claude Code を -p モードや CI/CD で回すとき、「Claude が暴走して git push したら本番が壊れる」みたいな事故をピンポイントで止めたい場面があります。--disallowedTools はそのための起動時の追加スイッチで、「この命令だけは絶対に使わせない」というブラックリストを Claude Code に渡せます。

素のままだとどんなふうに動かせるか、特に止めたい命令の書き分けはどうやるか、似た名前の --allowedTools--tools とどう違うか、このページで具体的に追います。

噛み砕くと

--disallowedTools は、Claude Code に「これらの命令は最初から渡されてないことにして」と伝える指定です。マンションの受付係に「101号室のお客さんは絶対に屋上に通さないで」と入口で釘を刺すイメージに近い。屋上の鍵自体を Claude から取り上げてしまうので、Claude が屋上に行きたくても物理的に行けません。

本人(Claude)には「やってもいいけど確認する」ではなく、「そもそも選択肢に存在しない」状態として渡ります。--allowedTools は「確認プロンプトなしで実行できる」許可スイッチで、ツール自体を消すわけではない。--disallowedTools は最初から取り上げてしまう。この差が後で効いてきます。なお、使えるツールのリストを丸ごと置き換えたいときは --tools という別物を使います。

大事な前提:書く中身は「permission rule」という形式

--disallowedTools の後ろに渡すのはツール名そのままではなく、「permission rule」と呼ばれる小さい構文です。ざっくり下記の書き分けができます。

  • Bash全 Bash 命令を止める(強すぎ注意)
  • Bash(git push *)git push で始まる Bash 命令だけ止める
  • Read(./.env) ← 特定ファイルの読み込みだけ止める
  • WebFetch(domain:example.com) ← 特定サイトへの fetch だけ止める
  • mcp__puppeteer ← 特定 MCP サーバーの全 tool を止める
  • Agent(Explore) ← 特定 subagent を止める

大事なのは「specifier」(カッコの中身)を入れるかどうか。入れないと丸ごと、入れるとピンポイント。これを誤ると意図と真逆に効きます。

「料理ブログの GitHub Actions で push だけ止める」を実演

題材は、料理ブログの記事更新を GitHub Actions に乗せて claude -p に任せる構成。Claude には「記事を1本足してまとめて保存しといて」までやらせたいけど、間違えて main に push されたら本番が壊れる。だから push だけ確実に止めたい、というケースです。

ステップ1: まずは何も止めずに動かしてみる

まず手元で挙動を見ます。プロジェクトのフォルダに入って、止めずに claude -p を叩いてみる。

$ cd ~/projects/cooking-blog
$ claude -p "記事を1本足して、保存して、main に push して"

Claude は順番に git addgit commitgit push origin main を試そうとします。-p モードは対話なしで一気に走るので、何も止めなければ本当に push まで通ります。これが怖い。

ステップ2: --disallowedTools で push だけブラックリストに入れる

次は push だけ精密に止めます。書き方はこう。

$ claude -p "記事を1本足して、保存して、main に push して" \
  --disallowedTools "Bash(git push *)"

ダブルクォートで囲んだ中に Bash(git push *) を入れています。これで「git push から始まる Bash 命令」だけがブラックリスト入りします。

ステップ3: Claude が push を試した瞬間に弾かれる

Claude は記事を書いてくれて、git addgit commit も普通に通ります。問題は最後の push。

Tool not allowed by permission rules: Bash(git push origin main)

こういう拒否ラインが出て、Claude はそこで止まります。「pushできなかったので人間に確認してください」みたいに、結果報告だけ返ってくる挙動になります。

ステップ4: 初心者がやりがちな勘違い

ここでよくやる事故が、--disallowedTools "Bash" と書いてしまうこと。これは 全 Bash 命令を丸ごと止める 指定なので、git addgit commitls も全部止まります。Claude は最初の git add で詰まって、何も進まなくなる。

「git push だけ止める」のような精密 deny にしたいなら、必ず specifier(カッコの中身)を付ける。Bash(git push *) の形まで書いて初めて狙い撃ちになります。

ステップ5: ローカルには変更が残っているか確認

ジョブが終わったあとに状態を見ます。

$ git log --oneline -1
a1b2c3d 記事追加: 春キャベツのペペロンチーノ

$ git ls-remote origin refs/heads/main
e4f5g6h refs/heads/main

ローカルの一番上は a1b2c3d、リモート main の先頭は e4f5g6h。一致してない=push されてない、が確認できます。これで「Claude には作業を任せたいけど、本番への反映は人間が最後に押す」運用が回せます。

ステップ6: GitHub Actions の YAML に組み込む

本番は GitHub Actions のジョブに入れます。書き方はこう。

- name: Claude で記事更新
  run: |
    claude -p "記事を1本足して、保存して" \
      --disallowedTools "Bash(git push *) Bash(git push) Bash(gh pr merge *)"

ダブルクォートの中で半角スペース区切りで複数の rule を並べられます。「push の単体形」「pattern つき push」「gh pr merge」をまとめて潰しておくと、Claude が抜け道を見つけて別の方法でマージしてくる事故も防げます。

つまり --disallowedTools は何をしてくれるのか

  • やってくれる:特定の Bash 命令・特定ファイルの読み込み・特定 MCP サーバー・特定 subagent を「Claude の選択肢から消す」
  • やってくれる:deny の優先勝ち。--allowedTools や設定ファイルで許可されていても、disallowed に書けば必ず止まる
  • やってくれない:Bash 経由・組み込みツール経由しか塞げない。Claude が Python スクリプトを書いて中で subprocess.run("curl ...") を呼ぶような迂回までは塞げない
  • 意味が薄い場面:人間が対話で逐一確認する通常モード。許可確認のたびに人間が判断するなら、ブラックリストを積まなくても事故は起きにくい

使いどころ3シナリオ(具体題材で再現)

シナリオ1: 料理ブログの GitHub Actions で自動記事更新

毎週日曜の朝9時、Actions が走って Claude が今週の人気レシピを1本下書きする運用。claude -p "..." --disallowedTools "Bash(git push *)" で push だけ止めると、下書きの commit がローカルのワークツリーに積まれた状態で止まります。人間は月曜の朝に commit の中身を確認して、自分で git pushgh pr create を手動で叩けば本番反映できる。Claude が暴走しても push は絶対に通らないので、安心して任せられます。

シナリオ2: 在庫管理アプリの修正で本番DBに触らせない

在庫管理アプリの不具合修正を Claude にやらせるとき、修正中に Claude が動作確認のつもりで本番 PostgreSQL に直接クエリを投げると、データが壊れる可能性があります。--disallowedTools "Bash(psql *) Bash(mysql *) Read(./prod-secrets.json)" と書いておけば、本番 DB 接続コマンドと秘密ファイルの読み込みをまとめて遮断できる。Claude は「ローカルの開発DBで確認した結果から判断しました」みたいに、安全な範囲で作業を進めてくれます。

シナリオ3: スクレイピング検証中に puppeteer MCP だけ1セッション止める

普段は puppeteer MCPを使ってブラウザ自動操作でスクレイピングしてるけど、今日は「puppeteer なしで API 経由だけで取れる範囲を測りたい」場面。claude --disallowedTools "mcp__puppeteer" と書いて起動すれば、そのセッション中だけ puppeteer が Claude から消えます。設定ファイルを書き換えなくていいので、一時的な切り分けに便利。

初心者が踏みやすい落とし穴

  • BashBash(git push *) の違い。前者は全 Bash 命令を止めるので、git addls も止まる。後者は git push から始まるものだけ止める精密 deny。specifier を入れ忘れて全部止まる事故が一番多い
  • 空白の有無で挙動が逆転するBash(ls *)ls -la にはマッチするが lsof にはマッチしない(空白が単語の区切りになる)。一方 Bash(ls*)lsof もマッチしてしまう。「空白あり=厳密」「空白なし=前方一致」と覚える
  • 同時に --allowedTools を書いても deny が勝つ。「First matching rule wins, deny → ask → allow の順で評価」が公式の規定。同じ起動の中で「許可と禁止の両方を書いたら禁止が通る」設計
  • 組織管理者が deny したものは --disallowedTools を外しても解除できない。Managed settings(組織レベルの設定)で禁じられたものは、ユーザー側でひっくり返せない。「私の手元では --allowedTools 書いたのに使えない」みたいな現象はこれ
  • --tools とは別物--tools は「使える tool の白リストを完全置換」する強い指定で、--disallowedTools は「使えない tool のブラックリストを足す」緩い指定。混同して --tools "Bash" と書くと「Bash だけになる」状態になり、Read も Write も Edit も同時に消える。意図と全然違う動きになるので注意
  • Bash 経由しか塞げないBash(curl *) を deny しても、Claude が Python スクリプトの中で urllib を呼べば通ってしまう。OS レベルで通信を切りたいなら、別途 sandbox や Actions の network 制限を併用する必要がある。公式ドキュメントにも警告として明記されている
  • WebFetch のドメイン制約は弱いWebFetch(domain:example.com) で example.com への fetch は止まるが、Claude が同じ内容を Bash 経由の curlwget で取りに行く抜け道は残る。WebFetch だけでなく Bash 側も同時に塞ぐのが安全
  • rule を半角スペース区切りでダブルクォート1個に収める--disallowedTools "Bash(git push *)" "Read(./.env)" のように rule ごとにクォートを分けても通るが、ターミナルの種類によっては片方が読み飛ばされることがある。--disallowedTools "Bash(git push *) Read(./.env)" のように1つの指定にまとめるのが事故が少ない

書き方

claude --disallowedTools "<rule1> <rule2> ..."

# rule の例
# Bash                       全Bash命令を止める
# Bash(git push *)           git push で始まる命令だけ止める
# Read(./.env)               特定ファイルの読み込みを止める
# WebFetch(domain:example.com) 特定サイトへのfetchを止める
# mcp__puppeteer             特定MCPサーバーを止める
# Agent(Explore)             特定subagentを止める

やってみるとこうなる

入力

claude -p "記事を1本足して、保存して、main に push して" --disallowedTools "Bash(git push *)"

出力例

Claude は記事を書き、git add と git commit までは通常通り実行する。最後の push を試みた瞬間、次のような拒否ラインが出て止まる:

  Tool not allowed by permission rules: Bash(git push origin main)

ローカルの変更履歴には残るが、リモートの main には反映されない。git log と git ls-remote origin を見比べると差分が出ているのが確認できる

このページに出てきた言葉

permission rule
Claude Code が「この命令を使っていいか」を判定する書式。<code>ツール名(具体パターン)</code> の形で書く
specifier
permission rule のカッコの中身。<code>Bash(git push *)</code> なら <code>git push *</code> がそれにあたる
word boundary
<code>Bash(ls *)</code> のカッコ内の半角スペースのこと。これがあると <code>lsof</code> のような前方一致は対象外になる
deny rule
「使わせない」と指定する rule。Claude Code は deny → ask → allow の順で評価し、最初にマッチした rule が勝つ。deny は常に最強
Managed settings
組織管理者がパソコン全体にかける設定。ここで deny されたものは、ユーザー側で <code>--allowedTools</code> や <code>--disallowedTools</code> を変えても解除できない
MCP
Claude Code に外部サービスを足し込む仕組み。<code>mcp__puppeteer</code> のように mcp__サーバー名 の名前で参照する

関連項目

公式ドキュメント

https://code.claude.com/docs/en/cli-reference

-

← 戻る