@vfi-pub/tmux
TypeScript library for programmatically controlling tmux. Provides a typed object model (Server → Session → Window → Pane), workspace config management, and a CLI — inspired by the Python libraries libtmux (MIT) and tmuxp (MIT).
Install
bun add @vfi-pub/tmux
npm install @vfi-pub/tmux
Quick Start
import { Server } from "@vfi-pub/tmux"
const server = new Server()
const session = server.newSession({ sessionName: "dev" })
const editor = session.newWindow({ windowName: "editor" })
const terminal = editor.split({ direction: "horizontal" })
terminal.sendKeys("npm run dev", { literal: true })
const output = terminal.capturePane()
console.log(output)
console.log(server.sessions)
console.log(server.windows)
console.log(server.panes)
Object Model
Mirrors the tmux hierarchy:
Server
├── Session ($0, $1, ...)
│ ├── Window (@0: editor, @1: terminal, ...)
│ │ ├── Pane (%0)
│ │ ├── Pane (%1)
│ │ └── Pane (%2)
│ └── Window (@2: logs)
│ └── Pane (%3)
└── Session ($1)
└── ...
Server
const server = new Server({ socketName: "myapp" })
server.isAlive()
server.sessions
server.windows
server.panes
server.newSession({ ... })
server.hasSession("dev")
server.getSession("dev")
server.killSession("dev")
Session
session.name
session.sessionId
session.windows
session.activeWindow
session.panes
session.newWindow({ windowName: "logs" })
session.killWindow("logs")
session.rename("new-name")
session.kill()
Window
window.name
window.windowId
window.index
window.panes
window.activePane
window.split({ direction: "horizontal", percent: 30 })
window.selectLayout("tiled")
window.rename("new-name")
window.kill()
Pane
pane.paneId
pane.width
pane.height
pane.currentPath
pane.currentCommand
pane.isActive
pane.sendKeys("echo hello", { literal: true })
pane.sendKeys("C-c")
pane.capturePane()
pane.capturePane({ start: -100 })
pane.split({ direction: "vertical" })
pane.resize({ direction: "right", adjustment: 10 })
pane.kill()
Workspace Configs
Load tmuxp-compatible YAML/JSON workspace configs:
session_name: myproject
start_directory: ~/code/myproject
windows:
- window_name: editor
panes:
- shell_command: vim .
- window_name: server
layout: even-horizontal
panes:
- shell_command: npm run dev
- shell_command: npm run test:watch
- window_name: terminal
panes:
-
import { loadConfig, buildWorkspace, Server } from "@vfi-pub/tmux"
const config = loadConfig("workspace.yaml")
const server = new Server()
const session = await buildWorkspace(server, config, { killExisting: true })
import { freezeSession } from "@vfi-pub/tmux"
const frozen = freezeSession(session)
Config Features
- Shorthand panes:
"echo hello" expands to { shell_command: ["echo hello"] }
- Directory inheritance:
start_directory trickles from session → window → pane
- Command inheritance:
shell_command_before trickles from session → window
- Path expansion:
~ and $VAR are expanded in start_directory
- Layouts: Any tmux layout string (built-in or custom)
Plugins
Extend workspace builds with lifecycle hooks:
import { TmuxPlugin } from "@vfi-pub/tmux"
class LoggingPlugin extends TmuxPlugin {
name = "logging"
onWindowCreate(window) {
console.log(`Created: ${window.name}`)
}
afterWindowFinished(window) {
console.log(`Configured: ${window.name} (${window.panes.length} panes)`)
}
}
await buildWorkspace(server, config, {
plugins: [new LoggingPlugin()],
})
CLI
vfi-tmux list
vfi-tmux load workspace.yaml
vfi-tmux load workspace.yaml --kill-existing
vfi-tmux freeze mysession
vfi-tmux freeze mysession -o workspace.yaml
vfi-tmux freeze mysession -f json
vfi-tmux convert workspace.yaml
vfi-tmux convert workspace.json
Acknowledgements
This library is a TypeScript port inspired by the design patterns of:
- libtmux — typed Python ORM API for tmux (MIT License)
- tmuxp — tmux workspace manager built on libtmux (MIT License)
Both libraries are created by Tony Narlock and the tmux-python community.
License
MIT