Plugin installer strips execute permissions from hook scripts
Summary
The Claude Code plugin installer does not preserve file permissions (specifically the execute bit) when extracting plugins from GCS archives. This causes plugin hook scripts to fail with Permission denied errors even though the upstream repository correctly marks them as executable (100755).
Reproduction
- Install a plugin that ships executable hook scripts (e.g.,
ralph-loopfromclaude-plugins-official) - Observe the stop hook error on every session end:
````
Stop hook error: Failed with non-blocking status code: /bin/sh:
/Users/<user>/.claude/plugins/marketplaces/claude-plugins-official/plugins/ralph-loop/hooks/stop-hook.sh: Permission denied
- Inspect the file permissions:
```
$ ls -la ~/.claude/plugins/marketplaces/claude-plugins-official/plugins/ralph-loop/hooks/stop-hook.sh
-rw-r--r-- 1 user staff 7533 Mar 25 08:18 stop-hook.sh
644
The file is (not executable) despite being 100755` in the git repo.
Root Cause
The plugin system downloads marketplace archives from GCS (evidenced by the .gcs-sha file in the marketplace directory) rather than using git clone. The archive extraction process does not preserve git file mode bits, so all files end up with default 644 permissions regardless of their original mode.
Upstream repo confirms the file is correctly marked executable:
// GET /repos/anthropics/claude-plugins-official/git/trees/main?recursive=1
{"mode": "100755", "path": "plugins/ralph-loop/hooks/stop-hook.sh"}
Impact
- Affected: Any plugin that ships executable scripts (hook scripts, helper binaries, etc.)
- Severity: The error appears on every session stop/start, polluting the user experience. The
ralph-loopplugin's stop hook silently fails to run, which could leave background processes orphaned. - Workaround: Users can manually
chmod +xthe affected script, but this is reset on every plugin update.
Expected Behavior
The plugin installer should preserve execute permissions from the source repository when extracting plugin archives. Two possible approaches:
- Preserve file modes in the GCS archive — if using tar/zip, ensure the archive format retains permission bits and the extraction respects them
- Post-extraction fixup — after extracting, scan for
.shfiles (or read a manifest) and set+xon scripts that need it
Environment
- OS: macOS (Darwin 25.3.0)
- Plugin:
ralph-loop@claude-plugins-official - Marketplace source:
anthropics/claude-plugins-officialvia GCS archive - Archive SHA:
b10b583de281385442474e836644534b938b2678
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗