Bound large exec output while preserving searchable artifacts

Open 💬 5 comments Opened Jul 1, 2026 by enzodevs
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Large shell/unified-exec outputs can currently become very large model-visible and UI-visible payloads. This can bloat the agent context, make transcript rendering expensive, and obscure the useful part of the result.

I would like to propose bounding the inline command output while preserving the full output as a local artifact path that the agent can inspect with normal lexical tools such as rg, sed, or tail.

Proposed behavior

  • Keep small command outputs inline as today.
  • When command output exceeds a configurable threshold, write the full output to a temp artifact file.
  • Return a bounded preview plus metadata that includes the saved file path, byte count, approximate token count, and suggested inspection commands.
  • Ensure telemetry/log previews do not create spill artifacts.
  • Ensure app-server/TUI command transcript display prefers bounded formatted output when it exists, rather than loading the raw full output.

Why this helps

This keeps model-visible context bounded without losing access to the complete command result. It also protects TUI transcript rendering from very large command cells while keeping the full output available for follow-up searches.

Validation from prototype

A prototype branch adds config, core spill handling, unified exec wiring, app-server display handling, and tests for the spill paths. Targeted spill tests pass locally, and app-server-protocol tests pass locally.

I understand external code contributions are by invitation only; opening this issue first to see whether the approach aligns with the maintainers' intended direction.

View original on GitHub ↗

5 Comments

enzodevs · 1 month ago

Prototype branch is available here:

https://github.com/enzodevs/tars/tree/codex/exec-output-spill

It is based on current openai/codex@db887d03e1 and contains one commit: 85e392d4ec Bound large exec output with spill artifacts.

Local validation from the prototype branch:

  • just fmt
  • just test -p codex-core spill - 15 passed
  • just test -p codex-app-server-protocol - 253 passed
  • just fix -p codex-core
  • just fix -p codex-app-server-protocol
  • git diff --check

I also attempted just test -p codex-core; it failed locally in broad integration tests around CLI stream, MCP/search, sandbox, and network-denial behavior that appear unrelated to this change. The targeted spill coverage passed.

I tried to open a draft PR from the fork, but GitHub returned CreatePullRequest permission denied for this account, which seems consistent with the by-invitation contribution policy documented in this repo. Happy to reopen as a PR if maintainers decide the approach aligns and invite a contribution.

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #29929

Powered by Codex Action

enzodevs · 1 month ago

A small repro that shows the failure mode this is intended to address:

python3 - <<'PY'
for i in range(200_000):
    print(f"spill-line-{i:08d} repeated payload for spill threshold check")
PY

Without a spill guard, the command result can become a very large model-visible/tool-output payload. In the TUI, the command cell transcript path can also become expensive if it tries to render the full aggregated output.

With the prototype branch, the inline result stays bounded and includes metadata like:

Full output saved to: /tmp/exec_outputs/<hash>.txt
Full output bytes: ...
Approximate output tokens: ...
Suggested inspection:
- rg -n "pattern" -- /tmp/exec_outputs/<hash>.txt
- sed -n '1,160p' /tmp/exec_outputs/<hash>.txt

The full output remains available for lexical follow-up. For example, in local testing I could verify the final marker without loading the full output into the model/TUI context:

rg -n "spill-line-00200000" /tmp/exec_outputs/<hash>.txt

This is the behavior I think is important: bound everything injected into model-visible and UI-visible context, while keeping the complete command result inspectable from disk when needed.

Dave-London · 1 month ago

Strong proposal — bounded preview + on-disk artifact + inspection hints is the right shape for arbitrary exec. Complementary angle for the frequent structured commands (git/npm/docker/etc.): return them already-bounded at the source. I wrap those as MCP servers in Pare that emit stripped, schema-validated JSON instead of raw output, so the common dev-tool calls never hit the spill threshold — your artifact path would then mainly catch the genuinely-large arbitrary exec cases. Not a replacement for bounding exec, just narrows what needs spilling.

enzodevs · 1 month ago

I took a closer look at #29929. It seems like a concrete example of the problem I was trying to solve: large terminal output reaches the Desktop main process and eventually runs into buffer or string allocation limits.

My prototype caps output in the exec path and writes the full result to a searchable file. Downstream consumers get a short preview instead of the full payload. I have not verified whether the failure in #29929 goes through that same path, so it may also need a Desktop-specific cap before IPC or string construction.

The branch is still available at enzodevs/tars:codex/exec-output-spill, commit 85e392d4ec. If this is close to the direction the team wants, I can narrow the scope or write up the relevant code paths before submitting anything.