Claude Codeのパーミッションプロンプトを設計する——allowlistとsettings.jsonで確認頻度を最適化する

Claude Codeのパーミッションプロンプトを設計する——allowlistとsettings.jsonで確認頻度を最適化する

Claude Codeのパーミッションプロンプトが頻繁に出て作業が止まる問題を解決する。settings.jsonのallowlist設定、プロジェクト別権限とグローバル権限の使い分け、危険コマンドは残しつつ安全なコマンドを通す設計パターンを実装例付きで解説。

エンジニアのゆとです。

Claude Codeを使い始めた直後の感想として「確認ダイアログが多すぎる」という話をよく聞く。

ファイルを読むたびに「許可しますか?」、コマンドを実行するたびに「これは安全ですか?」——作業のリズムが完全に崩れる。

かといって全部許可すると今度はセキュリティが心配になる。

このトレードオフをどう設計するかを整理した。自分がyuto-lab.comの運用で実際に使っているsettings.json構成を全部公開する。


Claude Codeのパーミッション設計の基本

Claude Codeのパーミッションは2つの軸で管理されている。

スコープの軸

  • グローバル設定(~/.claude/settings.json): 全プロジェクトに適用
  • プロジェクト設定(.claude/settings.json): そのプロジェクトのみ適用

許可の軸

  • allow: 確認なしで実行OK
  • deny: 実行禁止
  • デフォルト: 都度確認ダイアログ

settings.jsonの基本構造

{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(git diff*)",
      "Read(**)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)"
    ]
  }
}

allowlistはglobパターンで書ける。* が「何でも」、** が「パスを含めた何でも」。


グローバルとプロジェクトの分け方

自分の運用方針はシンプルだ。

グローバル設定(~/.claude/settings.json)に書くもの

  • どのプロジェクトでも安全と判断できるコマンド
  • 読み込み系・情報表示系のコマンド
  • git の参照系コマンド

プロジェクト設定(.claude/settings.json)に書くもの

  • そのプロジェクト固有の書き込み系コマンド
  • 特定のスクリプト実行
  • 他のプロジェクトでは許可したくないコマンド

実際のグローバル設定

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Bash(ls*)",
      "Bash(pwd)",
      "Bash(echo *)",
      "Bash(cat *)",
      "Bash(head *)",
      "Bash(tail *)",
      "Bash(wc *)",
      "Bash(date *)",
      "Bash(which *)",
      "Bash(git status)",
      "Bash(git log*)",
      "Bash(git diff*)",
      "Bash(git branch*)",
      "Bash(git show*)",
      "Bash(git remote*)",
      "Bash(launchctl list*)",
      "Bash(ps aux*)",
      "Bash(df *)",
      "Bash(du *)"
    ],
    "deny": [
      "Bash(sudo rm*)",
      "Bash(rm -rf /)",
      "Bash(sudo mkfs*)",
      "Bash(sudo dd*)",
      "Bash(curl * | bash*)",
      "Bash(wget * | sh*)"
    ]
  }
}

「読む」「確認する」コマンドは全部グローバルで通す。「書く」「消す」系は都度確認かdeny。


ブログプロジェクトの実際の設定

{
  "permissions": {
    "allow": [
      "Bash(npm run build*)",
      "Bash(npm run dev*)",
      "Bash(npx astro*)",
      "Bash(git add src/content/blog/*)",
      "Bash(git add src/assets/*)",
      "Bash(git commit*)",
      "Bash(git push origin main)",
      "Bash(python3 scripts/gen_thumb_gpt.py*)",
      "Bash(python3 scripts/auto_publish.py*)",
      "Write(src/content/blog/**)",
      "Write(src/assets/**)"
    ]
  }
}

ブログプロジェクトでやること(ビルド・記事追加・サムネ生成・push)に絞っている。git push origin main はプロジェクト設定に書くので、他リポジトリへの誤pushは起きない。


パターン別設計指針

パターン1: 読み取り専用プロジェクト

レポジトリ分析や調査目的でClaudeを使う場合。

{
  "permissions": {
    "allow": ["Read(**)", "Bash(git log*)", "Bash(git diff*)", "Bash(grep*)", "Bash(find*)"],
    "deny": ["Write(**)", "Bash(git commit*)", "Bash(git push*)"]
  }
}

書き込みをdenyに入れると、事故的なファイル変更を完全に防げる。

パターン2: フルオートメーション用プロジェクト

自動化スクリプトを動かすプロジェクト。確認を最小化したい。

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Write(**)",
      "Bash(python3 *)",
      "Bash(node *)",
      "Bash(git *)",
      "Bash(npm *)"
    ],
    "deny": [
      "Bash(sudo *)",
      "Bash(rm -rf /)",
      "Bash(curl * | *)"
    ]
  }
}

システムレベルの操作(sudo)とパイプ経由の実行(curl | bash)だけはdenyに残す。

パターン3: 本番環境があるプロジェクト

デプロイコマンドや本番DBへの接続があるプロジェクト。

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Write(src/**)",
      "Bash(npm run test*)",
      "Bash(npm run build*)"
    ],
    "deny": [
      "Bash(npm run deploy*)",
      "Bash(*production*)",
      "Bash(psql *prod*)"
    ]
  }
}

本番環境に触れるコマンドは明示的にdenyに入れる。テスト・ビルドはOK、デプロイは手動確認必須。


Hooksと組み合わせる

パーミッション設定だけでなく、Hooksの PreToolUse でより細かい制御もできる。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/check_dangerous.sh"
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# check_dangerous.sh — 危険コマンドをブロック
TOOL_INPUT="$TOOL_INPUT_COMMAND"

# 本番環境へのアクセスを全ブロック
if echo "$TOOL_INPUT" | grep -qE "(production|prod-db|DROP TABLE)"; then
  echo '{"decision": "block", "reason": "本番環境への操作は手動で実行してください"}' 
  exit 0
fi

echo '{"decision": "approve"}'

Hooksはコマンドの内容を動的に検査できるので、「特定のキーワードを含む場合だけブロック」という柔軟な制御が可能。パーミッション設定のglobパターンでは実現できない条件を補完できる。


よくある誤設定と対策

誤設定1: Bash(*) でBash全許可

// これはやめる
"allow": ["Bash(*)"]

rm -rf * も sudo も全部通ってしまう。「Bashは全部OK」は危険すぎる。

誤設定2: denyが機能していない

// allowにワイルドカードがあるとdenyが無意味になる場合がある
"allow": ["Bash(*git*)"],
"deny": ["Bash(git push origin main)"]

allowが広すぎてdenyが負けるケース。Claude Codeの評価順はallow優先なので、より具体的なパターンでdenyを書く必要がある。

誤設定3: グローバルに書きすぎる

プロジェクト固有の書き込み許可をグローバルに書くと、全プロジェクトでその権限が有効になる。

// グローバルに書くのはNG
"allow": ["Write(src/content/blog/**)"]

プロジェクトのsettings.jsonに書く。


設定のメンテナンス

実際に運用していると「このコマンドがよく確認される」という傾向が分かってくる。

Claude Codeには /permissions コマンドで現在の設定を確認できる機能がある。確認が多いコマンドを定期的にallowlistに追加して最適化していくのが現実的な運用法だ。

また、セキュリティ感度の高いプロジェクト(本番DB、APIキーが含まれる処理)はあえてallowlistを絞って、確認ダイアログを「安全のトリガー」として残すのも一つの判断だ。

「確認が多くて鬱陶しい」は解決できるが、「確認を全部消す」のが正解ではない。


記事が見つかりません:

記事が見つかりません:

記事が見つかりません:

← 記事一覧に戻る