Claude Codeで毎回同じコマンドの確認に答えるのが面倒な人、逆に危険な操作だけは確実に止めたい人向け
Claude Codeで npm 系を毎回承認するのが面倒だから自動で通したい、でも本番への git push と .env のような秘密ファイルだけは確実に止めたい、という場面で、許可リスト・拒否リストに1行ずつ書いて使う。
Claude Codeを使っていると、コマンドを実行するたびに「これ動かしていい?」と確認が出ます。安全のための仕組みですが、毎回 npm run build を承認するのは正直だるい。逆に、本番サイトへの反映だけは絶対に勝手にやってほしくない、という場面もあります。
Allow / Deny Rules は、その「いちいち確認」と「絶対に止めたい」を、コマンド単位・ファイル単位で1つずつ決めておく仕組みです。許可(allow)・確認(ask)・拒否(deny)の3種類を書いておくと、Claude Codeがそれを見て自動で判断してくれます。
噛み砕くと
会社の入館証みたいなものです。「この部屋は顔を見せれば入れる(allow)」「この部屋は毎回受付に声かけて(ask)」「この部屋は誰が来ても入室禁止(deny)」を、ドアごとに札で貼っておく感じ。
Claude Codeは何か操作する前にこの札を1枚ずつ確認します。禁止の札があればそこで止まる。許可の札があれば素通り。札がなければ「念のため確認」が出ます。
大事なのは禁止が最強だという点。許可の札を10枚貼っても、同じドアに禁止の札が1枚あれば入れません。ここが後でつまずきやすい。
モード(permission-modes)との関係を先に整理する
確認の頻度には「モード」という別の仕組みもあります。これは「読むだけは自動」「編集も自動」みたいに、確認の頻度をまとめてざっくり切り替える大きなつまみです。
対して Allow / Deny Rules は、「このコマンドだけ自動」「このファイルだけ絶対ブロック」という個別スイッチ。モードが全体の温度設定なら、ルールは部屋ごとの個別スイッチ、という関係です。
公式もModes set the baseline. Layer permission rules on topと書いています。モードで土台を決めて、その上にルールを重ねる。両方を組み合わせて使うのが前提です。
大事な前提:ルールを守らせるのはClaude Code本体であって、AIではない
ここを勘違いすると事故ります。CLAUDE.md(プロジェクトの覚え書きファイル)やプロンプトに「本番にはpushしないでね」と書いても、それは許可・拒否の設定にはなりません。
公式の言い方だとPermission rules are enforced by Claude Code, not by the model.。ルールを強制するのはClaude Code本体で、AIモデルではない、という意味です。プロンプトやCLAUDE.mdは「Claudeが何をやろうとするか」の方向づけをするだけで、「Claude Codeが何を許すか」は変えられません。
つまり、本気で止めたいものは Allow / Deny Rules か後述の止め方で設定しておく必要があります。お願いベースでは止まりません。
「ポートフォリオサイト開発」を例に、実際の手順を見る
自分のポートフォリオサイトをClaude Codeで作っている、という設定で進めます。npmまわりは毎回確認なしで通したいけど、本番への反映と秘密ファイルだけは触らせたくない。よくある状況です。
ステップ1: /permissions で今のルール一覧を見る
まずチャット欄で /permissions と打ちます。今どんな許可・確認・拒否のルールがあるか、そしてそれぞれがどの設定ファイル由来かが一覧で出ます。
公式もThis UI lists all permission rules and the settings.json file they are sourced from.と書いています。全ルールと、その出どころの設定ファイルを一覧表示してくれる。最初は空っぽか、ほぼ何もない状態が普通です。
ステップ2: npm系を確認なしで通す
npm run build を毎回承認するのが面倒なので、許可リストに足します。設定ファイル settings.json をこう書きます。
{
"permissions": {
"allow": [
"Bash(npm run *)"
]
}
}
Bash(npm run *) の * は「ここから先は何でも」という意味。npm run build も npm run dev もまとめて許可されます。これで npm run 系は確認なしで通ります。
ステップ3: 本番への反映だけは絶対に止める
逆に、git push origin main(本番サイトへの反映)は事故ると痛い。これは拒否リストに入れます。
{
"permissions": {
"allow": [
"Bash(npm run *)"
],
"deny": [
"Bash(git push *)"
]
}
}
拒否は最優先で効くので、これで git push 系は確実に止まります。許可をいくら盛っても、この1行が勝ちます。
ステップ4: 秘密ファイルを読ませない
APIキーなどを書いた .env ファイルは、そもそも読ませたくない。拒否リストに Read(.env) を足します。
{
"permissions": {
"deny": [
"Bash(git push *)",
"Read(.env)"
]
}
}
ここが地味に便利なところで、Read(.env) は Read(**/.env) と同じ扱いになります。サイトのどのフォルダにある .env でも、深さに関係なく全部止まる。1行で守れます。
ステップ5: ここで初心者がやりがちな勘違い
「許可に Bash(git *) を入れておけば、push も通るんでしょ?」と思いがちです。通りません。
ルールは deny → ask → allow の順に上から見て、最初に当たった札が勝ちます。Bash(git push *) という拒否があれば、Bash(git *) という許可があっても push は止まる。拒否が先に当たるからです。許可で上書きはできません。
ステップ6: /permissions でちゃんと効いているか確認
最後にもう一度 /permissions を開いて、足したルールが一覧に出ているか、どの設定ファイル由来になっているかを見ます。ここで Bash(git push *) が拒否側に並んでいれば設定完了です。
つまり Allow / Deny Rules は何をしてくれるのか
- やってくれる: コマンド単位・ファイル単位で「自動で通す」「毎回確認」「絶対ブロック」を1つずつ決めておける。拒否は最優先で確実に止まる
- やってくれない: CLAUDE.mdやプロンプトに書いた「お願い」を許可・拒否に変換すること。設定として書かない限り効かない
- 意味が薄い場面:
lsやcatのような読むだけのコマンド。これらは設定しなくても最初から確認なしで通るので、わざわざ許可に足す必要がない
使いどころ3シナリオ(ポートフォリオサイト開発で再現)
シナリオ1: npm系を全部まとめて確認なしで通したいとき
ポートフォリオの開発中、npm install も npm run dev も npm run build も毎回確認が出ると集中が切れます。許可に Bash(npm *) を1行入れておけば、npm に続くコマンドが全部素通り。開発のテンポが一気に上がります。
ただし広く開ける分、想定外の npm 系コマンドも通る点だけは頭に置いておきます。心配なら Bash(npm run *) のように範囲を絞るのが安全寄りです。
シナリオ2: 本番への反映だけは絶対に止めたいとき
ポートフォリオは公開サイトなので、git push origin main が走ると即本番に出てしまいます。レビュー前に反映されると恥ずかしい。拒否に Bash(git push *) を入れておけば、push系は何があっても止まります。
拒否は許可より先に判定されるので、他で git を広く許可していても、ここだけはきっちり堰き止められる。私はこの1行を最初に入れる派です。
シナリオ3: 秘密ファイルを読ませたくないとき
APIキーを書いた .env や、サーバーへの鍵が入った ~/.ssh/** は、Claudeに読ませる理由がありません。拒否に Read(.env) と Read(~/.ssh/**) を入れておきます。
~/.ssh/** の ** はフォルダをまたいで再帰的にという意味で、その中のファイル全部が対象になります。鍵まわりは1行でまとめて締めておくと安心です。
初心者が踏みやすい落とし穴
- 拒否が常に最優先。判定は
deny → ask → allowの順で、最初に当たったルールが勝ちます。許可をいくら盛っても、同じ対象に拒否があれば負ける。「許可したのに止まる」の正体はだいたいこれです *の前のスペースの有無で結果が変わる。Bash(ls *)はls -laに当たるけどlsofには当たらない。Bash(ls*)はスペースがないので両方に当たる。狙いと違う範囲を巻き込むので要注意- カッコなしの
BashとBash(rm *)は別物。前者はそのコマンド自体をClaudeから見えなくしてしまう。後者はコマンドは使えるまま、その書き方の時だけブロックする。意図せず全Bashを隠してしまう事故に注意 /Users/alice/fileは絶対の場所指定ではない。これはプロジェクトのフォルダから見た相対扱いになります。本当にパソコン全体から見た指定にしたいなら、先頭に//をつけて//Users/alice/fileと書く。公式が名指しで注意している罠です- つなげたコマンドは部品ごとに別判定。
&&や;でつないだコマンドは、それぞれが独立して審査されます。Bash(safe-cmd *)という許可があっても、safe-cmd && rm -rf .は通らない。後ろの危険な部品にも当たるルールが要るからです - ルールを守らせるのはClaude Code本体。CLAUDE.mdやプロンプトに「pushしないで」と書いても許可・拒否は変わりません。書き言葉でのお願いは「やろうとすること」を方向づけるだけ。確実に止めたいなら拒否で設定します
- 読むだけのコマンドは最初から確認なし。
lscatechogrepfindなどは設定しなくても常に通ります。逆に、これらに毎回確認を出させたいなら、確認(ask)か拒否(deny)を自分で足す必要があります - コマンドの後ろを文字で絞る指定は当てにならない。たとえば
curlのURL制限は、前に別指定を置く・httpsに変える・余分なスペースを入れるだけで簡単にすり抜けます。確実に止めたいなら、拒否でcurlやwgetごと止めて、代わりにWebFetch(domain:...)を使うか、PreToolUse hookで止めるのが公式推奨です
書き方
// .claude/settings.json に書く
{
"permissions": {
"allow": ["Bash(npm run *)"],
"deny": ["Bash(git push *)", "Read(.env)"]
}
}
やってみるとこうなる
入力
{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(git commit *)"],
"deny": ["Bash(git push *)"]
}
}
出力例
npm run build は確認なしで通り、git push origin main はルールに当たって止まる。/permissions を開くと、足したルールと、その出どころの settings.json が一覧で確認できる。
このページに出てきた言葉
- allow / ask / deny
- 許可(確認なしで通す)・確認(毎回聞く)・拒否(やらせない)の3種類。判定は <code>deny → ask → allow</code> の順で、最初に当たったものが勝つ
- settings.json
- Claude Codeの設定をまとめて書くファイル。プロジェクト用は <code>.claude/settings.json</code> に置き、許可・拒否のルールもここに書く
- ワイルドカード(*)
- 「ここから先は何でも」を表す記号。<code>Bash(npm run *)</code> なら <code>npm run</code> で始まる全部にまとめて当たる
- スペースの有無
- <code>Bash(ls *)</code> は <code>ls -la</code> に当たるが <code>lsof</code> には当たらない。<code>Bash(ls*)</code> は両方に当たる。* の前のスペースで結果が変わる
- read-only コマンド
- <code>ls</code> <code>cat</code> <code>grep</code> <code>find</code> など読むだけのコマンド。設定しなくても最初から確認なしで通る
- PreToolUse hook
- コマンドが動く直前に自前のチェック処理を割り込ませる仕組み。許可・拒否のルールでは書ききれない細かい判定に使う