# How Freebuff Uses tmux Helper Scripts for End-to-End Testing

> Learn how Freebuff leverages tmux helper scripts to automate its end-to-end testing suite. Discover how shell scripts and TypeScript wrappers control the interactive TUI for seamless testing.

- Repository: [Codebuff/freebuff](https://github.com/CodebuffAI/freebuff)
- Tags: how-to-guide
- Published: 2026-09-01

---

**Freebuff drives its end-to-end test suite by launching the CLI inside a detached tmux session, using a combination of shell scripts in `scripts/tmux/` and TypeScript wrappers in [`freebuff/e2e/utils/tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main/freebuff/e2e/utils/tmux-helpers.ts) to programmatically control the interactive TUI.**

Freebuff's testing framework relies on **tmux helper scripts** to create isolated terminal environments for reliable end-to-end validation. These utilities enable the test suite to launch the CLI application, inject commands, capture output, and clean up resources automatically. The architecture separates low-level tmux operations implemented in shell scripts from high-level orchestration logic written in TypeScript.

## The Testing Architecture

The solution is split between Bash scripts handling raw tmux operations and TypeScript utilities providing a typed interface for test authors. The shell scripts reside in `scripts/tmux/` while the programmatic API lives in [`freebuff/e2e/utils/tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main/freebuff/e2e/utils/tmux-helpers.ts). This separation allows the test suite to leverage tmux's terminal multiplexing capabilities while maintaining type safety and clean abstraction boundaries in the test code.

## Starting a tmux Session with tmuxStart

The `tmuxStart` function builds the argument list and delegates to [`scripts/tmux/tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-start.sh) to initialize the testing environment.

### Session Initialization and Metadata

According to the source code in [`/scripts/tmux/tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main//scripts/tmux/tmux-start.sh) (lines 35-40), the script generates a unique session name or accepts a supplied identifier. It records session metadata under `debug/tmux-sessions/<session>/` (lines 38-46), creating a dedicated directory for logs and debugging artifacts. The script finally prints the session name in plain text or JSON format (lines 76-84) for the TypeScript wrapper to consume.

### Command Selection and Launch

The helper automatically determines which binary to execute. As implemented in lines 94-118 of [`tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-start.sh), it prioritizes custom commands, falls back to compiled binaries, or defaults to `bun dev` if no specific target is provided. The session launches with configurable dimensions specified via the `-w` (width) and `-h` (height) parameters (lines 120-126), ensuring consistent terminal sizing across test runs.

## Interacting with the Session

Once running, the test suite communicates with the tmux pane through three primary TypeScript functions defined in [`/freebuff/e2e/utils/tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main//freebuff/e2e/utils/tmux-helpers.ts) (lines 33-71).

### Sending Input and Keystrokes

The `tmuxSend` and `tmuxSendKey` functions invoke [`scripts/tmux/tmux-send.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-send.sh) to feed text or special key events into the active pane. This allows tests to simulate user typing and keyboard shortcuts programmatically without blocking the main test process.

### Capturing Terminal Output

For assertions and debugging, `tmuxCapture` executes [`scripts/tmux/tmux-capture.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-capture.sh) to retrieve the current visible content of the tmux pane. The capture script can also save timestamped GIFs of the terminal state, providing visual regression testing capabilities.

## Session Lifecycle Management

Proper cleanup is critical for CI/CD environments to prevent resource leaks.

### Safe Session Termination

The `tmuxStop` function (lines 73-82 in [`tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-helpers.ts)) executes [`scripts/tmux/tmux-stop.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-stop.sh) to kill the session. The underlying shell script is designed to be idempotent, silently ignoring "session not found" errors when called multiple times.

### High-Level Orchestration with FreebuffSession

The `FreebuffSession` class in [`/freebuff/e2e/utils/freebuff-session.ts`](https://github.com/CodebuffAI/freebuff/blob/main//freebuff/e2e/utils/freebuff-session.ts) encapsulates the complete lifecycle (lines 28-71 and 112-123). It creates temporary project directories, starts the CLI via `tmuxStart`, and exposes methods like `send()`, `sendKey()`, `capture()`, and `waitForReady()`. The class ensures automatic cleanup by calling `tmuxStop` in its teardown methods.

## Practical Usage Example

The following TypeScript pattern demonstrates how the Freebuff test suite utilizes these helpers to validate CLI behavior:

```typescript
import { FreebuffSession } from './utils/freebuff-session'

// 1️⃣ Start a CLI instance in a tmux session
const session = await FreebuffSession.start('/path/to/cli/binary')

// 2️⃣ Wait until the UI is ready (enough non-empty lines)
await session.waitForReady()

// 3️⃣ Send a command (e.g., open a new file)
await session.send('new myfile.txt')

// 4️⃣ Capture the terminal output for verification
const output = await session.capture()
if (!output.includes('myfile.txt')) {
  throw new Error('File creation not reflected in UI')
}

// 5️⃣ Clean up the tmux session and temp directory
await session.stop()

```

## Summary

- **tmuxStart** in [`scripts/tmux/tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-start.sh) creates uniquely named sessions with configurable dimensions and stores metadata in `debug/tmux-sessions/`.
- **Interaction helpers** (`tmuxSend`, `tmuxSendKey`, `tmuxCapture`) in [`freebuff/e2e/utils/tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main/freebuff/e2e/utils/tmux-helpers.ts) wrap shell scripts to simulate user input and capture output.
- **tmuxStop** provides idempotent cleanup, safely ignoring errors if sessions are already terminated.
- **FreebuffSession** offers a high-level TypeScript API managing the full lifecycle from temporary directory creation to automatic resource cleanup.

## Frequently Asked Questions

### What tmux commands does Freebuff use for testing?

Freebuff uses a dedicated suite of shell scripts including [`tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-start.sh) to create detached sessions, [`tmux-send.sh`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-send.sh) to pipe input, [`tmux-capture.sh`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-capture.sh) to read pane contents, and [`tmux-stop.sh`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-stop.sh) for cleanup. These scripts handle the raw tmux CLI invocations while TypeScript wrappers in [`tmux-helpers.ts`](https://github.com/CodebuffAI/freebuff/blob/main/tmux-helpers.ts) provide the test-friendly interface.

### How does Freebuff handle session cleanup after tests?

The `tmuxStop` function executes [`scripts/tmux/tmux-stop.sh`](https://github.com/CodebuffAI/freebuff/blob/main/scripts/tmux/tmux-stop.sh), which is designed to be idempotent and ignores "session not found" errors. The `FreebuffSession` class automatically triggers this cleanup during teardown, ensuring temporary directories and tmux sessions are removed even if tests fail.

### Can I use Freebuff's tmux helpers for other CLI applications?

Yes, the architecture is generic enough to test any terminal-based application. The `FreebuffSession.start()` method accepts a path to any compiled binary or command, and the interaction methods (`send`, `sendKey`, `capture`) work with any process running inside the tmux pane.

### Where does Freebuff store tmux session logs and snapshots?

Session metadata, logs, and timestamped captures are stored under `debug/tmux-sessions/<session-name>/` as defined in [`/scripts/tmux/tmux-start.sh`](https://github.com/CodebuffAI/freebuff/blob/main//scripts/tmux/tmux-start.sh) (lines 38-46). This directory structure provides isolated debugging artifacts for each test session, including optional GIF recordings of terminal activity.