From 1eadb903e05a6d4e4b666cb8085f6a09e93174bd Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 20 Feb 2026 08:31:49 -0600 Subject: [PATCH 1/2] Fix Stop hook example prompt to prevent JSON parsing failures The anti-rationalization Stop hook example uses a prompt hook evaluated by Haiku. Without an explicit formatting constraint, Haiku wraps the JSON response in markdown code fences or adds explanatory text, which fails JSON parsing and silently breaks the hook. Fix the example prompt to prepend a JSON-only output instruction and add a timeout. Document the pitfall so others don't hit it. Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 988da07..297d569 100644 --- a/README.md +++ b/README.md @@ -307,7 +307,8 @@ On Linux, replace the command with `notify-send 'Claude Code' 'Claude needs your "hooks": [ { "type": "prompt", - "prompt": "Review the assistant's final response. Reject it if the assistant is rationalizing incomplete work. Common patterns: claiming issues are 'pre-existing' or 'out of scope' to avoid fixing them, saying there are 'too many issues' to address all of them, deferring work to a 'follow-up' that was not requested, listing problems without fixing them and calling that done, or skipping test/lint failures with excuses. If the response shows any of these patterns, respond {\"ok\": false, \"reason\": \"You are rationalizing incomplete work. [specific issue]. Go back and finish.\"}. If the work is genuinely complete, respond {\"ok\": true}." + "prompt": "You are a JSON-only evaluator. You MUST respond with a single JSON object and NOTHING else. No markdown, no code fences, no explanation, no preamble. Just the raw JSON object.\n\nReview the assistant's final response. Reject if the assistant is rationalizing incomplete work: claiming issues are 'pre-existing' or 'out of scope', saying 'too many issues' to fix, deferring to unrequested 'follow-ups', listing problems without fixing them, or skipping test/lint failures with excuses.\n\nIf any of those patterns apply, respond:\n{\"ok\": false, \"reason\": \"You are rationalizing incomplete work. [specific issue]. Go back and finish.\"}\n\nOtherwise respond:\n{\"ok\": true}", + "timeout": 30 } ] } @@ -317,6 +318,8 @@ On Linux, replace the command with `notify-send 'Claude Code' 'Claude needs your This uses `type: "prompt"` instead of `type: "command"` -- Claude Code sends the hook's prompt plus the assistant's response to a fast model (Haiku), which returns a yes/no judgment. If rejected, the `reason` is fed back to Claude as its next instruction, forcing it to continue. +**Important:** The prompt must explicitly instruct the evaluator to respond with raw JSON only. Without this, Haiku wraps the JSON in markdown code fences or adds explanatory text, which fails JSON parsing and silently breaks the hook. + ### Plugins and Skills Claude Code's capabilities come from plugins, which provide skills (reusable workflows), agents (specialized subagents), and commands (slash commands). Plugins are distributed through marketplaces. From 1868fefa1183231b1d44087620b88e1e7dd8bacd Mon Sep 17 00:00:00 2001 From: Dan Guido Date: Wed, 25 Feb 2026 12:49:25 -0500 Subject: [PATCH 2/2] Remove redundant timeout field, mention it in prose instead The default timeout for prompt hooks is already 30s. Move the timeout documentation to the prose note rather than cluttering the example JSON with a no-op field. Co-Authored-By: Claude Opus 4.6 --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 297d569..de283cb 100644 --- a/README.md +++ b/README.md @@ -307,8 +307,7 @@ On Linux, replace the command with `notify-send 'Claude Code' 'Claude needs your "hooks": [ { "type": "prompt", - "prompt": "You are a JSON-only evaluator. You MUST respond with a single JSON object and NOTHING else. No markdown, no code fences, no explanation, no preamble. Just the raw JSON object.\n\nReview the assistant's final response. Reject if the assistant is rationalizing incomplete work: claiming issues are 'pre-existing' or 'out of scope', saying 'too many issues' to fix, deferring to unrequested 'follow-ups', listing problems without fixing them, or skipping test/lint failures with excuses.\n\nIf any of those patterns apply, respond:\n{\"ok\": false, \"reason\": \"You are rationalizing incomplete work. [specific issue]. Go back and finish.\"}\n\nOtherwise respond:\n{\"ok\": true}", - "timeout": 30 + "prompt": "You are a JSON-only evaluator. You MUST respond with a single JSON object and NOTHING else. No markdown, no code fences, no explanation, no preamble. Just the raw JSON object.\n\nReview the assistant's final response. Reject if the assistant is rationalizing incomplete work: claiming issues are 'pre-existing' or 'out of scope', saying 'too many issues' to fix, deferring to unrequested 'follow-ups', listing problems without fixing them, or skipping test/lint failures with excuses.\n\nIf any of those patterns apply, respond:\n{\"ok\": false, \"reason\": \"You are rationalizing incomplete work. [specific issue]. Go back and finish.\"}\n\nOtherwise respond:\n{\"ok\": true}" } ] } @@ -318,7 +317,7 @@ On Linux, replace the command with `notify-send 'Claude Code' 'Claude needs your This uses `type: "prompt"` instead of `type: "command"` -- Claude Code sends the hook's prompt plus the assistant's response to a fast model (Haiku), which returns a yes/no judgment. If rejected, the `reason` is fed back to Claude as its next instruction, forcing it to continue. -**Important:** The prompt must explicitly instruct the evaluator to respond with raw JSON only. Without this, Haiku wraps the JSON in markdown code fences or adds explanatory text, which fails JSON parsing and silently breaks the hook. +**Important:** The prompt must explicitly instruct the evaluator to respond with raw JSON only. Without this, Haiku wraps the JSON in markdown code fences or adds explanatory text, which fails JSON parsing and silently breaks the hook. Prompt hooks default to a 30-second timeout; adjust with the `timeout` field if needed. ### Plugins and Skills