Core Library0.xHome

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.

Edit this page on GitHub

tmux client library for TypeScript

Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, watch for changes via control mode, capture pane contents.

Install

bun add libtmux

libtmux 0.1.0 is pre-1.0 and can change between minor versions. Pin to a range:

"libtmux": "~0.1.0"

At a glance

Server → Session → Window → Pane. Each level of the tmux hierarchy has its own entry in the TypeScript API, with the tmux object it wraps.

TypeWraps
server.Server A tmux server
session.Session A session, ID $n
window.Window A window in a session, ID @n
pane.Pane A pane in a window, ID %n

What it does

Start with TypeScript

Example details
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { Server } from "libtmux";
const directory = await mkdtemp(join(tmpdir(), "ltx-home-"));
const server = new Server({
socketPath: join(directory, "tmux.sock"),
configFile: "/dev/null",
timeoutMs: 5_000,
});
const signal = AbortSignal.timeout(5_000);
const session = await server.newSession({ name: "work", signal });
const editor = await session.newWindow({
name: "editor",
shellCommand: "sh",
signal,
});
await editor.split({ signal });
const pane = editor.activePane;
if (!pane) throw new Error("The window has no active pane");
await pane.sendKeys("printf '\\nhello\\n'", { signal });
for (;;) {
const lines = await pane.capture({ signal });
if (lines.includes("hello")) {
console.log("hello");
break;
}
await delay(20, undefined, { signal });
}
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { Server } from "libtmux";
const directory = await mkdtemp(join(tmpdir(), "ltx-home-"));
const server = new Server({
socketPath: join(directory, "tmux.sock"),
configFile: "/dev/null",
timeoutMs: 5_000,
});
try {
const signal = AbortSignal.timeout(5_000);
const session = await server.newSession({ name: "work", signal });
const editor = await session.newWindow({
name: "editor",
shellCommand: "sh",
signal,
});
await editor.split({ signal });
const pane = editor.activePane;
if (!pane) throw new Error("The window has no active pane");
await pane.sendKeys("printf '\\nhello\\n'", { signal });
for (;;) {
const lines = await pane.capture({ signal });
if (lines.includes("hello")) {
console.log("hello");
break;
}
await delay(20, undefined, { signal });
}
} catch (error) {
throw new Error("tmux quickstart failed", { cause: error });
}
import { mkdtemp, readdir, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { Server } from "libtmux";
const directory = await mkdtemp(join(tmpdir(), "ltx-home-"));
const server = new Server({
socketPath: join(directory, "tmux.sock"),
configFile: "/dev/null",
timeoutMs: 5_000,
});
try {
const signal = AbortSignal.timeout(5_000);
const session = await server.newSession({ name: "work", signal });
const editor = await session.newWindow({
name: "editor",
shellCommand: "sh",
signal,
});
await editor.split({ signal });
const pane = editor.activePane;
if (!pane) throw new Error("The window has no active pane");
await pane.sendKeys("printf '\\nhello\\n'", { signal });
for (;;) {
const lines = await pane.capture({ signal });
if (lines.includes("hello")) {
console.log("hello");
break;
}
await delay(20, undefined, { signal });
}
} finally {
if ((await readdir(directory)).includes("tmux.sock")) {
await server.kill();
}
await rm(directory, { recursive: true });
}
import { mkdtemp, readdir, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { Server } from "libtmux";
const directory = await mkdtemp(join(tmpdir(), "ltx-home-"));
const server = new Server({
socketPath: join(directory, "tmux.sock"),
configFile: "/dev/null",
timeoutMs: 5_000,
});
const failures: unknown[] = [];
try {
const signal = AbortSignal.timeout(5_000);
const session = await server.newSession({ name: "work", signal });
const editor = await session.newWindow({
name: "editor",
shellCommand: "sh",
signal,
});
await editor.split({ signal });
const pane = editor.activePane;
if (!pane) throw new Error("The window has no active pane");
await pane.sendKeys("printf '\\nhello\\n'", { signal });
for (;;) {
const lines = await pane.capture({ signal });
if (lines.includes("hello")) {
console.log("hello");
break;
}
await delay(20, undefined, { signal });
}
} catch (error) {
failures.push(error);
}
try {
if ((await readdir(directory)).includes("tmux.sock")) {
await server.kill();
}
await rm(directory, { recursive: true });
} catch (error) {
failures.push(new Error(`Cleanup failed: ${directory}`, {
cause: error,
}));
}
if (failures.length) throw new AggregateError(failures);
Run this example

POSIX shell, Git, tmux 3.3a or newer and Bun 1.4.2.

Save the program above as quickstart.ts in a new directory, along with the files below.

Cleanup is omitted; the private tmux server and its temporary files may remain. Select Cleanup to remove them when the program finishes. The program stops its private tmux server and removes any temporary files it created when it finishes. Error handling adds diagnostics; every version checks required results and deadlines.

package.json
{"type":"module","private":true,"dependencies":{"libtmux":"file:./source/packages/libtmux"}}

Setup and run

git init -q source
git -C source fetch -q --depth=1 \
https://github.com/libtmux/libtmux-ts.git \
46cccfef2a546de55ce8b308249b8c76339089a0
git -C source checkout -q --detach FETCH_HEAD
bun install
unset TMUX TMUX_PANE
export ENV=/dev/null BASH_ENV=/dev/null SHELL=/bin/sh
bun run quickstart.ts

Expected output

hello

Library revision: 46cccfef2a54.

Typed API

What you get over the tmux CLI

Esc

Type to search.

Reference previewOpen reference