最初の hook をセットアップする
Hook を作成するには、設定ファイル にhooks ブロックを追加します。このチュートリアルではデスクトップ通知 hook を作成するため、Claude があなたの入力を待っているときにアラートを受け取ることができます。ターミナルを監視する代わりに。
hook を設定に追加する
~/.claude/settings.json を開き、Notification hook を追加します。以下の例は macOS 用に osascript を使用しています。Linux と Windows のコマンドについては、Claude が入力を必要とするときに通知を受け取る を参照してください。hooks キーがある場合は、オブジェクト全体を置き換えるのではなく、Notification を既存のイベントキーの兄弟として追加します。各イベント名は単一の hooks オブジェクト内のキーです:設定を確認する
/hooks と入力して hooks ブラウザを開きます。利用可能なすべての hook イベントのリストが表示され、hooks が設定されているイベントの横に数が表示されます。Notification を選択して、新しい hook がリストに表示されることを確認します。Hook を選択すると、その詳細が表示されます:イベント、マッチャー、タイプ、ソースファイル、およびコマンド。自動化できるもの
Hooks を使用すると、Claude Code のライフサイクルの主要なポイントでコードを実行できます:編集後にファイルをフォーマットし、実行前にコマンドをブロックし、Claude が入力を必要とするときに通知を送信し、セッション開始時にコンテキストを注入するなど。Hook イベントの完全なリストについては、Hooks リファレンス を参照してください。 各例には、設定ファイル に追加する準備ができた設定ブロックが含まれています。最も一般的なパターン:- Claude が入力を必要とするときに通知を受け取る
- 編集後にコードを自動フォーマットする
- 保護されたファイルへの編集をブロックする
- 圧縮後にコンテキストを再注入する
- 設定変更を監査する
- ディレクトリまたはファイルが変更されたときに環境をリロードする
- 特定の許可プロンプトを自動承認する
Claude が入力を必要とするときに通知を受け取る
Claude が作業を完了して入力を必要とするときはいつでもデスクトップ通知を取得し、ターミナルをチェックせずに他のタスクに切り替えることができます。 この hook はNotification イベントを使用します。これは Claude が入力または許可を待っているときに発火します。以下の各タブはプラットフォームのネイティブ通知コマンドを使用します。これを ~/.claude/settings.json に追加します:
- macOS
- Linux
- Windows (PowerShell)
通知が表示されない場合
通知が表示されない場合
osascript は組み込みの Script Editor アプリを通じて通知をルーティングします。Script Editor に通知権限がない場合、コマンドは静かに失敗し、macOS はそれを付与するよう求めません。Terminal でこれを 1 回実行して、Script Editor を通知設定に表示させます:編集後にコードを自動フォーマットする
Claude が編集するすべてのファイルで Prettier を自動的に実行し、手動操作なしでフォーマットの一貫性を保ちます。 この hook はPostToolUse イベントを Edit|Write マッチャーで使用するため、ファイル編集ツールの後にのみ実行されます。コマンドは jq で編集されたファイルパスを抽出し、Prettier に渡します。これをプロジェクトルートの .claude/settings.json に追加します:
このページの Bash の例は JSON 解析に
jq を使用します。brew install jq(macOS)、apt-get install jq(Debian/Ubuntu)でインストールするか、jq ダウンロード を参照してください。保護されたファイルへの編集をブロックする
Claude が.env、package-lock.json、.git/ 内のものなどの機密ファイルを変更するのを防ぎます。Claude は編集がブロックされた理由を説明するフィードバックを受け取るため、アプローチを調整できます。
この例は hook が呼び出す別のスクリプトファイルを使用します。スクリプトはターゲットファイルパスを保護されたパターンのリストに対してチェックし、終了コード 2 で編集をブロックします。
圧縮後にコンテキストを再注入する
Claude のコンテキストウィンドウがいっぱいになると、圧縮は会話を要約してスペースを解放します。これは重要な詳細を失う可能性があります。compact マッチャーで SessionStart hook を使用して、すべての圧縮後に重要なコンテキストを再注入します。
コマンドが stdout に書き込むテキストは Claude のコンテキストに追加されます。この例はプロジェクト規約と最近の作業を Claude に思い出させます。これをプロジェクトルートの .claude/settings.json に追加します:
echo を git log --oneline -5 などの動的出力を生成するコマンドに置き換えて、最近のコミットを表示できます。すべてのセッション開始時にコンテキストを注入する場合は、代わりに CLAUDE.md を使用することを検討してください。環境変数については、リファレンスの CLAUDE_ENV_FILE を参照してください。
設定変更を監査する
セッション中に設定またはスキルファイルが変更されたときを追跡します。ConfigChange イベントは外部プロセスまたはエディタが設定ファイルを変更したときに発火するため、コンプライアンスのために変更をログに記録したり、不正な変更をブロックしたりできます。
この例は各変更を監査ログに追加します。これを ~/.claude/settings.json に追加します:
user_settings、project_settings、local_settings、policy_settings、または skills。変更が有効になるのをブロックするには、終了コード 2 で終了するか、{"decision": "block"} を返します。完全な入力スキーマについては、ConfigChange リファレンス を参照してください。
ディレクトリまたはファイルが変更されたときに環境をリロードする
一部のプロジェクトは、どのディレクトリにいるかに応じて異なる環境変数を設定します。direnv などのツールはシェルで自動的にこれを行いますが、Claude の Bash ツールはそれらの変更を自動的に取得しません。SessionStart hook を CwdChanged hook とペアリングすることでこれを修正します。SessionStart は起動したディレクトリの変数をロードし、CwdChanged は Claude がディレクトリを変更するたびにそれらをリロードします。どちらも CLAUDE_ENV_FILE に書き込み、Claude Code は各 Bash コマンドの前にスクリプトプリアンブルとして実行します。これを ~/.claude/settings.json に追加します:
FileChanged を matcher で使用して、監視するファイル名をリストします(パイプで区切られています)。ウォッチリストを構築するために、この値は正規表現として評価されるのではなく、リテラルファイル名に分割されます。FileChanged を参照して、同じ値がファイルが変更されたときにどの hook グループが実行されるかをフィルタリングする方法を確認してください。この例は現在のディレクトリの .envrc と .env を監視します:
watchPaths 出力、および CLAUDE_ENV_FILE の詳細については、CwdChanged および FileChanged リファレンスエントリを参照してください。
特定の許可プロンプトを自動承認する
常に許可するツール呼び出しの承認ダイアログをスキップします。この例はExitPlanMode を自動承認します。これは Claude がプランの提示を終了して続行するよう求めるときに呼び出すツールです。プランが準備できるたびにプロンプトが表示されることはありません。
上記の終了コード例とは異なり、自動承認には hook が JSON 決定を stdout に書き込む必要があります。PermissionRequest hook は Claude Code が許可ダイアログを表示しようとするときに発火し、"behavior": "allow" を返すとあなたの代わりにそれに答えます。
マッチャーは hook を ExitPlanMode のみにスコープするため、他のプロンプトは影響を受けません。これを ~/.claude/settings.json に追加します:
setMode エントリを含む updatedPermissions 配列を含めることができます。mode 値は default、acceptEdits、または bypassPermissions などの任意の許可モードであり、destination: "session" は現在のセッションのみに適用します。
bypassPermissions は、セッションが既にバイパスモードで起動された場合にのみ適用されます:--dangerously-skip-permissions、--permission-mode bypassPermissions、--allow-dangerously-skip-permissions、または設定の permissions.defaultMode: "bypassPermissions"、および permissions.disableBypassPermissionsMode で無効化されていない場合。defaultMode として永続化されることはありません。acceptEdits に切り替えるには、hook は stdout に次の JSON を書き込みます:
.* でマッチングするか、マッチャーを空のままにすると、ファイル書き込みやシェルコマンドを含むすべての許可プロンプトが自動承認されます。決定フィールドの完全なセットについては、PermissionRequest リファレンス を参照してください。
hooks の仕組み
Hook イベントは Claude Code のライフサイクルの特定のポイントで発火します。イベントが発火すると、すべてのマッチングする hooks が並列で実行され、同一の hook コマンドは自動的に重複排除されます。以下の表は各イベントとそれがトリガーされるときを示しています:| Event | When it fires |
|---|---|
SessionStart | When a session begins or resumes |
UserPromptSubmit | When you submit a prompt, before Claude processes it |
UserPromptExpansion | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
PreToolUse | Before a tool call executes. Can block it |
PermissionRequest | When a permission dialog appears |
PermissionDenied | When a tool call is denied by the auto mode classifier. Return {retry: true} to tell the model it may retry the denied tool call |
PostToolUse | After a tool call succeeds |
PostToolUseFailure | After a tool call fails |
PostToolBatch | After a full batch of parallel tool calls resolves, before the next model call |
Notification | When Claude Code sends a notification |
SubagentStart | When a subagent is spawned |
SubagentStop | When a subagent finishes |
TaskCreated | When a task is being created via TaskCreate |
TaskCompleted | When a task is being marked as completed |
Stop | When Claude finishes responding |
StopFailure | When the turn ends due to an API error. Output and exit code are ignored |
TeammateIdle | When an agent team teammate is about to go idle |
InstructionsLoaded | When a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded during a session |
ConfigChange | When a configuration file changes during a session |
CwdChanged | When the working directory changes, for example when Claude executes a cd command. Useful for reactive environment management with tools like direnv |
FileChanged | When a watched file changes on disk. The matcher field specifies which filenames to watch |
WorktreeCreate | When a worktree is being created via --worktree or isolation: "worktree". Replaces default git behavior |
WorktreeRemove | When a worktree is being removed, either at session exit or when a subagent finishes |
PreCompact | Before context compaction |
PostCompact | After context compaction completes |
Elicitation | When an MCP server requests user input during a tool call |
ElicitationResult | After a user responds to an MCP elicitation, before the response is sent back to the server |
SessionEnd | When a session terminates |
PreToolUse hook が deny を返すと、他が何を返すかに関わらず、ツール呼び出しがキャンセルされます。1 つの hook が ask を返すと、残りが allow を返しても、許可プロンプトが強制されます。additionalContext からのテキストはすべての hook から保持され、Claude に一緒に渡されます。
各 hook には、それがどのように実行されるかを決定する type があります。ほとんどの hooks は "type": "command" を使用し、シェルコマンドを実行します。他の 4 つのタイプが利用可能です:
"type": "http":イベントデータを URL に POST します。HTTP hooks を参照してください。"type": "mcp_tool":既に接続されている MCP サーバー上のツールを呼び出します。MCP tool hooks を参照してください。"type": "prompt":シングルターン LLM 評価。プロンプトベースの hooks を参照してください。"type": "agent":ツールアクセス付きマルチターン検証。エージェント hooks は実験的であり、変更される可能性があります。エージェントベースの hooks を参照してください。
入力を読み取り、出力を返す
Hooks は stdin、stdout、stderr、および終了コードを通じて Claude Code と通信します。イベントが発火すると、Claude Code はイベント固有のデータを JSON としてスクリプトの stdin に渡します。スクリプトはそのデータを読み取り、作業を行い、終了コードを通じて Claude Code に次に何をするかを伝えます。Hook 入力
すべてのイベントにはsession_id と cwd などの共通フィールドが含まれていますが、各イベントタイプは異なるデータを追加します。たとえば、Claude が Bash コマンドを実行するとき、PreToolUse hook は stdin で次のようなものを受け取ります:
UserPromptSubmit hooks は代わりに prompt テキストを取得し、SessionStart hooks は source(startup、resume、clear、compact)を取得するなど。リファレンスの 共通入力フィールド で共有フィールドを参照し、各イベントのセクションでイベント固有のスキーマを参照してください。
Hook 出力
スクリプトは stdout または stderr に書き込み、特定のコードで終了することで、Claude Code に次に何をするかを伝えます。たとえば、コマンドをブロックしたいPreToolUse hook:
- 終了 0:アクションが続行されます。
UserPromptSubmit、UserPromptExpansion、およびSessionStarthooks の場合、stdout に書き込むすべてのものが Claude のコンテキストに追加されます。 - 終了 2:アクションがブロックされます。stderr に理由を書き込み、Claude はそれをフィードバックとして受け取るため、調整できます。
- その他の終了コード:アクションが続行されます。トランスクリプトは
<hook name> hook error通知を表示し、その後 stderr の最初の行が続きます。完全な stderr は デバッグログ に記録されます。
構造化 JSON 出力
終了コードは 2 つのオプションを提供します:許可またはブロック。より多くの制御のために、終了 0 して stdout に JSON オブジェクトを出力します。終了 2 で stderr メッセージでブロックするか、終了 0 で JSON で構造化制御を使用します。混在させないでください:Claude Code は終了 2 のときに JSON を無視します。
PreToolUse hook はツール呼び出しを拒否して理由を Claude に伝えたり、ユーザーの承認のためにエスカレートしたりできます:
"deny" を使用すると、Claude Code はツール呼び出しをキャンセルし、permissionDecisionReason を Claude にフィードバックとして返します。これらの permissionDecision 値は PreToolUse に固有です:
"allow":インタラクティブな許可プロンプトをスキップします。Deny および ask ルール(エンタープライズ管理 deny リストを含む)は引き続き適用されます"deny":ツール呼び出しをキャンセルし、理由を Claude に送信します"ask":通常どおりユーザーに許可プロンプトを表示します
"defer" は、-p フラグ付きの 非インタラクティブモード で利用可能です。プロセスを終了し、ツール呼び出しを保持して、Agent SDK ラッパーが入力を収集して再開できるようにします。リファレンスの ツール呼び出しを後で延期する を参照してください。
"allow" を返すとインタラクティブプロンプトをスキップしますが、許可ルール をオーバーライドしません。Deny ルールがツール呼び出しにマッチする場合、hook が "allow" を返しても呼び出しはブロックされます。Ask ルールがマッチする場合、ユーザーはまだプロンプトが表示されます。これは、管理設定 を含むすべての設定スコープからの deny ルールが、hook 承認よりも常に優先されることを意味します。
他のイベントは異なる決定パターンを使用します。たとえば、PostToolUse および Stop hooks はトップレベルの decision: "block" フィールドを使用し、PermissionRequest は hookSpecificOutput.decision.behavior を使用します。リファレンスの サマリーテーブル でイベント別の完全な内訳を参照してください。
UserPromptSubmit hooks の場合、代わりに additionalContext を使用して Claude のコンテキストにテキストを注入します。プロンプトベースの hooks(type: "prompt")は出力を異なる方法で処理します:プロンプトベースの hooks を参照してください。
マッチャーで hooks をフィルタリングする
マッチャーなしでは、hook はそのイベントのすべての発生で発火します。マッチャーを使用すると、それを絞り込むことができます。たとえば、ファイル編集後にのみフォーマッターを実行したい場合(すべてのツール呼び出しの後ではなく)、PostToolUse hook にマッチャーを追加します:
"Edit|Write" マッチャーは Edit または Write ツール呼び出しでのみ発火し、Bash、Read、または他のツールでは発火しません。マッチャーパターン を参照して、プレーン名と正規表現がどのように評価されるかを確認してください。
各イベントタイプは特定のフィールドでマッチします:
| イベント | マッチャーがフィルタリングするもの | マッチャー値の例 |
|---|---|---|
PreToolUse、PostToolUse、PostToolUseFailure、PermissionRequest、PermissionDenied | ツール名 | Bash、Edit|Write、mcp__.* |
SessionStart | セッションがどのように開始されたか | startup、resume、clear、compact |
SessionEnd | セッションが終了した理由 | clear、resume、logout、prompt_input_exit、bypass_permissions_disabled、other |
Notification | 通知タイプ | permission_prompt、idle_prompt、auth_success、elicitation_dialog |
SubagentStart | エージェントタイプ | Bash、Explore、Plan、またはカスタムエージェント名 |
PreCompact、PostCompact | 圧縮をトリガーしたもの | manual、auto |
SubagentStop | エージェントタイプ | SubagentStart と同じ値 |
ConfigChange | 設定ソース | user_settings、project_settings、local_settings、policy_settings、skills |
StopFailure | エラータイプ | rate_limit、authentication_failed、billing_error、invalid_request、server_error、max_output_tokens、unknown |
InstructionsLoaded | ロード理由 | session_start、nested_traversal、path_glob_match、include、compact |
Elicitation | MCP サーバー名 | 設定した MCP サーバー名 |
ElicitationResult | MCP サーバー名 | Elicitation と同じ値 |
FileChanged | リテラルファイル名を監視(FileChanged を参照) | .envrc|.env |
UserPromptExpansion | コマンド名 | スキルまたはコマンド名 |
UserPromptSubmit、PostToolBatch、Stop、TeammateIdle、TaskCreated、TaskCompleted、WorktreeCreate、WorktreeRemove、CwdChanged | マッチャーサポートなし | すべての発生で常に発火 |
- すべての Bash コマンドをログに記録する
- MCP ツールをマッチさせる
- セッション終了時にクリーンアップする
Bash ツール呼び出しのみをマッチし、各コマンドをファイルにログに記録します。PostToolUse イベントはコマンドが完了した後に発火するため、tool_input.command は実行されたものを含みます。Hook は stdin で JSON としてイベントデータを受け取り、jq -r '.tool_input.command' はコマンド文字列のみを抽出し、>> はログファイルに追加します:if フィールドでツール名と引数でフィルタリングする
if フィールドには Claude Code v2.1.85 以降が必要です。以前のバージョンはそれを無視し、マッチしたすべての呼び出しで hook を実行します。if フィールドは 許可ルール構文 を使用して、ツール名と引数の両方で hooks をフィルタリングするため、hook プロセスはツール呼び出しがマッチするときにのみ生成されます。これは matcher を超えており、ツール名のみでグループレベルでフィルタリングします。
たとえば、すべての Bash コマンドではなく、Claude が git コマンドを使用するときにのみ hook を実行するには:
git * にマッチするときにのみ生成されます。または、コマンドが解析するには複雑すぎるときです。npm test && git push のような複合コマンドの場合、Claude Code は各サブコマンドを評価し、git push がマッチするため hook を発火させます。if フィールドは許可ルールと同じパターンを受け入れます:"Bash(git *)"、"Edit(*.ts)" など。複数のツール名をマッチさせるには、それぞれ独自の if 値を持つ別のハンドラーを使用するか、パイプ交替がサポートされている matcher レベルでマッチします。
if はツールイベントでのみ機能します:PreToolUse、PostToolUse、PostToolUseFailure、PermissionRequest、および PermissionDenied。他のイベントに追加すると、hook が実行されるのを防ぎます。
hook の場所を設定する
Hook を追加する場所がそのスコープを決定します:
Claude Code で
/hooks を実行して、イベント別にグループ化されたすべての設定済み hooks を参照します。すべての hooks を一度に無効にするには、設定ファイルで "disableAllHooks": true を設定します。
Claude Code が実行中に設定ファイルを直接編集する場合、ファイルウォッチャーは通常、hook の変更を自動的に取得します。
プロンプトベースの hooks
決定論的なルールではなく判断が必要な決定については、type: "prompt" hooks を使用します。シェルコマンドを実行する代わりに、Claude Code はプロンプトと hook の入力データを Claude モデル(デフォルトでは Haiku)に送信して決定を下します。より多くの機能が必要な場合は、model フィールドで異なるモデルを指定できます。
モデルの唯一の仕事は、yes/no 決定を JSON として返すことです:
"ok": true:アクションが続行されます"ok": false:アクションがブロックされます。モデルの"reason"は Claude にフィードバックとして返されるため、調整できます。
Stop hook を使用して、要求されたすべてのタスクが完了しているかどうかをモデルに尋ねます。モデルが "ok": false を返す場合、Claude は作業を続け、reason を次の指示として使用します:
エージェントベースの hooks
検証がファイルの検査またはコマンドの実行を必要とする場合、type: "agent" hooks を使用します。プロンプト hooks は単一の LLM 呼び出しを行いますが、エージェント hooks は条件を返す前にファイルを読み取り、コードを検索し、他のツールを使用できる subagent を生成します。
エージェント hooks はプロンプト hooks と同じ "ok" / "reason" 応答形式を使用しますが、デフォルトのタイムアウトが 60 秒で、最大 50 ツール使用ターンです。
この例は Claude が停止することを許可する前にテストが合格することを検証します:
HTTP hooks
type: "http" hooks を使用して、シェルコマンドを実行する代わりに、イベントデータを HTTP エンドポイントに POST します。エンドポイントはコマンド hook が stdin で受け取るのと同じ JSON を受け取り、HTTP レスポンスボディを使用して同じ JSON 形式で結果を返します。
HTTP hooks は、Web サーバー、クラウド関数、または外部サービスに hook ロジックを処理させたい場合に便利です。たとえば、チーム全体のツール使用イベントをログに記録する共有監査サービス。
この例はすべてのツール使用をローカルログサービスに POST します:
hookSpecificOutput フィールドで 2xx レスポンスを返します。HTTP ステータスコードだけではアクションをブロックできません。
ヘッダー値は $VAR_NAME または ${VAR_NAME} 構文を使用した環境変数補間をサポートします。allowedEnvVars 配列にリストされている変数のみが解決されます。他のすべての $VAR 参照は空のままです。
完全な設定オプションとレスポンス処理については、リファレンスの HTTP hooks を参照してください。
制限とトラブルシューティング
制限
- コマンド hooks は stdout、stderr、および終了コードを通じてのみ通信します。これらは
/コマンドまたはツール呼び出しをトリガーできません。additionalContextを通じて返されたテキストは、Claude が平文として読むシステムリマインダーとして注入されます。HTTP hooks はレスポンスボディを通じて通信します。 - Hook タイムアウトはデフォルトで 10 分で、hook ごとに
timeoutフィールド(秒単位)で設定可能です。 PostToolUsehooks はツールが既に実行されているため、アクションを元に戻すことはできません。PermissionRequesthooks は 非インタラクティブモード(-p)では発火しません。自動化された許可決定にはPreToolUsehooks を使用します。Stophooks はタスク完了時だけでなく、Claude が応答を終了するたびに発火します。ユーザーの割り込みでは発火しません。API エラーは代わりに StopFailure を発火させます。- 複数の PreToolUse hooks が
updatedInputを返してツールの引数を書き直す場合、最後に完了したものが勝ちます。Hooks は並列で実行されるため、順序は非決定的です。同じツールの入力を変更する複数の hooks を持つことを避けてください。
Hooks と許可モード
PreToolUse hooks は任意の許可モードチェックの前に発火します。permissionDecision: "deny" を返す hook は、bypassPermissions モードまたは --dangerously-skip-permissions でもツールをブロックします。これにより、ユーザーが許可モードを変更してバイパスできないポリシーを適用できます。
逆は真ではありません:"allow" を返す hook は、設定からの deny ルールをバイパスしません。Hooks は制限を厳しくできますが、許可ルールが許可する範囲を超えて緩和することはできません。
Hook が発火しない
Hook は設定されていますが、実行されません。/hooksを実行し、hook が正しいイベントの下に表示されることを確認します- マッチャーパターンがツール名と正確にマッチすることを確認します(マッチャーは大文字小文字を区別します)
- 正しいイベントタイプをトリガーしていることを確認します(例:
PreToolUseはツール実行前に発火し、PostToolUseは後に発火します) - 非インタラクティブモード(
-p)でPermissionRequesthooks を使用している場合は、代わりにPreToolUseに切り替えます
Hook エラーが出力に表示される
トランスクリプトに「PreToolUse hook error: …」というメッセージが表示されます。- スクリプトが予期せずゼロ以外のコードで終了しました。サンプル JSON をパイプして手動でテストします:
- 「command not found」が表示される場合は、絶対パスを使用するか、スクリプトを参照するために
$CLAUDE_PROJECT_DIRを使用します - 「jq: command not found」が表示される場合は、
jqをインストールするか、JSON 解析に Python/Node.js を使用します - スクリプトがまったく実行されていない場合は、実行可能にします:
chmod +x ./my-hook.sh
/hooks に設定された hooks が表示されない
設定ファイルを編集しましたが、hooks がメニューに表示されません。
- ファイル編集は通常自動的に取得されます。数秒後に表示されていない場合、ファイルウォッチャーが変更を見逃した可能性があります:セッションを再開して強制的にリロードします。
- JSON が有効であることを確認します(末尾のコンマとコメントは許可されていません)
- 設定ファイルが正しい場所にあることを確認します:プロジェクト hooks の場合は
.claude/settings.json、グローバル hooks の場合は~/.claude/settings.json
Stop hook が永遠に実行される
Claude は無限ループで作業を続けます。停止する代わりに。 Stop hook スクリプトは、それが既にトリガーされたかどうかをチェックする必要があります。JSON 入力からstop_hook_active フィールドを解析し、true の場合は早期に終了します:
JSON 検証に失敗しました
Claude Code は hook スクリプトが有効な JSON を出力しているにもかかわらず、JSON 解析エラーを表示します。 Claude Code が hook を実行するとき、プロファイル(~/.zshrc または ~/.bashrc)をソースするシェルを生成します。プロファイルに無条件の echo ステートメントが含まれている場合、その出力は hook の JSON に前置されます:
$- 変数はシェルフラグを含み、i はインタラクティブを意味します。Hooks は非インタラクティブシェルで実行されるため、echo はスキップされます。
デバッグ技術
トランスクリプトビュー(Ctrl+O で切り替え)は、発火した各 hook の 1 行のサマリーを表示します:成功は無音、ブロッキングエラーは stderr を表示し、非ブロッキングエラーは <hook name> hook error 通知を表示し、その後 stderr の最初の行が続きます。
完全な実行詳細(どの hooks がマッチしたか、それらの終了コード、stdout、stderr など)については、デバッグログを読みます。claude --debug-file /tmp/claude.log で Claude Code を開始して既知のパスに書き込み、別のターミナルで tail -f /tmp/claude.log を実行します。そのフラグなしで開始した場合は、セッション中に /debug を実行してログを有効にし、ログパスを見つけます。
詳細を学ぶ
- Hooks リファレンス:完全なイベントスキーマ、JSON 出力形式、非同期 hooks、および MCP ツール hooks
- セキュリティに関する考慮事項:共有または本番環境に hooks をデプロイする前に確認してください
- Bash コマンドバリデーター例:完全なリファレンス実装