Claude Code の Hooks を「設定したいけど何から始めればいいかわからない」と感じていませんか?
この記事では、コピペしてすぐ使える実践レシピにフォーカスして解説します。Hooks の仕組みや設定方法の基礎は「Claude Code Hooks 完全ガイド」をご覧ください。
[目次を開く]
Hooks を使う前に:最小限の準備
ディレクトリとファイルの構成
Hooks スクリプトはどこに置いても動きますが、以下の構成がおすすめです。
~/.claude/
├── settings.json # Hooks の設定を記述する
└── hooks/ # スクリプトをまとめて管理
├── block-env.sh
├── audit-log.sh
└── notify-slack.sh スクリプトに実行権限を付与する
スクリプトファイルを作成したら、必ず実行権限を付与します。
chmod 755 ~/.claude/hooks/*.sh jq のインストール確認
フックスクリプトで stdin の JSON を解析するために jq が必要です。
# インストール確認
jq --version
# 未インストールの場合(Mac)
brew install jq
# 未インストールの場合(Ubuntu/WSL)
sudo apt-get install jq レシピ集
レシピ① 全ツール実行の監査ログを記録する
どのツールがいつ実行されたかを記録する、最もシンプルで汎用性の高いフックです。まず最初に設定することをおすすめします。
#!/bin/bash
# ~/.claude/hooks/audit-log.sh
INPUT=$(cat)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')
LOG_FILE="$HOME/.claude/audit.log"
mkdir -p "$(dirname "$LOG_FILE")"
echo "[$TIMESTAMP] session=$SESSION_ID tool=$TOOL_NAME input=$TOOL_INPUT" >> "$LOG_FILE"
exit 0 settings.json への追加(PostToolUse):
{
"hooks": {
"PostToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/audit-log.sh"
}
]
}
]
}
} 💡 ログファイルは tail -f ~/.claude/audit.log でリアルタイムに確認できます。 レシピ② .env・シークレットファイルへのアクセスをブロックする
AI エージェントに API キーや認証情報を読み取られないよう、ファイルレベルで防御します。
#!/bin/bash
# ~/.claude/hooks/block-secrets.sh
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# ブロック対象のパターン
SECRET_PATTERN='\.env|\.env\.local|\.env\.production|id_rsa|id_ed25519|\.pem$|\.key$'
# Bash コマンドでシークレットファイルを読もうとしている場合
if [ "$TOOL_NAME" = "Bash" ]; then
if echo "$COMMAND" | grep -qE "(cat|less|more|head|tail|echo).*($SECRET_PATTERN)"; then
echo '{"decision": "block", "reason": "シークレットファイルへのアクセスはブロックされています。"}'
exit 2
fi
fi
# Read ツールでシークレットファイルを開こうとしている場合
if [ "$TOOL_NAME" = "Read" ]; then
if echo "$FILE_PATH" | grep -qE "$SECRET_PATTERN"; then
echo '{"decision": "block", "reason": "シークレットファイルへのアクセスはブロックされています。"}'
exit 2
fi
fi
exit 0 settings.json への追加(PreToolUse):
{
"hooks": {
"PreToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/block-secrets.sh"
}
]
}
]
}
} ⚠️ このフックは settings.json の deny ルールと組み合わせて使うと、より堅牢な二重防御になります。詳しくは「.env のベストプラクティス」をご覧ください。 レシピ③ 危険な rm コマンドに確認を挟む
rm -rf など破壊的なコマンドを検知して、Claude がそのまま実行しないようブロックします。
#!/bin/bash
# ~/.claude/hooks/block-dangerous-commands.sh
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if [ "$TOOL_NAME" = "Bash" ]; then
# rm -rf を含むコマンドをブロック
if echo "$COMMAND" | grep -qE 'rm\s+-[a-z]*r[a-z]*f|rm\s+-[a-z]*f[a-z]*r'; then
echo '{"decision": "block", "reason": "rm -rf コマンドは自動実行できません。必要な場合は手動で実行してください。"}'
exit 2
fi
# 本番環境への直接 push をブロック
if echo "$COMMAND" | grep -qE 'git push.*origin.*main|git push.*origin.*master'; then
echo '{"decision": "block", "reason": "main/master への直接 push はブロックされています。PR を作成してください。"}'
exit 2
fi
fi
exit 0 レシピ④ TypeScript ファイル編集後に自動で型チェックを実行
ファイルを編集するたびに型エラーをすぐ検知できます。CI より早い段階でフィードバックを得られます。
#!/bin/bash
# ~/.claude/hooks/post-edit-typecheck.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# TypeScript / TSX ファイルが対象
if echo "$FILE_PATH" | grep -qE '\.tsx?$'; then
echo "[TypeCheck] $FILE_PATH が編集されました。型チェックを実行中..." >&2
# プロジェクトルートで実行($PWD を使用)
npx tsc --noEmit 2>&1 | tail -10 >&2
fi
exit 0 settings.json への追加(PostToolUse):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/post-edit-typecheck.sh"
}
]
}
]
}
} 💡Edit以外にWriteやMultiEditも対象にしたい場合はmatcherを"Edit|Write|MultiEdit"にします。
レシピ⑤ セッション終了時に Slack へ通知する
長時間の自動タスクを Claude に任せたあと、完了したら Slack で知らせてほしい——そんなニーズに対応します。
#!/bin/bash
# ~/.claude/hooks/notify-slack-on-stop.sh
INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // "完了"')
# SLACK_WEBHOOK_URL は事前に環境変数に設定しておく
if [ -n "$SLACK_WEBHOOK_URL" ]; then
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-type: application/json' \
--data "$(jq -n --arg sid "$SESSION_ID" --arg reason "$STOP_REASON" \
'{text: ("✅ Claude Code タスク完了\nSession: " + $sid + "\n理由: " + $reason)}')" \
> /dev/null
fi
exit 0 settings.json への追加(Stop):
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/notify-slack-on-stop.sh"
}
]
}
]
}
} 💡 Slack Webhook URL の取得方法は Slack 公式ドキュメント をご覧ください。環境変数SLACK_WEBHOOK_URLは~/.bashrcまたは~/.zshrcに設定しておくと便利です。
レシピ⑥ 複数フックを組み合わせた settings.json の全体像
上記のレシピをまとめて設定した settings.json の例です。
{
"hooks": {
"PreToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/block-secrets.sh"
},
{
"type": "command",
"command": "~/.claude/hooks/block-dangerous-commands.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/audit-log.sh"
}
]
},
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/post-edit-typecheck.sh"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/notify-slack-on-stop.sh"
}
]
}
]
}
} フックのデバッグ方法
フックが期待通り動かない場合は、以下の手順で確認します。
ステップ①:スクリプトを単体で動かす
まず Claude Code を介さず、スクリプト単体で動作確認します。
echo '{"session_id": "test", "tool_name": "Bash", "tool_input": {"command": "cat .env"}}' \
| bash ~/.claude/hooks/block-secrets.sh
echo "終了コード: $?" ステップ②:stderr への出力を確認する
フックスクリプト内で >&2 に出力したメッセージは Claude Code のターミナルに表示されます。デバッグ情報は積極的に stderr へ出力しましょう。
echo "[DEBUG] TOOL_NAME=$TOOL_NAME" >&2
echo "[DEBUG] FILE_PATH=$FILE_PATH" >&2 ステップ③:ログファイルを確認する
レシピ①の監査ログフックを入れておくと、フックの実行状況をいつでも確認できます。
tail -f ~/.claude/audit.log よくある質問(FAQ)
Q. フックスクリプトが実行されているか確認するには?
A. レシピ①の監査ログフックを先に設定すると、全ツール実行の記録が残るためすぐ確認できます。
Q. Windows(WSL)でも同じスクリプトが動きますか?
A. WSL2 上の Ubuntu 環境であれば、Mac や Linux と同様に動作します。WSL 外(PowerShell 等)からの実行は想定されていません。
Q. フックスクリプトが 60 秒以上かかる処理はどうすれば?
A. デフォルトのタイムアウトは 60 秒です。重い処理はバックグラウンドで実行し、フック本体はすぐ exit 0 するようにします。
# バックグラウンドで実行してすぐ終了
(your-heavy-command &)
exit 0 Q. PreToolUse でブロックしたとき Claude はどう動きますか?
A. exit 2 と {"decision": "block", "reason": "..."} を返すと、Claude はそのツール実行をスキップし、reason の内容を元に代替手段を検討します。
まとめ
Claude Code Hooks を活用すると、AI エージェントをより安全・便利に使えるようになります。
- まず入れておくべき: レシピ①(監査ログ)と②(シークレットブロック)
- 開発効率アップ: レシピ④(自動型チェック)+ レシピ③(危険コマンドブロック)
- 長時間タスクに: レシピ⑤(Slack 通知)
Hooks の技術的な詳細(フック種別・stdin の JSON 構造・セキュリティ設計)については「Claude Code Hooks 完全ガイド」をあわせてご覧ください。
次の記事では、Claude Code と MCP サーバーの連携について解説します。

