You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Windows: all hooks fail with SyntaxError ([eval]:1) because inline node -e regex backslashes are collapsed by bash -c #3746
On native Windows (Claude Code + Git Bash), every ECC hook in hooks/hooks.json (v2.2.3) fails with a JavaScript SyntaxError before the bootstrap ever runs. Only SessionStart is visible to the user; the other hooks fail silently (non-blocking), so effectively no ECC hook runs on Windows.
What the user sees on startup:
SessionStart:startup hook error
Failed with non-blocking status code: [eval]:1
SessionStart:startup hook error
Failed with non-blocking status code: [eval]:1
Full stderr (from the session transcript):
[eval]:1
const p=require('path');const r=(function(){ ... require(s)
^^^^^^^
Expected ',', got 'string literal'
SyntaxError: missing ) after argument list
at makeContextifyScript (node:internal/vm:194:14)
at compileScript (node:internal/process/execution:388:10)
at evalTypeScript (node:internal/process/execution:260:22)
Root cause
The inline node -e "..." root-resolver contains backslash-heavy regexes in the WSL branch:
On Windows, Claude Code spawns Git Bash with the hook as bash.exe -c "<command>" through the Windows command line. The backslashes get collapsed along the way (Windows argv quoting + MSYS argv parsing + bash double-quote parsing), so node receives:
d.match(/^([A-Za-z]):[\/]/)// still validd.slice(2).replace(/\/g,'/')... // regex literal now swallows the rest -> SyntaxError
Running the same command from a script file (bash file.sh) works, which is why this is easy to miss when testing manually.
Reproduction
Windows 11, Git for Windows bash, Node v24.22.1, Claude Code on native Windows (not WSL), ECC 2.2.3 installed as a plugin.
// repro.js — run from the plugin rootconst{ spawnSync }=require('child_process');constcmd=require('./hooks/hooks.json').hooks.SessionStart[0].hooks[0].command;constr=spawnSync('C:\\Program Files\\Git\\usr\\bin\\bash.exe',['-c',cmd],{input: '{}',encoding: 'utf8',env: { ...process.env,CLAUDE_PLUGIN_ROOT: process.cwd()}});console.log(r.status,r.stderr.match(/SyntaxError.*/)?.[0]);// -> 1 SyntaxError: missing ) after argument list
Suggested fix
Avoid backslashes in the inline code entirely. This local patch fixed all 27 hooks for me (verified with the repro above, exit 0):
- var m=d.match(/^([A-Za-z]):[\\\\/]/);+ var m=d.match(/^([A-Za-z]):/);
...
- d='/mnt/'+dl+d.slice(2).replace(/\\\\/g,'/')+ d='/mnt/'+dl+d.slice(2).split(String.fromCharCode(92)).join('/')
(The code already uses d.charCodeAt(1)===92 elsewhere for the same reason.) Longer term, moving the resolver out of node -e into a small script file would avoid shell-quoting issues on all platforms and may also help with #2687, which is about the same inline bootstrap.
A regression test that runs each hooks.json command through bash -c via child_process.spawnSync on a Windows CI runner would catch this.
Confirming on another machine, same errors on native Windows:
ECC 2.2.3 (ecc@ecc, user scope, installed with npx ecc-universal@2.2.3 setup)
Windows x64 (native, not WSL), Git for Windows 2.55.0
Node v24.18.0, Claude Code 2.1.310
Same stderr: Expected ',', got 'string literal' / SyntaxError: missing ) after argument list.
One extra data point: re-running setup with hooks=off does not remove the SessionStart errors. Presumably the inline bootstrap fails to parse before it can read the hook preference, so Windows users currently can't silence it through ECC's own setting.
+1 for moving the resolver into a script file and adding the Windows CI regression test.
Activity
drummondbr-com commentedon Oct 26, 2026
Confirming on another machine, same errors on native Windows:
npx ecc-universal@2.2.3 setup)Same stderr:
Expected ',', got 'string literal'/SyntaxError: missing ) after argument list.One extra data point: re-running setup with hooks=off does not remove the SessionStart errors. Presumably the inline bootstrap fails to parse before it can read the hook preference, so Windows users currently can't silence it through ECC's own setting.
+1 for moving the resolver into a script file and adding the Windows CI regression test.