Repository navigation
docs: FAQ on command output appearing only at exit - #453
Conversation
Programs that block-buffer stdout when it is not a TTY (python, perl, C stdio tools) show their output only at exit under duct. Document why duct cannot fix this transparently and the per-program workarounds. Closes con#218 Co-Authored-By: Claude Code 2.1.285 / Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #453 +/- ##
=======================================
Coverage 92.03% 92.03%
=======================================
Files 15 15
Lines 1344 1344
Branches 182 182
=======================================
Hits 1237 1237
Misses 71 71
Partials 36 36 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
It is a documentation-only FAQ addition whose workarounds, links, formatting, and table escaping are accurate and consistent with existing README conventions.
Review effort: Balanced
Findings: None
What changed in this PR
This PR adds a new README FAQ entry explaining why some commands' stdout appears only at exit under duct — a consequence of duct attaching pipes (not a PTY) to the child, which triggers block-buffering in programs like Python, Perl, and C stdio tools. Rather than implementing the --buffer-flush option proposed in #218, it documents per-program workarounds, keeping duct's "output as-is" behavior intact. It builds directly on the preceding TTY FAQ and closes #218.
Changes:
- Adds FAQ "My command's output only appears when it finishes" after the related TTY FAQ.
- Provides a workaround table (
python -u/PYTHONUNBUFFERED=1,stdbuf -oL, Perl$| = 1;, andunbuffer/scriptas a catch-all). - Documents limitations:
stdbufhas no effect on Python/Perl/static/setuid binaries, and PTY wrappers inject escape codes into the captured logs.
| File | Description |
|---|---|
| README.md | Adds a new FAQ section with a per-program workaround table and caveats for commands that buffer stdout when not attached to a TTY. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Under duct, programs that block-buffer stdout when it isn't a TTY (python, perl, C stdio tools) show their output only at exit. duct can't fix this transparently without a PTY (#26) or mutating the child's env, so instead of the
--buffer-flushoption proposed in #218, this adds a README FAQ with per-program workarounds.Closes #218
python -u/PYTHONUNBUFFERED=1,stdbuf -oL(C stdio, incl. pipelines), perl$| = 1;, andunbuffer/scriptas a catch-allstdbufignored by python/perl/static/setuid; PTY wrappers put escape codes in the captured logsHow the table was verified
Fedora 42, glibc, duct on main. Each child printed 3 lines 1 s apart; measured the spread between the first and last stdout line as seen on duct's terminal side (2.0 s = live, 0.0 s = buffered to exit).
echolooppython -u,PYTHONUNBUFFERED=1,unbuffer,script -qefcstdbuf -oLduct stdbuf -oL cmd,stdbuf -oL duct cmd$|=1,unbuffer,script -qefcstdbuf -oLloop | grepinbash -cgrep --line-buffered,stdbuf -oL bash -c …,unbuffer,script -qefcloop | gawkinbash -cstdbuf -oL bash -c …PTY log cost:
grep --color=autounderunbufferorscriptwrote 20 ESC bytes into_stdout(0 without). Static binaries were not tested (no static libc on the test host); macOSgstdbufnot tested.🤖 Generated with Claude Code