フック: クロード コードのイベント駆動型オートメーション
Claude Code はそれ自体強力なツールですが、拡張すると真の強みが現れます イベント駆動型自動化システム: gli フック。フックはシェルコマンドです ライフサイクル中の特定のイベントに応じて自動的に実行されます。 Claude Code セッションの結果、応答性の高い AI アシスタントが プロアクティブかつカスタマイズされた開発システム.
別のプロセスと通信を作成する必要がある MCP サーバーとは異なります。 構造化されたプロトコルを介して、フックは単純に実行されるシェル スクリプトのように動作します。 クロード コード プロセスから直接。これにより、非常に軽く、高速に動作します。 サーバーの複雑さを必要としない自動化に最適です。 献身的。この記事では、フックのあらゆる側面を詳しく調べます: dalla 実際のユースケースからベストユースケースまで、構成から複雑な自動化の作成まで 効果的に活用するための実践方法。
何を学ぶか
- Claude Code のイベント駆動型フック システムを理解する
- JSON設定ファイルでフックを構成する
- 利用可能な 6 つのフック イベントをすべてマスターする
- 複雑な自動化のためのカスタムフックを作成する
- Britfix、CC Notify、cchooks などのコミュニティ フックを使用する
- フックでのエラー、パフォーマンス、セキュリティの処理
- エージェント間の高度な通信パターンを実装する
- 堅牢なフック エコシステムのベスト プラクティスを適用する
シリーズ概要
| # | アイテム | 集中 |
|---|---|---|
| 1 | テクニカルパートナーとしてのクロード | セットアップと最初のステップ |
| 2 | プロジェクトのコンテキストとセットアップ | CLAUDE.mdと設定 |
| 3 | コンセプトと要件 | MVP とユーザーペルソナ |
| 4 | バックエンドとフロントエンドのアーキテクチャ | Spring Boot と Angular |
| 5 | コードの構造 | 組織と規約 |
| 6 | 高度なエンジニアリングプロンプト | 高度なテクニック |
| 7 | テストと品質 | 戦略とテストの生成 |
| 8 | 専門的な文書 | README、API、ADR |
| 9 | デプロイとDevOps | Docker、CI/CD、モニタリング |
| 10 | 進化と維持 | リファクタリングとスケーラビリティ |
| 11 | 実際のプロジェクトの統合 | クロード・コードの運用中 |
| 12 | 高度な CLI とコマンド | コマンドラインの習得 |
| 13 | カスタムスラッシュコマンドとスキル | クロードコードの拡張 |
| 14 | サブエージェントと委任 | 専門エージェントを調整する |
| 15 | フック: イベント駆動型オートメーション (ここにいます) | イベントベースの自動化 |
| 16 | ラルフ ウィガム: 自律型 AI ループ | 反復的な自律開発 |
| 17 | BMAD 手法: アジャイル AI 開発 | アジャイルな AI 主導の方法論 |
| 18 | マルチエージェントオーケストレーション | エージェントのチームを調整する |
| 19 | コラボレーションとコワーキング AI | クロードと協力して |
| 20 | セキュリティと権限 | ワークフローを保護する |
| 21 | 監視と最適化 | 指標とパフォーマンス |
1. クロード・コード著「フックとは何か」
クロード・コードのフックは、 ユーザー定義のシェルコマンド 誰が来ますか セッション中の特定のイベントで自動的に実行されます。 これらは、開発フレームワークの git フックまたはライフサイクル フックと同様に機能します。 ワークフローの重要な瞬間にフックし、ロジックを挿入できるようにします。 エージェントのコア動作を変更せずにカスタマイズできます。
フックの背後にある哲学はシンプルですが強力です: クロードを要求するのではなく プロンプト経由でアクションを実行する (エージェントが異なる解釈をする可能性がある) 予想より)、フックは実行を保証します 決定的で信頼できる。 コマンドは毎回、変更せずに定義どおりに実行されます。 または創造的な解釈。
フックと MCP サーバー: いつ何を使用するか
| 特性 | フック | MCPサーバー |
|---|---|---|
| 複雑 | 低 - シェルスクリプト | 高分離プロセス |
| レイテンシ | 最小 - 直接実行 | 専攻 - IPC通信 |
| モデルチェック | いいえ - LLM が決定しません | はい - LLM がそれらをいつ使用するかを選択します |
| 決定論 | 合計 - 常に実行される | 部分的 - コンテキストに依存します |
| 構成 | settings.json 内の JSON | SDKを備えた専用サーバー |
| ユースケース | 自動化、通知、検証 | 複雑なツール、API 統合 |
| 安全性 | 制御されたローカル実行 | ツールごとの細かい権限 |
フックシステムのアーキテクチャ
フック システムは、クロード コードの実行ループにレイヤーとして適合します。 透明なインターセプトの。サポートされているイベントが発生するたびに、 クロード コードは、そのイベント用に設定されたフックがあるかどうかを確認し、 標準入力経由でコンテキストを JSON 入力として取得し、指定されたシェル コマンドを実行します そして出力を処理して、フローへの変更を判断します。
フックは、構造化入力を JSON 形式で受け取ります。 stdin そして彼らはできる
JSON 出力を返す stdout 行動に影響を与える
エージェントの。このストリームベースのアプローチにより、パイプラインの構成が可能になります。
シンプルでユニバーサルなインターフェイスを維持しながら、複雑な処理を実現します。
┌──────────────────────┐
│ Evento Trigger │
│ (es. PreToolUse) │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Preparazione Input │
│ (JSON via stdin) │
│ - tool_name │
│ - tool_input │
│ - session_id │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Esecuzione Comando │ ← Script shell definito dall'utente
│ (shell command) │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Elaborazione Output │
│ (JSON via stdout) │
│ - decision: allow │
│ - decision: block │
│ - decision: modify │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Continuazione Flusso│
│ Claude Code │
└──────────────────────┘
2. フックの構成
フックはファイル内で設定されます .claude/settings.json 内側
プロジェクト ディレクトリまたはグローバル ユーザー設定内
(~/.claude/settings.json)。構成構造は JSON オブジェクトです
イベントをフックのリストにマップします。各フックは実行するコマンドを指定します。
オプションで、フックをアクティブにするツールまたは条件をフィルタリングするためのマッチャー。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"command": "/path/to/script.sh"
}
],
"PostToolUse": [
{
"matcher": "Bash",
"command": "python3 /path/to/logger.py"
}
],
"Stop": [
{
"command": "notify-send 'Claude Code' 'Task completato!'"
}
]
}
}
フックのプロパティ
設定フィールド
| 分野 | タイプ | 義務的 | 説明 |
|---|---|---|---|
matcher | 文字列 (正規表現) | No | アクティブ化をフィルターするための正規表現パターン。論理 OR のパイプをサポートします。 |
command | string | Si | 実行するシェルコマンド。絶対パスまたは相対パスを指定できます。 |
timeout | 番号 | No | ミリ秒単位のタイムアウト。デフォルト: 60000 (60 秒)。 |
フィールド matcher 正規表現をサポートしているため、特に強力です
完了しました。これは、特定の応答のみに応答するフックを作成できることを意味します。
ツールまたはツールの組み合わせを使用して、システムの応答性とパフォーマンスを維持します。
// Singolo tool
"matcher": "Write"
// Multipli tool con OR
"matcher": "Write|Edit|MultiEdit"
// Pattern regex complesso
"matcher": "^(Bash|Terminal)$"
// Tutti i tool (nessun matcher = wildcard)
// Omettere il campo matcher
// Tool che iniziano con "File"
"matcher": "^File.*"
// Escludere specifici tool (negazione regex)
"matcher": "^(?!Read).*$"
構成レベル
Claude Code は、フックの 3 つの階層レベルの設定をサポートしています。 これにより、さまざまな粒度レベルで自動化を定義できます。
- プロジェクト (
.claude/settings.json): 現在のリポジトリに固有のフック。リンティング、フォーマット、チーム通知などのプロジェクト関連の自動化に最適です。 - ユーザー (
~/.claude/settings.json): すべてのユーザー セッションに適用されるグローバル フック。デスクトップ通知やログなどの個人的な設定に最適です。 - エンタープライズ (
/etc/claude/settings.json): 組織全体のフック。監査ログやコンプライアンスチェックなどの会社ポリシーに使用されます。
同じイベントに複数のレベルのフックが存在する場合、それらはすべて実行されます。 優先順位: 最初に企業、次にユーザー、最後にプロジェクト。これにより保証されます 構成に関係なく、会社のポリシーが常に尊重されること 地元の。
3. 6 つのフック イベントの詳細
Claude コードは、フックをアタッチできる 6 つの異なるイベントを公開します。あらゆるイベント セッションのライフサイクルの特定の瞬間に対応し、コンテキストを提供します JSON 入力経由で特定。それぞれの出来事を深く理解することが不可欠です 効果的で堅牢な自動化を設計します。
3.1 PreToolUse: 実行前のインターセプト
イベント プレツールの使用 アクティブ化されています 前に クロード・コードが実行すること あらゆるツール。これは最も強力な迎撃ポイントです。 検査、変更、またはブロック 楽器を演奏する システムに影響を与える前に。
PreToolUse の JSON 入力
| 分野 | タイプ | 説明 |
|---|---|---|
tool_name | string | ツール名 (例: "Write"、"Bash"、"Edit") |
tool_input | 物体 | 機器に渡されるパラメータ |
session_id | string | 一意のセッション識別子 |
フックは、次の 3 つの可能な決定を含む出力 JSON を返すことができます。
"decision": "allow"- 機器を変更せずに実行できるようにします"decision": "block"- 実行を完全にブロックします。フィールドが必要ですreasonモチベーションを持って。"decision": "modify"- 実行前に機器パラメータを編集します。フィールドが必要ですtool_inputパラメータが更新されました。
#!/bin/bash
# Hook PreToolUse: blocca operazioni su file protetti
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input')
# Blocca scrittura su file di configurazione critica
if [ "$TOOL_NAME" = "Write" ] || [ "$TOOL_NAME" = "Edit" ]; then
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // .path // ""')
# Lista file protetti
PROTECTED_FILES=(".env" ".env.production" "secrets.json" "credentials.yaml")
for PROTECTED in "${PROTECTED_FILES[@]}"; do
if [[ "$FILE_PATH" == *"$PROTECTED"* ]]; then
echo "{\"decision\": \"block\", \"reason\": \"File protetto: $PROTECTED. Modifica manuale richiesta.\"}"
exit 0
fi
done
fi
# Blocca comandi Bash distruttivi
if [ "$TOOL_NAME" = "Bash" ]; then
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // ""')
# Pattern pericolosi
if echo "$COMMAND" | grep -qE "rm\s+-rf\s+/|DROP\s+TABLE|DELETE\s+FROM.*WHERE\s+1=1|format\s+c:"; then
echo "{\"decision\": \"block\", \"reason\": \"Comando potenzialmente distruttivo bloccato.\"}"
exit 0
fi
fi
# Permettere tutto il resto
echo '{"decision": "allow"}'
#!/bin/bash
# Hook PreToolUse: aggiunge automaticamente header ai nuovi file
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
if [ "$TOOL_NAME" = "Write" ]; then
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path')
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content')
# Aggiungi header copyright ai file TypeScript
if [[ "$FILE_PATH" == *.ts ]]; then
HEADER="// Copyright $(date +%Y) - MyCompany\n// Auto-generated header by Claude Code hook\n\n"
MODIFIED_CONTENT="${HEADER}${CONTENT}"
echo "$INPUT" | jq --arg content "$MODIFIED_CONTENT" \
'{decision: "modify", tool_input: (.tool_input + {content: $content})}'
exit 0
fi
fi
echo '{"decision": "allow"}'
3.2 PostToolUse: 実行後の対応
イベント ポストツール使用 アクティブ化されています dopo ツールが完成したこと その実行。に最適なスポットです ロギング、結果の検証、 出力変換 操作の結果に基づいたその後のアクション。
PreToolUse とは異なり、PostToolUse は操作をブロックしたり変更したりすることはできません (それはすでに起こっています)しかし、クロードが結果をどのように解釈するかに影響を与える可能性があります ログの更新、通知の送信、トリガーなどのサイドアクションを実行できます。 外部パイプライン。
PostToolUse の JSON 入力
| 分野 | タイプ | 説明 |
|---|---|---|
tool_name | string | 実行するツールの名前 |
tool_input | 物体 | 実行に使用されるパラメータ |
tool_output | string | ツールの結果 |
session_id | string | セッション識別子 |
#!/usr/bin/env python3
"""Hook PostToolUse: logga tutte le operazioni di scrittura file."""
import json
import sys
from datetime import datetime
from pathlib import Path
def main():
input_data = json.loads(sys.stdin.read())
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
session_id = input_data.get("session_id", "unknown")
# Logga solo operazioni di modifica file
if tool_name in ("Write", "Edit", "MultiEdit"):
log_entry = {
"timestamp": datetime.now().isoformat(),
"session_id": session_id,
"tool": tool_name,
"file": tool_input.get("file_path", "N/A"),
"operation": "write" if tool_name == "Write" else "edit"
}
log_file = Path(".claude/hooks/activity.log")
log_file.parent.mkdir(parents=True, exist_ok=True)
with open(log_file, "a") as f:
f.write(json.dumps(log_entry) + "\n")
# Logga comandi Bash eseguiti
if tool_name == "Bash":
command = tool_input.get("command", "")
log_entry = {
"timestamp": datetime.now().isoformat(),
"session_id": session_id,
"tool": "Bash",
"command": command[:200], # Tronca per sicurezza
"exit_code": "success"
}
log_file = Path(".claude/hooks/bash-history.log")
log_file.parent.mkdir(parents=True, exist_ok=True)
with open(log_file, "a") as f:
f.write(json.dumps(log_entry) + "\n")
if __name__ == "__main__":
main()
3.3 UserPromptSubmit: ユーザープロンプトのインターセプト
イベント ユーザープロンプト送信 ユーザーがプロンプトを送信すると起動します クロード・コードに。このフックにより、次のことが可能になります。 前処理、強化、またはフィルタリング ユーザーメッセージがモデルに到達する前に。特に便利なのは、 自動コンテキストの追加、プロンプト テンプレートの適用、またはフィルターの実装 受信メッセージのセキュリティ。
#!/bin/bash
# Hook UserPromptSubmit: aggiunge contesto Git automatico
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
# Aggiungi informazioni sul branch corrente
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "N/A")
LAST_COMMIT=$(git log --oneline -1 2>/dev/null || echo "N/A")
DIRTY_FILES=$(git status --porcelain 2>/dev/null | wc -l)
# Crea contesto arricchito
CONTEXT="[Git Context: branch=$BRANCH, last_commit=$LAST_COMMIT, dirty_files=$DIRTY_FILES]"
# Modifica il prompt aggiungendo il contesto
ENRICHED_PROMPT="$CONTEXT\n\n$PROMPT"
echo "$INPUT" | jq --arg prompt "$ENRICHED_PROMPT" \
'{decision: "modify", prompt: $prompt}'
3.4 停止: 世代終了時のアクション
イベント 停止 クロード コードが生成を完了するとアクティブになります。 応答するか、タスクを完了します。に最適なスポットです 通知、クリーンアップ、 レポートの生成 完了時に実行する必要があるアクション 相互作用の。このフックは、長時間のタスクの場合に特に役立ちます。 ユーザーが端末の前にいない可能性があります。
#!/bin/bash
# Hook Stop: invia notifica desktop quando Claude completa
INPUT=$(cat)
STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // "completed"')
# Notifica su Linux (notify-send)
if command -v notify-send &> /dev/null; then
notify-send "Claude Code" "Task completato: $STOP_REASON" \
--icon=dialog-information \
--urgency=normal
fi
# Notifica su macOS (osascript)
if command -v osascript &> /dev/null; then
osascript -e "display notification \"Task completato: $STOP_REASON\" with title \"Claude Code\""
fi
# Suono di completamento
if command -v aplay &> /dev/null; then
aplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null &
elif command -v afplay &> /dev/null; then
afplay /System/Library/Sounds/Glass.aiff &
fi
3.5 SessionStart: セッションの初期化
イベント セッション開始 新しいセッションが開始されるたびにアクティブ化されます クロード・コード。理想的な時期です 環境セットアップ、コンテキストの読み込み 追加の前提条件の検証 必要なリソースの準備 ワークセッション用に。
#!/bin/bash
# Hook SessionStart: prepara l'ambiente di sviluppo
# Verifica prerequisiti
echo "Verificando ambiente di sviluppo..." >&2
# Controlla che Node.js sia disponibile
if ! command -v node &> /dev/null; then
echo '{"warning": "Node.js non trovato. Alcune funzionalità potrebbero non funzionare."}' >&2
fi
# Controlla che il database di sviluppo sia raggiungibile
if command -v pg_isready &> /dev/null; then
if ! pg_isready -q 2>/dev/null; then
echo '{"warning": "PostgreSQL non raggiungibile. Avviare il database."}' >&2
fi
fi
# Carica variabili d'ambiente dal .env
if [ -f ".env" ]; then
export $(grep -v '^#' .env | xargs) 2>/dev/null
fi
# Registra inizio sessione
echo "{\"session_start\": \"$(date -Iseconds)\", \"cwd\": \"$(pwd)\"}" \
>> .claude/hooks/sessions.log 2>/dev/null
# Pulisci file temporanei di sessioni precedenti
find /tmp -name "claude-hook-*" -mtime +1 -delete 2>/dev/null
3.6 SessionEnd: クリーンアップと最終レポート
イベント セッション終了 クロード コード セッションが閉じられるとアクティブになります。 に最適なスポットです 状態を保存し、セッションレポートを生成し、 クリーンアップを実行する 将来のセッションに役立つ情報を保存します。
#!/usr/bin/env python3
"""Hook SessionEnd: genera un report della sessione di lavoro."""
import json
import sys
from datetime import datetime
from pathlib import Path
def main():
input_data = json.loads(sys.stdin.read())
session_id = input_data.get("session_id", "unknown")
# Leggi il log delle attivita
log_file = Path(".claude/hooks/activity.log")
activities = []
if log_file.exists():
with open(log_file) as f:
for line in f:
try:
entry = json.loads(line.strip())
if entry.get("session_id") == session_id:
activities.append(entry)
except json.JSONDecodeError:
continue
# Genera report
report = {
"session_id": session_id,
"end_time": datetime.now().isoformat(),
"total_operations": len(activities),
"files_modified": list(set(
a.get("file", "") for a in activities
if a.get("tool") in ("Write", "Edit", "MultiEdit")
)),
"bash_commands": sum(
1 for a in activities if a.get("tool") == "Bash"
)
}
# Salva report
reports_dir = Path(".claude/hooks/reports")
reports_dir.mkdir(parents=True, exist_ok=True)
report_file = reports_dir / f"session-{session_id[:8]}.json"
with open(report_file, "w") as f:
json.dump(report, f, indent=2)
print(f"Report sessione salvato: {report_file}", file=sys.stderr)
if __name__ == "__main__":
main()
フックイベントの概要
| イベント | 起動時 | ブロックできますか? | 編集できますか? |
|---|---|---|---|
| プレツールの使用 | ツールを実行する前に | Si | はい (ツールパラメータ) |
| ポストツール使用 | ツールを実行した後 | No | いいえ(副作用のみ) |
| ユーザープロンプト送信 | ユーザーがプロンプトを送信するとき | Si | はい (プロンプトテキスト) |
| 停止 | クロードが生成を完了したとき | No | No |
| セッション開始 | 新しいセッションの開始時 | No | No |
| セッション終了 | セッションの終わりに | No | No |
4. コミュニティフック: すぐに使えるソリューション
Claude Code コミュニティは、問題を解決する多くの洗練されたフックを開発しました。 開発者の共通のニーズ。これらのオープンソース プロジェクトは多用途性を示しています フック システムの一部であり、直接使用することも、カスタマイズのベースとして使用することもできます。
4.1 Britfix: アメリカ英語とイギリス英語の自動変換
ブリットフィックス スペルを自動的に変換する PostToolUse フックです クロード・コードによって書かれたファイル内のイギリス英語綴りのアメリカ英語。それは 英国の基準に準拠しながらも AI モデルを使用するチーム向けに作成されました 主にアメリカのテキストでトレーニングを受けました。
フックはすべてのファイル書き込み操作をインターセプトし、内容を単語ごとに解析します。 アメリカのスペル (「color」、「optimize」、「center」など) を使用して、次のように置き換えます。 英国のバリアント (「カラー」、「最適化」、「センター」)。プロセスは透明です 手動による介入は必要ありません。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "npx britfix --auto-fix"
}
]
}
}
4.2 CC Notify: スマートデスクトップ通知
CC通知 さらに進化した高度なデスクトップ通知システムです 簡単な完了通知。タイプごとに区別された通知をサポート イベント、通知履歴、メッセージング システムとの統合 (Slack、Discord、Telegram) およびアクティビティ タイプごとの詳細な構成。
CC Notify の特に便利な機能は、時間を見積もる機能です。 以前のセッションの履歴に基づいて長時間のタスクが残されているため、許可されます。 クロード コードを実行しながら、ユーザーはより効率的に時間を計画できます。 バックグラウンドで動作します。
{
"hooks": {
"Stop": [
{
"command": "cc-notify --channel slack --sound chime --message 'Task completato'"
}
],
"SessionStart": [
{
"command": "cc-notify --channel desktop --message 'Sessione Claude avviata'"
}
],
"PreToolUse": [
{
"matcher": "Bash",
"command": "cc-notify --log-activity bash"
}
]
}
}
4.3 cchooks: プロフェッショナル フック用の Python SDK
チョーク 作成を劇的に簡素化する Python SDK です 複雑なフックの。手動の JSON 解析を使用してシェル スクリプトを作成する代わりに、cchooks 型付き Python デコレータ、自動入出力処理、および 一般的な操作のためのユーティリティ ライブラリ。
#!/usr/bin/env python3
"""Hook creato con cchooks SDK."""
from cchooks import hook, PreToolUseInput, HookDecision
@hook("PreToolUse")
def validate_file_size(event: PreToolUseInput) -> HookDecision:
"""Blocca la scrittura di file troppo grandi."""
if event.tool_name == "Write":
content = event.tool_input.get("content", "")
max_lines = 500
if content.count("\n") > max_lines:
return HookDecision.block(
reason=f"File troppo grande: {content.count(chr(10))} righe "
f"(max {max_lines}). Suddividi in file più piccoli."
)
return HookDecision.allow()
@hook("PostToolUse")
def auto_lint(event):
"""Esegue linting automatico dopo ogni modifica file."""
import subprocess
if event.tool_name in ("Write", "Edit"):
file_path = event.tool_input.get("file_path", "")
if file_path.endswith(".ts") or file_path.endswith(".js"):
subprocess.run(
["npx", "eslint", "--fix", file_path],
capture_output=True, timeout=30
)
elif file_path.endswith(".py"):
subprocess.run(
["python3", "-m", "black", file_path],
capture_output=True, timeout=30
)
4.4 クロード コード フック通信: エージェント間のリアルタイム通信
クロードコードフック通信 間のリアルタイム通信を可能にします。 同じプロジェクトまたは関連するプロジェクトで動作するクロード コードの複数のインスタンス。 共有ファイルまたはソケットベースのメッセージング システムを使用して調整する 複数のエージェントのアクティビティを回避し、作業の競合や重複を回避します。
このフックは、複数のエージェントが存在するマルチエージェント開発シナリオで特に役立ちます。 Claude コードはプロジェクトのさまざまな側面 (フロントエンドとバックエンドなど) で作業します。 また、共有インターフェイスへの変更を同期する必要があります。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "claude-hook-comms publish --topic file-changes --data-from-stdin"
}
],
"SessionStart": [
{
"command": "claude-hook-comms subscribe --topic file-changes --handler sync-handler.sh"
}
]
}
}
// sync-handler.sh - Gestisce le notifiche di cambio file
#!/bin/bash
INPUT=$(cat)
CHANGED_FILE=$(echo "$INPUT" | jq -r '.file_path')
AGENT_ID=$(echo "$INPUT" | jq -r '.agent_id')
echo "[SYNC] Agente $AGENT_ID ha modificato: $CHANGED_FILE" >> .claude/hooks/sync.log
5. カスタムフックの作成: ステップバイステップガイド
カスタムフックを作成するには、入出力形式を理解する必要があります。 適切なスクリプト言語の選択と堅牢性への注意 効率性。このセクションでは、作成から プロ仕様のフックの製作。
ステップ 1: 目的を定義する
コードを記述する前に、フックが何を行うべきかを明確に定義することが重要です。
- どのイベントですか? フックが介入する正確な瞬間を特定する
- どのようなアクションですか? 実行する必要があることを定義します (ブロック、変更、ログ、通知)。
- どのような条件ですか? フックをいつ起動するかを指定します (マッチャー)
- どのような影響がありますか? ワークフローに対するフックの影響を評価する
ステップ 2: スクリプトを作成する
#!/bin/bash
set -euo pipefail
# Leggi input JSON da stdin
INPUT=$(cat)
# Estrai campi comuni
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // ""')
# ================================
# LOGICA DEL HOOK
# ================================
# Esempio: loggare l'operazione
echo "[$(date -Iseconds)] Hook triggered: tool=$TOOL_NAME session=$SESSION_ID" >&2
# ================================
# OUTPUT (solo per PreToolUse/UserPromptSubmit)
# ================================
# Opzione 1: Permettere
echo '{"decision": "allow"}'
# Opzione 2: Bloccare
# echo '{"decision": "block", "reason": "Motivo del blocco"}'
# Opzione 3: Modificare
# echo '{"decision": "modify", "tool_input": {...}}'
ステップ 3: フックをテストする
スクリプト内のエラーによってブロックされる可能性があるため、フックのテストは不可欠です または、クロード コード セッション全体の速度を低下させます。テストに対する構造化されたアプローチは次のとおりです。
#!/bin/bash
# Testa un hook simulando l'input JSON
HOOK_SCRIPT="./my-hook.sh"
# Simula input PreToolUse per Write
echo '{
"tool_name": "Write",
"tool_input": {
"file_path": "/tmp/test.ts",
"content": "console.log(\"hello\");"
},
"session_id": "test-session-001"
}' | bash "$HOOK_SCRIPT"
echo "---"
# Simula input PreToolUse per Bash con comando pericoloso
echo '{
"tool_name": "Bash",
"tool_input": {
"command": "rm -rf /"
},
"session_id": "test-session-001"
}' | bash "$HOOK_SCRIPT"
echo "---"
# Verifica exit code
echo "Exit code: $?"
ステップ 4: 登録とアクティブ化
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"command": "bash .claude/hooks/pre-tool-guard.sh"
},
{
"matcher": "Bash",
"command": "bash .claude/hooks/bash-validator.sh"
}
],
"PostToolUse": [
{
"command": "python3 .claude/hooks/post-tool-logger.py"
}
],
"Stop": [
{
"command": "bash .claude/hooks/notify-complete.sh"
}
],
"SessionStart": [
{
"command": "bash .claude/hooks/session-init.sh"
}
],
"SessionEnd": [
{
"command": "python3 .claude/hooks/session-report.py"
}
]
}
}
6. フックの高度なパターン
基本的な使い方に加えて、フックを組み合わせて洗練されたパターンを作成することもできます。 複雑な自動化ニーズを解決します。このセクションではいくつかを紹介します コミュニティの経験から生まれた最も有用なパターンをまとめました。
パターン: チェックポイントでの自動コミット
このパターンでは、定期的に Git コミットが自動的に作成されます。 開発セッション。作業が決して失われないようにします。 きめ細かなロールバック ポイントを提供します。
#!/bin/bash
# Hook PostToolUse: crea checkpoint automatici
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
# Solo per operazioni di modifica file
if [ "$TOOL_NAME" = "Write" ] || [ "$TOOL_NAME" = "Edit" ]; then
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
# Controlla se ci sono abbastanza modifiche per un checkpoint
CHANGES=$(git diff --stat 2>/dev/null | tail -1)
NUM_FILES=$(git diff --name-only 2>/dev/null | wc -l)
if [ "$NUM_FILES" -ge 3 ]; then
git add -A 2>/dev/null
git commit -m "checkpoint: auto-save dopo $NUM_FILES file modificati" \
--no-verify 2>/dev/null
echo "[CHECKPOINT] Commit automatico: $NUM_FILES file" >&2
fi
fi
パターン: 品質ゲートの事前コミット
このパターンは、品質チェック (リンティング、型チェック、 単体テスト)、書き込み操作を許可する前に、各 変更はプロジェクト標準に準拠します。
#!/bin/bash
# Hook PreToolUse: quality gate per file TypeScript
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
if [ "$TOOL_NAME" = "Write" ]; then
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path')
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content')
if [[ "$FILE_PATH" == *.ts ]]; then
# Scrivi il contenuto in un file temporaneo per analisi
TEMP_FILE=$(mktemp /tmp/claude-hook-XXXXXX.ts)
echo "$CONTENT" > "$TEMP_FILE"
# Esegui type checking
ERRORS=$(npx tsc --noEmit --strict "$TEMP_FILE" 2>&1 || true)
rm -f "$TEMP_FILE"
if echo "$ERRORS" | grep -q "error TS"; then
ERROR_COUNT=$(echo "$ERRORS" | grep -c "error TS")
echo "{\"decision\": \"block\", \"reason\": \"Type check fallito: $ERROR_COUNT errori TypeScript trovati. Correggi prima di scrivere.\"}"
exit 0
fi
fi
fi
echo '{"decision": "allow"}'
パターン: コンテキスト強化パイプライン
このパターンでは、各ユーザー プロンプトに情報が自動的に追加されます。 リポジトリのステータス、最近変更されたファイルなどの関連コンテキスト、 失敗したテストとプロジェクトの指標。
#!/bin/bash
# Hook UserPromptSubmit: pipeline di arricchimento contesto
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
# Raccogli contesto
CONTEXT_PARTS=()
# 1. Stato Git
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
if [ -n "$BRANCH" ]; then
DIRTY=$(git status --porcelain 2>/dev/null | wc -l)
CONTEXT_PARTS+=("[Branch: $BRANCH, File modificati: $DIRTY]")
fi
# 2. Test falliti recenti
if [ -f "test-results.json" ]; then
FAILED=$(jq '.numFailedTests // 0' test-results.json 2>/dev/null)
if [ "$FAILED" -gt 0 ]; then
CONTEXT_PARTS+=("[WARNING: $FAILED test falliti]")
fi
fi
# 3. TODO in sospeso
TODO_COUNT=$(grep -r "TODO\|FIXME\|HACK" src/ --include="*.ts" 2>/dev/null | wc -l)
if [ "$TODO_COUNT" -gt 0 ]; then
CONTEXT_PARTS+=("[TODO aperti nel codice: $TODO_COUNT]")
fi
# Costruisci contesto aggregato
if [ ${#CONTEXT_PARTS[@]} -gt 0 ]; then
CONTEXT=$(printf "%s " "${CONTEXT_PARTS[@]}")
ENRICHED="$CONTEXT\n\n$PROMPT"
echo "$INPUT" | jq --arg p "$ENRICHED" '{decision: "modify", prompt: $p}'
else
echo '{"decision": "allow"}'
fi
7. パフォーマンス、セキュリティ、ベストプラクティス
フックはクロード コードのライフサイクルで同期的に実行されます。 つまり、遅いフックや機能不全のフックは大幅に劣化する可能性があります ユーザーエクスペリエンス。パフォーマンスとセキュリティのベスト プラクティスに従うことが不可欠です スムーズで安全なワークフローを維持します。
パフォーマンスの最適化
フックを実行するための黄金律
| ルール | モチベーション | 実装 |
|---|---|---|
| 積極的なタイムアウト | セッションのフリーズを回避する | セット timeout クリティカルなフックの場合は 5 ~ 10 秒 |
| 特定のマッチャー | 不必要な実行を減らす | ワイルドカードの代わりに正確な正規表現を使用する |
| 非同期操作 | 遅い I/O のためにブロックしない | 負荷の高い操作をバックグラウンドプロセスに委任する |
| ローカルキャッシュ | コストのかかる再計算を回避する | 中間結果を一時ファイルに保存する |
| 早期退場 | 実行時間を最小限に抑える | スクリプトの先頭で終了条件を確認する |
| 制御されたロギング | 過剰なディスク I/O を回避する | ログのローテーションと重大度レベルを使用する |
フックの安全性
フックは、現在のユーザーの権限を使用してシェル コマンドを実行します。 利点 (システムへの完全なアクセス) とリスク (実行) の両方を表します。 制御されていない)。厳格な安全原則を適用することが不可欠です。
- 最小特権の原則: 各フックは、その操作に厳密に必要なリソースのみにアクセスできる必要があります。
- 入力の検証: 標準入力経由で受信したすべてのデータは、使用前に検証およびサニタイズする必要があります
- ハードコードされたシークレットはありません: API キー、パスワード、トークンをフック スクリプトに直接含めないでください。
- 監査証跡: トレーサビリティのためにフックによって実行されたすべてのアクションのログを保持します。
- 定期的なレビュー: 設定されたフックを定期的に確認して、新たなリスクを特定する
警告: セキュリティリスク
プロジェクトフック (で定義されています) .claude/settings.json) が実行される
リポジトリでクロード コード セッションを開くと、自動的に実行されます。これはつまり、
悪意のあるリポジトリには悪意のあるフックが含まれている可能性があります。 常にチェックする
信頼できないリポジトリでセッションを開く前に設定ファイルを削除します。
エラー管理
何も言わずに失敗するフックは、存在しないフックよりも悪いです。実装する 堅牢なエラー処理はシステムの保守性にとって非常に重要です。
#!/bin/bash
set -euo pipefail
# Trap per gestire errori e cleanup
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "[HOOK ERROR] Exit code: $exit_code" >&2
echo "{\"error\": \"Hook fallito con codice $exit_code\"}" >&2
fi
# Cleanup risorse temporanee
rm -f /tmp/claude-hook-$.tmp 2>/dev/null
}
trap cleanup EXIT
# Timeout per l'intero script
TIMEOUT=10
(
sleep $TIMEOUT
echo "[HOOK TIMEOUT] Script superato $TIMEOUT secondi" >&2
kill $ 2>/dev/null
) &
TIMEOUT_PID=$!
# Logica principale con error handling
INPUT=$(cat) || {
echo '{"decision": "allow"}' # Fallback sicuro
exit 0
}
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null) || TOOL_NAME=""
# ... logica del hook ...
# Cancella il timer di timeout
kill $TIMEOUT_PID 2>/dev/null || true
echo '{"decision": "allow"}'
8. 完全な例: Angular プロジェクトのフック エコシステム
結論として、構成されたフック エコシステムの完全な例を示します。 SSR を使用した Angular プロジェクトの場合、6 つのイベントすべてをカバーし、デモンストレーションを行います フックがどのように連携して堅牢な自動開発環境を作成するか。
{
"hooks": {
"SessionStart": [
{
"command": "bash .claude/hooks/check-dependencies.sh",
"timeout": 15000
}
],
"PreToolUse": [
{
"matcher": "Write|Edit",
"command": "bash .claude/hooks/validate-angular-conventions.sh",
"timeout": 5000
},
{
"matcher": "Bash",
"command": "bash .claude/hooks/block-dangerous-commands.sh",
"timeout": 3000
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "bash .claude/hooks/auto-lint-format.sh",
"timeout": 10000
},
{
"command": "python3 .claude/hooks/activity-tracker.py",
"timeout": 5000
}
],
"UserPromptSubmit": [
{
"command": "bash .claude/hooks/enrich-with-project-context.sh",
"timeout": 5000
}
],
"Stop": [
{
"command": "bash .claude/hooks/desktop-notification.sh"
}
],
"SessionEnd": [
{
"command": "python3 .claude/hooks/generate-session-report.py",
"timeout": 10000
}
]
}
}
#!/bin/bash
# PreToolUse: valida convenzioni Angular per nuovi file
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
# Verifica naming convention per componenti Angular
if [[ "$FILE_PATH" == *.component.ts ]]; then
# Controlla che il nome segua kebab-case
FILENAME=$(basename "$FILE_PATH" .component.ts)
if ! echo "$FILENAME" | grep -qE '^[a-z][a-z0-9]*(-[a-z0-9]+)*






