Claude Code Hooks 入門-危険なコマンドを自動でブロックして安心して使う方法
はじめに
Claude Code はターミナルから自然言語でコーディングタスクを依頼できる AI エージェントです。ファイルの編集やコマンドの実行を自律的に行ってくれるため、開発効率を大幅に高められます。一方で、使い慣れてくると「rm -rf のような危険なコマンドを誤って実行されたらどうしよう」「長時間作業を任せているときにタスクが終わっても気づかない」といった不安が出てきます。
こうした悩みを解決する機能が Hooks です。Hooks を使うと、Claude Code のライフサイクル上の特定のタイミングで、シェルコマンドを自動的に実行できます。重要なのは、これが 決定論的な制御 であるという点です。CLAUDE.md に「危険なコマンドは実行しないで」と書いても LLM がそれに従うかは確率的ですが、Hooks で設定したルールは毎回必ず実行されます。
この記事では Hooks の基本的な仕組みと設定ファイルの書き方を説明した上で、すぐに使える実践例を3つ紹介します。
Hooks とは何か
Hooks は Claude Code のライフサイクル上の決まったポイントで自動実行される、ユーザー定義のシェルコマンドです。公式ドキュメント(code.claude.com/docs/en/hooks-guide)では次のように説明されています。
Hooks are user-defined shell commands that execute at specific points in Claude Code's lifecycle. They provide deterministic control over Claude Code's behavior, ensuring certain actions always happen rather than relying on the LLM to choose to run them.
CLAUDE.md との本質的な違い
CLAUDE.md はセッション開始時に読み込まれる指示ファイルですが、あくまで Claude への「お願い」です。LLM はその指示に従おうとしますが、確率的な動作であるため、複雑な状況では無視されることもあります。Hooks はそれとは根本的に異なり、システムイベントに基づいて強制的に実行される仕組みです。LLM がツールを呼び出そうとしたとき、Hooks がそのツール呼び出しを「横取り」します。
Hook のタイプ
Hooks には実行方式が4種類あります。
| タイプ | 説明 |
|---|---|
command |
ローカルでシェルコマンドを実行する。最も一般的な方式 |
http |
外部の HTTP エンドポイントにリクエストを送る |
prompt |
Claude の軽量モデル(デフォルトは Haiku)に判断を委ねる |
agent |
サブエージェントを起動してファイルやコードを確認させる(実験的機能) |
入門段階では command タイプを使えば大半のユースケースをカバーできます。
イベントの種類と役割
Hooks を設定するには、どのタイミングで発火させるかを「イベント」で指定します。主なイベントは次のとおりです。
| イベント | 発火タイミング |
|---|---|
PreToolUse |
Claude がツールを実行する直前 |
PostToolUse |
Claude がツールを実行した直後 |
SessionStart |
セッション開始時(再開・クリア・コンパクションも含む) |
Notification |
Claude が入力待ちになったとき |
Stop |
Claude が応答を終了したとき |
SubagentStop |
サブエージェントが完了したとき |
PreToolUse は実行前にブロックできるため、危険なコマンドの防止に最適です。PostToolUse は実行後の処理に使いますが、すでに実行されたあとなので取り消しはできません。この違いを意識して使い分けましょう。
また、matcher を使うと特定のツールや条件に絞ってフックを発火させられます。正規表現が使えるため、Edit|Write のように複数のツールをまとめて指定することも可能です。
設定ファイルの書き方
Hooks は .claude/settings.json(プロジェクト単位)または ~/.claude/settings.json(ユーザー全体)に記述します。基本的な構造は次のとおりです。
{ "hooks": { "イベント名": [ { "matcher": "対象ツール名(正規表現)", "hooks": [ { "type": "command", "command": "実行するシェルコマンド" } ] } ] } }
設定後は Claude Code 上で /hooks コマンドを実行すると、現在設定されているすべての Hooks をイベントごとに確認できます。設定の追加・変更・削除はファイルを直接編集するか、Claude Code 上で「このコマンドをブロックする Hook を設定して」のように依頼することでも対応できます。
実践例① 危険なコマンドのブロック
rm -rf や DROP TABLE のような取り返しのつかないコマンドを実行させないようにするには、PreToolUse フックで Bash ツールの入力を検査します。
まず、ブロック判定を行うスクリプトを .claude/hooks/block-dangerous.sh として作成します。
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
DANGEROUS_PATTERNS=("rm -rf" "DROP TABLE" "DROP DATABASE" "format c:")
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
if echo "$COMMAND" | grep -qi "$pattern"; then
echo "Blocked: '$pattern' is not allowed" >&2
exit 2
fi
done
exit 0
スクリプトを実行可能にします。
chmod +x .claude/hooks/block-dangerous.sh
次に .claude/settings.json に Hook を登録します。
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous.sh" } ] } ] } }
exit 2 で終了するとそのツール呼び出しはブロックされ、stderr の内容が Claude へのエラーメッセージとして返ります。Claude はそのフィードバックをもとにアプローチを変えようとします。
動作確認は Claude Code 上で「rm -rf /tmp/test を実行して」と依頼してみましょう。ブロックされれば設定は成功です。
実践例② タスク完了通知
長時間のタスクを Claude Code に任せて別の作業をしていると、完了しても気づかないことがあります。Notification イベントを使うと、Claude が入力待ちになったタイミングでデスクトップ通知を送れるため、ターミナルを監視しなくてよくなります。
macOS の場合は ~/.claude/settings.json に次の設定を追加します。
{ "hooks": { "Notification": [ { "matcher": "", "hooks": [ { "type": "command", "command": "osascript -e 'display notification \"作業が完了しました\" with title \"Claude Code\"'" } ] } ] } }
Linux では notify-send 'Claude Code' '作業が完了しました' に置き換えてください。matcher を空にすることで、すべての Notification タイプで発火します。特定の状況(許可待ちのときだけなど)に絞りたい場合は、permission_prompt や idle_prompt といった値を指定できます。
初回設定後に通知が届かない場合は、macOS の「システム設定 → 通知」で Script Editor の通知を許可する必要があります。ターミナルで osascript -e 'display notification "test"' を一度実行すると、通知設定に Script Editor が表示されるようになります。
実践例③ コンパクション後のコンテキスト再注入
長時間の作業でコンテキストウィンドウが上限に近づくと、Claude Code は自動的に会話を要約して圧縮(コンパクション)します。このとき、最初のほうで共有したプロジェクトのルールや進捗情報が失われることがあります。
SessionStart イベントはセッションの起動・再開・クリア・コンパクションなど、さまざまなタイミングで発火します。matcher に compact を指定することで、コンパクション時だけに絞って発火させられます。stdout に書き出した内容が、システムリマインダーとして Claude に渡されます。
{ "hooks": { "SessionStart": [ { "matcher": "compact", "hooks": [ { "type": "command", "command": "echo 'パッケージマネージャーは npm ではなく Bun を使う。コミット前に bun test を実行すること。現在のスプリント: 認証機能のリファクタリング。'" } ] } ] } }
echo を git log --oneline -5 などに変えると、直近のコミット情報を動的に注入することもできます。毎回のセッション開始時に読み込ませたい固定の内容は CLAUDE.md に書く方が適していますが、コンパクション後の復元には SessionStart フックが有効です。
まとめ
Hooks は Claude Code の動作に決定論的なガードレールを設けるための機能です。CLAUDE.md による確率的な指示とは異なり、設定した処理は必ず実行されます。
今回紹介した3つの実践例から始めると効果を実感しやすいでしょう。
まずプロジェクトの .claude/settings.json に PreToolUse で危険コマンドのブロック、~/.claude/settings.json に Notification でタスク完了通知を設定するだけで、Claude Code をより安心して使えるようになります。慣れてきたら SessionStart でのコンテキスト再注入や、PostToolUse でのコードフォーマット自動実行なども試してみてください。設定は Claude Code 上で「こういう Hook を設定して」と依頼するだけでも作ってもらえるので、ぜひ活用してみてください。
この記事がどなたかのお役に立てれば幸いです。
◆ 塩野 正人
◆ マネージドサービス部 所属
◆ X(Twitter):@shioccii
◆ 過去記事はこちら
前職ではオンプレミスで仮想化基盤の構築や運用に従事。現在は運用部隊でNew Relicを使ってサービス改善に奮闘中。New Relic User Group運営。