# Capturing output

Source: https://libtmux.org/en/ruby/latest/guides/capturing-output/

> Read a pane's screen or scrollback and wait for output or a completion signal.

Capture a pane to read its visible screen or scrollback. After [Sending
keys](../sending-keys/), wait for the expected output or a completion signal
before reading the result.

## Visible pane vs. scrollback

`tmux capture-pane` distinguishes the currently visible screen from the
scrollback history above it, and every port exposes that split rather than
flattening it:

Java's `pane.capture()` and .NET's `pane.CaptureAsync()` return the visible
pane as a list of lines; neither's own README shows a scrollback option as
of this page, so check the port's reference before assuming one exists.
Sources: TypeScript's is `examples/capture/capture.ts`, run by `bun test
examples/capture`. Go's is `examples/quickstart/main.go`. Rust's is
`crates/libtmux/README.md`'s capability table, doctested via `#![doc =
include_str!("../README.md")]`. C++'s is `README.md`'s "Read a pane"
section, quoted verbatim from `examples/05-readme.cpp`'s `capture` region
and checked by `tools/docs/check_readme.py`. Swift's is `README.md`,
"Change what is there."

<a id="dont-poll-wait-for-the-text-instead"></a>

## Wait for the expected text

An immediate capture can race the shell, as [Sending
keys](../sending-keys/#the-race-you-cant-see-from-the-call-site) explains. Wait
for the expected text with a timeout so your program stops promptly when the
output arrives and reports a failure if it never does:

Python's pytest plugin supplies isolated test servers; see [Testing with
libtmux](../testing-with-libtmux/). For Python and C++ signal-based waiting, use
the `wait-for` APIs below. This page does not include a wait-for-text helper for
those ports.

Sources: Go's is `tmux/tmuxtest/screen.go`, quoted in `README.md`'s "Testing
your own code" section. Rust's is `crates/libtmux/README.md`, doctested.
TypeScript's is `examples/agent/agent.ts`, run by the integration suite and
quoted in `packages/libtmux/README.md` (`<!-- runs: examples/agent/agent.ts
-->`). Java's is `examples/.../WatchPaneOutput.java`. .NET's is `README.md`,
one of the `csharp run` blocks `ReadmeExampleTests` runs. Swift's is
`Examples/Sources/ExampleCode/Waiting.swift`, matched against
`<doc:Waiting>` and the README by `Scripts/check_examples.py`; the same
file's `server.capture(pane, since: mark)`, called in a loop with the cursor
it returns, is the "watch as it prints" shape for output too large or too
open-ended to wait on a single pattern.

## When the pane can announce itself: `wait-for`, not scraping

If you control the command, have it signal completion with `tmux wait-for -S
done`. Wait on the same channel to avoid matching screen text:

The Python example is a doctest in `src/libtmux/server.py`. C++'s
`Server::wait_for(channel, timeout)`, declared in `include/libtmux/server.hpp`,
also detects a server that dies during the wait. Swift's `server.wait(for:)`
example waits for a build to signal completion:

Source: `Examples/Sources/ExampleCode/Waiting.swift`. Rust's
`crates/libtmux/README.md` documents the same pattern under "tmux keeps a
signal nobody is waiting on, so the job finishing first does not lose the
race, and nothing polls," runnable as `examples/orchestrate.rs`.

## Where to go next

- [Filtering and querying, in practice](../querying-and-filtering/): once
  you're reading more than one pane, finding the right one to capture.
- [Testing with libtmux](../testing-with-libtmux/): the isolated-server
  fixtures that make waiting on real tmux practical inside a test suite.
- [Capture pane output](/examples/capture-pane-output/): the full
  sourced code for the patterns above.
