Summary
ctx_batch_execute corrupts shell commands that use heredocs because runBatchCommands() appends 2>&1 directly to each command string before passing it to the shell executor.
For a command like:
node - <<'NODE'
console.log('heredoc works')
NODE
ctx_batch_execute effectively executes:
node - <<'NODE'
console.log('heredoc works')
NODE 2>&1
That changes the heredoc terminator from NODE to NODE 2>&1, so the shell does not terminate the heredoc where intended. The batch result can then show (no output) or otherwise misleading indexed/search output even though the command itself is valid.
Reproduction
Call ctx_batch_execute with a heredoc command:
{
"commands": [
{
"label": "heredoc node simple",
"command": "node - <<'NODE'\nconsole.log('heredoc works');\nconsole.log(process.version);\nNODE"
}
],
"queries": ["heredoc works node version"],
"timeout": 5000
}
Observed output includes an indexed section for the command, but the section body is empty / (no output).
For comparison, the same command works through ctx_execute(language: "shell", code: ...).
Expected behavior
ctx_batch_execute should execute the user's command string as provided. It should not append shell syntax after the command body because that can alter multiline shell constructs such as heredocs.
Stderr should still be captured and indexed alongside stdout.
Likely cause
Current upstream main still appears to append redirection in src/server.ts:
code: `${nodeOptsPrefix}${cmd.command} 2>&1`,
This appears in both the serial and parallel runBatchCommands() paths.
Suggested fix
Do not mutate the command with 2>&1. Instead:
- Execute the command string as-is:
code: `${nodeOptsPrefix}${cmd.command}`,
- Combine the executor's captured streams before formatting/indexing:
const combinedOutput = result.stderr
? `${result.stdout}${result.stdout && !result.stdout.endsWith("\n") ? "\n" : ""}${result.stderr}`
: result.stdout;
formatCommandOutput(cmd.label, combinedOutput, onFsBytes)
Apply the same pattern in both serial and parallel paths.
Environment
context-mode: 1.0.146
- npm latest checked:
1.0.146
- Platform observed: macOS / Pi coding agent
Impact
This is easy for agents to hit because ctx_batch_execute is recommended as the primary data-gathering tool, and heredoc-based Node/Python snippets are a common way to keep complex analysis code readable inside shell commands.
Summary
ctx_batch_executecorrupts shell commands that use heredocs becauserunBatchCommands()appends2>&1directly to each command string before passing it to the shell executor.For a command like:
ctx_batch_executeeffectively executes:That changes the heredoc terminator from
NODEtoNODE 2>&1, so the shell does not terminate the heredoc where intended. The batch result can then show(no output)or otherwise misleading indexed/search output even though the command itself is valid.Reproduction
Call
ctx_batch_executewith a heredoc command:{ "commands": [ { "label": "heredoc node simple", "command": "node - <<'NODE'\nconsole.log('heredoc works');\nconsole.log(process.version);\nNODE" } ], "queries": ["heredoc works node version"], "timeout": 5000 }Observed output includes an indexed section for the command, but the section body is empty /
(no output).For comparison, the same command works through
ctx_execute(language: "shell", code: ...).Expected behavior
ctx_batch_executeshould execute the user's command string as provided. It should not append shell syntax after the command body because that can alter multiline shell constructs such as heredocs.Stderr should still be captured and indexed alongside stdout.
Likely cause
Current upstream
mainstill appears to append redirection insrc/server.ts:This appears in both the serial and parallel
runBatchCommands()paths.Suggested fix
Do not mutate the command with
2>&1. Instead:Apply the same pattern in both serial and parallel paths.
Environment
context-mode:1.0.1461.0.146Impact
This is easy for agents to hit because
ctx_batch_executeis recommended as the primary data-gathering tool, and heredoc-based Node/Python snippets are a common way to keep complex analysis code readable inside shell commands.