Zellij Terminal Automation Skill
Automate Zellij terminal multiplexer for testing terminal applications, orchestrating multi-pane workflows, and capturing terminal output.
Quick Reference
code
┌─────────────────────────────────────────────────────────────────┐ │ COMMON TESTING PATTERNS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Start test session zellij -s test-session │ │ Run command in pane zellij run -- <command> │ │ Send keystrokes zellij action write-chars "text" │ │ Capture output zellij action dump-screen /tmp/out.txt │ │ Clean up zellij kill-session test-session │ │ │ └─────────────────────────────────────────────────────────────────┘
Timing Guidelines
Zellij actions are fast. Use minimal sleeps:
| Operation | Recommended Sleep |
|---|---|
| Session creation | sleep 0.5 |
| After sending command + Enter | sleep 0.5 (fast commands) |
| After sending command + Enter | sleep 1-2 (slow commands like network/API calls) |
| Before dump-screen | sleep 0.5 (after fast commands) |
| Pane/tab operations | No sleep needed |
Tip: For interactive shells (PowerShell, bash), most commands complete in under 0.5s. Only add longer sleeps for operations that genuinely take time (network requests, builds, etc.).
Tip: For long outputs, have the command write to a file instead of scrolling through the terminal:
bash
# Instead of trying to scroll through output: zellij -s session action write-chars 'Get-AzResource | Out-File /tmp/output.txt' zellij -s session action write 13 sleep 1 cat /tmp/output.txt # Read directly
Session Management
List Sessions
bash
zellij list-sessions # List all active sessions zellij ls # Alias
Output format: session-name [CREATED timestamp] (ATTACHED/DETACHED)
Create Session
bash
# Start new session (foreground - blocks terminal) zellij -s my-session # Start with layout zellij -s my-session -l compact # Start detached (for scripting) - use a subshell (zellij -s test-session &) sleep 0.5 # Wait for session to initialize
Attach to Session
bash
zellij attach my-session # Attach to existing session zellij a my-session # Alias
Kill/Delete Sessions
bash
zellij kill-session my-session # Kill specific session zellij k my-session # Alias zellij kill-all-sessions # Kill all sessions zellij ka # Alias zellij delete-session my-session # Delete (must be dead first) zellij delete-all-sessions # Delete all dead sessions
Running Commands in Panes
Open New Pane with Command
bash
# Run command in new pane (session must exist) zellij -s my-session run -- ls -la zellij -s my-session run -- npm test # Specify direction zellij -s my-session run --direction right -- htop zellij -s my-session run --direction down -- tail -f log.txt # Run in floating pane zellij -s my-session run --floating -- python script.py # Run in specific working directory zellij -s my-session run --cwd /path/to/dir -- make build # Keep pane open after command exits zellij -s my-session run --close-on-exit false -- ./quick-test.sh
Direction Options
- •
right- Split current pane, new pane on right - •
down- Split current pane, new pane below - •
left- Split current pane, new pane on left - •
up- Split current pane, new pane above
Sending Input to Panes
Write Characters (Text Input)
bash
# Send text to focused pane zellij -s my-session action write-chars "hello world" # Send command + Enter zellij -s my-session action write-chars "npm test" zellij -s my-session action write 13 # Enter key (byte 13) # Combined pattern for running a command zellij -s my-session action write-chars "echo hello" zellij -s my-session action write 13
Write Raw Bytes
bash
# Send specific key codes zellij -s my-session action write 13 # Enter zellij -s my-session action write 27 # Escape zellij -s my-session action write 3 # Ctrl+C zellij -s my-session action write 4 # Ctrl+D (EOF) zellij -s my-session action write 9 # Tab zellij -s my-session action write 127 # Backspace
Common Key Codes
| Key | Byte Code | Usage |
|---|---|---|
| Enter | 13 | Submit command |
| Escape | 27 | Cancel/exit modes |
| Ctrl+C | 3 | Interrupt process |
| Ctrl+D | 4 | EOF/exit |
| Ctrl+Z | 26 | Suspend process |
| Tab | 9 | Autocomplete |
| Backspace | 127 | Delete char |
| Ctrl+L | 12 | Clear screen |
| Ctrl+A | 1 | Beginning of line |
| Ctrl+E | 5 | End of line |
| Ctrl+U | 21 | Clear line |
| Ctrl+W | 23 | Delete word |
Arrow Keys (Escape Sequences)
bash
# Arrow keys require escape sequences zellij -s my-session action write 27 91 65 # Up arrow zellij -s my-session action write 27 91 66 # Down arrow zellij -s my-session action write 27 91 67 # Right arrow zellij -s my-session action write 27 91 68 # Left arrow
Capturing Output
Dump Screen Content
bash
# Dump focused pane content to file zellij -s my-session action dump-screen /tmp/screen.txt # Full path required zellij -s my-session action dump-screen "$(pwd)/output.txt"
Dump Layout
bash
# Get current layout structure zellij -s my-session action dump-layout
Query Tab Names
bash
zellij -s my-session action query-tab-names
Pane Management
Focus Navigation
bash
# Move focus zellij -s my-session action move-focus right zellij -s my-session action move-focus left zellij -s my-session action move-focus up zellij -s my-session action move-focus down # Cycle through panes zellij -s my-session action focus-next-pane zellij -s my-session action focus-previous-pane
Close Panes
bash
zellij -s my-session action close-pane
Resize Panes
bash
zellij -s my-session action resize increase left zellij -s my-session action resize increase right zellij -s my-session action resize increase up zellij -s my-session action resize increase down zellij -s my-session action resize decrease left # ... etc
Floating Panes
bash
# Toggle floating pane visibility zellij -s my-session action toggle-floating-panes # Toggle current pane between floating/embedded zellij -s my-session action toggle-pane-embed-or-floating
Fullscreen
bash
zellij -s my-session action toggle-fullscreen
Rename Pane
bash
zellij -s my-session action rename-pane "Server" zellij -s my-session action undo-rename-pane
Tab Management
Create Tabs
bash
# New tab zellij -s my-session action new-tab # New tab with name zellij -s my-session action new-tab --name "Tests" # New tab with layout zellij -s my-session action new-tab --layout compact
Navigate Tabs
bash
zellij -s my-session action go-to-next-tab zellij -s my-session action go-to-previous-tab zellij -s my-session action go-to-tab 1 # 1-indexed zellij -s my-session action go-to-tab-name "Tests"
Close/Rename Tabs
bash
zellij -s my-session action close-tab zellij -s my-session action rename-tab "NewName" zellij -s my-session action undo-rename-tab
Move Tabs
bash
zellij -s my-session action move-tab left zellij -s my-session action move-tab right
Scrolling
bash
# Scroll in focused pane zellij -s my-session action scroll-up zellij -s my-session action scroll-down zellij -s my-session action page-scroll-up zellij -s my-session action page-scroll-down zellij -s my-session action half-page-scroll-up zellij -s my-session action half-page-scroll-down zellij -s my-session action scroll-to-top zellij -s my-session action scroll-to-bottom
Testing Patterns
Pattern 1: Simple Command Test
bash
#!/bin/bash
SESSION="test-$$"
# Setup
zellij -s "$SESSION" run -- bash &
sleep 0.5
# Run test command
zellij -s "$SESSION" action write-chars "echo 'Hello World'"
zellij -s "$SESSION" action write 13
sleep 0.3
# Capture output
zellij -s "$SESSION" action dump-screen /tmp/output.txt
# Verify
if grep -q "Hello World" /tmp/output.txt; then
echo "PASS"
else
echo "FAIL"
fi
# Cleanup
zellij kill-session "$SESSION"
Pattern 2: Interactive Application Test
bash
#!/bin/bash SESSION="interactive-test" # Start session with the app zellij -s "$SESSION" run -- vim testfile.txt & sleep 0.5 # Simulate user input zellij -s "$SESSION" action write-chars "iHello from vim" # Enter insert mode + text zellij -s "$SESSION" action write 27 # Escape zellij -s "$SESSION" action write-chars ":wq" # Save and quit zellij -s "$SESSION" action write 13 # Enter sleep 0.3 # Verify file was created cat testfile.txt # Cleanup zellij kill-session "$SESSION" 2>/dev/null rm -f testfile.txt
Pattern 3: Multi-Pane Server/Client Test
bash
#!/bin/bash SESSION="server-client-test" # Start session zellij -s "$SESSION" run -- bash & sleep 0.5 # Start server in first pane zellij -s "$SESSION" action write-chars "python -m http.server 8000" zellij -s "$SESSION" action write 13 sleep 0.5 # Server startup # Open client pane zellij -s "$SESSION" run --direction right -- bash sleep 0.3 # Test from client pane zellij -s "$SESSION" action write-chars "curl -s localhost:8000" zellij -s "$SESSION" action write 13 sleep 0.5 # Capture client output zellij -s "$SESSION" action dump-screen /tmp/client-output.txt # Move to server pane and stop it zellij -s "$SESSION" action move-focus left zellij -s "$SESSION" action write 3 # Ctrl+C # Cleanup zellij kill-session "$SESSION"
Pattern 4: Watch Output Until Pattern
bash
#!/bin/bash
# Wait for specific output pattern
SESSION="$1"
PATTERN="$2"
TIMEOUT="${3:-30}"
start=$(date +%s)
while true; do
zellij -s "$SESSION" action dump-screen /tmp/watch-output.txt 2>/dev/null
if grep -q "$PATTERN" /tmp/watch-output.txt 2>/dev/null; then
echo "Pattern found!"
exit 0
fi
now=$(date +%s)
if (( now - start > TIMEOUT )); then
echo "Timeout waiting for pattern"
exit 1
fi
sleep 0.5
done
Usage: ./wait-for-pattern.sh my-session "Server ready" 60
Pattern 5: Test with Custom Layout
Create layout file test-layout.kdl:
kdl
layout {
pane split_direction="vertical" {
pane name="server" command="bash"
pane name="client" command="bash"
}
pane size=10 name="logs" command="bash"
}
bash
#!/bin/bash SESSION="layout-test" # Start with layout zellij -s "$SESSION" -l ./test-layout.kdl & sleep 0.5 # Now all panes are ready # Navigate by name or position zellij -s "$SESSION" action go-to-tab 1 # Continue with tests...
Utility Functions
Helper: Send Command and Wait
bash
zellij_exec() {
local session="$1"
local cmd="$2"
local wait="${3:-0.3}"
zellij -s "$session" action write-chars "$cmd"
zellij -s "$session" action write 13
sleep "$wait"
}
# Usage
zellij_exec "my-session" "echo hello" # Fast command, default 0.3s
zellij_exec "my-session" "npm install" 5 # Slow command, explicit wait
zellij_exec "my-session" "npm test" 10
Helper: Capture and Return Output
bash
zellij_capture() {
local session="$1"
local output_file="/tmp/zellij-capture-$$.txt"
zellij -s "$session" action dump-screen "$output_file"
cat "$output_file"
rm -f "$output_file"
}
# Usage
output=$(zellij_capture "my-session")
echo "$output" | grep -q "SUCCESS" && echo "Test passed"
Helper: Clean Session Start
bash
zellij_start() {
local session="$1"
# Kill existing session if present
zellij kill-session "$session" 2>/dev/null
sleep 0.2
# Start fresh
zellij -s "$session" run -- bash &
sleep 0.5
echo "$session"
}
# Usage
SESSION=$(zellij_start "test-run")
Troubleshooting
Session Already Exists
bash
zellij kill-session my-session 2>/dev/null sleep 0.2 # Then create new session
Commands Not Executing
bash
# Ensure pane has a shell running # Add explicit Enter after commands zellij -s "$SESSION" action write-chars "command" zellij -s "$SESSION" action write 13 # Don't forget Enter!
Output Not Captured
bash
# Wait for command to complete before capturing sleep 0.5 # Increase for slow commands zellij -s "$SESSION" action dump-screen /tmp/out.txt
Focus on Wrong Pane
bash
# Check current layout zellij -s "$SESSION" action dump-layout # Navigate explicitly zellij -s "$SESSION" action move-focus right
Session Won't Start in Background
bash
# Use subshell with & (zellij -s test-session &) sleep 0.5 # Or use run command on existing session zellij -s existing run -- bash
Limitations
- •No Direct Pane Targeting: Most actions operate on the focused pane. Navigate first, then act.
- •Timing Sensitive: Add minimal
sleepdelays (0.3-0.5s for fast commands, longer for slow operations). - •Screen Dump is Plain Text: No ANSI colors preserved in dump-screen output.
- •Session Names: Avoid special characters; use alphanumeric and hyphens.
- •Foreground Blocking:
zellij -s nameblocks; useruncommand or background with&.