Hooks
ライフサイクルイベントに応答してClaude Codeの動作をカスタマイズ
Hooksとは?
HooksはClaude Codeの特定のイベントに応答して実行されるJavaScript関数です。動作のカスタマイズ、ポリシーの適用、外部ツールの統合、ワークフローの自動化が可能です。
イベント駆動
特定のライフサイクルイベントに自動的に応答
完全にカスタマイズ可能
JavaScriptであらゆる動作をカスタマイズ
ポリシー適用
チーム標準とセキュリティポリシーを適用
外部統合
外部サービスとツールに接続
利用可能なフックイベント
PreToolUse
Claudeがツールを使用する前に実行。ツールの使用を検証、変更、またはブロック可能。
PostToolUse
ツールが完了した後に実行。結果の処理、通知のトリガー、アクションのログ記録が可能。
UserPromptSubmit
ユーザーがプロンプトを送信したときに実行。プロンプトの変更、コンテキストの追加、ワークフローのトリガーが可能。
Notification
Claudeが通知を送信するときに実行。通知動作をカスタマイズ可能。
SessionStart
Claudeセッションが開始されるときに実行。リソースの初期化やコンテキストの読み込みが可能。
SessionEnd
セッションが終了するときに実行。リソースのクリーンアップやセッションデータの保存が可能。
Setup
--init、--init-only、--maintenanceフラグでトリガーされます。リポジトリのセットアップとメンテナンスタスクに適しています。
SubagentStop
サブエージェントが作業を完了したときに実行。結果の処理や後続アクションのトリガーが可能。
SubagentStart
サブエージェントが開始しようとしているときに実行。サブエージェントの起動を監視またはコンテキストを注入可能。
PermissionRequest
権限が要求されたときに実行。自動承認/拒否または権限リクエストのログ記録が可能。
PreCompact
コンテキスト圧縮が発生する前に実行。コンテキストが圧縮される前に重要な情報を保存可能。
プロンプトベースフック
フックでLLMベースの意思決定を使用します。JavaScriptロジックを書く代わりに、自然言語で欲しいものを説明します。
{
"hooks": {
"PreToolUse": [
{
"type": "prompt",
"matcher": { "tool": "Write" },
"prompt": "Review this file write operation. Check if it follows
our coding standards. Respond with 'allow' or 'deny'
and explain why."
}
]
}
}使用するタイミング
- +コードで書くのが難しい複雑な決定ロジック
- +コードレビューと品質チェック
- +コンテキスト認識検証
レスポンス形式
{
"decision": "allow" | "deny" | "skip",
"reason": "Optional explanation",
"modifiedInput": { /* optional */ }
}実践例
編集後にコードを自動フォーマット
Claudeがファイルを編集した後、自動的にPrettierを実行
// Auto-format files after Edit tool
export async function postToolUse({ tool, result }) {
if (tool.name === 'Edit' && result.success) {
const { execSync } = require('child_process');
try {
execSync(`prettier --write "${tool.params.file_path}"`);
console.log('✓ Formatted', tool.params.file_path);
} catch (error) {
console.error('Format failed:', error.message);
}
}
}機密ファイルの保護
Claudeが重要な設定ファイルを編集できないように防止
// Protect sensitive files
export async function preToolUse({ tool }) {
const protectedFiles = [
'.env',
'credentials.json',
'package-lock.json'
];
if (['Edit', 'Write'].includes(tool.name)) {
const filePath = tool.params.file_path;
if (protectedFiles.some(f => filePath.includes(f))) {
return {
allow: false,
reason: `Cannot modify protected file: ${filePath}`
};
}
}
return { allow: true };
}Slack通知の送信
デプロイが発生したときにチームに通知
// Notify team on deployment
export async function postToolUse({ tool, result }) {
if (tool.name === 'Bash' &&
tool.params.command.includes('deploy')) {
const webhook = process.env.SLACK_WEBHOOK;
await fetch(webhook, {
method: 'POST',
body: JSON.stringify({
text: `🚀 Deployment completed!
Success: ${result.success}
Command: ${tool.params.command}`
})
});
}
}セキュリティ上の考慮事項
Hooksは任意のJavaScriptコードを実行します。次のセキュリティベストプラクティスに従ってください:
フックファイルにシークレットを保存しないでください - 環境変数を使用
外部コマンドを実行する前にすべての入力を検証
外部ソースのフックを使用する前にレビュー
エラーを適切に処理するためにtry-catchブロックを使用
ベストプラクティス
フックをシンプルに保つ
各フックは1つのことをうまく実行する必要があります。複雑なロジックはClaudeを遅くする可能性があります。
エラーを適切に処理
常にtry-catchブロックを使用し、意味のあるエラーメッセージを提供してください。
Async/Awaitの使用
フックは外部API呼び出しとファイル操作のための非同期関数をサポートします。
フックのテスト
ワークフローを妨げないように、デプロイ前にフックを徹底的にテストしてください。