@@ -146,8 +146,8 @@ pub struct CommandSpec {
146146 pub stdin_prompt : Option < String > ,
147147}
148148
149- /// Byte threshold above which prompts are delivered via stdin instead of CLI
150- /// arg to avoid OS `ARG_MAX` limits . ~100K chars ≈ 100 KB.
149+ /// Byte threshold above which prompts are delivered via stdin for backends
150+ /// that support stdin prompt input (currently codex) . ~100K chars ≈ 100 KB.
151151const STDIN_PROMPT_THRESHOLD : usize = 100_000 ;
152152
153153/// Build the command arguments for invoking a backend with a prompt.
@@ -210,6 +210,9 @@ pub fn build_command_args(
210210 if final_prompt. len ( ) > STDIN_PROMPT_THRESHOLD {
211211 stdin_prompt = Some ( final_prompt) ;
212212 } else {
213+ // Use `--` to prevent prompt content from being parsed as flags
214+ // (e.g. file content starting with `---`)
215+ args. push ( "--" . to_string ( ) ) ;
213216 args. push ( final_prompt) ;
214217 }
215218 } else {
@@ -263,9 +266,14 @@ pub fn build_command_args(
263266 prompt. to_string ( )
264267 } ;
265268 if final_prompt. len ( ) > STDIN_PROMPT_THRESHOLD {
266- // Placeholder arg for -p; actual prompt comes via stdin
267- args. push ( "(prompt via stdin)" . to_string ( ) ) ;
268- stdin_prompt = Some ( final_prompt) ;
269+ // claude/gemini/grok require a positional value for -p. Feeding stdin
270+ // here produces incorrect results because the backend reads the -p arg.
271+ // Keep the prompt as an argument for correctness.
272+ tracing:: warn!(
273+ "prompt exceeds threshold for backend '{}'; passing via argv" ,
274+ backend. name
275+ ) ;
276+ args. push ( final_prompt) ;
269277 } else if final_prompt. starts_with ( '-' ) {
270278 args. push ( format ! ( " {}" , final_prompt) ) ;
271279 } else {
@@ -374,7 +382,10 @@ mod tests {
374382 let backend = make_backend ( "codex" ) ;
375383 let spec = build_command_args ( & backend, "hello" , None , None , true , None ) ;
376384 assert_eq ! ( spec. binary, "/usr/bin/codex" ) ;
377- assert_eq ! ( spec. args, vec![ "exec" , "--full-auto" , "--json" , "hello" ] ) ;
385+ assert_eq ! (
386+ spec. args,
387+ vec![ "exec" , "--full-auto" , "--json" , "--" , "hello" ]
388+ ) ;
378389 }
379390
380391 #[ test]
@@ -441,14 +452,23 @@ mod tests {
441452 }
442453
443454 #[ test]
444- fn test_build_command_args_stdin_for_long_prompt ( ) {
445- let backend = make_backend ( "claude " ) ;
455+ fn test_build_command_args_stdin_for_long_prompt_codex ( ) {
456+ let backend = make_backend ( "codex " ) ;
446457 let long_prompt = "x" . repeat ( STDIN_PROMPT_THRESHOLD + 1 ) ;
447458 let spec = build_command_args ( & backend, & long_prompt, None , None , true , None ) ;
448459 assert ! ( spec. stdin_prompt. is_some( ) ) ;
449460 assert_eq ! ( spec. stdin_prompt. as_ref( ) . unwrap( ) . len( ) , long_prompt. len( ) ) ;
450461 }
451462
463+ #[ test]
464+ fn test_build_command_args_no_stdin_for_long_prompt_claude ( ) {
465+ let backend = make_backend ( "claude" ) ;
466+ let long_prompt = "x" . repeat ( STDIN_PROMPT_THRESHOLD + 1 ) ;
467+ let spec = build_command_args ( & backend, & long_prompt, None , None , true , None ) ;
468+ assert ! ( spec. stdin_prompt. is_none( ) ) ;
469+ assert_eq ! ( spec. args. last( ) , Some ( & long_prompt) ) ;
470+ }
471+
452472 #[ test]
453473 fn test_all_backend_specs_returns_all ( ) {
454474 let specs = all_backend_specs ( ) ;
0 commit comments