On Windows the lifecycle hooks run via PowerShell, which does not expand
cmd.exe-style %CLAUDE_PLUGIN_ROOT%. The path was passed literally, so the hook
launcher could not find the script and both SessionStart and UserPromptSubmit
failed with exit code 1 (issue #19). Switch the two commandWindows entries to
$env:CLAUDE_PLUGIN_ROOT, keeping the working node + .js invocation.
Add a regression test that rejects cmd.exe %VAR% syntax in commandWindows and
asserts every hook command points at a script that actually ships in hooks/.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hooks/hooks.json used ${PLUGIN_ROOT}, which Claude Code never defines, so the literal resolved against the hook process cwd and SessionStart/UserPromptSubmit failed with 'Cannot find module'. Switch to ${CLAUDE_PLUGIN_ROOT} (and %CLAUDE_PLUGIN_ROOT% for the Codex commandWindows variant); Codex aliases CLAUDE_PLUGIN_ROOT so both hosts resolve. Drop the duplicate inline hooks block from .claude-plugin/plugin.json so hooks load from a single canonical source.