0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hooksで「絶対に守らせたいルール」をClaude Codeに強制する

0
Posted at

はじめに

CLAUDE.mdに「rmは使わないでください」と書いても、Claudeがうっかり実行してしまうことがあります。CLAUDE.mdは所詮「お願い」だからです。確実に止めたい処理には、Hooks(フック)という別の仕組みを使います。

この記事で分かること

  • Hooksとは何か、CLAUDE.mdとの決定的な違い
  • フックイベントの種類(代表的な6つ)
  • settings.jsonでの基本的な書き方
  • PreToolUseでrmや環境変数ファイルへの書き込みをブロックする具体例
  • マッチャーパターンと環境変数の基本

① Hooksとは何か——CLAUDE.mdとの決定的な違い

Hooksは、Claude Codeが特定のタイミングで必ず実行する、あなたが書いたシェルコマンドです。

CLAUDE.mdとの最大の違いは、この「必ず実行される」という保証の有無です。

CLAUDE.md Hooks
役割 Claudeへの指示・文脈情報を伝える 毎回確実に実行したい処理を行う
実行の保証 確率的(読んで従おうとするが保証はない) 決定論的(設定した通り必ず実行される)
実体 マークダウンの文章 シェルコマンド

公式ドキュメントも、CLAUDE.mdは強制される設定ではなくコンテキストとして扱われるとし、動作を確実にブロックしたい場合はPreToolUseフックを使うよう案内しています。

② フックイベントの種類とHooksの基本構造

Hooksが発火するタイミング(イベント)は、2026年7月時点の公式ドキュメントで30種類あります。ここではセッションの流れに沿った代表的な6つを紹介します(一部です)。

イベント 発火タイミング ブロック可能か
SessionStart セッションの開始・再開時 -
UserPromptSubmit プロンプト送信直後、Claudeが処理する前 ✅
PreToolUse ツールの実行前 ✅
PostToolUse ツールの実行後 ❌(すでに実行済みのため)
Stop Claudeの応答が完了した時 ✅
SessionEnd セッションの終了時 -

Hooksは.claude/settings.jsonに、次のような入れ子構造で書きます。

{
  "hooks": {
    "イベント名": [
      {
        "matcher": "マッチャーパターン",
        "hooks": [
          {
            "type": "command",
            "command": "実行するコマンド",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

設定ファイルとスクリプトは、次のように分けて置くのが基本形です。

my-project/
└── .claude/
    ├── settings.json           # Hooksの設定
    └── hooks/
        └── protect-files.sh    # 実行されるスクリプト(③で作成)

③ 設定方法:rm・環境変数ファイルへの書き込みをブロックする

環境変数ファイル(.envなど)への書き込みをブロック

公式ドキュメントの実例です。Claude CodeはPreToolUse実行時、ツール名や引数をJSON形式でstdinに渡します。jq(brew install jq等で導入)でファイルパスを取り出します。スクリプトを.claude/hooks/protect-files.shに保存してください。

#!/bin/bash
# protect-files.sh

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
    exit 2
  fi
done

exit 0

保存したら実行権限を付与します(忘れるとフックが動きません)。

chmod +x .claude/hooks/protect-files.sh

.claude/settings.jsonにEdit・Write実行前にこのスクリプトを呼ぶよう登録します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

危険なコマンド(rmなど)をブロック

公式ドキュメントには、Bashコマンドにdrop tableという文字列が含まれる場合にブロックする例があります。同じ仕組みでrm -rfをブロックする完成版が次のスクリプトです。

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q "rm -rf"; then
  echo "Blocked: rm -rf is not allowed" >&2
  exit 2
fi

exit 0

ポイントは終了コード2です。返すとClaude Codeは実行をブロックし、stderrの内容がClaudeへのフィードバックになります。

④ マッチャーパターンと環境変数

matcherには次の書き方ができます。

書き方 意味 例
ツール名そのまま 完全一致 Bash
|または,区切り 複数ツールのいずれか Edit|Write
それ以外の記号を含む文字列 正規表現として評価 mcp__github__.*
空文字または* すべてにマッチ ""

フックのコマンド内では次の環境変数が使えます。

変数名 内容
$CLAUDE_PROJECT_DIR プロジェクトのルートディレクトリ
$CLAUDE_PLUGIN_ROOT プラグインのインストール先ディレクトリ
$CLAUDE_CODE_REMOTE リモートのWeb環境では"true"
$CLAUDE_EFFORT 現在のエフォートレベル
$CLAUDE_ENV_FILE direnv等と連携する際、各Bashコマンドの前に読み込まれるファイル

まとめ:まずPreToolUseフックを1つ試す

Hooksは、CLAUDE.mdの「お願い」だけでは心配な処理——危険なコマンドや、書き換えたくないファイルへの書き込み——を機械的に必ず止める仕組みです。まずは.claude/settings.jsonに次の最小構成を試してみてください。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'This command was checked by a hook' >&2"
          }
        ]
      }
    ]
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?