| name | tmux |
| description | Use tmux for background tasks, TUI testing, and debugging layouts. Philosophy: No background bash - use tmux for full observability and direct interaction. |
tmux - No Background Bash Philosophy
Core Philosophy
No background bash. Use tmux. Full observability, direct interaction.
Instead of implementing complex background task management in your application:
| ❌ 应用内实现 | ✅ 用 tmux |
|---|
& 后台运行,丢失输出 | tmux session 保持运行,随时查看 |
| 需要实现 job control | tmux 已有完整的 session 管理 |
| 输出不可见 | tmux attach 随时重连 |
| 进程难以管理 | tmux ls / tmux kill-session |
tmux gives you:
- Full observability - always see what's happening
- Direct interaction - attach and type commands
- Persistence - detach and reattach later
- Isolation - each task in its own session
⛔ Safety Rules — READ FIRST
Agent 误操作 tmux kill-server 曾导致用户丢失全部 tmux session。
以下规则是硬约束,违反即可能造成不可恢复的数据丢失。
绝对禁止
| 禁令 | 原因 |
|---|
禁止 tmux kill-server | 销毁整个 tmux 服务器,所有用户 session 全部消失 |
| 禁止遍历所有 session 并批量 kill | 通配符可能命中用户的 session,最后一个 session 被杀后 server 也会退出 |
| 禁止 kill 不是你创建的 session | 你不知道其他 session 的用途 |
禁止向唯一 pane 发送 exit / C-d | pane 关闭 → window 关闭 → session 关闭,连锁退出 |
正确做法
tmux kill-session -t "my-agent-task" 2>/dev/null
tmux -L agent-$$ new-session -d -s "my-task" "..."
tmux -L agent-$$ kill-session -t "my-task"
tmux list-sessions
如果需要"干净环境"
tmux kill-server
for s in $(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep '^my-prefix-'); do
tmux kill-session -t "$s" 2>/dev/null
done
TMUX_SOCK="tmux -L agent-$$"
$TMUX_SOCK new-session -d -s "task" "..."
$TMUX_SOCK kill-session -t "task"
Quick Reference
Session Management
tmux new -s <name>
tmux new -s build -d
tmux attach -t <name>
tmux detach (Ctrl-b d)
tmux ls
tmux kill-session -t <name>
Window & Pane Operations
Ctrl-b %
Ctrl-b " # Split horizontal (top/bottom)
Ctrl-b <arrow> # Navigate panes
Ctrl-b x # Kill pane
Ctrl-b z # Toggle pane zoom (fullscreen)
Ctrl-b Ctrl-<arrow> # Resize pane
Ctrl-b { / } # Swap panes
# Windows
Ctrl-b c # New window
Ctrl-b n / p # Next / Previous window
Ctrl-b <number> # Go to window number
Ctrl-b , # Rename window
Ctrl-b & # Kill window
Sending Commands (for scripting)
tmux send-keys -t <session> "command" Enter
tmux send-keys -t <session> Escape
tmux send-keys -t <session> C-c
tmux send-keys -t <session> C-o
tmux send-keys -t <session> M-x
tmux send-keys -t <session> Space
tmux send-keys -t <session> Up
tmux capture-pane -t <session> -p
tmux capture-pane -t <session> -p > out.txt
Common Workflows
Long-Running Build / Test
tmux new -s build
go build ./...
tmux attach -t build
Debugging Layout (Go + Delve)
┌─────────────────────────────────────────────────────┐
│ Pane 0: Program │
│ $ go run ./cmd/ai │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ Pane 1: Delve Debugger │
│ (dlv) break main.main │
│ (dlv) continue │
└─────────────────────────────────────────────────────┘
tmux new -s debug -d
tmux split-window -v -t debug
tmux send-keys -t debug:0.0 "go run ./cmd/ai" Enter
tmux send-keys -t debug:0.1 "dlv attach \$(pgrep ai)" Enter
tmux attach -t debug
TDD Layout (Code + Test Watch)
┌──────────────────────────────┬──────────────────────────────┐
│ Pane 0: Program │ Pane 1: Test Watch │
│ $ go run ./cmd/ai │ $ go test -v ./... │
├──────────────────────────────┴──────────────────────────────┤
│ Pane 2: Logs / Shell │
│ $ tail -f /var/log/ai.log │
└─────────────────────────────────────────────────────────────┘
tmux new -s tdd -d
tmux split-window -h -t tdd
tmux split-window -v -t tdd:0.0
tmux send-keys -t tdd:0.0 "go run ./cmd/ai" Enter
tmux send-keys -t tdd:0.1 "go test -v ./..." Enter
tmux send-keys -t tdd:0.2 "tail -f /var/log/ai.log" Enter
tmux attach -t tdd
Multiple Worktrees in Parallel
tmux new -s worktrees -d -c $(git rev-parse --show-toplevel)
tmux rename-window -t worktrees:0 "main"
for wt in $(git worktree list --porcelain | grep "^worktree" | cut -d' ' -f2); do
name=$(basename "$wt")
tmux new-window -t worktrees -n "$name" -c "$wt"
done
tmux attach -t worktrees
TUI Testing Pattern
Automated testing of terminal applications with controlled environment:
#!/bin/bash
SESSION="tui-test"
TMUX="tmux -L test"
cleanup() {
$TMUX kill-session -t $SESSION 2>/dev/null
}
trap cleanup EXIT
$TMUX new-session -d -s $SESSION -x 120 -y 40
$TMUX send-keys -t $SESSION "go run ./cmd/ai" Enter
sleep 2
$TMUX capture-pane -t $SESSION -p > /tmp/initial-state.txt
$TMUX send-keys -t $SESSION "help" Enter
sleep 1
$TMUX capture-pane -t $SESSION -p > /tmp/after-help.txt
if grep -q "Available commands" /tmp/after-help.txt; then
echo "✅ Test passed: Help command works"
else
echo "❌ Test failed: Help command not working"
cat /tmp/after-help.txt
exit 1
fi
$TMUX send-keys -t $SESSION Escape
$TMUX send-keys -t $SESSION C-c
echo "✅ All tests passed"
Special Keys Reference
| Key | tmux send-keys syntax |
|---|
| Escape | Escape |
| Enter | Enter |
| Space | Space |
| Tab | Tab |
| Backspace | BSpace |
| Delete | DC |
| Insert | IC |
| Home | Home |
| End | End |
| Page Up | PPrior |
| Page Down | PPage |
| Arrow keys | Up Down Left Right |
| Ctrl+X | C-x (lowercase) |
| Alt+X | M-x (lowercase) |
| Shift+Tab | BTab |
| F1-F12 | F1 F2 ... F12 |
Configuration
Add to ~/.tmux.conf:
set -g mouse on
set -g base-index 1
setw -g pane-base-index 1
set -g history-limit 50000
set -g default-terminal "screen-256color"
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind r source-file ~/.tmux.conf \; display "Config reloaded!"
set -g status-right '#(git branch 2>/dev/null | grep -e "\*" | sed "s/* //") | %H:%M'
set -s escape-time 0
set -g allow-rename off
Integration with ad Editor
When running ai as a plugin in ad editor:
tmux new -s ad-dev -d
tmux split-window -h -t ad-dev
tmux send-keys -t ad-dev:0.0 "ad ." Enter
tmux send-keys -t ad-dev:0.1 "# shell for go test, git, etc." Enter
tmux attach -t ad-dev
Checking Background Task Status
When you've started a long-running task in tmux, use these commands to check status:
| Task | Command |
|---|
| List all sessions | tmux ls |
| Check if session exists | tmux ls | grep <name> |
| View current output | tmux capture-pane -t <name> -p |
| View last N lines | tmux capture-pane -t <name> -p -S -50 |
| Attach to session | tmux attach -t <name> |
| Send interrupt (Ctrl+C) | tmux send-keys -t <name> C-c |
| Kill session | tmux kill-session -t <name> ⛔ 禁止 kill-server |
| Wait for completion | tmux_wait.sh <name> [timeout] |
Example workflow:
tmux new -s build -d "go build ./... 2>&1 | tee /tmp/build.log"
tmux capture-pane -t build -p -S -20
tmux attach -t build
~/.ai/skills/tmux/bin/tmux_wait.sh build 600
When to Use
| Scenario | tmux Pattern |
|---|
| Long build/test | Single session, detach |
| Debugging | Split pane: program + debugger |
| TDD workflow | Split pane: program + test watch |
| Multiple features | Window per worktree |
| TUI testing | Automated script with capture-pane |
Summary
Don't implement background task management in your app. Use tmux.
- ✅ Simple - no code to write
- ✅ Observable - always see output
- ✅ Interactive - attach anytime
- ✅ Persistent - survives disconnect
- ✅ Standard - everyone knows tmux