Bug: Spaces in ${CLAUDE_PLUGIN_ROOT} break hook commands

Resolved 💬 7 comments Opened Mar 12, 2026 by tigeryst Closed Apr 27, 2026

Preflight Checklist

  • [x] I'm on the latest version of Claude Code
  • [x] I've searched existing issues for duplicates
  • [x] I've read the troubleshooting guide

What's Wrong?

When hooks.json commands reference ${CLAUDE_PLUGIN_ROOT} and the expanded path contains spaces, the hook command fails because Claude Code passes the expanded string to /bin/sh -c without quoting. The shell splits the path at space boundaries.

This is not a duplicate of #24529 (variable not being set). Here the variable IS set and expanded — the expanded value just isn't properly quoted.

What Should Happen?

Hook commands using ${CLAUDE_PLUGIN_ROOT} should work regardless of whether the plugin installation path contains spaces. Claude Code should either:

  1. Quote the expanded variable when passing to /bin/sh -c, or
  2. Use execFile-style invocation that avoids shell word splitting

Error Messages/Logs

/bin/sh: /Users/someone/My: No such file or directory

(The actual path was /Users/someone/My Projects/plugin-name/hooks/run.sh but the shell split at the space.)

Steps to Reproduce

  1. Create a test plugin in a directory with a space in the path:
mkdir -p "/tmp/My Plugins/test-plugin/hooks"
mkdir -p "/tmp/My Plugins/test-plugin/.claude-plugin"

cat > "/tmp/My Plugins/test-plugin/.claude-plugin/plugin.json" << 'PJSON'
{"name": "test-spaces", "version": "1.0.0", "description": "Repro for spaces bug"}
PJSON

cat > "/tmp/My Plugins/test-plugin/hooks/hooks.json" << 'HJSON'
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/test-hook.sh"}]
      }
    ]
  }
}
HJSON

cat > "/tmp/My Plugins/test-plugin/hooks/test-hook.sh" << 'HOOK'
#!/bin/bash
echo "HOOK EXECUTED" > /tmp/hook-ran.txt
cat
HOOK
chmod +x "/tmp/My Plugins/test-plugin/hooks/test-hook.sh"
  1. Run Claude Code with the plugin:
claude --plugin-dir "/tmp/My Plugins/test-plugin" --print "read the file /etc/hostname"
  1. Check if the hook ran:
cat /tmp/hook-ran.txt 2>&1 || echo "Hook never ran — bug confirmed"
  1. Compare with a no-spaces path (identical plugin at /tmp/MyPlugins/test-plugin) — works fine.

Workaround

Escape quotes in hooks.json:

"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run.sh\" args"

Claude Model

Sonnet

Is this a regression?

I don't know

Claude Code Version

2.1.73

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app

Additional Information

This affects all platforms since the expansion + /bin/sh -c pattern is platform-independent. Any user whose home directory or plugin install path contains a space will hit this.

View original on GitHub ↗

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