| name | tmux-automation |
| description | Run commands in detached tmux sessions and programmatically send input, capture output, and manage sessions |
Tmux Automation Skill
When to Use This Skill
Use this skill when you need to:
- Run interactive CLI tools (vim, git rebase, REPLs) from scripts
- Execute long-running commands that survive terminal disconnect
- Automate interactive workflows programmatically
- Run commands in a persistent session across multiple operations
Key Commands
Create Detached Session
tmux new-session -d -s <session-name> "<command>"
tmux new-session -d -s <session-name> -c /path/to/dir "<command>"
tmux new-session -d -s <session-name>
Send Input to Session
tmux send-keys -t <session> 'echo "hello"' Enter
tmux send-keys -t <session> C-c
tmux send-keys -t <session> Escape
tmux send-keys -t <session> Up
tmux send-keys -t <session> Down
tmux send-keys -t <session> Tab
tmux send-keys -t <session> 'i' 'Hello World' Escape ':wq' Enter
Capture Session Output
tmux capture-pane -t <session> -p
tmux capture-pane -t <session> -p -S -1000
Manage Sessions
tmux has-session -t <session> 2>/dev/null && echo "exists"
tmux kill-session -t <session>
tmux ls
Target Format
Sessions are referenced as:
session-name — session (window 0)
session-name.0 — first window in session
session-name:0 — alternative syntax for window
session-name.0.0 — specific pane (window 0, pane 0)
Workflow Pattern
SESSION="my-session"
tmux new-session -d -s "$SESSION" "python manage.py shell"
sleep 0.3
tmux send-keys -t "$SESSION" 'from users.models import User' Enter
tmux send-keys -t "$SESSION" 'User.objects.count()' Enter
OUTPUT=$(tmux capture-pane -t "$SESSION" -p)
echo "$OUTPUT"
tmux kill-session -t "$SESSION"
Common Key Names
| Key | tmux send-keys value |
|---|
| Enter | Enter |
| Escape | Escape |
| Tab | Tab |
| Ctrl+C | C-c |
| Ctrl+D | C-d |
| Ctrl+X | C-x |
| Up/Down/Left/Right | Up, Down, Left, Right |
| Home | Home |
| End | End |
Best Practices
- Always wait after session creation — Add 100-500ms sleep before first capture/send
- Use descriptive session names — Makes debugging easier
- Clean up when done — Always kill-session to avoid orphaned sessions
- Check session exists — Before sending keys, verify with
has-session
- Enter is a separate argument — Don't include it in the text string
- Use -c for working directory — Ensures commands run in correct location
Example Use Cases
Run Django Management Command
SESSION="django-migrate"
tmux new-session -d -s "$SESSION" "python manage.py migrate"
sleep 2
tmux capture-pane -t "$SESSION" -p
tmux kill-session -t "$SESSION"
Interactive Python REPL Automation
SESSION="python-repl"
tmux new-session -d -s "$SESSION" "python"
sleep 0.3
tmux send-keys -t "$SESSION" 'import json' Enter
tmux send-keys -t "$SESSION" 'print(json.dumps({"a": 1}))' Enter
tmux capture-pane -t "$SESSION" -p
tmux send-keys -t "$SESSION" 'exit()' Enter
tmux kill-session -t "$SESSION"
Run Long-Remaining Server
SESSION="dev-server"
tmux new-session -d -s "$SESSION" -c /project "npm run dev"
tmux capture-pane -t "$SESSION" -p
tmux kill-session -t "$SESSION"
Troubleshooting
| Problem | Solution |
|---|
| Blank screen on capture | Add sleep 0.3 after session creation |
| Command not executing | Send explicit Enter key as separate argument |
\n doesn't work | Use Enter not \n |
| Session not found | Check with tmux has-session -t <name> first |
| Keys sent to wrong window | Use session:window.pane format explicitly |