fix: send claude prompt via stdin so Windows shell mode does not mangle it (#2174)

askClaude() passed the full multi-line prompt as a claude

Fix: keep only the short, safe flags (--model, -p) as args and send the prompt over stdin via spawnSync input. The prompt never touches the shell command line, so multi-line/special-char prompts arrive intact. claude -p reads stdin on macOS/Linux too, so behavior is unchanged there.

Verified on Windows 11 (Node 24, claude CLI via npm): real turns now return correct responses, and node tests/scripts/claw.test.js passes 19/19.

Co-authored-by: skausage-ops <268783127+skausage-ops@users.noreply.github.com>
This commit is contained in:
skausage-ops
2026-06-07 01:25:48 -04:00
committed by GitHub
parent 70fde3c14f
commit 3e671ff848

View File

@@ -89,13 +89,17 @@ function askClaude(systemPrompt, history, userMessage, model) {
if (model) {
args.push('--model', model);
}
args.push('-p', fullPrompt);
args.push('-p');
// On Windows, the `claude` binary installed via npm is `claude.cmd`.
// Node's spawn() cannot resolve `.cmd` wrappers via PATH without shell: true,
// so this call fails with `spawn claude ENOENT` on Windows otherwise.
// On Windows the `claude` binary installed via npm is `claude.cmd`/`claude.ps1`,
// and Node's spawn() cannot resolve those wrappers via PATH without shell: true.
// But shell mode concatenates args *unescaped*, so a multi-line prompt passed as
// an arg gets mangled (newlines and the `===` section markers truncate it, and
// claude receives an empty prompt). Fix: send the prompt over stdin via `input`
// and keep only the short, safe flags (`--model`, `-p`) as args.
// 'claude' is a hardcoded literal here (not user input), so shell mode is safe.
const result = spawnSync('claude', args, {
input: fullPrompt,
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
env: { ...process.env, CLAUDECODE: '' },