見出し画像

Claude Code の承認プロンプトを安全に減らす — settings.json の allow / deny 設計とコピペテンプレ

Claude Code を使っていると、コマンドのたびに「実行していい?」と確認が出ます。
安全のための仕組みですが、毎回止まると集中も途切れます。

かといって、全部スキップするモード(bypassPermissions)を常用するのは危険です。
プロンプトインジェクションや、AIの勘違いで `rm` が走ったときに、止める壁がなくなります。

落としどころは「安全なものは自動で通し、危険なものだけ確認・拒否する」設計です。
今回は、私が使っている `settings.json` の許可設計を、コピペできるテンプレと判断基準の形で渡します。

まず仕組みを最小限だけ

承認ルールは `settings.json` の `permissions` に書きます。
配列は3つです。

  • allow: 確認なしで実行してよいもの

  • ask: 毎回確認するもの

  • deny: そもそも実行させないもの

大事なのは評価の順番です。
ルールは deny → ask → allow の順で見て、最初に一致したものが勝ちます。
つまり deny が最優先。
危険なものを deny に入れておけば、後から allow を広げても、deny が必ず先に止めます。

もう1つ知っておくと得なのが、読み取り系のコマンドは最初から確認なしで動くことです。
`ls` `cat` `grep` `find` `head` `tail` `pwd`、それに読み取りだけの `git`(status や diff など)は、設定しなくても止まりません。
だから、これらをわざわざ allow に書く必要はありません。

コピペできるテンプレ

`.claude/settings.json`(プロジェクト直下)か、全プロジェクト共通なら `~/.claude/settings.json` に置きます。

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)",
      "Edit(/src/**)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(npm install *)"
    ],
    "deny": [
      "Bash(rm *)",
      "Bash(sudo *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Read(.env)",
      "Read(**/.env)",
      "Read(secrets/**)"
    ]
  }
}

各行の意図はこうです。

  • `Bash(npm run *)`: 自分で書いた package.json のスクリプトは自動で通す(テスト・ビルド・lint)

  • `Bash(git commit *)`: ローカルのコミットは自動で通す(push は別扱い)

  • `Edit(/src/**)`: `src` 配下の編集は自動で受け入れる(編集を毎回確認したい人は外す)

  • `Bash(git push *)` を ask: 外に出る操作は一回確認する

  • `Bash(npm install *)` を ask: 新しい依存を入れる前に立ち止まる

  • `Bash(rm *)` `Bash(sudo *)` を deny: 取り返しのつかない系は最初から禁止

  • `Bash(curl *)` `Bash(wget *)` を deny: 外部からの取得はインジェクションの入口になりやすい

  • `Read(.env)` `Read(/.env)` `Read(secrets/)` を deny: 秘密情報は読ませない(`Read(.env)` は全階層の `.env` に効きます)

自動許可してよい/ダメの判断チェックリスト

新しいコマンドを allow に足すか迷ったら、この基準で振り分けます。

allow(自動でよい)

  • 自分のプロジェクト内で完結し、繰り返し使う

  • 失敗しても取り返しがつく(テスト・lint・ビルド・ローカルのgit)

ask(毎回確認)

  • 外に影響する(push、デプロイ、新規依存のインストール)

  • たまにしか使わず、確認の手間が許容できる

deny(禁止)

  • 取り返しがつかない(`rm`、`sudo`、ディスク操作)

  • 外部ネットワークから取得する(`curl`、`wget`)

  • 秘密情報へのアクセス(`.env`、鍵、`secrets/`)

迷ったら deny か ask に寄せます。
deny は最優先で効くので、ここを固めておけば後が楽です。

つまずきやすい落とし穴

ここを外すと、設定したつもりで効いていない、ということが起きます。

スペースの有無で意味が変わる
`Bash(rm )` のように `` の前にスペースを入れると、「rm に続くもの」という境界ができます。
だから `Bash(rm )` は `rm -rf foo` を止めますが、`rmdir` は別コマンド扱いです。
逆にスペースなしの `Bash(ls)` は `ls` も `lsof` も両方拾います。

引数で安全を絞るのは脆い
「github へのcurlだけ許す」のような書き方は、`-X` を前に付けたり `https` に変えたりで簡単に回避されます。
URLで絞りたいなら、`curl` `wget` は丸ごと deny にして、許可したいドメインだけ `WebFetch(domain:github.com)` で通すほうが堅いです。

全許可は最終手段
`Bash`(カッコなし)や `Bash(*)` を allow に入れると、すべてのコマンドが素通りします。
bypassPermissions モードも同じで、コンテナなど壊れても困らない環境以外では常用しないほうがいいです。

Before / After

私の作業はこう変わりました。

  • Before: テストもビルドも、コマンドのたびに承認が出てリズムが切れる

  • After: 安全な定番は自動で流れ、push や install のときだけ手が止まる

体感として、止まる回数が大きく減って、危ないところだけ意識が向くようになりました。
「全部止まる」でも「全部素通り」でもない、真ん中が一番ストレスが少ないです。

まとめ

  • 承認を減らすなら、全スキップではなく allow / ask / deny の設計で

  • 評価は deny → ask → allow で、deny が最優先なので危険物はまず deny に固定する

  • 読み取り系(ls / cat / grep など)は元から確認不要なので allow に書かなくていい

  • 取り返しのつかない系(rm / sudo)・外部取得(curl / wget)・秘密情報(.env)は deny

  • 引数で安全を絞るのは脆いので、ネットワーク系は丸ごと deny + WebFetch でドメイン許可

次の一手としては、上のテンプレをそのまま置いて、1週間使ってみてください。
承認で止まった回数と、その内容をメモしておくと、自分の allow / ask / deny が育っていきます。


この記事が参考になったら、ぜひ「スキ」をお願いします。

あわせて読みたい

CLAUDE.md でAIの前提を整える設定はこちらに。

承認だけでなく、定型作業を自動化したいならこちら。


いいなと思ったら応援しよう!