diff --git a/lib/ai/claude_cli.js b/lib/ai/claude_cli.js index e8e222e..3fa32ad 100644 --- a/lib/ai/claude_cli.js +++ b/lib/ai/claude_cli.js @@ -107,8 +107,10 @@ export async function runClaudeTurn(opts) { args.push('--allowedTools', ...allowedTools); } - // Positional user message must come last - args.push(userText); + // NOTE: the user message is fed via STDIN, NOT as a positional arg. The + // variadic --tools/--allowedTools flags greedily consume trailing args, so a + // positional prompt after them is swallowed ("Input must be provided..."). The + // CLI reads the prompt from stdin in --print mode. // Child env: clone, strip API key env vars so CLI uses subscription/OAuth auth const childEnv = { ...process.env }; @@ -135,7 +137,7 @@ export async function runClaudeTurn(opts) { proc = spawn(claudeExe, args, { cwd: cwd || process.cwd(), env: childEnv, - stdio: ['ignore', 'pipe', 'pipe'], + stdio: ['pipe', 'pipe', 'pipe'], }); } catch (err) { emit({ type: 'error', message: err.message }); @@ -143,6 +145,12 @@ export async function runClaudeTurn(opts) { return; } + // Feed the prompt via stdin (see note above), then close stdin. + // Guard EPIPE: the child may exit before reading stdin. + proc.stdin.on('error', () => {}); + proc.stdin.write(userText); + proc.stdin.end(); + let timedOut = false; const timeout = setTimeout(() => { timedOut = true;