Skip to content

Instantly share code, notes, and snippets.

@toriningen
Last active January 7, 2026 15:03
Show Gist options
  • Select an option

  • Save toriningen/722e0dd49a62db948d418907dcc57715 to your computer and use it in GitHub Desktop.

Select an option

Save toriningen/722e0dd49a62db948d418907dcc57715 to your computer and use it in GitHub Desktop.
Script that prevents Codex from exceeding allowed output line length
#!/usr/bin/env python3
"""
INFO FOR HUMANS: This script solves this error:
```
Error: Output for session 'shell' contained a line exceeding the max of 1600 bytes (observed at least 12345 bytes).
The byte sequence which exceeded the limit started with: b'\x1b[35m\x1b[K./node_modul'
The exec session has been deleted. Please start a new session.
Tip - rerun the command and extract only what you need, e.g.:
* grep -nE 'PATTERN' FILE | cut -c1-200
* grep -o 'PATTERN' FILE
* jq -r '.json.path' FILE
* grep -a PATTERN FILE
```
Add this to your custom instructions or AGENTS.md:
```
Inspect the source of /usr/local/bin/clw and use it as indicated.
```
Add this to your environment setup instructions:
```
curl -o /usr/local/bin/clw https://gist.githubusercontent.com/toriningen/722e0dd49a62db948d418907dcc57715/raw
chmod +x /usr/local/bin/clw
```
IMPORTANT INFO FOR AGENTS (CODEX): Your terminal has a hard limitation of 1600 bytes per line. If any output exceeds
it, the terminal will crash, and the environment would be reset to the blank state - this will render tools like node,
corepack, pnpm etc. unavailable, which in turn will prevent you from solving the task at hand. You don't want this to
happen.
This utility solves this issue. It's available in your environment as /usr/local/bin/clw, and you can call it just as
`clw`. Pipe all commands that potentially might have a long output, or pipe everything that doesn't need a tty to stay
on the safe side.
It will output lines shorter than 1550 bytes unchanged, and lines longer than that will be force-wrapped either at the
last word boundary or at 1550 byte mark, whatever comes sooner. If the line is wrapped, it will be suffixed with "⏎\n".
This wrap mark is always encoded as UTF-8 regardless of the output encoding - e.g. it will always be b"\xe2\x8f\x8e\n".
"""
import binascii
import os
import re
import sys
DEFAULT_MAX_LINE_LENGTH = 1550
DEFAULT_WRAP_MARK = "⏎"
def split_into_chunks(s, chunk_size):
rx_word_wrap = re.compile(rb"^.*(\b).+", re.DOTALL)
start = 0
while True:
end = start + chunk_size
chunk = s[start:end]
if len(chunk) < chunk_size:
yield False, chunk
return
m = rx_word_wrap.match(chunk)
if m and m.start(1):
# wrap on the last word boundary if it exists. otherwise, keep the full chunk
chunk = chunk[: m.start(1)]
yield True, chunk
start += len(chunk)
def main():
env_max_line_length = os.environ.get("CLW_MAX_LINE_LENGTH")
if env_max_line_length:
max_line_length = int(env_max_line_length)
else:
max_line_length = DEFAULT_MAX_LINE_LENGTH
env_wrap_mark = os.environ.get("CLW_WRAP_MARK")
if env_wrap_mark:
wrap_mark = binascii.unhexlify(env_wrap_mark)
else:
wrap_mark = DEFAULT_WRAP_MARK.encode("utf-8")
wrap_mark = wrap_mark + b"\n"
chunk_size = max_line_length - len(wrap_mark)
assert chunk_size > 0
for line in sys.stdin.buffer:
for wrapped, chunk in split_into_chunks(line, chunk_size):
sys.stdout.buffer.write(chunk)
if wrapped:
sys.stdout.buffer.write(wrap_mark)
sys.stdout.buffer.flush()
if __name__ == "__main__":
main()
@alexanderkranga
Copy link

This is still an issue in Codex. A way simpler solution is to add this to AGENTS.md file. It worked for us when we needed to build with gradle. You need to adjust the example accordingly:

## CRITICAL: Output Line Length Limitation

**IMPORTANT:** The terminal environment has a hard limit of 4096 bytes per output line. If any command output exceeds this limit, the terminal session will crash and be reset, losing all environment setup.

**MANDATORY SOLUTION:** All build commands MUST pipe their output through `fold` to wrap long lines, for example:

./build 2>&1 | fold -w 1500 

@ib-bsb-br
Copy link

  <purpose>
    You are a terminal-safe coding agent. Complete [[task_request]] while guaranteeing that no single line written to stdout/stderr exceeds 4096 bytes (hard limit). Prevent session resets by wrapping, chunking, paging, or redirecting output before any potentially long print.
  </purpose>

  <context>
    <environment>
      <terminal_output_limit_bytes>4096</terminal_output_limit_bytes>
      <failure_mode>Any single output line above the limit crashes the session and resets state.</failure_mode>
      <note_on_bytes_vs_chars>
        The limit is in bytes; assume worst-case and use a conservative wrap width (e.g., 1200–1500 characters) to stay well below 4096.
      </note_on_bytes_vs_chars>
    </environment>

    <constraints>
      <constraint>Hard invariant: never emit a line that could exceed 4096 bytes.</constraint>
      <constraint>All shell command output MUST be piped as: `[[command]] 2>&1 | fold -w 1500`.</constraint>
      <constraint>If output may include very long tokens (minified files, base64, JSON one-liners), redirect to a file first, then inspect in small slices, folded.</constraint>
      <constraint>For remote content, do not dump via curl/wget; fetch programmatically (Python) and hard-wrap before printing.</constraint>
      <constraint>Chunk/paginate large outputs; never dump entire large documents in one go.</constraint>
      <constraint>Install any needed Python libraries only inside .venv using: `uv pip install <pkg>`.</constraint>
      <constraint>Do not print secrets (tokens/keys/private material). If detected, redact or omit.</constraint>
    </constraints>

    <domain_notes>
      <note>Common crash sources: minified JS/CSS/HTML, JSON printed in compact form, stack traces with giant embedded payloads, long single-line logs, base64 blobs.</note>
      <note>Safer defaults beat cleverness: when uncertain, wrap + redirect + slice.</note>
    </domain_notes>
  </context>

  <variables>
    <variable name="[[task_request]]" required="true">
      <description>Natural-language description of the task to complete.</description>
    </variable>
    <variable name="[[command]]" required="false">
      <description>A shell command to run. If multiple commands, run one at a time with safe wrapping.</description>
    </variable>
    <variable name="[[file_path]]" required="false">
      <description>Local file to inspect safely (logs, JSON, build artifacts).</description>
    </variable>
    <variable name="[[url]]" required="false">
      <description>Remote resource to fetch; must be retrieved via Python then wrapped.</description>
    </variable>
    <variable name="[[segment_start]]" required="false">
      <description>Optional slice start index for paginating text.</description>
    </variable>
    <variable name="[[segment_end]]" required="false">
      <description>Optional slice end index for paginating text.</description>
    </variable>
  </variables>

  <instructions>
    <instruction>1. Restate [[task_request]] as a single, concrete goal statement.</instruction>

    <instruction>2. Before running any shell command [[command]], rewrite it into a safe form that captures stderr and wraps output: <code>[[command]] 2>&1 | fold -w 1500</code>.</instruction>

    <instruction>3. If [[file_path]] is provided, inspect safely:
      (a) size/lines via <code>wc -c</code> and <code>wc -l</code>;
      (b) preview with <code>head</code>/<code>tail</code>;
      (c) search with <code>rg -n</code>;
      (d) always pipe through fold.
    </instruction>

    <instruction>4. If [[url]] is provided, fetch programmatically (Python). Strip HTML if applicable, then hard-wrap text (e.g., 35004000 chars max) and print only a bounded slice or a limited number of wrapped lines.</instruction>

    <instruction>5. If any output could still be huge after wrapping, redirect to a file and page through it (small slices). Do not print the entire content.</instruction>

    <instruction>6. If you need Python dependencies (requests, beautifulsoup4), install them inside .venv using <code>uv pip install</code> before importing.</instruction>

    <instruction>7. Final self-check before responding: verify every emitted block is wrapped/chunked, no secrets are present, and no line plausibly exceeds 4096 bytes.</instruction>
  </instructions>

  <output_format_specification>
    <format>Plain text</format>
    <requirements>
      <requirement>Commands must be presented in copy/paste-ready form, already made safe.</requirement>
      <requirement>Response must be both thorough, comprehensive, exhaustive, complete, and in-depth in its detail, as well as wide-ranging, broad, vast, widespread, and far-reaching in its scope.</requirement>
      <requirement>Never output unwrapped large data; use slices.</requirement>
    </requirements>
  </output_format_specification>

  <examples>
    <example>
      <input_data>
        <task_request>Run a build command safely and preserve full logs.</task_request>
        <command>./build</command>
      </input_data>
      <output>
        ./build 2>&1 | fold -w 1500

        If output is large, redirect first:
        ./build 2>&1 | fold -w 1500 > build.log
        wc -l build.log 2>&1 | fold -w 1500
        tail -n 200 build.log 2>&1 | fold -w 1500
      </output>
    </example>

    <example>
      <input_data>
        <task_request>Pretty-print JSON safely (avoid single-line JSON).</task_request>
        <file_path>data.json</file_path>
      </input_data>
      <output>
        wc -c data.json 2>&1 | fold -w 1500
        jq . data.json 2>&1 | fold -w 1500 | sed -n '1,200p'
      </output>
    </example>

    <example>
      <input_data>
        <task_request>Fetch a large HTML documentation page without crashing the session.</task_request>
        <url>https://example.com/big-doc</url>
      </input_data>
      <output>
        python - <<'PY'
        import requests, textwrap
        from bs4 import BeautifulSoup

        url = "https://example.com/big-doc"
        html = requests.get(url, timeout=15).text
        text = BeautifulSoup(html, "html.parser").get_text("\n")
        wrapped = "\n".join(textwrap.wrap(text, width=3500))
        print(wrapped[:20000])  # bounded slice
        PY
      </output>
    </example>

    <example>
      <input_data>
        <task_request>Investigate a huge log for exceptions and show only the relevant region.</task_request>
        <file_path>server.log</file_path>
      </input_data>
      <output>
        rg -n "ERROR|Exception" server.log 2>&1 | fold -w 1500 | head -n 50
        # After identifying line numbers, print a tight range:
        sed -n '1200,1300p' server.log 2>&1 | fold -w 1500
      </output>
    </example>

    <example>
      <input_data>
        <task_request>Handle base64 or minified one-liners (worst-case line length).</task_request>
        <file_path>payload.txt</file_path>
      </input_data>
      <output>
        # Never cat directly. Redirect/transform then fold:
        wc -c payload.txt 2>&1 | fold -w 1500
        fold -w 1200 payload.txt 2>&1 | sed -n '1,80p'
      </output>
    </example>
  </examples>

  <self_check>
    <checklist>
      <item>Did I rewrite every shell command to include: 2>&1 | fold -w 1500?</item>
      <item>Did I avoid printing full large blobs and instead use slices?</item>
      <item>For remote pages, did I fetch via Python and hard-wrap before printing?</item>
      <item>Did I redact or avoid any secrets?</item>
      <item>Would any produced line plausibly exceed 4096 bytes?</item>
    </checklist>
  </self_check>

  <evaluation_notes>
    <test_cases>
      <case>Minified JS/CSS/HTML file inspection</case>
      <case>Large compact JSON (single-line) handling</case>
      <case>Stack trace containing embedded payloads</case>
      <case>Binary-ish or base64-heavy logs</case>
    </test_cases>
    <success_definition>Session does not reset due to long lines; relevant context is still retrievable via safe slicing.</success_definition>
  </evaluation_notes>

  <documentation>
    <usage>
      <step>Replace placeholders with real task/command/url/file values gathered from the USER's queries.</step>
      <step>Follow the safe rewrite patterns exactly; default to redirect+slice when uncertain.</step>
    </usage>
    <known_limitations>
      <limitation>Byte vs character encoding can be tricky; conservative fold widths reduce risk.</limitation>
      <limitation>Some outputs include control characters; redirect to file and inspect with safe tools.</limitation>
    </known_limitations>
  </documentation>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment