You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Long-running bash commands with large outputs cause truncation and agent retry loops #11313
Long-running bash commands with verbose output are being truncated and/or timed out, causing agents to re-attempt commands instead of polling the saved tool output. This creates serious idempotency issues in workflows where commands should run to completion.
Current behavior:
Bash commands have a hardcoded 2-minute default timeout (src/tool/bash.ts:21)
Output is truncated at 2,000 lines or 50KB (src/tool/truncation.ts:10-11)
When output is truncated, full output is saved to ~/.opencode/data/tool-output/, but agents frequently re-run the command instead of reading the saved output
Commands are killed after timeout, even if they would have completed successfully
The problem:
Commands that produce large build logs, test outputs, or verbose diagnostics get truncated
Agents see truncated output and often retry the command instead of using Read with offset/limit on the saved output file
This creates duplicate work, wasted API calls, and potential side effects from non-idempotent commands
For CI/CD workflows, this behavior is unacceptable - commands should never exit until a proper exit code is received
Current configuration options:
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS - env var for timeout (exists)
No configuration for MAX_LINES or MAX_BYTES truncation limits (hardcoded)
Proposed solution:
Add opencode.json configuration for these limits:
{
"experimental": {
"bash": {
"timeout_ms": 600000, // 10 minutes"max_lines": 10000, // or null to disable"max_bytes": 512000// or null to disable
}
}
}
This would allow users to configure behavior appropriate for their workflows without needing environment variables.
Plugins
None
OpenCode version
Current (main branch)
Steps to reproduce
Run a command that produces more than 2,000 lines of output (e.g., npm install with verbose logging, large test suite)
Observe output is truncated with message about saved file
Watch agent retry the command instead of reading the saved output
For timeout: run any command that takes longer than 2 minutes
Screenshot and/or share link
No response
Operating System
macOS
Terminal
No response
Reacted by naourass, Peter Ivanov, Tim Woerner, seanmamasde, icceey, chromatic, Daniil Zulin, Roscoe A. Bartlett and Miguel Aranha Baldi Horlle
After reviewing the related issues, here's what I've gathered:
Timeout configuration - This has been addressed. OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS was added in December 2025 (#1721, #3950, #4197). The max timeout cap was removed, so agents can set arbitrarily long timeouts per-command. The env var sets the default.
Output truncation - This is the unaddressed gap. The hardcoded limits in truncation.ts (2000 lines, 50KB) have no configuration mechanism. Related issues:
"we will have something more appropriate in the config later, for now we will have: OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT (supported in next release also this is in milliseconds)"
This suggests the pattern for new settings: start with OPENCODE_EXPERIMENTAL_* env vars, then graduate to opencode.json config once the feature is stable.
Proposed First Phase (Safe, Low-Risk)
Following the established pattern, add two new env vars to flag.ts:
This is ~4 lines of code, follows the exact pattern used for OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS, and gives power users an escape hatch while the team decides on the proper config schema.
Why This Issue Should Be Primary
This issue consolidates the truncation + timeout + idempotency concerns that are scattered across multiple threads:
The unique contribution here is identifying the agent retry loop problem: when output is truncated, agents often re-run commands instead of reading the saved output file. This creates real workflow issues beyond just "I want more output" - it causes duplicate side effects and wasted compute.
Happy to submit a PR for the env var approach if maintainers confirm this is the right direction.
Hello! I tested the solution proposed in the last comment and it worked perfectly on my end.
In my case, I’m developing some MCP tools that return internal documentation, and the current ~50KB tool response limit often truncates the docs. When that happens, the agent tends to misinterpret the truncated response and enters a retry/loop pattern.
After building a version with the solution proposed by @nabilfreeman, the agent behaved as expected: long tool outputs were handled without getting stuck in a retry loop.
Just a +1 to the proposed direction of making these limits configurable (timeout + max_bytes/max_lines) via env vars -> opencode.json so it’s not hardcoded and can be tuned per workflow.
Command output truncation has been the bane of my existence recently.
It's really frustrating that so many of the model providers have trained/steered their models to aggressively truncate context. I firmly believe this makes the models perform worse and is entirely done for cost saving measures.
Opencode's truncation is not for the same reason but it's holding back large context workflows.
If we can get this behaviour changed, then people can finally use npx fullcontext npm test etc. to bypass the head and tail abuse by Claude et al.
@thdxr hey there! I saw you are assigned to this issue. Just wondering if you have any thoughts? I am happy to plan out and do the PR for this. We are desperate for this addition to OC and are willing to invest the labor to make it happen.
Because it will probably involve adding settings to the opencode.json file, it would be very helpful to have some steering from the Opencode team on the best approach here.
Many thanks
Reacted by seanmamasde, chromatic, Tim Woerner, Pedro Serey and Miguel Aranha Baldi Horlle
You can control the default timeout using: OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS (defaults to 2 minutes but the agent can also change the timeout whenever it calls the tool so it can override it too).
We should prolly add a simple way to disable timeout too
Reacted by Tim Woerner, Nabs and Miguel Aranha Baldi Horlle
@rekram1-node Disabling timeout would be greatly appreciated. We are still relying on tons of prompt steering and tool layers to use nohup all the time which is convoluted.
One small problem we had to work around. Agents don't know about the overridden timeout, they still think it's 2 minutes. So, they often try to put a 10 minute timeout on the bash instead of our 2 hour timeout. I have outlined this bug here: #25913
The solution was to create a plugin that intercepts the agent's bad timeout usage:
bash-timeout-clamp.plugin.ts
/** * Clamp the opencode bash tool's `timeout` parameter to a 2-hour minimum. * * Opencode's bash tool computes `params.timeout ?? DEFAULT_TIMEOUT` (see * opencode source: packages/opencode/src/tool/bash.ts ~line 597). Without * this plugin, an LLM that supplies any `timeout` — even a too-small one * like 60000 (60s) — overrides the operator's default and causes premature * SIGTERM on long-running commands. * * This plugin uses the `tool.execute.before` hook to mutate `args.timeout` * by reference, raising any value below MIN_TIMEOUT_MS to MIN_TIMEOUT_MS. * Values >= MIN_TIMEOUT_MS, undefined values, and non-finite values are * left untouched. * * @type {import("@opencode-ai/plugin").Plugin} */constMIN_TIMEOUT_MS=7_200_000;// 2 hours; mirrors DEFAULT_BASH_TIMEOUT_MS in harnessexportdefaultasync()=>({"tool.execute.before": async(input: {tool: string;sessionID: string;callID: string},output: {args: Record<string,unknown>},)=>{if(input.tool!=="bash")return;constt=output.args.timeout;// Only clamp finite numbers below the floor; leave undefined / non-numbers// for opencode's schema validator to handle.if(typeoft==="number"&&Number.isFinite(t)&&t<MIN_TIMEOUT_MS){output.args.timeout=MIN_TIMEOUT_MS;}},});
Personal thoughts
Respectfully I still think that Opencode is way too opinionated on this, presumably for context management / cost considerations. Restricting models' access to context reliably degrades quality as the trade-off.
The remaining sharp edge here looks less like "how large should the defaults be?" and more like "does the model see the effective execution contract it is about to override?"
If the operator sets a two-hour shell default plus larger tool_output limits, the agent still needs a machine-visible receipt before it chooses an explicit shorter timeout: effective timeout, effective max lines/bytes, persisted output path, and a recommended next action such as read_saved_output versus rerun_command. Without that, the model can accidentally turn an operator-level policy into a smaller per-call timeout and recreate the retry loop.
In MartinLoop terms, I would treat truncated output or timeout as an admission decision for the next attempt: rerun only if the command or failure class changed; otherwise read the saved artifact. That might be a small fixture worth adding around this issue: "large output saved, assistant's next step reads the saved path instead of rerunning."
Well, my comment is specifically about the pull request. That is fixing the problem that the tool description is hard coding 2 minutes no matter what you set for the experimental bash timeout arg. I don’t think there is much to argue about this, it’s just closing a gap in the implementation. If you guys could please take a look at that and merge, opencode would be improved.
As for the opinionation - if I want to turn off truncation and timeouts as a harness engineer, why is the harness fighting me? If I have a 2 million context model and a 12+ hour agentic loop, I want to be able to use open code for the harness. There is no need for truncation or timeouts, they are not serving any useful purpose. You are right, you guys are the best platform right now. That’s why I’m using opencode and not something else. And actually you are so close to an unopinionated harness platform. I would prefer to use something that I believe will become industry standard instead of building something unmaintainable on Pi.
The future of agentic development will be fine tuned custom harnesses and we need a deterministic platform to build on. Hoping that is opencode. You guys can achieve that while also serving people that want a turnkey solution for the short term. And I and other contributors am very willing to help and contribute towards that balance!
@nabilfreeman totally valid, just wanted to be clear what ur need is, i actually have a separate PR that's open rn for allowing disabling of truncation. U can technically disable it by mutating tool output metadata in a plugin but its not documented and its non obvious
These are good points! And yeah we are making progress, in next week or two we will launch a revamped opencode (opencode v2) that prioritizes composability and customization, killing poor old apis and having a much more intuitive surface along with some new features too.
Activity
github-actions commentedon Jan 30, 2026
This issue might be a duplicate of existing issues. Please check:
Feel free to ignore if your specific case addresses concerns not covered by these issues.
nabilfreeman commentedon Jan 30, 2026
Context from Related Issues
After reviewing the related issues, here's what I've gathered:
Timeout configuration - This has been addressed.
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MSwas added in December 2025 (#1721, #3950, #4197). The max timeout cap was removed, so agents can set arbitrarily long timeouts per-command. The env var sets the default.Output truncation - This is the unaddressed gap. The hardcoded limits in
truncation.ts(2000 lines, 50KB) have no configuration mechanism. Related issues:The maintainer perspective (from @rekram1-node in #3950):
This suggests the pattern for new settings: start with
OPENCODE_EXPERIMENTAL_*env vars, then graduate toopencode.jsonconfig once the feature is stable.Proposed First Phase (Safe, Low-Risk)
Following the established pattern, add two new env vars to
flag.ts:Then in
truncation.ts:This is ~4 lines of code, follows the exact pattern used for
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS, and gives power users an escape hatch while the team decides on the proper config schema.Why This Issue Should Be Primary
This issue consolidates the truncation + timeout + idempotency concerns that are scattered across multiple threads:
The unique contribution here is identifying the agent retry loop problem: when output is truncated, agents often re-run commands instead of reading the saved output file. This creates real workflow issues beyond just "I want more output" - it causes duplicate side effects and wasted compute.
Happy to submit a PR for the env var approach if maintainers confirm this is the right direction.
pserey commentedon Mar 10, 2026
Hello! I tested the solution proposed in the last comment and it worked perfectly on my end.
In my case, I’m developing some MCP tools that return internal documentation, and the current ~50KB tool response limit often truncates the docs. When that happens, the agent tends to misinterpret the truncated response and enters a retry/loop pattern.
After building a version with the solution proposed by @nabilfreeman, the agent behaved as expected: long tool outputs were handled without getting stuck in a retry loop.
Just a +1 to the proposed direction of making these limits configurable (timeout + max_bytes/max_lines) via env vars ->
opencode.jsonso it’s not hardcoded and can be tuned per workflow.nabilfreeman commentedon Mar 11, 2026
@pserey really glad to hear it!
Command output truncation has been the bane of my existence recently.
It's really frustrating that so many of the model providers have trained/steered their models to aggressively truncate context. I firmly believe this makes the models perform worse and is entirely done for cost saving measures.
Opencode's truncation is not for the same reason but it's holding back large context workflows.
If we can get this behaviour changed, then people can finally use
npx fullcontext npm testetc. to bypass theheadandtailabuse by Claude et al.QC2168 commentedon Mar 12, 2026
I configured OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS in bashrc, but it did not take effect
nabilfreeman commentedon Mar 23, 2026
@thdxr hey there! I saw you are assigned to this issue. Just wondering if you have any thoughts? I am happy to plan out and do the PR for this. We are desperate for this addition to OC and are willing to invest the labor to make it happen.
Because it will probably involve adding settings to the
opencode.jsonfile, it would be very helpful to have some steering from the Opencode team on the best approach here.Many thanks
rekram1-node commentedon Apr 27, 2026
You can control truncation logic by using these fields in your opencode.json (pay no attention to the numbers):
You can control the default timeout using: OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS (defaults to 2 minutes but the agent can also change the timeout whenever it calls the tool so it can override it too).
We should prolly add a simple way to disable timeout too
timwkosatec commentedon Apr 27, 2026
seems like there was a duplicate issue that just fixed what we asked here except for the timeout
Issue: #22565
PR: #23770
nabilfreeman commentedon Apr 27, 2026
Thank you guys for the improvement! 👏
@rekram1-node Disabling timeout would be greatly appreciated. We are still relying on tons of prompt steering and tool layers to use nohup all the time which is convoluted.
nabilfreeman commentedon May 11, 2026
Quick update here, we now have tool output configured in our harness plus reliable injection of the experiment environment flag.
We have been able to completely eliminate timeouts and truncations as a result!
Start opencode with this command
Bash commands will run for 2 hours before timing out (BUT, you must apply the below plugin until the related issue is fixed)
opencode.json
50k lines or 1mb of text on any bash output
Was still getting timeouts despite the above!
One small problem we had to work around. Agents don't know about the overridden timeout, they still think it's 2 minutes. So, they often try to put a 10 minute timeout on the bash instead of our 2 hour timeout. I have outlined this bug here: #25913
The solution was to create a plugin that intercepts the agent's bad timeout usage:
bash-timeout-clamp.plugin.ts
Personal thoughts
Respectfully I still think that Opencode is way too opinionated on this, presumably for context management / cost considerations. Restricting models' access to context reliably degrades quality as the trade-off.
nabilfreeman commentedon May 23, 2026
There is still an open issue that needs fixing: #25913 - and the pull request #25917
cc @rekram1-node
rekram1-node commentedon May 23, 2026
@nabilfreeman what is it too opinionated about? Every agent has this same truncation logic ours is actually the least restrictive rn
Keesan12 commentedon May 23, 2026
The remaining sharp edge here looks less like "how large should the defaults be?" and more like "does the model see the effective execution contract it is about to override?"
If the operator sets a two-hour shell default plus larger
tool_outputlimits, the agent still needs a machine-visible receipt before it chooses an explicit shorter timeout: effective timeout, effective max lines/bytes, persisted output path, and a recommended next action such asread_saved_outputversusrerun_command. Without that, the model can accidentally turn an operator-level policy into a smaller per-call timeout and recreate the retry loop.In MartinLoop terms, I would treat truncated output or timeout as an admission decision for the next attempt: rerun only if the command or failure class changed; otherwise read the saved artifact. That might be a small fixture worth adding around this issue: "large output saved, assistant's next step reads the saved path instead of rerunning."
nabilfreeman commentedon May 23, 2026
@rekram1-node hey 👋
Well, my comment is specifically about the pull request. That is fixing the problem that the tool description is hard coding 2 minutes no matter what you set for the experimental bash timeout arg. I don’t think there is much to argue about this, it’s just closing a gap in the implementation. If you guys could please take a look at that and merge, opencode would be improved.
As for the opinionation - if I want to turn off truncation and timeouts as a harness engineer, why is the harness fighting me? If I have a 2 million context model and a 12+ hour agentic loop, I want to be able to use open code for the harness. There is no need for truncation or timeouts, they are not serving any useful purpose. You are right, you guys are the best platform right now. That’s why I’m using opencode and not something else. And actually you are so close to an unopinionated harness platform. I would prefer to use something that I believe will become industry standard instead of building something unmaintainable on Pi.
The future of agentic development will be fine tuned custom harnesses and we need a deterministic platform to build on. Hoping that is opencode. You guys can achieve that while also serving people that want a turnkey solution for the short term. And I and other contributors am very willing to help and contribute towards that balance!
rekram1-node commentedon May 24, 2026
@nabilfreeman totally valid, just wanted to be clear what ur need is, i actually have a separate PR that's open rn for allowing disabling of truncation. U can technically disable it by mutating tool output metadata in a plugin but its not documented and its non obvious
These are good points! And yeah we are making progress, in next week or two we will launch a revamped opencode (opencode v2) that prioritizes composability and customization, killing poor old apis and having a much more intuitive surface along with some new features too.
bartlettroscoe commentedon Jun 19, 2026
@rekram1-node and @nabilfreeman, is this PR still needed or has it already been addressed with some other Issue & PR?
github-actions commentedon Aug 19, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.