Claude CodeでBashコマンド別に許可・確認・禁止を設定する|git・npm・rmのレシピ集

Claude CodeでBashコマンド別に許可・確認・禁止を設定する|git・npm・rmのレシピ集 AI開発

Claude Codeに任せたいBashコマンドと、任せたくないコマンドは、プロジェクトごとに違います。テストやLintは確認なしで走らせたい、git commitは見てから通したい、git pushは止めたい、といった線引きを、settings.jsonのpermissionsで書けます。

この記事は、Bashコマンド別の設定レシピ集です。allow・ask・denyの意味や評価順序、denyで防げない迂回といった基本はClaude Codeのpermissions.allow・denyの違い|安全な設定例で説明しているため、ここでは「このコマンドはどのルールに振り分けるか」に絞ります。内容はClaude Codeの公式ドキュメント(2026年10月時点)に沿っています。

スポンサーリンク

設定の前提:3つのルールの振り分け方

Bashコマンドは、危険度で3つに分けると設計しやすくなります。

  • allow:頻繁に使い、副作用が小さいコマンド(テスト、Lint、状態確認)
  • ask:必要だが、実行前に人が見たいコマンド(依存の追加、commit)
  • deny:通常のコーディングで自動実行する必要のないコマンド(push、publish、削除)

評価はdeny、ask、allowの順です。広いdenyを、狭いallowで例外にすることはできません。たとえばdenyにBash(git push *)を書いたうえで、allowにBash(git push origin staging)を書いても、後者は通りません。詳しくはClaude Codeのpermissions.allow・denyの違い|安全な設定例を参照してください。

npm:scriptは許可、installは確認、publishは禁止

npmは、サブコマンドの違いで危険度がまったく変わります。Bash(npm *)と書くとnpm installやnpm publishまで含まれるため、npm runまでで止めます。

npmの振り分け
{
  "permissions": {
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(npm run typecheck *)"
    ],
    "ask": [
      "Bash(npm install *)"
    ],
    "deny": [
      "Bash(npm publish *)"
    ]
  }
}

Bash(npm run *)と書けば、npm run buildもnpm run test --watchも許可できます。ただし、package.jsonのscriptsに何が入っているかは、そのルールの外です。scriptの中でdeployのような処理を呼んでいるなら、npm run deployまで許可されてしまうので、許可するscript名を絞るほうが安全です。

引数なしの完全一致に注意
Bash(npm run test)のように*を付けないルールは、そのコマンドそのものにだけ一致します。npm run test -- --watchは一致しません。引数付きでも許可したいときはBash(npm run test *)と書きます。末尾の*の前に空白があると、引数なしのnpm run testにも一致します。

git:読み取りは許可、commitは確認、pushは禁止

gitは、読み取り、ローカルへの書き込み、リモートへの反映の3段階に分けます。Bash(git *)と書くとすべてのサブコマンドが含まれるので、サブコマンド単位で書きます。

gitの3段階
{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)"
    ],
    "ask": [
      "Bash(git add *)",
      "Bash(git commit *)"
    ],
    "deny": [
      "Bash(git push *)"
    ]
  }
}

なおgit statusやgit diffのような読み取り専用の形は、組み込みの読み取り専用コマンドとして、もともと確認なしで実行されます。それでもallowに書いておくと、意図が設定ファイルに残ります。

Bash(git * main)のように、サブコマンドの位置に*を置くのは避けます。*はサブコマンドもオプションも含めて何にでも一致し、git -c core.fsmonitor=...のように、プログラムを実行させるオプションまで含んでしまいます。*は、可能な限りサブコマンドの後ろに置きます。

rm・削除系:denyは「ガードレール」と割り切る

削除系のdeny
{
  "permissions": {
    "deny": [
      "Bash(rm *)"
    ]
  }
}

これでrm -rf build/は拒否されます。ただし、/bin/rm -rf build/やbash -c 'rm -rf build/'は別の文字列なので一致しません。同じことがgit pushのdenyにも言え、git -C . push origin mainは止められません。

denyは、Claudeが普通に書くコマンドを止めるガードレールです。本当に破られたくない境界は、Sandboxやフックで守ります。フックについてはClaude Code Hooks完全ガイド|Command・HTTP・Prompt・Agentフックの設定と実践活用を参照してください。

findはallowしても、削除系の形は通らない

findは読み取り専用コマンドですが、-execや-deleteを付けるとファイルを変更できます。公式ドキュメントによると、Bash(find *)のような前方一致のルールでは、-execや-delete付きの形は自動承認されません。そうした形を許可するなら、コマンド全体を書いた完全一致のルールにします。

docker・環境ランナー:内側のコマンドまで書く

docker exec、npx、mise exec、devbox runのようなランナーは、引数を別のコマンドとして実行します。そのためBash(devbox run *)を許可すると、devbox run rm -rf .も通ってしまいます。許可するときは、内側のコマンドまで書き、1つずつ追加します。

ランナーは内側まで書く
{
  "permissions": {
    "allow": [
      "Bash(devbox run npm test)"
    ]
  }
}

逆にtimeout、time、nice、nohup、stdbufのラッパーは、取り除かれてから照合されます。Bash(npm test *)はtimeout 30 npm testにも一致します。

複合コマンドは部分ごとに判定される

Claudeはnpm run test && git push origin mainのように、コマンドをつないで実行することがあります。複合コマンドは分解され、部分ごとに照合されます。npm run testが許可されていても、後ろのgit pushがdenyなら、全体は止まります。

このため、複合コマンド全体を1つの長い文字列で許可する必要はありません。確認ダイアログで「Yes, and don’t ask again」を選んだ場合も、確認が必要だった部分ごとにルールが保存されます(1回の複合コマンドで最大5つ)。

Bash(command:…)は書かない

Bash(command:rm *)のように、command:を付けて書くことはできません。この形のルールは無視され、起動時に警告が出ます。Bashでは、Bash(rm *)のようにコマンドの文字列をそのまま書きます。

Bash全体を禁止する場合

Claudeにシェルコマンドを一切実行させたくないなら、denyにツール名だけを書きます。

Bashツールを使わせない
{
  "permissions": {
    "deny": ["Bash"]
  }
}

ツール名だけのdenyは、Bashツールそのものをコンテキストから消します。Bash(rm *)のように範囲を絞ったdenyは、ツールを残したまま、一致する呼び出しだけをブロックする点が違います。

許可リスト運用:dontAskと組み合わせる

allowに書いていないコマンドは、通常のモードでは確認が出るだけで、禁止はされません。「許可したコマンドだけを実行し、それ以外は聞かずに拒否」したいなら、dontAskモードにします。夜間の自動処理など、人が確認ダイアログに答えられない環境に向いています。

許可したコマンドだけを実行する
{
  "permissions": {
    "defaultMode": "dontAsk",
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(npm run typecheck *)",
      "Bash(git status)",
      "Bash(git diff *)"
    ]
  }
}

dontAskでは、確認が必要になる呼び出しは自動で拒否され、allowで事前に承認したものと、もともと確認が不要な操作は実行されます。この場合、使う予定のコマンドを漏れなくallowに書いておく必要があります。なお、確認を省く目的でbypassPermissionsを使うのは避けてください。公式ドキュメントでは、コンテナやVMのような隔離環境でのみ使うよう警告されています。

3パターンの設定例

ここまでを組み合わせた、用途別の設定例です。コマンド名は自分のプロジェクトに合わせて変更してください。

開発用(手元で使う)
{
  "permissions": {
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)"
    ],
    "ask": [
      "Bash(npm install *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(docker build *)"
    ],
    "deny": [
      "Bash(git push *)",
      "Bash(npm publish *)",
      "Bash(rm *)"
    ]
  }
}
自動処理用(人が確認できない環境)
{
  "permissions": {
    "defaultMode": "dontAsk",
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(git diff *)"
    ],
    "deny": [
      "Bash(git push *)",
      "Bash(npm publish *)"
    ]
  }
}
Bashを使わせない(調査・レビュー用)
{
  "permissions": {
    "deny": ["Bash"]
  }
}

チームで共有するルールは.claude/settings.jsonに、個人だけが追加したい許可は.claude/settings.local.jsonに書きます。複数の設定ファイルのルールはマージされ、どこかでdenyされたものは他のレベルのallowで許可できません。ファイル同士の関係はClaude Codeのsettings.jsonが反映されない原因|User・Project・Localの優先順位を参照してください。

設定が効いているか確認する

/permissionsで、現在のルールと、各ルールの出どころの設定ファイルを確認できます。ルールを追加・削除すると、次のツール呼び出しから反映されます。「常に許可」で知らないうちに増えたルールも、ここで見直せます。チーム全体の設計はClaude Code 権限・パーミッション設定完全ガイド|settings.jsonでツール使用を制御してチーム運用を安全にする方法、機密情報の守り方はClaude Code セキュリティ完全ガイド|プロンプトインジェクション対策・権限設計・機密情報保護・監査ログも参考にしてください。

よくある質問

QBash(npm run test)と書いたのに、引数付きだと確認が出ます。なぜですか?

A*のないBashルールは、コマンド全体への完全一致です。引数付きも許可するならBash(npm run test *)と書きます。

Qlsやcatをallowに書く必要はありますか?

Aありません。ls、cat、echo、grepなどの組み込みの読み取り専用コマンドは、確認なしで実行されます。確認を求めたいときはaskかdenyを書きます。

Qgit pushを確実に止めるには、どうすればよいですか?

ABash(git push *)のdenyは、git -C . pushのような別の形には一致しません。確実に止めたいときは、Sandboxや、実行前にコマンド全体を検査するPreToolUseフックを併用します。

Qallowに書いていないコマンドを、すべて拒否できますか?

AdontAskモードにすれば、確認が必要な呼び出しを自動で拒否できます。使うコマンドを漏れなくallowに書いてください。

QCLAUDE.mdに「pushしない」と書くだけでは足りませんか?

A足りません。CLAUDE.mdはClaudeが読む指示で、実行を強制しません。通常のpushを止めるなら、Bash(git push *)をdenyに書きます。

まとめ

Bashの権限は、コマンドを「許可・確認・禁止」の3つに振り分けて書きます。npmはrunまでを許可してinstallを確認、publishを禁止にし、gitは読み取りを許可、commitを確認、pushを禁止にする、というのが基本の形です。

*はサブコマンドの後ろに置き、ランナーは内側のコマンドまで書き、複合コマンドは部分ごとに判定されると覚えておきます。そして、Bashのdenyは書かれた文字列に対するガードレールであり、確実な境界ではありません。人が確認できない環境では、dontAskと具体的なallowの組み合わせで、許可したコマンドだけを実行する構成にできます。