Core Library0.xAPI Reference

Choose documentation 3

latest

Current version

latest
English

Early release libtmux is released, and its APIs may still change between releases. This site's structure and URLs may change too.

method libtmux-rs latest

Pane.send_keys

Send keys to the pane as if typed.

Source and package
Qualified name
libtmux::pane::Pane::send_keys
Module
pane
Declared in
Pane
Package
libtmux
Source
crates/libtmux/src/pane.rs
Other languages
Perlmethod Erlang PowerShell Julia Elixir Haskell Common LispPythonRubyLuaTypeScriptGo Java C#C++SwiftKotlinScalaOCaml F# Clojure
pub async fn send_keys( &self, keys: impl Into<OsString> ) -> Result<(), Error>

Description#

The text is sent literally with tmux's -l flag, so key names such as C-c are typed rather than interpreted. Use Pane::send_key_names() for tmux's key vocabulary.

The text is marked sensitive, so it never reaches Debug, an error, or a tracing span: a pane is where passwords get typed.

Errors

Returns an error when tmux refuses the command.

Examples#

Send literal text and named keys. Wait for a shell prompt, send literal text without Enter, then submit a named Enter key. Use Rust 1.85 or newer with Cargo, and tmux 3.3a or newer, on a Unix system. In an empty directory, create a project and add the published crates:

Terminal window
$ cargo init --name libtmux-api-example &&
cargo add libtmux@0.1.2 tempfile@3.20 &&
cargo add tokio@1.40 --features macros,rt,time

Replace src/main.rs with this complete program. It owns a private tmux socket, applies a ten-second task deadline, and reports both task and cleanup errors. Server::kill() stops its daemon; Server::shutdown() closes its client executor. Successful cleanup removes the temporary directory even when the task fails. View source

//! Send literal text and a named Enter key to a ready shell.
use std::error::Error;
use std::time::Duration;
use libtmux::{NewSessionOptions, PaneWait, Server};
type ExampleError = Box<dyn Error>;
async fn demonstrate(server: &Server) -> Result<(), ExampleError> {
let session = server
.new_session(
NewSessionOptions::new("input").command("env ENV=/dev/null PS1='api-ready> ' sh"),
)
.await?;
let panes = session.panes().await?;
let pane = panes.first().ok_or("session has no pane")?;
if pane
.wait_for_text("api-ready>", Duration::from_secs(5))
.await?
!= PaneWait::Arrived
{
return Err("shell prompt did not become ready".into());
}
pane.send_keys("printf '\\nC-c is text\\n'").await?;
pane.send_key_names(["Enter"]).await?;
loop {
let lines = pane.capture().await?;
if lines.iter().any(|line| line.as_bytes() == b"C-c is text") {
break;
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
println!("input: C-c is text");
Ok(())
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), ExampleError> {
let root = std::path::Path::new("/tmp/libtmux-rs-dev");
std::fs::create_dir_all(root)?;
let directory = tempfile::Builder::new()
.prefix("api-input-")
.tempdir_in(root)?;
std::fs::write(
directory.path().join("owner"),
std::process::id().to_string(),
)?;
let server = Server::builder()
.socket_path(directory.path().join("tmux.sock"))
.config_file("/dev/null")
.default_timeout(Duration::from_secs(5))
.build()?;
let outcome = tokio::time::timeout(Duration::from_secs(10), demonstrate(&server)).await;
// Stop the owned daemon before closing the client executor.
let killed = server.kill().await;
let closed = server.shutdown().await;
let cleanup_failed = killed.is_err() || closed.is_err();
let mut failures = Vec::new();
match outcome {
Ok(Ok(())) => {}
Ok(Err(error)) => failures.push(format!("example failed: {error}")),
Err(error) => failures.push(format!("example deadline: {error}")),
}
if let Err(error) = killed {
failures.push(format!("daemon cleanup: {error}"));
}
if let Err(error) = closed {
failures.push(format!("executor cleanup: {error}"));
}
if cleanup_failed {
let retained = directory.keep();
failures.push(format!("inspect retained directory {}", retained.display()));
} else if let Err(error) = directory.close() {
failures.push(format!("directory cleanup: {error}"));
}
if failures.is_empty() {
Ok(())
} else {
Err(failures.join("; ").into())
}
}

Run the consumer. Success exits with status 0; setup, operation, deadline or cleanup failures exit unsuccessfully and print diagnostics to stderr:

Terminal window
$ cargo run --quiet

Expected output:

input: C-c is text
Parameters

tmux command#

The tmux commands behind send_keys.

tmux C API#

The C declarations in tmux that implement these commands.

Guides#

Pages that discuss send_keys.

Guides

In other ports#

Send keystrokes to a pane

Equivalents of Send keystrokes to a pane in other languages
Language Equivalent
Python libtmux.Pane.send_keys
Ruby LibTmux::Pane#send_keys
Lua libtmux.Pane:send_keys
Erlang tmux_pane:send_keys/2
Haskell No public Haskell equivalent is implemented; the current modules expose scalar values and version parsing.
Common Lisp libtmux:send-keys
TypeScript pane.Pane.sendKeys
Go tmux.Pane.SendKeys
Java no direct equivalent; Pane.paste writes a buffer instead
Clojure libtmux.core/send-keys!
Kotlin io.github.libtmux.kotlin.Pane.sendKeys
Scala io.github.libtmux.scaladsl.Pane.sendKeys
C# LibTmux.Pane.SendKeysAsync
C++ libtmux::Pane::send_text
Swift Server.sendKeys(_:to:literally:)
OCaml Libtmux_unix.Client.send_keys
Perl LibTmux::Server::send_keys Explicit Server operation. Captured entities remain local observations; use a new snapshot to observe changes.

No equivalent is recorded in PowerShell, Julia, Elixir or F#.

Esc

Type to search.

Reference previewOpen reference