How to Save Agent stdout to a Log File
Long agent runs are hard to reproduce or audit from terminal scrollback alone. Chat UI summaries get truncated when the session changes, and re-asking “what did it say?” is expensive. An agent log file via shell redirection and tee lets the next session open the same path and trace the failure.
This post covers three axes only: where to redirect? · how to keep failures only? · how do you read it next session? No pricing, plans, token limits, affiliates, or invented reviews.
Grounded in POSIX/Bash redirections (>, 2>, 2>&1, &>) and GNU tee (file + stdout). We do not discuss paid product log quotas or prices.
Where should you redirect?
One-line answer: Write stdout/stderr under a fixed directory + timestamped filename. Use tee if you still want the terminal; use > / 2> for file-only. Prefer a path the next session can find—e.g. logs/ beside the worktree—not a forgotten /tmp scratch name.
Recommended targets:
| Target | Example | Use |
|---|---|---|
| Combined log | logs/agent-20260925-2100.log | stdout+stderr in one file (debug, ticket attach) |
| stderr only | logs/agent-20260925-2100.err | Skim failures/warnings fast |
| Session meta | logs/agent-20260925-2100.cmd | One-line cmd, cwd, timestamp |
Screen + file:
mkdir -p logs
LOG="logs/agent-$(date +%Y%m%d-%H%M).log"
# stdout and stderr to both file and terminal
your-agent-cli run --task brief.md 2>&1 | tee "$LOG"
File only (quiet CI / headless):
your-agent-cli run --task brief.md >"$LOG" 2>&1
echo "exit=$?" >>"$LOG"
Split streams:
your-agent-cli run --task brief.md \
>"logs/agent-out.log" \
2>"logs/agent-err.log"
In Bash, &>file sends both streams to one file. 2>&1 merges stderr into the current stdout—order matters before a pipe (2>&1 | tee).
Avoid:
- Writing only
/tmp/agent.logwith no path in the ticket (lost on the next machine/session). - Always overwriting the same file with
>and deleting the previous failure (no comparison). - Mixing unlimited binary/tool dumps into the log (extract with
head/rgwhen needed).
How do you keep failures only?
One-line answer: Always write a temp log, then keep it only when exit code ≠ 0. For stderr-only archives use 2>, or cut error/fail lines from a combined log with rg into a small failure summary.
Pattern A — keep on failure:
mkdir -p logs/fail
TMP="$(mktemp -t agent.XXXXXX.log)"
LOG="logs/fail/agent-$(date +%Y%m%d-%H%M).log"
set +e
your-agent-cli run --task brief.md >"$TMP" 2>&1
rc=$?
set -e
if [ "$rc" -ne 0 ]; then
{
echo "# cmd: your-agent-cli run --task brief.md"
echo "# cwd: $(pwd)"
echo "# exit: $rc"
echo "# when: $(date -Iseconds)"
cat "$TMP"
} >"$LOG"
echo "saved failure log: $LOG" >&2
else
rm -f "$TMP"
fi
exit "$rc"
Pattern B — always keep stderr; drop stdout on success:
ERR="logs/agent-$(date +%Y%m%d-%H%M).err"
your-agent-cli run --task brief.md 2>"$ERR"
# stdout stays on the terminal/pipe; start analysis from .err
Pattern C — summarize failure signals from a combined log:
rg -n -i 'error|fail|traceback|denied|EPERM|ENOENT' "$LOG" \
>"logs/$(basename "$LOG" .log).fail.txt" || true
Practical rules:
- Pin exit code in the log header — “something felt off” is not reproducible next session.
- Keep success logs short or rotate — optional
logs/ok/with a small N; keeplogs/fail/longer. - Watch secrets — tokens on stdout make the log an exfil surface. Mask with
rgbefore attaching to tickets, or enable quiet/redact options when the tool documents them.
To watch the screen with tee and still keep failures only, use pattern A: temp file → conditional move. tee alone does not filter by exit code (enable pipefail if you need pipe failures to surface).
set -o pipefail
your-agent-cli run --task brief.md 2>&1 | tee "$TMP"
rc=$?
# then decide keep/delete from rc as in pattern A
How do you read it next session?
One-line answer: Agree on path rules + a header (cmd, cwd, exit, time). Next session starts with ls logs/fail → less / rg. Hand the agent the log path, not the whole chat transcript, and scope the retry to that evidence.
Read order:
- List —
ls -lt logs/fail | headfor recent failures. - Header — first 5–10 lines for cmd, exit, time.
- Signals —
rg -n -i 'error|fail|traceback' LOG. - Tail —
tail -n 80 LOG(agents often leave summary/stack at the end). - Retry prompt — paste only the path into the template below.
## Prior run (read-only evidence)
Log: logs/fail/agent-20260925-2100.log
Exit: 1 (see header)
## Task
Fix the failure shown in that log. Do not re-run unrelated steps.
## Constraints
- Quote path:line from the log when explaining the root cause.
- Do not paste secrets from the log into new files.
- After fix, re-run the same CLI and save a new log under logs/.
## Done when
- New run exit 0, or a new fail log with a different root cause noted in the header.
Cross-session checklist:
[ ] Is logs/ (or logs/fail/) documented in one line in README / AGENTS.md?
[ ] Do filenames include date/time so runs do not overwrite each other?
[ ] Does the header include cmd, cwd, exit, when?
[ ] Does the next agent call get a log path instead of the full chat?
[ ] Is the success/failure retention policy shared with the team?
Tip: Long runs can also be recorded with tmux / script, but this post’s axis is a reproducible text log file. Do not rely on UI-only history.
One-line wrap-up: Write with 2>&1 | tee under fixed logs/ → keep failures in logs/fail/ → next session reads that path as evidence.
FAQ
Q. > or tee?
A. Use 2>&1 | tee FILE when you need the live terminal; use >FILE 2>&1 for headless/CI. Both are enough to leave an agent log file.
Q. Is stderr alone enough?
A. Not if the tool mixes errors into stdout. When unsure, default to a combined log (2>&1) and cut a failure summary with rg.
Q. Logs got huge—what then?
A. Delete/rotate successes; attach header + rg hits + tail to tickets. Store full dumps as artifacts and keep only the link.
Q. Windows / non-Bash?
A. Same idea (split or merge streams, write files). Examples here are Bash/tee. PowerShell uses forms like *>—an OS difference, not a pricing topic.
Sources
- Bash Manual — Redirections —
>,2>,2>&1,&> - tee(1) man page — file + stdout,
-aappend - GNU Coreutils — tee invocation
- Adjacent: subagent-brief, opencode-session-resume, agent-eval-checklist