Plugin hook scripts fail when synced without execute permissions
Plugin hook scripts fail when synced without execute permissions
Summary
Claude Code plugin hooks that use shell scripts fail with "Permission denied" when the plugin cache is synced between machines using cloud sync services (pCloud, Dropbox, iCloud Drive, etc.) that don't preserve Unix file permissions.
Environment
- Claude Code version: (current)
- OS: macOS 15.3 (also affects Linux users syncing configs)
- Shell: bash/zsh
Steps to Reproduce
- Install Claude Code on Machine A
- Enable plugins that include shell-based hooks (e.g.,
learning-output-style) - Sync
~/.claude/plugins/directory to Machine B via a cloud sync service - Start Claude Code on Machine B
- Observe "Permission denied" errors for plugin hook scripts
Error Output
/bin/sh: /Users/rcfa/.claude/plugins/cache/claude-plugins-official/learning-output-style/e30768372b41/hooks-handlers/session-start.sh: Permission denied
Root Cause
Plugin hook scripts are executed directly (e.g., /bin/sh script.sh or ./script.sh) which requires the execute bit to be set. Cloud sync services typically sync file contents but not Unix permissions, resulting in scripts with -rw-r--r-- permissions that cannot be executed.
Suggested Fix
Modify the plugin hook execution logic to use one of these approaches instead of direct execution:
Option 1: Source the script
bash -c "source /path/to/hook.sh"
Option 2: Pass script as argument to interpreter
/bin/bash /path/to/hook.sh
Option 3: Read and execute
/bin/bash -c "$(cat /path/to/hook.sh)"
This matches the pattern already used in user-configured hooks in ~/.claude/settings.json:
{
"command": "bash -c 'source ~/.claude/merge-history.sh'"
}
Workaround
Users can work around this by periodically running:
find ~/.claude/plugins -name "*.sh" -type f -exec chmod +x {} \;
Or setting up a LaunchAgent/systemd service to watch the directory and fix permissions automatically.
Impact
- Affects users who sync their Claude configuration between multiple machines
- Causes plugin hooks to silently fail or produce error output
- Common with developers who work across multiple computers
Related
This applies to all plugin shell scripts, not just hooks - any .sh file in the plugin structure that gets executed directly will fail.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗