libtmux
English
Reference MCP Search

Sending keys

Edit this page on GitHub

Every port’s version of send_keys is really tmux send-keys wearing that port’s calling convention, and send-keys has one behavior worth understanding before you rely on it: tmux can read the text you send either as literal characters or as tmux’s own key vocabulary (C-c, Enter, Up). Without a literal flag, q sent to a pane running less is a keypress; the same q sent literally is the character q, which happens to also quit less — so the ambiguity mostly hides until the text you’re sending collides with a real key name.

Literal text, key names, and whether Enter followsLink to section

Each block below sends the same two things a port can send — text and, separately, a named key — and shows whether pressing Enter is the default, an option, or a second call you make yourself. Source citations sit as comments in each block; see Attach and send keys for the same calls in their full, checked context.

# literal=True disables tmux's key-name lookup; left at its default, a
# string that happens to look like a key name is interpreted as one.
pane.send_keys(cmd, literal=True)
# enter defaults to True. Pass enter=False to type without submitting, then
# press Enter yourself — the README's own example, to show the steps apart.
pane.send_keys('echo hey', enter=False)
pane.enter()

Java, .NET, and Swift send exactly the text given, without a separate literal switch to reach for — the type signature doesn’t offer the ambiguous path in the first place. Confirm against your own port’s reference before assuming a call is unambiguous for input that looks like a key name (a literal # in an option value has this same class of gotcha — see the option-naming note in Concepts).

The race you can’t see from the call siteLink to section

tmux accepts a send-keys command the instant it’s issued — before the shell in that pane has necessarily started, and before whatever you sent has necessarily finished. Two ports say this outright, and a third ships the fix without spelling out the reason:

  • Rust: “tmux hands back a pane the moment it forks, before the shell in it has started” — the comment sits directly above a retry_until loop in README.md’s query example.
  • Go: doesn’t say the same sentence, but ships the fix for it — tmuxtest.WaitForShellReady exists specifically for a pane that hasn’t started its shell yet.
  • .NET: “tmux accepts a command before the shell has finished it, so the result is waited for rather than assumed” — from README.md’s “Running something, and reading it back” section.

The fix in every case is the same shape: don’t read a pane immediately after sending to it; wait for the text you expect to actually appear. That waiting mechanism — what each port offers instead of a fixed sleep — is the subject of the next guide.

Where to go nextLink to section

  • Capturing output — reading back what you just sent, and waiting for it correctly instead of guessing a delay.
  • Attach and send keys — the full sourced round trip this guide picks apart piece by piece.
Esc

Type to search.