fix: Windows CRLF crash + npm shim / native binary detection#2
fix: Windows CRLF crash + npm shim / native binary detection#2kurushimee wants to merge 3 commits into
Conversation
… on Windows
On Windows, `which('claude')` returns an npm-generated shim script
(a `#!/bin/sh` wrapper or `.cmd` batch file) rather than the actual
binary. `resolvePathToInstallationType` sees an unrecognized text
file and falls through to the hardcoded search paths, which may not
find the installation either.
New `resolveNpmShimTarget()` reads the shim content and extracts the
real target path:
- sh shim: `"$basedir/node_modules/.../claude.exe"`
- .cmd shim: `"%dp0%\node_modules\...\claude.exe"`
The PATH detection now tries the shim resolver (including the `.cmd`
variant alongside the bare shim) before falling back to search paths.
Also adds native binary search paths (`bin/claude.exe`) that mirror
the existing CLIJS search locations for CC 2.1.116+, which ships as
a native binary inside the npm package with no `cli.js`.
Verified on Windows 11 with CC 2.1.118 installed via npm — detection
now finds `bin/claude.exe` through the npm shim chain without needing
hardcoded search path fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, system prompt `.md` files have CRLF (`\r\n`) line endings.
The newline escaping for `"` and `'` delimited JS strings only replaced
`\n` via `/\n/g`, leaving `\r` (0x0D) as a bare character in the output.
A bare `\r` is a line terminator in JavaScript and is illegal inside
double-quoted and single-quoted string literals, producing a syntax error
that Bun reports as:
TypeError: Expected CommonJS module to have a function wrapper
All 273 `.md` files are affected — 4,875 stray `\r` characters end up
in the patched JS, but `node --check` fails on the first one it hits
(the Computer tool action parameter description, which lives in a
double-quoted JSON schema `description` field).
Fix: change the newline replacement regex from `/\n/g` to
`/\r\n|\r|\n/g` for both `"` and `'` delimiters, correctly handling
all three line-ending variants (CRLF, lone CR, LF).
Also normalize `\r\n` → `\n` in the backtick branch before
`escapeDepthZeroBackticks` runs. While `\r` is syntactically valid
inside template literals, the original cli.js doesn't contain bare `\r`
and injecting them would alter the actual prompt text sent to the model.
Verified:
- `node --check` on the patched JS after stripping `\r`: exit 0.
- Unit test: old escaping turns `\r\n` into `\r\n` (invalid in JS
strings); new escaping turns `\r\n` into `\n` (valid).
- `npm run lint` clean; `npm test`: 228 passed, 4 skipped (baseline).
- End-to-end: `--apply` then `claude` launches without error on
Windows 11 with CC 2.1.118.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Read through this. Looks mostly good, but I have two notes 1.
|
- resolveNpmShimTarget: switch to matchAll and require node_modules in candidate path. Single-match form grabbed the "$basedir/node" probe at the top of npm-cli-shim sh scripts and silently no-op'd for JS-style shims. - systemPrompts.test.ts: commit three CRLF regression tests, one per delimiter branch (double-quote, single-quote, backtick). Bare \r is invisible in source, so not.toMatch(/\r/) is the assertion that catches a future revert to /\n/g. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Two Windows-specific fixes that together resolve the
TypeError: Expected CommonJS module to have a function wrappercrash after--applyon Windows with CC 2.1.118..mdfiles have\r\nline endings. The newline escaping for"and'JS string contexts only replaced\n, leaving bare\r(a JS line terminator) in the patched output. All 273 prompt files are affected (4,875 stray\rchars). Changed/\n/gto/\r\n|\r|\n/gfor quote contexts; added\rnormalization in the backtick branch too.which('claude')returns an npm shim (sh/cmd wrapper), not the actual binary. NewresolveNpmShimTarget()follows the shim to the real executable. Also addsbin/claude.exesearch paths for CC 2.1.116+ which ships as a native binary with nocli.js.Verification
node --checkon the patched JS after stripping\rfrom the pre-fix output: exit 0 (confirms\ris the sole syntax cause)\r\n(invalid); new escaping turns it into\n(valid)pnpm run lintclean;pnpm test: 228 passed, 4 skipped (baseline)--restore→--apply→claudelaunches without error on Windows 11, CC 2.1.118 (npm install)Test plan
node dist/index.mjs --applythenclaude— should launch without TypeErrornode --check "%USERPROFILE%\.tweakcc\native-claudejs-patched.js"— should exit 0🤖 Generated with Claude Code