Hook runner doesn't properly quote ${CLAUDE_PLUGIN_ROOT} on Windows paths with spaces
Bug Description
When a Windows user account has spaces in its name (e.g., C:\Users\Redux Gamer\), plugin hooks that reference ${CLAUDE_PLUGIN_ROOT} fail with word-splitting errors.
Steps to Reproduce
- Install Claude Code on a Windows machine where the user profile path contains spaces (e.g.,
C:\Users\Redux Gamer\) - Enable a plugin that registers hooks using
${CLAUDE_PLUGIN_ROOT}(e.g.,ralph-loop) - The plugin's
hooks.jsoncontains a command like:
``json``
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh\""
}
- When the hook fires, the following happens:
- JSON parsing removes the escaped quotes, producing:
"${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh" - The hook runner expands the variable:
"/c/Users/Redux Gamer/.claude/plugins/.../stop-hook.sh" - The hook runner strips the literal
"characters before passing to bash - Bash receives the unquoted path:
/c/Users/Redux Gamer/.claude/plugins/.../stop-hook.sh - Word splitting occurs on the space →
bash: /c/Users/Redux: No such file or directory
Expected Behavior
The hook runner should properly handle spaces in ${CLAUDE_PLUGIN_ROOT} by either:
- Preserving the quotes around the expanded path when passing to bash
- Using proper shell escaping for the expanded variable
- Or wrapping the entire command in a way that prevents word splitting
Actual Behavior
bash: /c/Users/Redux: No such file or directory
This error appears on every Stop hook invocation for the ralph-loop plugin.
Workaround
Replacing ${CLAUDE_PLUGIN_ROOT} with the Windows 8.3 short name (e.g., /c/Users/REDUXG~1/...) avoids spaces entirely. However, this workaround:
- Gets overwritten on plugin updates
- Is machine-specific (8.3 names can vary)
- Is not guaranteed stable across Windows updates
Environment
- OS: Windows 11 Pro 10.0.26200
- Shell: Git Bash
- User path:
C:\Users\Redux Gamer\ - Affected plugin:
ralph-loop(Stop hook) - Potentially affected: Any plugin using
${CLAUDE_PLUGIN_ROOT}in hooks on Windows paths with spaces
Notes
The superpowers plugin also uses ${CLAUDE_PLUGIN_ROOT} in its SessionStart hook but uses a .cmd polyglot wrapper with %~dp0 for internal path resolution, which may explain why it works. The issue appears specific to how bash receives the expanded path for direct .sh script references.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗