Prerelease This site documents an alpha of libtmux. Its structure, URLs and APIs are subject to change.

Edit this page on GitHub

Send input to a pane and capture its screen to interact with a running program. Attach and send keys provides examples. Sending keys and Capturing output are task guides; this page compares input defaults, capture ranges, and completion handling.

Typing into a paneLink to section

Two questions come up every time you send something to a pane: should tmux press Enter afterward, and should tmux interpret what you sent as key names (Enter, C-c) rather than literal characters? Ports answer both, but disagree on whether that’s one method with flags or two separate methods:

PythonLink to section

Type without Enter: pane.send_keys(text, enter=False)

Type + Enter (default): pane.send_keys(text)

How “literal” is chosen: literal=True flag on the same method

TypeScriptLink to section

Type without Enter: pane.sendKeys(text, { enter: false })

Type + Enter (default): pane.sendKeys(text)

How “literal” is chosen: { literal: true } option

GoLink to section

Type without Enter: pane.SendKeys(ctx, SendKeysRequest{Command: &text, SkipEnter: true})

Type + Enter (default): pane.SendKeys(ctx, SendKeysRequest{Command: &text})

How “literal” is chosen: Literal: true field

RustLink to section

Type without Enter: pane.send_keys(keys): always literal, key names typed as text

Type + Enter (default): pane.send_line(text)

How “literal” is chosen: send_keys sends literal text; send_key_names interprets tmux key names.

JavaLink to section

Type without Enter: pane.send(keys)

Type + Enter (default): pane.sendLine(command)

How “literal” is chosen: Separate text and key-sending methods.

.NETLink to section

Type without Enter: SendKeysAsync(new SendKeysRequest(text, enter: false))

Type + Enter (default): SendTextAsync(text) (defaults enter: true)

How “literal” is chosen: Literal field on SendKeysRequest; SendTextAsync hardcodes it

C++Link to section

Type without Enter: pane->send_text(text)

Type + Enter (default): send_text(text) then send_key("Enter") separately: no combined convenience exists

How “literal” is chosen: send_text is always literal; send_key is always a key name

SwiftLink to section

Type without Enter: server.sendKeys([text], to: pane)

Type + Enter (default): server.run(text, in: pane) (sugar for sendKeys([text, "Enter"], to: pane))

How “literal” is chosen: literally: true option on sendKeys

ExamplesLink to section

Rust’s send_keys always sends literal text. Use send_key_names for tmux key names. Passing "Enter" to send_keys types those characters; it does not press the key.

Text and Enter can be separate commands. Python, TypeScript, Go, and .NET normally send Enter after the text. If the second operation fails, the text may already be in the pane; retrying the entire request can duplicate it. C++‘s separate send_text and send_key("Enter") calls have the same risk.

Rust’s send_line and Java’s sendLine append a literal \r to the text and send it in one send-keys -l command. They avoid a separate Enter dispatch.

Send a command line and press Enter:

Reading a pane backLink to section

Capture methods return lines from the pane’s visible screen by default: pane.capture_pane() in Python, pane.capture() in TypeScript, Rust, Java, and C++, pane.Capture(ctx, ...) in Go, CaptureAsync(...) in .NET, and server.capture(pane) in Swift. Request scrollback explicitly, such as with Python’s start and end or Swift’s includingHistory.

Waiting for something to finishLink to section

A send call completes when input reaches tmux. It does not wait for the shell command to finish. Wait for expected output or a completion signal:

Capture pane output has the checked, per-port code for the polling-with-a-marker version of this; reach for a port’s native wait primitive above it where one exists.

Esc

Type to search.