55import os
66import platform
77import re
8+ import shlex
89import shutil
910import sys
1011import tempfile
@@ -169,8 +170,13 @@ def _build_settings_value(self) -> str | None:
169170
170171 return json .dumps (settings_obj )
171172
172- def _build_command (self ) -> list [str ]:
173- """Build CLI command with arguments."""
173+ def _build_command (self ) -> list [str ] | str :
174+ """Build CLI command with arguments.
175+
176+ Returns either a list of command arguments (for direct execution)
177+ or a shell command string (when command line is too long and
178+ shell command substitution is needed on Unix systems).
179+ """
174180 cmd = [self ._cli_path , "--output-format" , "stream-json" , "--verbose" ]
175181
176182 if self ._options .system_prompt is None :
@@ -333,11 +339,12 @@ def _build_command(self) -> list[str]:
333339 # String mode: use --print with the prompt
334340 cmd .extend (["--print" , "--" , str (self ._prompt )])
335341
336- # Check if command line is too long (Windows limitation )
342+ # Check if command line is too long (platform-specific limits )
337343 cmd_str = " " .join (cmd )
338344 if len (cmd_str ) > _CMD_LENGTH_LIMIT and self ._options .agents :
339- # Command is too long - use temp file for agents
340- # Find the --agents argument and replace its value with @filepath
345+ # Command is too long - use temp file for agents with shell command substitution
346+ # Note: The @filepath syntax is not supported by the CLI, so we use
347+ # shell command substitution $(cat filepath) on Unix systems instead.
341348 try :
342349 agents_idx = cmd .index ("--agents" )
343350 agents_json_value = cmd [agents_idx + 1 ]
@@ -353,13 +360,37 @@ def _build_command(self) -> list[str]:
353360 # Track for cleanup
354361 self ._temp_files .append (temp_file .name )
355362
356- # Replace agents JSON with @filepath reference
357- cmd [agents_idx + 1 ] = f"@{ temp_file .name } "
363+ if platform .system () != "Windows" :
364+ # Unix: use shell command substitution $(cat filepath)
365+ # Build shell command with proper quoting
366+ quoted_parts = []
367+ for i , arg in enumerate (cmd ):
368+ if i == agents_idx + 1 :
369+ # Replace agents JSON with cat command substitution
370+ # Use double quotes around $(...) to preserve JSON whitespace
371+ quoted_parts .append (
372+ f'"$(cat { shlex .quote (temp_file .name )} )"'
373+ )
374+ else :
375+ quoted_parts .append (shlex .quote (arg ))
358376
359- logger .info (
360- f"Command line length ({ len (cmd_str )} ) exceeds limit ({ _CMD_LENGTH_LIMIT } ). "
361- f"Using temp file for --agents: { temp_file .name } "
362- )
377+ shell_cmd = " " .join (quoted_parts )
378+
379+ logger .info (
380+ f"Command line length ({ len (cmd_str )} ) exceeds limit "
381+ f"({ _CMD_LENGTH_LIMIT } ). Using shell command substitution "
382+ f"for --agents: { temp_file .name } "
383+ )
384+
385+ return shell_cmd
386+ else :
387+ # Windows: command line limits are stricter and shell substitution
388+ # is not as straightforward. Log a warning.
389+ logger .warning (
390+ f"Command line length ({ len (cmd_str )} ) exceeds Windows limit "
391+ f"({ _CMD_LENGTH_LIMIT } ). Large agent configurations may not "
392+ f"work correctly on Windows."
393+ )
363394 except (ValueError , IndexError ) as e :
364395 # This shouldn't happen, but log it just in case
365396 logger .warning (f"Failed to optimize command line length: { e } " )
0 commit comments