How Worktrunk's Output Rendering Streams Data Progressively

Worktrunk uses a Cmd builder abstraction in src/shell_exec.rs to progressively render command output through two distinct streaming modes—immediate stream() and threshold-based delayed_stream()—ensuring responsive terminal feedback while maintaining complete command traceability.

The max-sixty/worktrunk repository implements a sophisticated output rendering system that streams command data progressively rather than waiting for process completion. This architecture, centered in the shell execution layer, balances real-time user feedback with intelligent noise suppression for fast-running commands. By leveraging the Cmd struct and its associated tracing infrastructure, Worktrunk ensures that every byte of output is either displayed immediately or buffered strategically based on execution duration.

The Cmd Abstraction: Core of Worktrunk Output Rendering

At the heart of Worktrunk's progressive rendering lies the Cmd struct defined in src/shell_exec.rs. This builder-pattern abstraction wraps shell command execution and provides two distinct pathways for output handling: immediate streaming and delayed streaming. The implementation spans lines 2109–2134 of the source file, where the Cmd type orchestrates child process spawning, signal forwarding, and I/O redirection.

The Cmd builder allows configuration of stdout/stderr handles alongside working directories and environment variables. When executed, the builder resolves into one of the streaming modes depending on the latency requirements of the specific operation.

Immediate Streaming with stream()

stream() attaches the child process's stdout and stderr directly to the parent's terminal (or a custom Stdio handle). Because the child writes directly to the terminal file descriptors, output appears line-by-line in real time without intermediate buffering.

This mode is essential for interactive commands such as pagers or editors where user interaction depends on immediate visual feedback. The implementation forwards signals like Ctrl-C to the child process, ensuring that terminal control behaves intuitively during long-running interactive sessions.

Delayed Streaming for Noise Reduction

How delayed_stream() Works

delayed_stream() implements a threshold-based buffering strategy to prevent "flash-of-output" for commands that complete quickly. The method accepts a delay parameter in milliseconds and an optional progress message. Worktrunk buffers the child process output internally, and only flushes the buffered content to the terminal if the command execution exceeds the specified threshold.

If the command finishes before the delay elapses, the buffered output is discarded silently, keeping the terminal clean. If the threshold is crossed, Worktrunk streams the buffered data progressively while displaying the configured progress message. This approach ensures that users see real-time feedback for slow operations while avoiding visual noise from fast commands.

The buffering logic and threshold checking reside within the Cmd struct implementation in src/shell_exec.rs.

Progress Messages and Tracing

When delayed_stream() activates, Worktrunk optionally displays a progress hint (e.g., "working…") to indicate ongoing activity. The helper method log_delayed_stream_start (lines 1353–1356 in src/shell_exec.rs) records this start event in the command trace, ensuring that the delayed streaming initiation is logged even before output appears.

Command Tracing and Observability

Every Cmd execution generates a CommandTrace structure that captures the command string, start time, exit status, and any captured I/O. This trace is emitted by the trace::emit module (lines 44–46 in src/trace/emit.rs), integrating streamed commands into the [wt-trace] timeline.

When a streamed command terminates, Cmd resolves the trace via CommandTrace::complete or CommandTrace::fail, depending on the exit status. This guarantees that every command appears in the audit log regardless of whether its output was displayed immediately, delayed, or suppressed entirely.

Integration with the Output Layer

Higher-level modules in src/output/* invoke the Cmd streaming methods based on context. Interactive tasks such as invoking a pager call Cmd::stream(), while latency-sensitive operations like git worktree add invoke Cmd::delayed_stream() with appropriate millisecond thresholds. The output layer forwards the Cmd result directly, delegating logging responsibilities to the tracing subsystem.

Testing Progressive Rendering

The integration test suite in tests/integration_tests/switch.rs validates both streaming behaviors explicitly. Lines 66–84 verify that a zero-delay threshold forces immediate streaming even when using the delayed API:

Cmd::delayed_stream(0, …)

Conversely, lines 2903–2927 confirm that non-zero thresholds (e.g., 50ms) correctly postpone streaming until the delay elapses, ensuring the buffering logic functions as designed under real async execution conditions.

Practical Implementation Examples

The following examples demonstrate the two streaming modes in production contexts:

// Example 1 – Immediate streaming for an interactive command (e.g. a pager)
use std::process::Stdio;
use worktrunk::shell_exec::Cmd;

fn show_help(pager_path: std::path::PathBuf) -> anyhow::Result<()> {
    Cmd::new("less")
        .args([pager_path.to_string_lossy().as_ref()])
        .stdout(Stdio::inherit())
        .stdin(Stdio::null())
        .forward_signals()           // forward Ctrl‑C to the pager
        .stream()?;                  // output appears line‑by‑line
    Ok(())
}
// Example 2 – Delayed streaming for a potentially‑slow git operation
use worktrunk::shell_exec::Cmd;

fn add_worktree(repo_path: &std::path::Path, wt_path: &std::path::Path) -> anyhow::Result<()> {
    // Start streaming only after 250 ms; show a progress hint meanwhile.
    Cmd::new("git")
        .args(["worktree", "add", wt_path.to_string_lossy().as_ref(), "feature"])
        .current_dir(repo_path)
        .delayed_stream(250, Some("Creating worktree…".to_string()))?;
    Ok(())
}

Summary

  • Worktrunk implements progressive output rendering through the Cmd struct in src/shell_exec.rs, offering both immediate and delayed streaming modes.
  • stream() provides real-time, line-by-line output by attaching child processes directly to the parent terminal.
  • delayed_stream() buffers output with a configurable millisecond threshold, suppressing fast commands while streaming slow ones with optional progress messages.
  • The CommandTrace system ensures complete observability via src/trace/emit.rs, logging every command regardless of streaming mode.
  • Integration tests in tests/integration_tests/switch.rs verify both zero-delay immediate streaming and threshold-based delayed behavior.

Frequently Asked Questions

What is the difference between stream() and delayed_stream() in Worktrunk?

stream() attaches the child process directly to the terminal, displaying output immediately as it is produced. delayed_stream() buffers output and only displays it if the command duration exceeds a specified millisecond threshold, keeping the terminal clean for fast commands while providing feedback for slow operations.

How does Worktrunk prevent flash-of-output for fast commands?

Worktrunk uses delayed_stream() with a configurable delay parameter (e.g., 250ms) to buffer command output internally. If the process exits before the threshold elapses, the buffer is discarded and no output is shown. If the threshold is exceeded, the buffered content streams to the terminal progressively.

How does command tracing work when output is streamed in real time?

Every execution creates a CommandTrace instance that records the command string, start time, and exit status. Whether using stream() or delayed_stream(), the Cmd struct resolves the trace via CommandTrace::complete or fail upon termination, ensuring the [wt-trace] timeline captures all execution metadata even when output renders progressively.

Where is the progressive rendering logic tested?

The progressive rendering behavior is validated in tests/integration_tests/switch.rs, which includes tests for zero-delay immediate streaming (lines 66–84) and non-zero delay thresholds (lines 2903–2927) to verify that the buffering and flushing mechanisms operate correctly under various timing conditions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →