この記事は playpark Blog からの転載です。
この記事で分かること
- Claude CodeのPreToolUse Hooks(Pythonスクリプト)とPermissions(deny rules)の役割の違い
- deny rulesのワイルドカードがHooksの動的検査をどこまで代替できるか
- どちらを選ぶべきかの判断基準
背景: Hooks + deny rulesの2層構成で運用していた
Claude Codeの安全設計として、以下の構成を運用していた。
| レイヤー | 仕組み | 役割 |
|---|---|---|
| 静的deny |
permissions.deny(170超) |
パターンマッチで即座にブロック |
| 動的Hook | PreToolUse + Python 3スクリプト | コマンド内容を動的解析して判定 |
| 自動承認 | PreToolUseのallow応答 |
安全な操作の承認ダイアログ省略 |
Pythonスクリプトは3本、合計200行超。refspecの解析、安全コマンドの自動承認、MCP呼び出しの安全判定を行っていた。
選択肢の検討
| アプローチ | メリット | デメリット |
|---|---|---|
| Hooks + deny(現状維持) | 動的判定が可能 | 設定が分散、Python依存、変更箇所が3箇所 |
| deny rulesに一本化 | 設定1ファイル完結、依存なし | 動的判定不可 |
| deny rules + 監視系Hooksのみ | ブロックと監視の役割分担が明確 | Hooksの柔軟性は一部失う |
なぜdeny rulesへの移行を選んだか
理由1: Hooksがやっていた仕事の大部分がパターンマッチだった
protect-branches.pyは80行かけてrefspecを解析していたが、deny rulesのワイルドカードで同等の精度を実現できる。
"Bash(git push *:main)",
"Bash(git push *:master)",
"Bash(git push *:dev)"
*:mainで「任意のソースからmainへのpush」を全てキャッチする。
理由2: permissions.allowでauto-approveが不要になった
permissions.allowに"Bash"を含めるとBashコマンドはデフォルト許可になる。危険パターンだけpermissions.denyでブロックすれば、auto-approve用のHookは完全に不要。
"permissions": {
"allow": ["Bash", "Read", "Write", "Edit", ...],
"deny": ["Bash(git push *:main)", "Bash(git push --force:*)", ...]
}
denyは常にallowより優先されるため、「広く許可して危険だけ塞ぐ」設計が成立する。
理由3: メンテナンスコストの集約
| 観点 | Before(Hooks併用) | After(deny rules中心) |
|---|---|---|
| 新パターン追加 | denyリスト or Python修正の判断が必要 | denyリストに1行追加 |
| デバッグ | Python実行ログ + deny判定の2箇所 | deny判定のみ |
| 新規メンバー理解 | settings.json + Python3本 | settings.json1ファイル |
| 環境依存 | Python3が必要 | なし |
HooksとPermissionsの使い分け基準
deny rulesに移行した後も、Hooks自体は使い続けている。役割が違う。
deny rules が適切:
- パターンマッチで判定可能なブロック処理
- ワイルドカードで表現できる禁止パターン
- 設定の一元管理が重要な場合
Hooks が適切:
- 外部API呼び出しが必要な判定
- 実行時コンテキストに基づく判定
- イベント通知・監視系の処理
「この操作を制御したい」
├─ ブロック/許可? → パターンマッチ可能?
│ ├─ Yes → permissions.deny
│ └─ No(外部API/ランタイム情報必要)→ PreToolUse Hook
└─ 通知/監視? → SessionStart / PostToolUse Hook
まとめ: どういう場面で移行すべきか
PreToolUse Hookが「パターンマッチ」しかしていないなら、deny rulesへの移行で設定を集約できる。外部API呼び出しや複雑な条件分岐が必要なHookは、そのまま残す。
HooksとPermissionsは排他ではなく、「ブロック」はdeny rules、「監視・通知」はHooksという役割分担がシンプルで保守しやすい。
さらに深掘りしたい方へ
この記事ではHooksからPermissionsへの移行理由と判断基準を解説しました。
【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド ではさらに:
- Before/After の設定差分と実際のコミット履歴(段階的移行の4ステップ)
- 全deny rulesパターンの網羅的解説(force push、ブランチ削除等)
- 移行チェックリストと判断フローチャート
playpark について
playpark LLC - 業務自動化・AI活用・Web開発