hooks-development について
hooks-developmentは、Claude Code hooksの開発とデバッグ向けのスキルです。出力の可視性、安全な入力処理、shellとBunの選択、検証手順を扱います。
主な機能
- 01Hook出力の可視性ルール
- 02AskUserQuestionの安全な処理
- 03shellとBunの選択指針
- 04作成・デバッグ用チェックリスト
活用シーン
- 01PreToolUseまたはPostToolUse hookの作成
- 02Claudeに見えないhookメッセージの診断
- 03hook設定と出力の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill hooks-developmentインストール後、Claude Code で/hooks-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/debugging-guide.mdevolution-log.mdhook-templates.mdlifecycle-reference.mdvisibility-patterns.md詳細
フックの開発
適切な出力表示パターンを使って Claude Code のフックを開発するためのガイドです。
自己進化するスキル:このスキルは使用を通じて改善されます。指示が誤っている場合、パラメーターがずれている場合、または回避策が必要になった場合は、先送りせず、すぐにこのファイルを修正してください。実際に再現可能な問題がある場合のみ更新してください。
このスキルを使うタイミング
- 新しい PostToolUse または PreToolUse フックを作成するとき
- フックの出力が Claude に表示されないとき(最もよくある問題)
- ユーザーが
decision: blockパターンについて質問したとき - フックのメッセージが表示されない理由をデバッグするとき
- ユーザーが「Claude Code hooks」または「hook visibility」と言及したとき
クイックリファレンス:表示パターン
重要なポイント:PostToolUse フックの stdout は、JSON に "decision": "block" が含まれている場合にのみ Claude に表示されます。
| 出力形式 | Claude への表示 |
|---|---|
| プレーンテキスト | 表示されない |
decision: block を含まない JSON | 表示されない |
decision: block を含む JSON | 表示される |
終了コードの動作:
| 終了コード | stdout の動作 | Claude への表示 |
|---|---|---|
| 0 | JSON が解析され、詳細モードでのみ表示 | "decision": "block" の場合のみ |
| 2 | 無視され、代わりに stderr を使用 | stderr が Claude に表示される |
| その他 | stderr が詳細モードで表示される | Claude には表示されない |
AskUserQuestion を書き換えない
PreToolUse フックは、AskUserQuestion に対して updatedInput を返してはいけません。直接返す場合も、allowWithInput を通じて返す場合も同様です。このツールでは、ダイアログがユーザーの answers を受け取るためのチャネルとして updatedInput が使われるため、これを返すフックは回答済みとして扱われます。その結果、メニューは表示されず、ツールは "The user did not answer the questions." を返します。2026-09-24 に全セッションのトランスクリプトを調査したところ、書き換えられた呼び出しは 86 件中 86 件が表示も回答もされなかった一方、通常の allow 呼び出しは 466 件中 465 件で表示され、回答されました。
- 通常の
allowは安全です。ダイアログは引き続き表示されます。 - ユーザーに表示する内容を変更するには、エージェントが再度質問すべき内容を正確に示した理由とともに
denyを返し、再質問が変更されずに通過することを確認してください。そうすればループは 1 回で解消します(実例はpretooluse-pr-premise-annotator.tsを参照してください)。 - 以下の 3 つの方法で強制されます。
allowWithInputは実行時にツールを拒否し、TOOL_SCHEMASにそのエントリーはなく、scripts/validate-plugins.mjsは、AskUserQuestionに一致する matcher を持つフックがupdatedInputを出力するかallowWithInputを呼び出すと、ゲートで失敗します。
最小限の動作パターン
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail
# Read hook payload from stdin
PAYLOAD=$(cat)
FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty')
[[ -z "$FILE_PATH" ]] && exit 0
# Your condition here
if [[ condition_met ]]; then
jq -n \
--arg reason "[HOOK] Your message to Claude" \
'{decision: "block", reason: $reason}'
fi
exit 0
SKILL_SCRIPT_EOF
重要なポイント:
- 有効な JSON を生成するには
jq -nを使います - 表示されるように
"decision": "block"を含めます - コード 0 で終了します
- 「ブロッキングエラー」というラベルは表記上のもので、処理は続行されます
言語の選択:shell と Bun/TypeScript
フックには shell(bash)を標準として使ってください。 フックは一致するイベントごとに実行され、その約 95% はすぐに終了するため、支配的なのは処理の起動レイテンシーであり、ロジックではありません。ワークステーションでの測定では、キーワード照合後すぐに終了する完全な bash フックは約 7 ms、何もしない Bun スクリプトは約 17 ms でした。bash はランタイム依存関係も不要で、既存のフック規約にも合致します。頻繁に実行される処理の早期終了は、bash の組み込み case を使ってください(jq やプロセスの起動は不要です)。devops-tools SCS hooks の pre-jq-fastpath を参照してください。
約 10 ms の起動コストを相殺できる実処理をフックが行う場合に限り、Bun/TypeScript を選んでください。たとえば、構造化データの解析や変換、API の呼び出し、多くのフック間での型付きモジュールの共有、状態の管理などです。単純な照合と通知の出力では、速度、堅牢性、規約の面で shell が適しています。(これは、言語に関する方針の「既存の規約と SOTA に適したエコシステムが Bun 優先の既定方針に優先する」という条項の実例です。)
TodoWrite テンプレート
PostToolUse フックの作成
1. [pending] Create hook script with shebang and set -euo pipefail
2. [pending] Parse PAYLOAD from stdin with jq
3. [pending] Add condition check for when to trigger
4. [pending] Output JSON with decision:block pattern
5. [pending] Register hook in hooks.json with matcher
6. [pending] Test by editing a matching file
7. [pending] Verify Claude sees the message in system-reminder
表示されないフック出力のデバッグ
1. [pending] Verify hook executes (add debug log to /tmp)
2. [pending] Check JSON format is valid (pipe to jq .)
3. [pending] Confirm decision:block is present in output
4. [pending] Verify exit code is 0
5. [pending] Check hooks.json matcher pattern
6. [pending] Restart Claude Code session
リファレンスドキュメント
- ライフサイクルリファレンス - 10 個すべてのフックイベント、図、ユースケース、設定時の落とし穴
- 可視性パターン - 終了コードと JSON スキーマの詳細
- フックテンプレート - よく使われるパターンのコピー&ペースト用テンプレート
- デバッグガイド - 出力が表示されない場合のトラブルシューティング
変更後チェックリスト(自己進化)
このスキルを更新する場合:
- 発見事項を evolution-log.md に記録する
- コード例が引き続き動作することを確認する
- ADR の更新が必要か確認する:PostToolUse Hook Visibility ADR
関連リソース
- ADR:PostToolUse Hook Visibility
- GitHub Issue #3983 - 元のバグ報告
- Claude Code Hooks Reference - 公式ドキュメント
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| フックの出力が表示されない | JSON に decision:block がない | JSON 出力に "decision": "block" を追加する |
| フックで JSON の解析エラーが発生する | JSON の構文が無効 | jq -n を使って有効な JSON を生成する |
| フックが実行されない | マッチャーパターンが間違っている | hooks.json のマッチャー正規表現がツール名と一致するか確認する |
| プレーンテキストの出力が無視される | JSON のみが解析される | 出力を decision:block を含む JSON で囲む |
| 終了コード 2 の動作 | stdout ではなく stderr が使われている | JSON を使う場合は exit 0、stderr メッセージの場合は exit 2 を使う |
| セッションに変更が反映されない | フックがキャッシュされている | フックの変更後に Claude Code セッションを再起動する |
| 詳細モードが表示されない | デフォルトで無効になっている | Claude Code の設定で詳細モードを有効にする |
| jq コマンドが見つからない | jq がインストールされていない | brew install jq |
実行後の振り返り
このスキルの実行後、終了する前に確認してください。
- コマンドは成功しましたか? — 成功しなかった場合は、失敗の原因となった指示またはエラーテーブルを修正します。
- パラメーターや出力に変更はありましたか? — 基盤となるツールのインターフェースに変更があった場合は、使用例とパラメーターテーブルを更新して整合させます。
- 回避策が必要でしたか? — 別のフラグや追加手順などの工夫が必要だった場合は、この SKILL.md を更新し、次回の実行で同じ回避策が不要になるようにします。
問題が実際に発生し、再現可能な場合に限って更新してください。憶測に基づく更新は行わないでください。