Plugin installer strips execute permissions from hook scripts

Resolved 💬 2 comments Opened Mar 26, 2026 by Vic563 Closed Mar 27, 2026

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

  1. Install a plugin that ships executable hook scripts (e.g., ralph-loop from claude-plugins-official)
  2. 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
``

  1. 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
`
The file is
644 (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-loop plugin's stop hook silently fails to run, which could leave background processes orphaned.
  • Workaround: Users can manually chmod +x the 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:

  1. Preserve file modes in the GCS archive — if using tar/zip, ensure the archive format retains permission bits and the extraction respects them
  2. Post-extraction fixup — after extracting, scan for .sh files (or read a manifest) and set +x on scripts that need it

Environment

  • OS: macOS (Darwin 25.3.0)
  • Plugin: ralph-loop@claude-plugins-official
  • Marketplace source: anthropics/claude-plugins-official via GCS archive
  • Archive SHA: b10b583de281385442474e836644534b938b2678

View original on GitHub ↗

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