Skip to content

khali/tmux-core

Repository files navigation

tmux-core

Generic tmux session management for programmatic control.

Installation

npm install tmux-core

Features

  • Session Management - Create, kill, check existence, rename sessions
  • Message Injection - Reliable text injection using load-buffer pattern
  • Pane Capture - Capture terminal output with parsing utilities
  • Special Keys - Send Escape, Ctrl+C, arrow keys, etc.
  • Input Detection - Detect prompts and unsent input buffer
  • Socket Isolation - Run tests in isolated tmux sockets
  • CLI Interface - All operations available from command line

CLI Usage

# List active sessions
tmux-core list
tmux-core list --json

# Check if session exists (exit code 0 if yes, 1 if no)
tmux-core exists my-session

# Inject text into session
tmux-core inject my-session "echo hello"
tmux-core inject my-session "partial" --no-enter

# Capture pane content
tmux-core capture my-session
tmux-core capture my-session --lines 50

# Send special key (Enter, Escape, CtrlC, CtrlD, CtrlZ, Tab, Up, Down, etc.)
tmux-core send-key my-session Enter
tmux-core send-key my-session CtrlC

# Create new session
tmux-core create my-session
tmux-core create my-session /workspace

# Kill session
tmux-core kill my-session

# Use custom socket for isolation
tmux-core --socket test-socket list
tmux-core --socket test-socket create test-session

Quick Start (TypeScript)

import { TmuxSession, injectText, capturePane, sendInterrupt } from "tmux-core";

// Create a session
const session = new TmuxSession("my-session");
await session.create("/workspace");

// Inject a command
await injectText("my-session", 'echo "Hello World"');

// Capture output
const output = await capturePane("my-session");
console.log(output);

// Send interrupt
await sendInterrupt("my-session");

// Clean up
await session.kill();

Socket Isolation

Use custom sockets to isolate test sessions from production:

const session = new TmuxSession("test-session", { socket: "my-test-socket" });
await session.create();

// All operations use the isolated socket
await injectText("test-session", "command", { socket: "my-test-socket" });

API Reference

Session Management

import { TmuxSession } from "tmux-core";

const session = new TmuxSession(name, { socket?: string });

await session.create(workingDirectory?: string);
await session.kill();
await session.exists(): Promise<boolean>;
await session.rename(newName: string);

// Batch operations
const sessions = await TmuxSession.listSessions(socket?: string);
const activeSet = await TmuxSession.getActiveSessions(socket?: string);

Message Injection

import { injectText, injectTextNoEnter } from "tmux-core";

// Inject text and press Enter
await injectText(sessionName, "echo hello", { socket?: string });

// Inject text without pressing Enter (build up input)
await injectTextNoEnter(sessionName, "partial input", { socket?: string });

Pane Capture

import { capturePane, getLastLines, waitForContent } from "tmux-core";

// Capture pane content
const content = await capturePane(sessionName, {
  socket?: string,
  lines?: number,      // Default: 100
});

// Get last N non-empty lines
const lines = await getLastLines(sessionName, 10);

// Wait for content to appear
const content = await waitForContent(
  sessionName,
  (content) => content.includes("ready"),
  5000 // timeout ms
);

Special Keys

import { sendKey, sendKeys, sendInterrupt, sendEscape, Keys } from "tmux-core";

// Send single key
await sendKey(sessionName, Keys.Escape);
await sendKey(sessionName, Keys.CtrlC);

// Send multiple keys
await sendKeys(sessionName, [Keys.Up, Keys.Up, Keys.Enter]);

// Convenience methods
await sendInterrupt(sessionName);     // Ctrl+C
await sendHardInterrupt(sessionName); // Ctrl+C twice
await sendEscape(sessionName);        // Escape

Input Detection

import { hasPrompt, getInputBuffer, getInputState, waitForIdle } from "tmux-core";

// Check if prompt is visible
const hasP = await hasPrompt(sessionName);

// Get text typed but not sent
const buffer = await getInputBuffer(sessionName);

// Full state analysis
const state = await getInputState(sessionName);
// { hasPrompt: true, promptLine: "> ", inputBuffer: "partial", isIdle: false }

// Wait for terminal to be idle
await waitForIdle(sessionName, 5000);

Error Handling

import { TmuxError, SessionNotFoundError, TimeoutError } from "tmux-core";

try {
  await capturePane("nonexistent");
} catch (error) {
  if (error instanceof SessionNotFoundError) {
    console.log("Session does not exist");
  }
}

License

MIT

About

TypeScript SDK for programmatic tmux session control

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors