Claude Code には、権限の確認を全部飛ばすモードがあります。--dangerously-skip-permissions で入るやつです。
止まらなくなるので速い。自分も普段これで動かしています。
このモードだと settings.json の deny も無効になる、と思っていました。 名前が名前なので。
気になるので、確かめました。
結果
$ curl --version
Permission to use Bash with command curl --version has been denied.
止まりました。 バージョンを表示するだけのコマンドです。
.claude/settings.local.json にはこう書いてあります。
{
"permissions": {
"deny": [
"Bash(curl *)"
]
}
}
skip-permissions は「確認を飛ばす」だけで、「禁止を解除する」ではありませんでした。
hook が止めたのではない
自分は deny とは別に PreToolUse hook も入れているので、どちらが止めたのか紛らわしいところです。メッセージの文言で分かります。
deny が止めた場合
Permission to use Bash with command curl --version has been denied.
hook が止めた場合
(自分でスクリプトに書いた文言がそのまま出る)
hook のほうは自分で書いた日本語が出るので、混ざりません。上のは deny です。
何が起きているか
このモードが飛ばしているのは、「実行していいですか」の確認プロンプトです。
確認プロンプト → 飛ばす
deny のリスト → 飛ばさない
順番で言うと、deny の判定のほうが先にあります。だから確認を飛ばしても、deny に当たったものは実行されません。
「危険なモード」という名前ですが、危険なのは確認が出ないことであって、禁止が消えることではありませんでした。
なので、最低限これだけは書いておく
自分は deny に68行入れていますが、このモードで動かすなら、まず戻せないやつだけでいいと思います。
{
"permissions": {
"deny": [
"Bash(git push *)",
"Bash(git reset --hard *)",
"Bash(git checkout -- *)",
"Bash(rm -rf *)",
"Bash(rm -r *)",
"Bash(rm -f *)",
"Bash(sudo *)"
]
}
}
基準は「間違いだったとき、元に戻せるか」の1つにしています。戻せないものだけ書く。
貼ったら Claude Code を終了して開き直してください。 設定は起動時に読まれるので、動いているセッションには反映されません。ここで2回ハマりました。
確認は、無害なコマンドでできます。
"Bash(echo DENYTEST *)"
これを足して開き直して、echo DENYTEST hello を実行させる。止まれば読み込まれています。危険なコマンドを打たずに確かめられます。
防げないこと
deny はコマンドの構造を見ています。書き方を変えると別物になります。
( git push )
sh -c "git push"
git -C /path/to/repo push
これらは手元で確認しました。Bash(git push *) にも Bash(git * push *) にも一致しません。書き方を増やす方向では塞げません。
同じことが、コマンドを呼ぶ入口が変わった場合にも起きます。自分の設定には npx を止める行がありますが、
"Bash(npx vercel *)"
bunx と pnpm dlx の行はありません。 同じことをするのに、文字列が違うので別扱いになります。
(こちらは設定を見て気づいた話で、bunx を実際に走らせて確かめたわけではありません)
なので自分は、deny を1段目、実行直前の hook を2段目にしています。hook のほうは文字の並びを見るので、丸かっこも bunx も拾えます。
それでも塞ぎきれません。 スクリプトファイルに書いてから実行されると、実行される文字列は「そのファイルを動かす」だけになるので、中身は見ていません。
まとめ
-
--dangerously-skip-permissionsでもdenyは効く(実測) - 飛ばしているのは確認プロンプトだけ。禁止は残る
- deny と hook はメッセージの文言で見分けられる
- 書くのは「戻せないもの」だけでいい
- 貼ったら開き直す。 動いているセッションには効かない
- deny は構造を見る。書き方が変わると抜ける
自分は文系の大学生で、プログラミングは得意ではありません。得意でないぶんこのモードをよく使うので、確認が出ない状態で何が残っているのかは先に知っておきたかった、という話です。
確かめていないことは、確かめていないと書きました。