Install
openclaw skills install openclaw-tmux-persistent-processRun programs that survive OpenClaw exec session cleanup and gateway restarts via tmux. Use when you need long-running servers, dev servers, tunnels (ngrok/cloudflared), coding agents, or any process that must outlive the current exec session. Solves: exec background processes getting SIGKILL on session cleanup. Recommended for all OpenClaw users running any long-lived process.
openclaw skills install openclaw-tmux-persistent-processRun programs that survive OpenClaw exec session cleanup and gateway restarts.
OpenClaw runs shell commands via exec. But exec has a critical limitation that most users don't realize until something breaks:
openclaw gateway restart — all running exec processes are gone.This means anything you expect to keep running — a tunnel for a client demo, a dev server, a long build — can die at any moment without notice.
The solution: Use tmux to create virtual terminals completely decoupled from the exec lifecycle. Programs in tmux survive gateway restarts, exec cleanup, and session timeouts. tmux runs independently of OpenClaw — even if the gateway goes down, your processes keep running.
Rule of thumb: If a command might run longer than 2 minutes, use tmux.
All operations use a dedicated socket to avoid interfering with the user's own tmux:
SOCK="/tmp/openclaw-tmux/openclaw.sock"
mkdir -p /tmp/openclaw-tmux
SESSION="my-server"
# Check if already running
if tmux -S "$SOCK" has-session -t "$SESSION" 2>/dev/null; then
echo "already running"
else
tmux -S "$SOCK" new -d -s "$SESSION" \
"cd /path/to/project && npm run dev"
echo "started"
fi
# List all sessions
tmux -S "$SOCK" list-sessions
# View last 30 lines of output
tmux -S "$SOCK" capture-pane -t "$SESSION" -p -S -30
# Check if process is idle (back to shell prompt)
tmux -S "$SOCK" capture-pane -t "$SESSION" -p -S -3 \
| grep -qE '\$\s*$|❯' && echo "IDLE" || echo "RUNNING"
# Send a command
tmux -S "$SOCK" send-keys -t "$SESSION" "command" Enter
# Send literal text (recommended, no special key parsing)
tmux -S "$SOCK" send-keys -t "$SESSION" -l -- "literal text"
tmux -S "$SOCK" send-keys -t "$SESSION" Enter
# Ctrl+C to interrupt
tmux -S "$SOCK" send-keys -t "$SESSION" C-c
# Kill one session
tmux -S "$SOCK" kill-session -t "$SESSION"
# Kill all
tmux -S "$SOCK" kill-server
# Clean stale socket
rm -f "$SOCK"
For programs that need startup time (e.g. coding agents, REPLs):
SESSION="my-task"
tmux -S "$SOCK" new -d -s "$SESSION"
tmux -S "$SOCK" send-keys -t "$SESSION" "cd ~/project && node" Enter
# Wait for prompt before sending commands
for i in $(seq 1 15); do
OUTPUT=$(tmux -S "$SOCK" capture-pane -t "$SESSION" -p -S -5)
if echo "$OUTPUT" | grep -qE '❯|>\s*$|ready'; then
break
fi
sleep 1
done
# Now safe to send input
tmux -S "$SOCK" send-keys -t "$SESSION" -l "your command"
tmux -S "$SOCK" send-keys -t "$SESSION" Enter
| Use case | Session name | Command example |
|---|---|---|
| Dev server | dev-server | npm run dev |
| Tunnel (ngrok) | tunnel-ngrok | ngrok http 3000 |
| Tunnel (localhost.run) | tunnel-lr | ssh -R 80:localhost:3000 nokey@localhost.run |
| Background worker | worker | python worker.py |
| Build task | build-app | npm run build |
Lowercase + hyphens. No spaces.
dev-server — development servers
tunnel-{name} — tunnels (ngrok, cloudflared, etc.)
build-{project} — build tasks
worker-{name} — background workers
tmux set-option -t "$SESSION" history-limit 10000list-sessions says "error connecting", delete the socket and recreate.tmux new -d -s name "export KEY=val && cmd"send-keys -l literal mode)tmux -Vbrew install tmux (macOS) or apt install tmux (Linux)