---
name: working-with-tmux
description: Instructions for using tmux to spawn multiple processes, inspect them, and capture their output. Useful for running servers or long-running tasks in the background.
metadata:
  source: https://github.com/ampcode/amp-contrib
---

This skill lets you manage multiple concurrent processes (like servers, watchers, or long builds) using `tmux` directly from the `Bash` tool.

You can spawn new windows or panes to handle these tasks without blocking your main communication channel.

## 1. Verify Environment & Check Status

First, verify you are running inside tmux:

```bash
echo $TMUX
```

If this returns empty, you are not running inside tmux. Use `echo "agent-$(openssl rand -hex 3)"` to generate a unique session ID, then create a new session with a window named after what you're working on. You may skip step 2.1, creating the new window within an existing session.

Once verified, check your current windows:

```bash
tmux list-windows
```

## 2. Spawn a Background Process

To run a command (e.g., a dev server) in a way that persists and can be inspected:

1.  **Create a new detached window** with a specific name. This keeps it isolated and easy to reference.

    ```bash
    tmux new-window -n "server-log" -d
    ```

    _(Replace "server-log" with a relevant name for your task)_

2.  **Send the command** to that window.
    ```bash
    tmux send-keys -t "server-log" "npm start" C-m
    ```
    _(`C-m` simulates the Enter key)_

## 3. Inspect Output (Read Logs)

You can read the output of that pane at any time without switching your context.

Get the current visible screen:

```bash
tmux capture-pane -p -t "server-log"
```

Get the entire history (scrollback, can produce _excessive_ tokens):

```bash
tmux capture-pane -p -S - -t "server-log"
```

Prefer to pipe the full scrollback buffer through grep/sed/tac/etc. to view just the content between your last command and the next prompt (exclusive).

### Filtering between prompts

When running commands on a remote shell, use `sed` to extract output between the shell prompt boundaries:

```bash
tmux capture-pane -p -S - -t "ID" | sed -n '/PROMPT_PATTERN/,/PROMPT_PATTERN/{//d;p}'
```

When prompts are long or appear in scrollback noise, generate random anchors to delimit output cleanly:

```bash
A=$(openssl rand -hex 4)
echo "A: $A"
tmux send-keys -t "ID" "echo ${A}-st; YOUR_COMMAND; echo ${A}-end" C-m
sleep 1
tmux capture-pane -p -S - -t "ID" | sed -n '/^'"$A"'-st$/,/^'"$A"'-end$/{/^'"$A"'/d;p}'
```

The `-st`/`-end` suffixes prevent matching the anchor inside the echoed command line.

When scrollback becomes too noisy, clear it:

```bash
tmux send-keys -t "ID" 'clear' C-m
tmux clear-history -t "ID"
```

## 4. Interact with the Process

If you need to stop or restart the process:

**Send Ctrl+C (Interrupt):**

```bash
tmux send-keys -t "server-log" C-c
```

**Kill the window (Clean up):**

```bash
tmux kill-window -t "server-log"
```

## 5. Advanced: Chaining Commands

You can chain multiple tmux commands in a single invocation using `';'` (note the quotes to avoid interpretation by the shell). This is faster and cleaner than running multiple `tmux` commands.

Example: Create window and start process in one go:

```bash
tmux new-window -n "server-log" -d ';' send-keys -t "server-log" "npm start" C-m
```

## 6. Parallel Work

Spin up multiple windows for independent tasks (downloads, research queries, builds):

```bash
for name in task-a task-b task-c; do tmux new-window -n "$name" -d; done
```

Send commands to each, then check results as they complete. Clean up finished windows:

```bash
tmux kill-window -t "task-a"
```

## Summary of Pattern

0. `echo $TMUX`
1. `tmux new-window -n "ID" -d`
2. `tmux send-keys -t "ID" "CMD" C-m`
3. `tmux capture-pane -p -t "ID"` (with anchor filtering for remote shells)
