[Bug] Stop hooks with exit code 2 fail to continue when installed via plugins
Summary
Stop hooks that return exit code 2 (to force agent continuation) work correctly when installed in .claude/hooks/ but fail when installed via the plugin system, displaying ⏺ Stop hook prevented continuation and halting instead of continuing.
Expected Behavior
When a Stop hook:
- Exits with code 2
- Outputs JSON to stderr containing
"decision": "block"and a"reason"field
Claude Code should:
- Parse the JSON from stderr
- Extract the
reasonfield - Feed the reason to Claude as continuation instructions
- Resume agent execution
This is the documented behavior and works correctly for hooks in .claude/hooks/.
Actual Behavior (Plugin Hooks Only)
When the same hook is installed via plugins:
- Hook executes and returns exit code 2 with JSON to stderr
- Claude Code displays:
⏺ Stop hook prevented continuation - Agent execution halts instead of continuing
Reproduction Evidence
Test script that proves identical behavior from both hook locations:
\\\`bash
Create test transcript with reflexive agreement pattern
cat > /tmp/test_transcript.json << 'INNER_EOF'
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"You're wrong"}]}}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"You're absolutely right."}]}}
INNER_EOF
Test direct hook
echo '{"session_id":"test","stop_hook_active":false,"transcript_path":"/tmp/test_transcript.json"}' | \
~/.claude/hooks/entrypoints/stop.rb 2>&1
echo "Exit: $?"
Test plugin hook
echo '{"session_id":"test","stop_hook_active":false,"transcript_path":"/tmp/test_transcript.json"}' | \
~/.claude/plugins/marketplaces/simpleclaude/plugins/sc-hooks/hooks/entrypoints/stop.rb 2>&1
echo "Exit: $?"
\\\`
Both produce identical output:
\\\json\
{"continue":true,"stopReason":"","suppressOutput":false,"decision":"block","reason":"I notice I just used a reflexive agreement phrase. Let me provide a more substantive response:\n\nInstead of simply agreeing, let me analyze your point with specific technical reasoning, consider potential edge cases or alternative approaches, and offer constructive insights that build collaboratively on your observation."}
\\
Exit code: 2 (both)
Root Cause
The hook implementation is correct. Claude Code has different code paths for:
- Direct hooks (
.claude/hooks/): Exit 2 → parse stderr → continue ✓ - Plugin hooks (
plugins/): Exit 2 → show error message → halt ✗
The plugin execution path appears to:
- Not read stderr properly, OR
- Not parse the JSON from stderr, OR
- Not extract/use the
reasonfield
Environment
- Platform: macOS
- Claude Code Version: 0.3.10
- Hook Implementation: Uses
claude_hooksRuby gem v0.7.0 - Plugin: SimpleClaude (
sc-hooks)
Workaround
Moving the Stop hook from plugins/sc-hooks/hooks/ to .claude/hooks/ makes it work correctly.
Related
Original discussion: https://github.com/gabriel-dehan/claude_hooks/issues/11
9 Comments
I can confirm this behaviour with
2.0.29on MacOS.I'm so sad that this isn't getting more attention. This is a very weird quirk of Claude-Code's internals that is making me not want to use a plugin for my hook system :(
Why would plugin hooks not respect the exit codes but user-level hook would?
closed in favor of https://github.com/anthropics/claude-code/issues/10875
I think this should be reopened as these are different issues with the same root cause.
The linked ticket is about the JSON output, but the behavior is also showing for exit code 2 without any JSON output
Are you able to reproduce it @secustor ? If so add your reproduction steps and I'll re-open. I was unable to reproduce it today.
Yes, I have used your reproduction as bases ( thanks for that ) to show the behaviour
https://github.com/secustor/claude-code-plugin-hook-reproduction#
Thanks @secustor I agree it's the same bug. I think https://github.com/anthropics/claude-code/issues/10875 demonstrates and explains it better though - so please upvote.
My use case does not involve JSON output, but it seems like this has been identified and confirmed.
https://github.com/anthropics/claude-code/issues/10875#issuecomment-3488536561
So it should be fine to keep it closed.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.