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:
- Python can poll capture output for a marker. Its test-support module also
provides
libtmux.test.retry_until(condition, ...)for arbitrary conditions. Waiting and retrying covers polling helpers across ports. - Swift ships a real primitive for exactly this:
server.waitForOutput(...)returns anOutputWaitonce a pattern shows up in the pane, rather than leaving you to write the loop. - Go and .NET expose tmux’s
wait-forsignal channel throughserver.WaitFor(ctx, WaitForRequest{...})andTmuxWaitChannel. Use a named signal when you control the command and can make it announce completion.
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.