[BUG] Plugin installation does not preserve executable permissions on shell script hooks

Resolved 💬 2 comments Opened Jan 23, 2026 by anton-abyzov Closed Feb 28, 2026

Description

When Claude Code installs plugins from a marketplace (GitHub or other sources), executable permissions are not preserved on shell script files (.sh). This causes hooks to fail silently on macOS and Linux.

Steps to Reproduce

  1. Create a marketplace plugin with a hook script:

``bash
# In your plugin's hooks/session-start.sh (with +x permission in git)
#!/bin/bash
echo '{"continue": true, "systemMessage": "Hello from hook"}'
``

  1. Ensure the file has executable permission in git:

``bash
chmod +x hooks/session-start.sh
git add hooks/session-start.sh
git commit -m "Add hook with executable permission"
``

  1. Install the plugin via Claude Code:

``bash
claude plugin marketplace add github:your-org/your-marketplace
claude plugin install your-plugin@your-marketplace
``

  1. Check file permissions after installation:

``bash
ls -la ~/.claude/plugins/marketplaces/your-marketplace/plugins/your-plugin/hooks/
# Expected: -rwxr-xr-x session-start.sh
# Actual: -rw-r--r-- session-start.sh
``

  1. The hook fails to execute because the OS won't run a script without the execute bit.

Expected Behavior

After plugin installation, shell scripts should retain their executable permissions (chmod +x), matching the source repository.

Actual Behavior

All files are installed with read/write permissions only (-rw-r--r--), losing the executable bit. Hooks silently fail to execute.

Impact

  • macOS: Affected ✓
  • Linux: Affected ✓
  • Windows: Not affected (Windows doesn't use Unix permissions; hooks run via Git Bash)

This affects any third-party marketplace that uses shell script hooks. Users experience:

  • Hooks not firing despite being correctly configured
  • Silent failures with no error messages
  • Difficult debugging (permissions aren't the first thing users check)

Workaround

Third-party marketplaces must provide a post-install script that runs chmod +x on hook files:

// SpecWeave's workaround in refresh-marketplace.ts
function fixHookPermissions(marketplacePath: string) {
  if (process.platform === 'win32') return; // Skip on Windows
  
  const hookFiles = findAllShellScripts(marketplacePath);
  for (const hookFile of hookFiles) {
    fs.chmodSync(hookFile, 0o755); // Make executable
  }
}

Suggested Fix

During plugin installation, preserve executable permissions from the source:

Option A: Check git metadata for executable bit and apply it

git ls-files -s | grep "^100755" # Files with executable permission

Option B: Auto-chmod .sh files in hooks/ directories after extraction

if (file.endsWith('.sh') && file.includes('/hooks/')) {
  fs.chmodSync(file, 0o755);
}

Environment

  • Claude Code version: 2.1.x
  • OS: macOS 15.x, Ubuntu 24.04
  • Shell: bash, zsh

Related

This issue affects the SpecWeave marketplace and likely any other third-party marketplace with shell script hooks.

View original on GitHub ↗

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