ralph-wiggum stop hook silently stops loops on tool_use-only assistant messages

Resolved 💬 3 comments Opened Mar 4, 2026 by anombyte93 Closed Mar 7, 2026

Bug Description

The ralph-wiggum plugin's stop-hook.sh silently kills self-referential loops when the assistant's last message contains only tool_use content blocks (no text blocks). This happens regularly during normal agentic usage — e.g., when Claude's final action in a turn is a TaskUpdate, Read, or Bash tool call with no accompanying text narration.

Root Cause

The stop hook extracts only the last JSONL line with role: assistant, filters for .type == "text" content blocks, and when none are found, treats it as "no content" and stops the loop by deleting the state file and exiting.

Affected code: plugins/ralph-wiggum/hooks/stop-hook.sh lines 80-112

Fix Already Exists

This exact bug was fixed in the sibling ralph-loop plugin in anthropics/claude-plugins-official:

  • adfc379 — fix(ralph-loop): stop hook fails when last assistant block is tool_use
  • 8644df9 — fix(ralph-loop): isolate loop state to the session that started it
  • 028eccf — address review: bound grep to tail -n 100; restore explicit error paths

The fix changes the hook to scan the last 100 assistant lines (not just the last 1), use jq -rs slurp mode, and treat empty text as "no promise tag found = continue loop" rather than "error = stop loop."

Impact

  • Loops stop silently with no user-visible error
  • Users cannot distinguish between a completed loop and a bug-killed loop
  • Any non-trivial agentic loop that produces tool_use-only messages will hit this
  • Tested and confirmed with 6 test cases (2 live tmux sessions, 4 direct hook tests)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗