TypeScript-first programmatic tmux for Node.js and Bun.

This package is an early-stage wrapper around the tmux CLI. Commands will be added as the project needs them, rather than trying to mirror all of tmux up front.
npm install tmux.ts
Requires a tmux binary of version 3.4 or newer — found on PATH by default, or
point at any binary with new TmuxClient({ executable: "/path/to/tmux" }). Tested
against tmux 3.4 through 3.7.
The package ships ESM-only with three entry points:
tmux.ts — standalone Promise-based API for Node-compatible runtimes. No Effect knowledge required.tmux.ts/bun — standalone Promise-based API backed by Bun platform services.tmux.ts/effect — Effect-native API (TmuxClient service + base layer + tagged errors) for Effect users.All entry points expose the same tagged error classes (TmuxExecutableNotFound, TmuxProcessError, TmuxServerNotRunning, TmuxTargetNotFound, TmuxCommandError, TmuxParseError, TmuxCommandOptionsError, TmuxClientConfigError). Importing any entry point spawns nothing; tmux only runs when a command is called.
import { TmuxClient, TmuxServerNotRunning } from "tmux.ts";
const tmux = new TmuxClient();
// Resolves with decoded sessions; rejects with TmuxServerNotRunning if no server.
const sessions = await tmux.listSessions();
try {
const windows = await tmux.listWindows();
console.log(windows);
} catch (error) {
// Expected tmux/config failures reject with tagged errors.
if (error instanceof TmuxServerNotRunning) {
console.error("no tmux server running");
}
}
import { NodeServices } from "@effect/platform-node";
import { Effect, Layer } from "effect";
import { TmuxClient } from "tmux.ts/effect";
const program = Effect.gen(function* () {
const tmux = yield* TmuxClient;
return yield* tmux.listSessions();
}).pipe(
Effect.provide(TmuxClient.layer().pipe(Layer.provide(NodeServices.layer))),
);
Effect.runPromise(program).then(console.log);
TmuxClient.layer() requires ChildProcessSpawner; provide NodeServices.layer for Node/Deno, BunServices.layer for Bun, or a fake spawner in tests. Pass { executable, socketName, socketPath } to target a custom tmux binary/socket.
pnpm install
pnpm test
pnpm check
This project uses Effect v4 as a language. The pieces are already installed; no extra setup is needed:
effect — core APIs (Context, Effect, Layer, Schema) and effect/unstable/process for child processes.@effect/platform-node / @effect/platform-bun — platform layers that provide ChildProcessSpawner for Promise entry points and Effect users.@effect/vitest — it.effect test runner.@effect/language-service — Effect-specific diagnostics (wired in tsconfig.json).Service pattern used here (see src/internal/Client.ts): a Context.Service with a dependency-requiring layer(config?) (requires ChildProcessSpawner, so tests and non-Node platforms can provide their own services). Errors stay in the typed channel as a Schema.TaggedError; nothing runs at import time.
Validation commands:
pnpm typecheck # tsc --noEmit (src only)
pnpm diagnostics # Effect language-service diagnostics
pnpm test # vitest
pnpm check # Biome lint + format
46 tmux commands are wrapped, each with typed options and results — see the API docs for per-command details:
breakPane capturePane clearHistory deleteBuffer displayMessage
hasSession joinPane killPane killServer killSession killWindow
lastPane lastWindow linkWindow listPanes listSessions listWindows
loadBuffer movePane moveWindow newSession newWindow nextLayout
nextWindow pasteBuffer pipePane previousLayout previousWindow
renameSession renameWindow resizePane resizeWindow respawnPane
respawnWindow rotateWindow saveBuffer selectLayout selectPane
selectWindow sendKeys setBuffer showBuffer splitWindow swapPane
swapWindow unlinkWindow
More are added incrementally.
ISC