Summary:
run_shell_command wraps the user's command in a bash group command { ; }; __code=0; ... (in useExecutionLifecycle.ts). This breaks all heredoc-terminated commands because the ; is appended directly to the heredoc delimiter, making bash unable to recognize it.
Steps to Reproduce:
Run a shell command ending in a heredoc:
cat << 'EOF' > output.txt
hello world
EOF
The CLI transforms this into:
{ cat << 'EOF' > output.txt
hello world
EOF; }; __code=0; pwd > "/tmp/xxx"; exit ;
Proposed Fix:
In packages/cli/src/ui/hooks/useExecutionLifecycle.ts, replace the semicolon with a newline before closing the brace:
commandToExecute = { ${command}\n}; __code=$?; pwd > "${pwdFilePath}"; exit $__code;
Impact:
Heredocs fail if the delimiter is on the final line, causing model retries and token waste.
I have verified the fix with reproduction scripts and added unit tests in packages/cli and packages/core.
Summary:
run_shell_command wraps the user's command in a bash group command { ; }; __code=0; ... (in useExecutionLifecycle.ts). This breaks all heredoc-terminated commands because the ; is appended directly to the heredoc delimiter, making bash unable to recognize it.
Steps to Reproduce:
Run a shell command ending in a heredoc:
cat << 'EOF' > output.txt
hello world
EOF
The CLI transforms this into:
{ cat << 'EOF' > output.txt
hello world
EOF; }; __code=0; pwd > "/tmp/xxx"; exit ;
Proposed Fix:
In packages/cli/src/ui/hooks/useExecutionLifecycle.ts, replace the semicolon with a newline before closing the brace:
commandToExecute =
{ ${command}\n}; __code=$?; pwd > "${pwdFilePath}"; exit $__code;Impact:
Heredocs fail if the delimiter is on the final line, causing model retries and token waste.
I have verified the fix with reproduction scripts and added unit tests in packages/cli and packages/core.