Split one stdin stream into two independently-filtered panes in a terminal TUI.
log stream | multiout "grep --color=always ERROR"
cargo install --path .Pipe any command into multiout. The upper pane shows raw output; the lower pane shows filtered output.
# Upper: raw log stream. Lower: only errors.
log stream | multiout "grep --color=always ERROR"
# Tail a log file, highlight errors in the lower pane.
tail -f /var/log/app.log | multiout "grep --color=always -i error"
# Both panes filtered: upper shows JSON prettified, lower shows errors.
kubectl logs -f my-pod | multiout -u "jq ." -l "grep ERROR"
# Without arguments: full-screen raw output.
cat large_file.txt | multioutFilter arguments are passed to sh -c, so pipe chains and shell syntax work:
access.log | multiout "grep 500 | awk '{print \$1,\$7}' | sort -u"| Key | Action |
|---|---|
q / Ctrl+C / Esc |
Quit |
Tab |
Switch active pane |
↑ / ↓ |
Scroll active pane 1 line |
PgUp / PgDn |
Scroll active pane 1 page |
End |
Jump to bottom (follow latest) |
| Mouse scroll | Scroll pane under cursor 3 lines |
The active pane label is highlighted in cyan. Scroll position is pinned when you scroll up — new data won't shift the view. Press End to resume following the latest output.
grep's --color=always and log stream coloured output are preserved. Supported codes:
- 16 standard and bright foreground colours (
30-37,90-97) - 256-colour palette (
38;5;N) - Truecolor (
38;2;R;G;B) - Bold
stdin ──→ StdinReader ──→ broadcast ──┬──→ passthrough ────→ UpperRingBuffer ──┐
│ │
└──→ sh -c "filter" ──→ LowerRingBuffer ──┤
│
TUI (ratatui) ←──────────────────────────────────────┘
A background thread reads stdin lines and broadcasts them. Each pane has a processor that either passes lines through directly or pipes them through a shell filter subprocess. Both processors write to independent ring buffers (10,000 lines each). The main thread runs a ratatui render loop with independent scrolling per pane.