@@ -4996,28 +4996,41 @@ Fix all issues by making necessary file changes. Be direct, don't ask questions.
49964996 ? `${ claudeCmd } ${ claudeArgs } `
49974997 : claudeCmd
49984998
4999- // Use script command to create pseudo-TTY for Ink compatibility
5000- // Platform-specific script command syntax
5001- let scriptCmd
4999+ // Use script command to create pseudo-TTY for Ink compatibility.
5000+ // Pass the inner command and tmp file to sh -c via environment
5001+ // variables so spaces / special chars in either cannot inject into
5002+ // the shell. Outer spawn uses shell: false.
5003+ let cmdBin : string
5004+ let cmdArgs : string [ ]
50025005 if ( WIN32 ) {
5003- // Try winpty (comes with Git for Windows)
50045006 const winptyCheck = await runCommandWithOutput ( 'where' , [ 'winpty' ] )
50055007 if ( winptyCheck . exitCode === 0 ) {
5006- scriptCmd = `winpty ${ claudeCommand } < "${ tmpFile } "`
5008+ cmdBin = 'winpty'
5009+ cmdArgs = [ 'sh' , '-c' , '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ]
50075010 } else {
5008- // No winpty, try direct (may fail with raw mode error)
5009- scriptCmd = ` ${ claudeCommand } < "${ tmpFile } "`
5011+ cmdBin = 'sh'
5012+ cmdArgs = [ '-c' , '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ]
50105013 }
50115014 } else {
5012- // Unix/macOS: use script command with quoted command
5013- scriptCmd = `script -q /dev/null sh -c '${ claudeCommand } < "${ tmpFile } "'`
5015+ cmdBin = 'script'
5016+ cmdArgs = [
5017+ '-q' ,
5018+ '/dev/null' ,
5019+ 'sh' ,
5020+ '-c' ,
5021+ '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ,
5022+ ]
50145023 }
50155024
50165025 const exitCode = await new Promise ( ( resolve , _reject ) => {
5017- const spawnPromise = spawn ( scriptCmd , [ ] , {
5026+ const spawnPromise = spawn ( cmdBin , cmdArgs , {
50185027 stdio : 'inherit' ,
50195028 cwd : rootPath ,
5020- shell : true ,
5029+ env : {
5030+ ...process . env ,
5031+ CLAUDE_CMD : claudeCommand ,
5032+ CLAUDE_TMP : tmpFile ,
5033+ } ,
50215034 } )
50225035
50235036 const child = spawnPromise . process
@@ -5317,30 +5330,42 @@ Fix the issue by making necessary file changes. Be direct, don't ask questions.`
53175330 log . substep ( `Running: claude ${ claudeArgs } ` )
53185331 }
53195332
5320- // Use script command to create pseudo-TTY for Ink compatibility
5321- // Platform-specific script command syntax
5322- let scriptCmd
5333+ // Use script command to create pseudo-TTY for Ink compatibility.
5334+ // Pass CLAUDE_CMD / CLAUDE_TMP via env so special chars in
5335+ // either cannot inject into the shell.
5336+ let cmdBin : string
5337+ let cmdArgs : string [ ]
53235338 if ( WIN32 ) {
5324- // Try winpty (comes with Git for Windows)
53255339 const winptyCheck = await runCommandWithOutput ( 'where' , [
53265340 'winpty' ,
53275341 ] )
53285342 if ( winptyCheck . exitCode === 0 ) {
5329- scriptCmd = `winpty ${ claudeCommand } < "${ tmpFile } "`
5343+ cmdBin = 'winpty'
5344+ cmdArgs = [ 'sh' , '-c' , '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ]
53305345 } else {
5331- // No winpty, try direct (may fail with raw mode error)
5332- scriptCmd = ` ${ claudeCommand } < "${ tmpFile } "`
5346+ cmdBin = 'sh'
5347+ cmdArgs = [ '-c' , '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ]
53335348 }
53345349 } else {
5335- // Unix/macOS: use script command with quoted command
5336- scriptCmd = `script -q /dev/null sh -c '${ claudeCommand } < "${ tmpFile } "'`
5350+ cmdBin = 'script'
5351+ cmdArgs = [
5352+ '-q' ,
5353+ '/dev/null' ,
5354+ 'sh' ,
5355+ '-c' ,
5356+ '"$CLAUDE_CMD" < "$CLAUDE_TMP"' ,
5357+ ]
53375358 }
53385359
53395360 const exitCode = await new Promise ( ( resolve , _reject ) => {
5340- const spawnPromise = spawn ( scriptCmd , [ ] , {
5361+ const spawnPromise = spawn ( cmdBin , cmdArgs , {
53415362 stdio : 'inherit' ,
53425363 cwd : rootPath ,
5343- shell : true ,
5364+ env : {
5365+ ...process . env ,
5366+ CLAUDE_CMD : claudeCommand ,
5367+ CLAUDE_TMP : tmpFile ,
5368+ } ,
53445369 } )
53455370
53465371 const child = spawnPromise . process
0 commit comments