Bug Description
Plugin SessionStart hooks that use ${CLAUDE_PLUGIN_ROOT} in bash commands fail on fresh session start. The environment variable is not being expanded, resulting in the hook trying to execute from the filesystem root.
Environment
- Claude Code: 2.1.84
- OS: macOS (Darwin 25.4.0)
- Plugins affected:
explanatory-output-style@claude-plugins-official, learning-output-style@claude-plugins-official
Steps to Reproduce
- Install
explanatory-output-style and learning-output-style from claude-plugins-official
- Start a fresh Claude Code session (
claude)
- Observe
SessionStart:startup hook error messages
Error
Both plugins' hooks.json contain:
{
"hooks": [{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks-handlers/session-start.sh"
}]
}
When executed, produces:
bash: /hooks-handlers/session-start.sh: No such file or directory
${CLAUDE_PLUGIN_ROOT} resolves to empty, so the path becomes /hooks-handlers/session-start.sh instead of the full plugin cache path.
Other plugins work fine
The superpowers plugin also uses ${CLAUDE_PLUGIN_ROOT} in its SessionStart hook but works correctly because it uses bash -c '"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd" session-start' (quoted expansion).
The context-mode plugin uses node ${CLAUDE_PLUGIN_ROOT}/hooks/sessionstart.mjs and also works fine.
Workaround
Disabled both affected plugins. The issue appears specific to how ${CLAUDE_PLUGIN_ROOT} is expanded (or not) for bash shell commands in certain plugin hook configurations.
Expected Behavior
${CLAUDE_PLUGIN_ROOT} should be expanded to the plugin's cache path before the hook command is executed, regardless of whether the command uses node, bash, or other shell execution.
Bug Description
Plugin SessionStart hooks that use
${CLAUDE_PLUGIN_ROOT}in bash commands fail on fresh session start. The environment variable is not being expanded, resulting in the hook trying to execute from the filesystem root.Environment
explanatory-output-style@claude-plugins-official,learning-output-style@claude-plugins-officialSteps to Reproduce
explanatory-output-styleandlearning-output-stylefrom claude-plugins-officialclaude)SessionStart:startup hook errormessagesError
Both plugins' hooks.json contain:
{ "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks-handlers/session-start.sh" }] }When executed, produces:
${CLAUDE_PLUGIN_ROOT}resolves to empty, so the path becomes/hooks-handlers/session-start.shinstead of the full plugin cache path.Other plugins work fine
The
superpowersplugin also uses${CLAUDE_PLUGIN_ROOT}in its SessionStart hook but works correctly because it usesbash -c '"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd" session-start'(quoted expansion).The
context-modeplugin usesnode ${CLAUDE_PLUGIN_ROOT}/hooks/sessionstart.mjsand also works fine.Workaround
Disabled both affected plugins. The issue appears specific to how
${CLAUDE_PLUGIN_ROOT}is expanded (or not) for bash shell commands in certain plugin hook configurations.Expected Behavior
${CLAUDE_PLUGIN_ROOT}should be expanded to the plugin's cache path before the hook command is executed, regardless of whether the command usesnode,bash, or other shell execution.