Plugin sync from GCS strips execute permission on .sh hook files

Resolved 💬 2 comments Opened Mar 27, 2026 by armatrix Closed Mar 27, 2026

Bug Description

Plugin .sh files lose their execute permission (+x) after every session sync. The plugin marketplace syncs plugins from GCS (Google Cloud Storage) on each session start, and since GCS object storage does not preserve POSIX file permissions, all downloaded .sh files default to 644 (-rw-r--r--).

This causes hook scripts to fail with Permission denied errors on every new session.

Reproduction

  1. Install a plugin that uses .sh hook files (e.g., ralph-loop which has hooks/stop-hook.sh)
  2. Manually fix: chmod +x ~/.claude/plugins/marketplaces/claude-plugins-official/plugins/ralph-loop/hooks/stop-hook.sh
  3. Start a new Claude Code session
  4. The permission is reset to 644 — the hook fails with Permission denied

Evidence

All .sh files in the plugin directory have identical timestamps and no execute permission after sync:

-rw-r--r--@ aaron staff 7533 Mar 27 13:24 ralph-loop/hooks/stop-hook.sh
-rw-r--r--@ aaron staff 3564 Mar 27 13:24 learning-output-style/hooks-handlers/session-start.sh
-rw-r--r--@ aaron staff 7044 Mar 27 13:24 ralph-loop/scripts/setup-ralph-loop.sh
-rw-r--r--@ aaron staff 1485 Mar 27 13:24 explanatory-output-style/hooks-handlers/session-start.sh
... (all .sh files are 644)

The .gcs-sha file (72b975468071669f5503fd49c37ab657d9212fbd) confirms the sync source is GCS.

Expected Behavior

After syncing plugins from GCS, the plugin system should automatically chmod +x all .sh files (or at minimum, files referenced as command in hooks.json).

Suggested Fix

After downloading/extracting plugin files, run something like:

find "$PLUGIN_DIR" -name "*.sh" -exec chmod +x {} \;

Or parse each plugin's hooks.json and ensure any file referenced in "command" fields has execute permission.

Environment

  • Claude Code: 2.1.84
  • macOS: 15.6.1 (Darwin 24.6.0)
  • Shell: zsh

View original on GitHub ↗

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