Ralph Loop plugin: stop-hook.sh missing execute permission on Linux
Status Fixed / completed
Maintainer reply ✓ Yes — dicksontsai
Workaround ✓ Mentioned in thread ↓
Activity 9 comments · opened Mar 25, 2026 · closed Aug 19, 2026
💡 Likely answer: A maintainer (dicksontsai, collaborator)
responded on this thread — see the highlighted reply below.
Note: This issue was filed by Claude Code (Opus 4.6) on behalf of the user.
Bug
After installing the official Ralph Loop plugin (ralph-wiggum), every Claude Code response triggers this error:
Stop hook error: Failed with non-blocking status code: /bin/sh: 1:
~/.claude/plugins/marketplaces/claude-plugins-official/plugins/ralph-loop/hooks/stop-hook.sh: Permission denied
Root Cause
The stop-hook.sh file is installed with mode 644 (no execute bit):
-rw-rw-r-- stop-hook.sh
It should be 755 so the shell can execute it.
Related Issue
This is the same root cause as #20432 (plugin installer does not preserve executable permissions on .sh hooks). That issue was closed as stale/inactive and is now locked — but the underlying bug was never fixed. This report confirms it still affects the official Anthropic marketplace plugin (ralph-wiggum), not just third-party marketplaces.
Workaround
find ~/.claude -name "*.sh" -exec chmod +x {} +
Expected Fix
The plugin should either:
- Ship
.shfiles with the execute bit set in the repository (git update-index --chmod=+x) - Or have the plugin installer set
+xon hook scripts during installation
Environment
- OS: Ubuntu 22.04 (Linux)
- Claude Code CLI
- Plugin: ralph-wiggum (official Anthropic marketplace)
Showing cached comments. Read the full discussion on GitHub ↗
8 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Additional finding: Permission denied persists even WITH execute permission set
Platform: Ubuntu Linux 6.17.0-19-generic
Claude Code: v2.1.76
The problem is NOT just missing +x
@NicoJorgensen1's report correctly identifies that the file is installed without
+x. However, even after fixing the permissions, the error persists.Evidence
Yet Claude Code still reports:
What we tried (none worked)
chmod +xon all.shfiles (marketplace + cache + unknown/) — no effecthooks.jsonto usebash "$_R/hooks/stop-hook.sh"instead of direct exec — Claude Code ignores patched hooks.json, uses its own internal command generationnoexecmount, no BOM, valid shebang, correct ownershipRoot cause hypothesis
Claude Code's hook runner appears to use a sandboxed execution environment that prevents
exec()of.shfiles on Linux, regardless of file permissions. The/bin/sh: 1: ... Permission deniederror comes from the kernel returningEACCESto the shell's exec syscall, not from missing file permissions.This is a separate bug from #38901 (which is about the installer not preserving
+x). Even with the permission fix from #38901 applied, this execution issue remains.Workaround
Disabling the plugin in
enabledPluginsstops the error, since the stop hook no longer fires:Suggested fix
The hook runner should invoke shell scripts via
bash /path/to/script.sh(explicit interpreter) instead of direct exec (/path/to/script.sh), which would bypass the exec permission requirement entirely.---
Investigated with Claude Code (Opus 4.6). Co-authored by @alessandropcostabr.
We've identified and addressed the issue, which started in v2.1.83, but it will require a new Claude Code release in v2.1.86 to fix. Sorry for the disruption.
Confirmed fixed in v2.1.86
Platform: Ubuntu Linux 6.17.0-19-generic
Claude Code: v2.1.86
Reinstalled
ralph-loop@claude-plugins-officialand the stop hook now executes withoutPermission denied. Clean session start and stop — no hook errors.Thanks @dicksontsai for the quick turnaround!
Note: the installer still writes
.shfiles as644(no execute bit) in bothmarketplaces/andcache/unknown/. The fix appears to be in the hook runner itself (likely using an explicit interpreter instead of direct exec), which is the right approach. The permission preservation issue (#38901) remains as a separate cosmetic bug.Correction: NOT fixed in v2.1.86 on our environment
Retracting my previous confirmation — the error persists on v2.1.86:
Claude Code: v2.1.86 (confirmed)
Platform: Ubuntu Linux 6.17.0-19-generic (native, not WSL)
Files are still installed as
644:The hook runner in v2.1.86 still appears to use direct exec rather than an explicit interpreter. Had to
claude plugins uninstall ralph-loop@claude-plugins-officialagain to stop the error.@dicksontsai — could the fix be platform-specific (macOS only) or only effective on fresh installs? Our install was done on v2.1.86 itself, so the files were written by the new version.
Still affecting me
Operating System: Amazon Linux 2023, aarch64 (ARM64), kernel 6.12.77
Additional bug: Cross-session interference due to empty
session_idin ralph-loop state fileWritten by Claude Code (Opus 4.6) on behalf of the issue author.
While investigating why unrelated Claude Code sessions were being hijacked by Ralph Loop prompts, I found a separate bug in the ralph-loop plugin — distinct from the permission issue reported in this thread.
Problem
The ralph-loop plugin creates its state file (
.claude/ralph-loop.local.md) with an emptysession_idfield:Why this causes cross-session interference
The stop hook's session isolation guard (
stop-hook.sh, lines 31–35) checks:Since
session_idis empty,-n ""evaluates to false, and the guard never triggers. The hook then fires on every Claude Code session opened in that project directory — injecting the original loop prompt into completely unrelated sessions.Observed behavior
max_iterations: 0andcompletion_promise: null— the loop has no termination conditionSuggested fix
The ralph-loop skill's start command should write the actual session ID into the state file when creating it. The isolation logic in
stop-hook.shis correct — it just never receives the data it needs.Workaround
Delete the stale state file:
---
This is a separate bug from the permission issue (#38686 / #38901). The permission bug prevents the hook from running at all; this bug causes the hook to run in sessions where it shouldn't.
The
chmod +xworkaround is one-time — the nextralph-wiggumupdate reinstallsstop-hook.shas644and it breaks again. Since you can't edit a plugin's own hook command, the durable fix for plugin-managed hooks is aSessionStartself-healer that re-adds+xto every.shunder~/.claude/hooksand~/.claude/pluginsbefore the other hooks run:Wire it as a SessionStart hook and invoke it via
bash "<abs path>"so it can't be broken by the very problem it fixes:For hooks you do control (your own, not a plugin's), the most robust fix is to invoke them as
bash "<path>"insettings.jsontoo — then the execute bit is never needed at all, on any machine or after any cloud sync.Full copy-paste with all three fixes (tested on Linux / macOS / WSL2), plus a browser checker that flags which of your configured hooks are missing the bit: https://gist.github.com/yurukusa/53547551d89283900d88d9cb13fcb617 . The self-healer also ships as a ready example (
hook-permission-fixer.sh) in cc-safe-setup (free, MIT).