playpark
ホーム会社概要サービスソリューションブログお知らせお問い合わせ
playpark

あらゆる仕事を楽しむ

会社概要サービスソリューションお問い合わせ特定商取引法に基づく表記

© 2019-2026 合同会社playpark All Rights Reserved.

  1. ホーム
  2. ブログ
  3. AIコーディングツール活用 完全ガイド
  4. 【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド
ブログ一覧に戻る
技術TipsAIコーディングツール活用 完全ガイド

【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド

Claude Codeの安全設計をHooksベース(Pythonスクリプト3本)からPermissions+deny rulesベースに移行した経緯・判断理由を解説。Before/After比較と移行判断フローチャート付き。

2026年3月13日26分で読める
Claude CodeClaude Code Hooksセキュリティ設定settings.jsonAI開発環境
【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド

Claude Code Hooks シリーズ

(3記事)
  1. 1.【Claude Code Hooks】テスト自動化で品質を仕組み化 - テスト忘れゼロ件を実現する設定ガイド
  2. 2.【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン
  3. 3.【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド

「Hooks完璧に動いてるのに、なんで移行するの?」

前回の安全設計記事でprotect-branches.py、auto-approve-git-safe.py、auto-approve-gh-mcp.pyの3本柱を紹介し、「止めるべきものは確実に止め、通すべきものはスムーズに通す」設計を運用してきました。

結論から言うと、この3つのPythonスクリプトは全部削除しました。現在はPermissions(permissions.deny)のワイルドカードパターンだけで安全設計を完結させています。

「え、あんなに力説してたのに?」...はい。でも「より良い手段が見つかったら乗り換える」のがエンジニアの仕事です。この記事では、なぜHooksをやめたのか、deny rulesだけで十分だった理由、そして移行する場合の判断基準を解説します。

この記事で学べること

  • HooksベースからPermissionsベースに移行した具体的な理由
  • deny rulesのワイルドカードパターンでHooksの動的検査を代替する方法
  • Before/After の設定差分と実際のコミット履歴
  • HooksとPermissions、どちらを選ぶべきかの判断フローチャート

前提知識

  • 【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン — Before の状態
  • 【Claude Code Hooks】テスト自動化で品質を仕組み化 — Hooks活用の別パターン
  • Claude Codeのsettings.jsonの基本構造を理解している

あわせて読みたい

【Claude Code】Agent Teams 実践ガイド — マルチエージェント並列開発でタスクを自動分解する
技術Tips20分

【Claude Code】Agent Teams 実践ガイド — マルチエージェント並列開発でタスクを自動分解する

Claude Code Agent Teamsでマルチエージェント並列開発を実践。セットアップから実践的なワークフロー、コスト最適化まで。Cowork・Workflow Studioとの違いも解説します。

読む

Before:Hooksベースの安全設計(サマリ)

移行前の安全設計は、3層構成でした。

レイヤー仕組み役割
L1: 静的denypermissions.deny(170超)パターンマッチで即座にブロック
L2: 動的フックPreToolUse + Python 3スクリプトコマンド内容を動的解析して判定
L3: 自動承認PreToolUseのallow応答安全な操作の承認ダイアログを省略

3つのPythonスクリプト

protect-branches.py(約80行)

  • gh pr mergeの宛先ブランチをgh APIで確認
  • 現在のブランチが保護ブランチならpushブロック
  • refspecの宛先(src:dstのdst)をパースして保護ブランチ検出

auto-approve-git-safe.py

  • git add && git commitのようなチェーンコマンドを分割
  • 全パートが安全リストに含まれていれば自動承認

auto-approve-gh-mcp.py

  • mcp__gh__プレフィックスのツール名で判定
  • 破壊的キーワード(merge, delete, secret等)を含まなければ自動承認

この設計は動いていました。事故もゼロ。ではなぜ移行したのか。

あわせて読みたい

【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン
技術Tips32分

【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン

Claude Code Hooksのprotect-branches.pyによるブランチ保護、auto-approve設計、170超のdenyルール分類を実コード付きで解説。PreToolUse・PostToolUse・Notificationの使い分けも紹介します。

読む

転換点:なぜHooksをやめたのか

理由1:メンテナンスコストが高い

Pythonスクリプト3本、合計200行超。動くには動くけど、変更のたびに3箇所を意識する必要がある。

settings.json    → denyリストの追加・修正
protect-branches.py → refspec解析ロジックの修正
auto-approve-*.py → 安全リスト・除外リストの修正

新しい保護パターンを追加するとき、「denyリストに追加すればいいのか、Pythonスクリプトにも手を入れるべきか」の判断が毎回必要。設定が1箇所に集約されていない時点で、運用コストが高い。

理由2:deny rulesのワイルドカードが想像以上に強力だった

前回の記事を書いた時点では、deny rulesのワイルドカードパターンの表現力を過小評価していました。

"Bash(git push *:main)",
"Bash(git push *:master)",
"Bash(git push *:dev)",
"Bash(git push *:refs/heads/main)",
"Bash(git push *:refs/heads/dev)"

このワイルドカードパターンで、protect-branches.pyのrefspec解析がやっていた仕事の大部分をカバーできることに気づいた。git push feature:mainもgit push +HEAD:refs/heads/mainも、*:mainのワイルドカードで引っかかる。

Pythonで80行書いてrefspecをパースするのと、denyリストに5行追加するの、どちらが安全で保守しやすいか。答えは明白でした。

理由3:auto-approveの仕組みが不要になった

auto-approve系フックは「Bashコマンドがデフォルトで承認確認を要求する環境」で価値がありました。安全なgitコマンドまでいちいち確認ダイアログが出るのを避けるために、フックでallowを返していた。

ところが、permissions.allowに"Bash"を含めると、Bashコマンドはデフォルトで許可されます。危険なコマンドだけpermissions.denyでブロックすれば、auto-approve用のPythonスクリプトは完全に不要。

"permissions": {
  "allow": ["Bash", "Read", "Write", "Edit", "MultiEdit", "Task", "Skill", "WebSearch", "mcp__*"],
  "deny": ["... 危険なパターンだけを列挙 ..."]
}

「denyが常にallowより優先される」というClaude Codeの仕様を活用して、allowは広く取り、denyで穴を塞ぐ。この設計なら、auto-approveフックの出番はない。

理由4:gh MCPサーバーの削除

auto-approve-gh-mcp.pyは、gh MCPサーバーのツール呼び出しに対して安全判定をしていました。しかし、gh MCPサーバー自体をdotfilesの管理対象から外したため、このスクリプトの存在意義がなくなりました。

After:現在のPermissionsベース設計

settings.jsonの構成

移行後のsettings.jsonは、大きく3つのセクションで構成されています。

{
  "permissions": {
    "allow": [
      "Read",
      "Write",
      "Edit",
      "MultiEdit",
      "Bash",
      "Task",
      "Skill",
      "WebSearch",
      "mcp__serena",
      "mcp__*"
    ],
    "deny": ["... 170超のdenyルール ..."],
    "defaultMode": "acceptEdits",
    "disableBypassPermissionsMode": "disable"
  },
  "hooks": {
    "SessionStart": ["..."],
    "PreToolUse": [],
    "PostToolUse": ["..."],
    "Notification": ["..."]
  }
}

注目すべきは "PreToolUse": []。以前は3つのPythonスクリプトが登録されていたこのセクションが、空配列になっています。

deny rulesでprotect-branches.pyを代替

protect-branches.pyがやっていた3つの検査を、deny rulesでどうカバーしているか見てみましょう。

検査1:保護ブランチへの直接push → ワイルドカードパターン

"Bash(git push origin HEAD:refs/heads/main)",
"Bash(git push origin HEAD:refs/heads/dev)",
"Bash(git push --set-upstream origin main)",
"Bash(git push --set-upstream origin dev)",
"Bash(git push origin main:main)",
"Bash(git push origin dev:dev)",
"Bash(git push *:main)",
"Bash(git push *:master)",
"Bash(git push *:dev)",
"Bash(git push *:refs/heads/main)",
"Bash(git push *:refs/heads/dev)"

*:mainのワイルドカードが、「任意のローカルブランチからmainにpushする」パターンを全てキャッチします。refspecパーサーで解析していたgit push origin feature:mainも、このパターンで静的にブロックされる。

検査2:force push → 全パターンのdeny

"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(git push --force-with-lease origin HEAD:refs/heads/main)",
"Bash(git push --force-with-lease origin HEAD:refs/heads/dev)",
"Bash(git push --mirror:*)",
"Bash(git push --all:*)"

force pushの全バリエーションを網羅。--force-with-leaseも保護ブランチ宛てならブロック。

検査3:ブランチ削除 → 明示的deny

"Bash(git push origin --delete dev)",
"Bash(git push origin --delete main)",
"Bash(git push origin --delete master)",
"Bash(git push origin :*)"

git push origin :main(空のrefspecでリモートブランチを削除)もorigin :*でブロック。

Hooksの現在の使い方

PreToolUseの3スクリプトは消えましたが、Hooks自体を全廃したわけではありません。Hooksが得意な仕事にはHooksを使い続けています。

"hooks": {
  "SessionStart": [
    {
      "matcher": "compact",
      "hooks": [{
        "type": "command",
        "command": "echo 'Context compacted. Reminder: Read CLAUDE.md for project context.'"
      }]
    },
    {
      "matcher": "startup",
      "hooks": [{
        "type": "command",
        "command": "SCRIPT=\"$HOME/.claude/skills/claude-zombie-kill/scripts/zombie-kill.sh\"; [[ -x \"$SCRIPT\" ]] && bash \"$SCRIPT\" --force --min-hours 48"
      }]
    }
  ],
  "PostToolUse": [
    {
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "python3 \"$HOME/.claude/hooks/memory-monitor.py\""
      }]
    }
  ]
}
Hook役割なぜdenyで代替しないのか
SessionStart(compact)トークン圧縮後のリマインダー「イベント通知」はHooksの得意分野
SessionStart(startup)ゾンビプロセス自動kill「初期化処理」はdenyルールの守備範囲外
PostToolUseメモリ使用量モニタリング「監視・計測」はdenyで代替不可能

ルール: 「ブロック/許可」はdeny rules、「通知/監視/初期化」はHooks。守備範囲で使い分ける。

Before/After 比較

設定ファイルの変化

項目BeforeAfter
PreToolUseフック3スクリプト登録空配列
Pythonスクリプト3本(200行超)0本(メモリ監視除く)
deny rules数170超170超(微増)
設定ファイル数settings.json + 3つの.pysettings.jsonのみ
依存Python3実行環境なし

実際のコミット履歴

移行は2026年3月6日に4つのコミットで実行されました。

順序コミット内容
1a694285未使用MCP serverの設定とhookを削除
2f322fe5gh MCP用の自動承認hookスクリプトを削除
3436c0d3Bash全許可済みのため冗長なgit auto-approve hookを削除
4c5a6053protect-branches hookを削除しdenyルールで代替

段階的に削除していった理由は、各ステップで「本当に安全か」を確認しながら進めるため。一括削除して事故が起きたら、どの変更が原因か特定しにくい。

メンテナンスの変化

観点BeforeAfter
新パターン追加denyリスト or Python修正の判断が必要denyリストに1行追加するだけ
デバッグPython実行ログ + deny判定の2箇所確認denyリストの文字列マッチのみ
新規メンバーの理解settings.json + Python3本の読解settings.json1ファイルの読解
環境依存Python3が必要なし

判断基準:どちらを選ぶべきか

Permissions(deny rules)が適切なケース

  • パターンマッチで判定可能な操作のブロック(git push、rm -rf等)
  • ワイルドカードで表現できる禁止パターン(*:main、--force:*等)
  • 設定を1ファイルに集約したい場合
  • メンテナンスの簡素さを重視する場合

Hooks(PreToolUse)が適切なケース

  • 外部APIの呼び出しが必要な判定(gh API、データベース参照等)
  • 実行時のコンテキスト(現在のブランチ名、ファイル内容等)に基づく判定
  • 複雑な条件分岐が必要な場合(AかつBだがCでない、等)
  • イベント通知・監視系の処理(メモリ監視、デスクトップ通知等)

判断フローチャート

「この操作を制御したい」
  ├─ ブロック or 許可?
  │   ├─ ブロック → パターンマッチで判定可能?
  │   │   ├─ Yes → permissions.deny に追加
  │   │   └─ No → 外部API/実行時コンテキスト必要?
  │   │       ├─ Yes → PreToolUse Hook
  │   │       └─ No → deny rulesのワイルドカードで再検討
  │   └─ 通知/監視/初期化?
  │       └─ → SessionStart / PostToolUse / Notification Hook
  └─ 自動承認?
      └─ permissions.allow で対応(Hookは不要)

移行チェックリスト

もし現在Hooksベースで安全設計をしていて、Permissionsベースへの移行を検討するなら、以下を確認してください。

  1. PreToolUseフックが「パターンマッチ」しかしていない → deny rulesで代替可能
  2. auto-approveフックが存在する → permissions.allowで代替可能
  3. 外部API呼び出しをしているフックがある → そのフックはHooksとして残す
  4. Python実行環境への依存を減らしたい → deny rulesへの移行が有効

まとめ

Claude Code Hooksの安全設計は、Hooksの機能が悪かったから移行したわけではありません。deny rulesの表現力が十分に高く、Hooksのオーバーヘッドなしに同等の安全性を実現できたから移行しました。

移行の本質は「3つのPythonスクリプトをやめた」ことではなく、「設定を1ファイルに集約し、メンテナンスコストを下げた」こと。170超のdenyルールは多く見えますが、JSONの1行追加で保護パターンを増やせるのは、Pythonスクリプトを修正するより圧倒的にシンプルです。

ただし、HooksとPermissionsは排他的な選択ではありません。現に私たちはメモリ監視やゾンビプロセスkillにはHooksを使い続けています。「ブロック」はdeny rules、「監視・通知」はHooks。それぞれの得意分野で使い分けるのが、現時点でのベストプラクティスです。


あわせて読みたい

  • 【2026年版】AIコーディングツール完全比較 — Claude Code・Codex・Antigravityの選び方
  • 【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン — 移行前の設計を詳しく知りたい方へ
  • 【Claude Code Hooks】テスト自動化で品質を仕組み化 — Hooksの別の活用パターン
  • 【Claude Code】settings.json完全ガイド — Permissions・Hooksの基本設定

お問い合わせはこちら


AIコーディングツール活用 完全ガイド — この記事を含む13本の記事で、AIコーディングツールの比較・導入から実践活用までを体系的に解説しています。

13 / 13 記事
前の記事
【Claude Code】Agent Teams 実践ガイド — マルチエージェント並列開発でタスクを自動分解する
シリーズ一覧を見る
Claude Code Hooks シリーズ — 3 / 3 記事
前の記事
【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン

この技術を活用した事例

記事の技術が実際のプロジェクトでどう活かされているかをご紹介します

【自社導入事例】ブログ運用を完全自動化 - GitHubリポジトリから記事・サムネイル・SNS投稿まで

「ブログ書くのしんどい」「SNS投稿めんどくさい」を解決。GitHubリポジトリから記事生成、サムネイル作成、SNS投稿文まで自動化した、playpark自身の導入事例を紹介します。

事例を読む

【PDF RAG】社内文書AI検索で検索時間90%削減 - RAG導入の実践事例

PDFをアップロードするだけで自然言語で質問できるAI検索システム。RAGで文書検索時間を90%削減し、社内ナレッジの活用率を3.5倍に向上させた事例をご紹介します。

事例を読む

【美容室・サロン向け】指名予約と連動するAIシフト作成アプリ|シフト管理の時間を80%削減

指名予約のお客様とスタッフのシフトが自動で連動。「担当者が休みだった」をゼロに。美容院・ネイルサロン・整体など予約制サロン(スタッフ5〜50名)に特化したAIシフト作成アプリ「Shift Bud」で、シフト管理の作成時間を80%削減。

事例を読む
AI開発の導入支援

Claude CodeやAIコーディングツールの導入・カスタマイズでお困りですか?playparkでは、AI開発環境の構築から運用まで、実践に基づいた技術支援を行っています。

サービス
AI開発について相談する
ブログ一覧に戻る

関連記事

すべての記事
【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン
技術Tips
2026年3月10日32分で読める
【Claude Code Hooks 安全設計】170超のdenyルールとPreToolUseフックで「やらかし」を防ぐ実践パターン

Claude Code Hooksのprotect-branches.pyによるブランチ保護、auto-approve設計、170超のdenyルール分類を実コード付きで解説。PreToolUse・PostToolUse・Notificationの使い分けも紹介します。

Claude CodeClaude Code Hooksセキュリティ設定+3
【Claude Code】settings.json × CLAUDE.md 完全ガイド — 設定ファイルの使い分けと実践テンプレート
実験レポート
2026年2月17日48分で読める
【Claude Code】settings.json × CLAUDE.md 完全ガイド — 設定ファイルの使い分けと実践テンプレート

Claude Codeのsettings.jsonとCLAUDE.mdの使い分けを徹底解説。コピペで使える設定テンプレート付き。hooks・permissions・参照分離パターンで最適なAI開発環境を構築する方法を紹介します。

Claude CodeClaude Code カスタマイズsettings.json+6
【実測比較】Claude Code vs Codex — 実プロジェクトで使い比べてわかった選び方
技術Tips
2026年3月16日20分で読める
【実測比較】Claude Code vs Codex — 実プロジェクトで使い比べてわかった選び方

Claude CodeとCodexを実プロジェクトで使い比べて比較。開発速度・品質・コスト・拡張性の4軸で実測データに基づく選び方を解説します。

Claude CodeCodexAIコーディングツール+3

この技術を活用したサービス

記事の技術を使って、業務課題を解決しませんか?playparkのソリューションをご覧ください。

ソリューション一覧へ