hooks-builder について
ツール操作、プロンプト、セッションのライフサイクルに応じて動作するClaude Codeフックの作成ガイドです。イベント選定、マッチャー、実装、安全対策、テストを説明します。
主な機能
- 0110種類のフックイベントの解説
- 02イベントとマッチャーの選定ガイド
- 03コマンド・スクリプト・プロンプトの実装例
- 04セキュリティと入力検証の確認
- 05手動テストと統合テストの手順
活用シーン
- 01危険なツール操作のブロック
- 02編集後のコード整形や検証
- 03ツール利用状況の監査
- 04セッション環境のセットアップ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mike-coulbourn/ claude-vibes --skill hooks-builderインストール後、Claude Code で/hooks-builderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/quality-hooks.mdsecurity-hooks.mdworkflow-hooks.mdreference/best-practices.mdsyntax-guide.mdtroubleshooting.mdtemplates/basic-hook.mdproduction-hooks.mdwith-decisions.mdwith-prompts.mdwith-scripts.md詳細
Hooks Builder
Claude Code のフックを作成するための包括的なガイドです。フックは、Claude のアクションを監視・制御するイベント駆動型の自動化機能です。
クイックリファレンス
10 種類のフックイベント
| イベント | 発生するタイミング | ブロック可能? | マッチャーをサポート? |
|---|---|---|---|
| PreToolUse | ツールの実行前 | はい | はい(ツール名) |
| PermissionRequest | 権限ダイアログの表示時 | はい | はい(ツール名) |
| PostToolUse | ツールの実行成功後 | いいえ | はい(ツール名) |
| Notification | Claude が通知を送信するとき | いいえ | はい |
| UserPromptSubmit | ユーザーがプロンプトを送信するとき | はい | いいえ |
| Stop | Claude の応答完了時 | 続行を強制可能 | いいえ |
| SubagentStop | サブエージェントの処理完了時 | 続行を強制可能 | いいえ |
| PreCompact | コンテキストの圧縮前 | いいえ | はい(手動/自動) |
| SessionStart | セッションの開始時 | いいえ | はい(起動/再開/クリア/圧縮) |
| SessionEnd | セッションの終了時 | いいえ | いいえ |
終了コードの意味
| 終了コード | 意味 | 効果 |
|---|---|---|
| 0 | 成功 | 制御用に stdout を JSON として解析 |
| 2 | ブロックするエラー | 拒否 — stderr が Claude に表示されます |
| その他 | ブロックしないエラー | デバッグモードで stderr が記録されます |
設定の場所
~/.claude/settings.json → Personal hooks (all projects)
.claude/settings.json → Project hooks (team, committed)
.claude/settings.local.json → Local overrides (not committed)
主な環境変数
| 変数 | 説明 |
|---|---|
$CLAUDE_PROJECT_DIR | プロジェクトのルートディレクトリ |
$CLAUDE_CODE_REMOTE | リモート/ローカルの識別子 |
$CLAUDE_ENV_FILE | 環境の永続化パス(SessionStart) |
$CLAUDE_PLUGIN_ROOT | プラグインディレクトリ(プラグインフック) |
主なコマンド
/hooks # View active hooks
claude --debug # Enable debug logging
chmod +x script.sh # Make script executable
6 段階のワークフロー
フェーズ 1:要件のヒアリング
AskUserQuestion を使って確認します:
-
どのイベントをこのフックのトリガーにしますか?
- ツールの実行(Pre/Post/Permission)→ PreToolUse、PostToolUse、PermissionRequest
- ユーザー入力 → UserPromptSubmit
- 応答の完了 → Stop、SubagentStop
- セッションのライフサイクル → SessionStart、SessionEnd
- コンテキストの管理 → PreCompact
- 通知 → Notification
-
トリガーされたときに何をしますか?
- 監視のみ(ログ記録、メトリクス)
- 条件に基づいてブロック/許可
- 実行前に入力を変更
- プロンプトにコンテキストを追加
- 続行を強制
-
ブロック、変更、または監視のみのどれを行いますか?
- オブザーバー:PostToolUse、Notification、SessionEnd(ブロック不可)
- ゲートキーパー:PreToolUse、PermissionRequest、UserPromptSubmit(ブロック可能)
- トランスフォーマー:updatedInput を使う PreToolUse(変更可能)
- コントローラー:Stop、SubagentStop(続行を強制可能)
-
セキュリティへの影響は何ですか?
- 信頼できない入力を扱いますか?
- 機密データが漏えいする可能性はありますか?
- 外部システムへのアクセスが必要ですか?
フェーズ 2:イベントの選択
ユースケースにイベントを対応させます:
| ユースケース | 最適なイベント |
|---|---|
| 危険な操作をブロックする | PreToolUse |
| 書き込み後にコードを自動フォーマットする | PostToolUse |
| ユーザープロンプトを検証する | UserPromptSubmit |
| 環境をセットアップする | SessionStart |
| タスクの完了を確実にする | Stop |
| すべてのツール使用を記録する | "*" マッチャーを指定した PostToolUse |
| 機密ファイルを保護する | Write/Edit 用の PreToolUse |
| プロジェクトのコンテキストを追加する | UserPromptSubmit |
マッチャーが必要かどうかを判断します:
- 特定のツールですか? → マッチャーを使用します:
"Write|Edit" - すべてのツールですか? →
"*"を使用するか、マッチャーを省略します - MCP ツールですか? →
mcp__server__toolパターンを使用します - Bash コマンドですか? →
Bash(git:*)パターンを使用します
フェーズ 3:マッチャーの設計
マッチャーパターンの構文:
// Exact match (case-sensitive!)
"matcher": "Write"
// OR pattern
"matcher": "Write|Edit"
// Prefix match
"matcher": "Notebook.*"
// Contains match
"matcher": ".*Read.*"
// All tools
"matcher": "*"
// MCP tools
"matcher": "mcp__memory__.*"
// Bash sub-patterns
"matcher": "Bash(git:*)"
よく使われるマッチャーパターン:
| パターン | 一致する対象 |
|---|---|
"Write" | Write ツールのみ |
"Write|Edit" | Write または Edit |
"Bash" | すべての Bash コマンド |
"Bash(git:*)" | git コマンドのみ |
"Bash(npm:*)" | npm コマンドのみ |
"mcp__.*__.*" | すべての MCP ツール |
".*" または "*" | すべて |
フェーズ 4:実装
実装方法を選択します:
-
インラインコマンド(シンプルで、外部ファイル不要):
{ "type": "command", "command": "echo \"$(date) | $tool_name\" >> ~/.claude/audit.log" } -
外部スクリプト(複雑なロジックで、再利用可能):
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate.sh" } -
プロンプトベース(LLM による評価とインテリジェントな判断):
{ "type": "prompt", "prompt": "Analyze if all tasks are complete: $ARGUMENTS", "timeout": 30 }
スクリプトテンプレート(Bash):
#!/bin/bash
set -euo pipefail
# Read JSON input from stdin
input=$(cat)
# Parse fields with jq
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
# Your logic here
if [[ "$file_path" == *".env"* ]]; then
echo "BLOCKED: Cannot modify .env files" >&2
exit 2
fi
# Success - output decision
echo '{"decision": "approve"}'
exit 0
スクリプトテンプレート(Python):
#!/usr/bin/env python3
import sys
import json
# Read JSON input from stdin
data = json.load(sys.stdin)
# Extract fields
tool_name = data.get('tool_name', '')
tool_input = data.get('tool_input', {})
file_path = tool_input.get('file_path', '')
# Your logic here
if '.env' in file_path:
print("BLOCKED: Cannot modify .env files", file=sys.stderr)
sys.exit(2)
# Success - output decision
output = {"decision": "approve"}
print(json.dumps(output))
sys.exit(0)
フェーズ 5:セキュリティの強化
重要:フックは、あなたの権限でシェルコマンドを実行します。
セキュリティチェックリスト:
- すべての変数を引用符で囲む:
"$VAR"を使い、$VARは使わない - JSON は jq または json.load で解析する(grep/sed は使わない)
- パスを検証する(
..がないこと、正規化されていること) - ログや出力に機密データを含めない
- sudo や権限昇格を使用しない
- スクリプトを事前に手動でテストする
- 実行前にプロジェクトのフックを監査する
- 適切なタイムアウトを設定する
- すべての失敗パターンに対するエラー処理を行う
安全なパターン:
# UNSAFE - injection risk
rm $file_path
# SAFE - quoted, prevents flag injection
rm -- "$file_path"
# UNSAFE - parsing risk
cat "$input" | grep "field"
# SAFE - proper JSON parsing
echo "$input" | jq -r '.field'
多層防御:
- 入力の検証(JSON を適切に解析する)
- パスのサニタイズ(正規化し、境界を確認する)
- 出力のサニタイズ(機密データを含めない)
- フェイルセーフなデフォルト(許可ではなく、エラー時にブロックする)
- タイムアウトによる保護(無限ループを防ぐ)
フェーズ 6:テスト
ステップ 1:スクリプトの手動テスト
# Create mock input
cat > /tmp/mock-input.json << 'EOF'
{
"session_id": "test-123",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.txt",
"content": "test content"
}
}
EOF
# Test script
cat /tmp/mock-input.json | ./my-hook.sh
echo "Exit code: $?"
ステップ 2:エッジケースのテスト
- 空の入力:
{} - フィールドの欠落:
{"tool_name": "Write"} - 悪意のある入力:
{"tool_input": {"file_path": "; rm -rf /"}} - 大きな入力:10KB 以上のコンテンツ
- Unicode:特殊文字を含むパス
ステップ 3:統合テスト
# Start Claude with debug mode
claude --debug
# Trigger the tool your hook targets
# Watch debug output for hook execution
ステップ 4:検証
# Check hooks are registered
/hooks
# Watch hook execution
claude --debug 2>&1 | grep -i hook
フックのパターン
オブザーバーパターン
ブロックせずにログを記録します — PostToolUse または Notification を使用します。
{
"hooks": {
"PostToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "echo \"$(date) | $tool_name\" >> ~/.claude/audit.log"
}]
}]
}
}
ゲートキーパーパターン
危険な操作をブロックします — PreToolUse または PermissionRequest を使用します。
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/file-protector.py"
}]
}]
}
}
トランスフォーマーパターン
実行前に入力を変更します — updatedInput を指定して PreToolUse を使用します。
# In script, output:
output = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"content": add_license_header(original_content)
}
}
}
print(json.dumps(output))
オーケストレーターパターン
複数のイベントを調整します — SessionStart + PreToolUse + PostToolUse を組み合わせます。
{
"hooks": {
"SessionStart": [{
"matcher": "startup",
"hooks": [{"type": "command", "command": "~/.claude/hooks/setup-env.sh"}]
}],
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "~/.claude/hooks/validate.sh"}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "~/.claude/hooks/format.sh"}]
}]
}
}
よくある落とし穴
1. ブロック時に終了コード 2 を忘れる
# WRONG - exit 1 doesn't block
echo "Error" >&2
exit 1
# RIGHT - exit 2 blocks Claude
echo "BLOCKED: reason" >&2
exit 2
2. マッチャーの大文字と小文字の区別
// WRONG - won't match "Write" tool
"matcher": "write"
// RIGHT - case-sensitive match
"matcher": "Write"
3. 変数を引用符で囲まない(インジェクションのリスク)
# WRONG - command injection vulnerability
rm $file_path
# RIGHT - properly quoted
rm -- "$file_path"
4. スクリプトにシバンがない
# WRONG - no shebang, may fail
set -euo pipefail
# RIGHT - explicit interpreter
#!/bin/bash
set -euo pipefail
5. スクリプトに実行権限を付与しない
# Don't forget!
chmod +x ~/.claude/hooks/my-hook.sh
6. JSON 内のパスを引用符で囲み忘れる
// WRONG - spaces in path will break
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/script.sh"
// RIGHT - quoted path
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/script.sh"
7. エラー処理がない
# WRONG - silent failures
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name')
# RIGHT - handle errors
input=$(cat) || { echo "Failed to read input" >&2; exit 1; }
tool=$(echo "$input" | jq -r '.tool_name') || { echo "Failed to parse JSON" >&2; exit 1; }
8. 機密データをログに記録する
# WRONG - may log secrets
echo "Processing: $input" >> /tmp/debug.log
# RIGHT - sanitize before logging
echo "Processing tool: $tool_name" >> /tmp/debug.log
フックを使用する場面
フックを使う場面:
- セキュリティの適用(危険な操作をブロックする)
- コード品質の自動化(保存時にフォーマット、リントを実行する)
- コンプライアンスと監査(すべての操作をログに記録する)
- 環境のセットアップ(一貫した設定)
- ワークフローの自動化(通知、連携)
- 入力の検証(プロンプトのチェック)
- タスク完了の確認
フックを使わない場面:
- 新しい機能を追加する場合(Skills を使用)
- 複雑な作業を委任する場合(Agents を使用)
- ユーザーが呼び出すプロンプトの場合(Commands を使用)
- 単発の簡単なタスクの場合(Claude に依頼する)
このスキルのファイル
テンプレート(段階的な複雑さ)
templates/basic-hook.md— 単一イベント、インラインコマンドtemplates/with-scripts.md— 外部シェルスクリプトtemplates/with-decisions.md— 権限の制御、入力の変更templates/with-prompts.md— LLM ベースの評価templates/production-hooks.md— 複数イベントに対応する完全なシステム
例(完成済みフック 18 件)
examples/security-hooks.md— 保護、検証、監査examples/quality-hooks.md— フォーマット、リント、テストexamples/workflow-hooks.md— セットアップ、コンテキスト、通知
リファレンス
reference/syntax-guide.md— 完全な JSON スキーマとすべてのイベントreference/best-practices.md— セキュリティ、設計、チームへの導入reference/troubleshooting.md— よくある問題 10 件とテスト手法