guide · computers

Hermes Terminal Output: The 50 KB Cap and the Pipe Fix

Hermes terminal output can stop before the line you need. Here is how to recognise the 50 KB cap, reduce noisy output, and recover the missing bottom safely.

July 14, 2026 · By Alastair Fraser

A retro robot redirects an overflowing terminal through a small filter pipe

The failure is easy to misread

I run a command, watch a substantial block of output arrive, and assume I saw the result. Then I make the wrong call because the useful line was at the bottom and the terminal tool never showed it.

That is the characteristic failure shape of the terminal output cap: the command can finish successfully while the visible stdout ends early. The tool has not necessarily crashed. The process has not necessarily hung. I simply asked it to return more text than it will place into the model’s working context.

This matters most with commands whose verdict comes last. Test runners print hundreds of passing cases before the failure summary. Builds put the real error beneath pages of warnings. Package managers finish with the version conflict. docker logs may put the latest exception after a day of routine traffic.

My shorthand for it is the “didn’t see the bottom” problem. If the output looks plausible but has no summary, footer, final prompt, exit explanation, or latest log line, I treat truncation as a possibility before drawing any conclusion.

Why Hermes caps terminal output

The terminal tool limits returned stdout to roughly 50 KB. That is not a shell limit, and it is not the same thing as a command failing. It is a boundary on how much command output gets handed back to the agent in one tool response.

There are two good reasons for it.

First, terminal output consumes model context. A dependency tree, minified bundle, recursive directory listing, or verbose test run can occupy tens of thousands of tokens without adding much useful evidence. Once that text enters the conversation, it competes with the instructions, source code, earlier decisions, and the agent’s final answer.

Second, the cap encourages focused output. Most troubleshooting questions do not need every line. They need the first error, the final summary, matching warnings, an exit code, or a small record from structured data. Sending less text usually makes the answer better, not merely cheaper.

The cap is therefore a guardrail, but it has a sharp edge: terminal output is often ordered chronologically, while the conclusion is printed last. A large response can look complete enough to trust even when the decisive tail is absent.

Fix 1: filter at the pipe

The quickest fix is to make the shell reduce the output before Hermes receives it. I choose the filter based on where I expect the useful evidence.

Use head when startup lines, headers, or the first failure matter:

some-command 2>&1 | head -n 80

Use tail when the command prints its verdict at the end:

npm run build 2>&1 | tail -n 100

Use grep when I know the signal words:

pytest -vv 2>&1 | grep -Ei 'failed|error|warning|summary'

The 2>&1 is worth noticing. Many programs write errors to stderr rather than stdout. Merging the two streams lets the filter see both. Without it, I can neatly filter the routine output while the actual error travels separately.

I also include context around matches when a single line is too thin:

some-command 2>&1 | grep -Ein -B 3 -A 8 'error|exception|failed'

There is one trap with head: it can close the pipe as soon as it has enough lines. Some upstream programs notice that closed pipe and exit early. That is fine for inspecting a harmless listing, but not for a command that must complete a migration, write an artefact, or finish a deployment. For those jobs, capture the complete output to a file first.

Fix 2: write everything to a file, then read selectively

When I need the command to run to completion and preserve all its evidence, I redirect the stream:

some-command > /tmp/some-command.log 2>&1

Then I inspect manageable slices:

tail -n 120 /tmp/some-command.log
grep -Ein -B 3 -A 8 'error|exception|failed' /tmp/some-command.log
wc -l -c /tmp/some-command.log

This is the safest pattern for long builds, test suites, imports, and deployments. The process gets an ordinary writable destination rather than a pipe that may close early. The full record remains available, and each follow-up read can answer one narrow question.

For files inside the Hermes workspace, I prefer the dedicated file-reading and search tools after capture. They support bounded reads, line numbers, and pagination, so I can inspect the beginning, the end, and exact matches without feeding the whole log back into context.

If I also want to watch the command live, tee preserves a copy:

some-command 2>&1 | tee /tmp/some-command.log

But tee still sends the full stream to terminal output, so the visible response may hit the cap. The file is the reliable copy; the live text is only a convenience.

Fix 3: ask the command for JSON

Many modern CLIs have a --json option. When they do, I use it. Structured output is easier to reduce accurately than decorative human output containing progress bars, tables, colour codes, headings, and repeated labels.

A common pattern is:

some-command --json | jq '{status, errors, summary}'

Or, for a list:

some-command --json | jq '.items[] | select(.status == "failed")'

The exact JSON fields vary by command, so I check that command’s help rather than guessing:

some-command --help | grep -i json

--json is not magic on its own. A giant JSON document can still exceed 50 KB. The advantage is that tools such as jq can select the exact fields or records I need without brittle text matching. It also avoids mistakes caused by wrapped columns or ANSI colour sequences.

When a CLI offers JSON Lines, sometimes called JSONL or NDJSON, filtering can be even cheaper because each line is a complete record. I can select failures as they stream instead of loading one enormous array.

How I confirm that I missed the bottom

I do not rerun the same noisy command and hope for a different result. I ask a smaller, explicit question.

For a build or test run, I rerun it with a tail and print the exit status:

npm run build > /tmp/build.log 2>&1
status=$?
tail -n 100 /tmp/build.log
printf 'exit_status=%s\n' "$status"

That separates two facts which are often blurred together: what the command printed, and whether it succeeded. A log can contain the word “error” in an expected test and still exit 0. It can also end without a readable exception and exit non-zero.

For an existing captured log, I check its byte count. A file much larger than the visible response is strong evidence that I only saw a slice. I then read the tail, search for the first failure, and inspect a little context around that line.

I also avoid saying “the build passed” merely because no error appeared in the visible block. Absence of an error in truncated output is not evidence of success. A completion marker or exit code is.

A practical decision rule

My order of preference is simple:

  1. Known signal: pipe through grep, head, or tail.
  2. Must complete or preserve evidence: redirect to a file, then inspect slices.
  3. CLI supports structured output: use --json, usually followed by jq.
  4. Still uncertain: capture the exit status separately.

The point is not to squeeze exactly 49 KB through the tool. It is to return the few lines that prove the claim I need to make.

The short version: when terminal output looks complete but the conclusion is missing, assume you may not have seen the bottom. Filter early, preserve the full log when the command matters, and verify success with the exit status rather than visual confidence.

#terminal#Hermes#troubleshooting#stdout#50

Submit a take

Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.

Your email address will not be published. Required fields are marked.