cli/docs/pkg/cli/streaming.md
Snider 7be4e243f2
Some checks failed
Deploy / build (push) Failing after 4s
Security Scan / security (push) Failing after 13s
docs: add human-friendly documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:02:39 +00:00

2.5 KiB

title description
Streaming Output Real-time token-by-token text rendering with optional word-wrap.

Streaming Output

The Stream type renders growing text as tokens arrive, with optional word-wrap. It is designed for displaying LLM output, log tails, or any content that arrives incrementally. Thread-safe for a single producer goroutine.

Basic Usage

stream := cli.NewStream()
go func() {
    for token := range tokens {
        stream.Write(token)
    }
    stream.Done()
}()
stream.Wait()

Done() ensures a trailing newline if the stream did not end with one. Wait() blocks until Done() is called.

Word Wrap

Wrap text at a column boundary:

stream := cli.NewStream(cli.WithWordWrap(80))

When word-wrap is enabled, the stream tracks the current column position and inserts line breaks when the column limit is reached.

Custom Output Writer

By default, streams write to os.Stdout. Redirect to any io.Writer:

var buf strings.Builder
stream := cli.NewStream(cli.WithStreamOutput(&buf))
// ... write tokens ...
stream.Done()
result := stream.Captured() // or buf.String()

Captured() returns the output as a string when using a *strings.Builder or any fmt.Stringer.

Reading from io.Reader

Stream content from an HTTP response body, file, or any io.Reader:

stream := cli.NewStream(cli.WithWordWrap(120))
err := stream.WriteFrom(resp.Body)
stream.Done()

WriteFrom reads in 256-byte chunks until EOF, calling Write for each chunk.

API Reference

Method Description
NewStream(opts...) Create a stream with options
Write(text) Append text (thread-safe)
WriteFrom(r) Stream from io.Reader until EOF
Done() Signal completion (adds trailing newline if needed)
Wait() Block until Done is called
Column() Current column position
Captured() Get output as string (requires *strings.Builder or fmt.Stringer writer)

Options

Option Description
WithWordWrap(cols) Set the word-wrap column width
WithStreamOutput(w) Set the output writer (default: os.Stdout)

Example: LLM Token Streaming

func streamResponse(ctx context.Context, model *Model, prompt string) error {
    stream := cli.NewStream(cli.WithWordWrap(100))

    go func() {
        ch := model.Generate(ctx, prompt)
        for token := range ch {
            stream.Write(token)
        }
        stream.Done()
    }()

    stream.Wait()
    return nil
}