automation/skills/tmux/SKILL.md
Persistent tmux sessions inside containers: shell reconnection, background commands, output capture, and key sending. Use when running long-lived or TTY-dependent commands. MUST be invoked before any work involving: ov tmux commands, persistent shells, background container commands, or TTY-dependent TUI programs.
npx skillsauth add overthinkos/overthink-plugins tmuxInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ov tmux manages tmux sessions inside running containers. It solves two problems:
ov tmux shell <image> again and you're back where you left off.openclaw models auth login need a real terminal to function. ov shell --tty piped through tee or redirected breaks the TUI event loop. ov tmux run provides a real tmux terminal that the TUI can use, while ov tmux capture reads the output without attaching.All operations translate to engine exec container tmux <args>. The tmux layer must be present in the image (layers/tmux/layer.yml — installs the tmux RPM).
| Action | Command | Description |
|--------|---------|-------------|
| Persistent shell | ov tmux shell <image> | Create or reattach to a shell session |
| Send command | ov tmux cmd <image> "command" -s <name> | Send command to session (with notification) |
| Run detached | ov tmux run <image> -s <name> "<command>" | Start command in new detached session |
| Attach | ov tmux attach <image> -s <name> | Attach to session interactively |
| List sessions | ov tmux list <image> | Show active tmux sessions |
| Capture output | ov tmux capture <image> -s <name> | Print pane output (for automation) |
| Send keys | ov tmux send <image> -s <name> "text" --enter | Send keystrokes to session |
| Kill session | ov tmux kill <image> -s <name> | Kill a tmux session |
All commands accept -i INSTANCE for multi-instance support.
ov tmux shell — Persistent ShellThe user-friendly entry point. Creates or reattaches to a persistent shell session.
# First call creates a "shell" session and attaches
ov tmux shell sway-browser-vnc
# After detaching (Ctrl-b d) or disconnect, reattach:
ov tmux shell sway-browser-vnc
# → Picks up right where you left off
# Use a custom session name:
ov tmux shell sway-browser-vnc -s dev
Behavior:
tmux attach-session -t <name>tmux new-session -s <name> (creates with bash)syscall.Exec with -it for a real terminalshellov tmux cmd — Send Command to SessionSends a command (text + Enter) to an existing tmux session. Returns immediately after sending. Sends a desktop notification by default (disable with --no-notify).
ov tmux cmd sway-browser-vnc "ls -la" -s oauth
ov tmux cmd jupyter "python train.py" -s training --no-notify
Behavior:
ov tmux list to see sessions)ov tmux send <image> -s <name> -l "command" --enterov tmux run — Detached CommandStarts a command in a new named tmux session. Returns immediately — the command runs in the background with a real TTY.
# Run OAuth flow in background with real terminal
ov tmux run sway-browser-vnc -s oauth \
"openclaw models auth login --provider openai-codex --set-default"
# Run any long-lived command
ov tmux run jupyter -s training "python train.py --epochs 100"
Behavior:
exec.Command, returns immediately-d (detached)ov tmux attach — Interactive AttachAttaches to an existing session. Use when you want to interact with a running command.
ov tmux attach sway-browser-vnc -s oauth
# Detach with Ctrl-b d
Behavior:
syscall.Exec replaces the processov tmux list to see sessions)ov tmux list — List Sessionsov tmux list sway-browser-vnc
# shell: 1 windows (created Sat Mar 21 16:54:15 2026)
# oauth: 1 windows (created Sat Mar 21 17:01:22 2026)
No sessions is not an error — prints an informational message.
ov tmux capture — Read OutputReads the current pane content without attaching. Essential for automation — Claude Code and scripts can check on running commands.
# Read visible pane content
ov tmux capture sway-browser-vnc -s oauth
# Read last 50 lines of history
ov tmux capture sway-browser-vnc -s oauth -n 50
Flags:
-n <lines> — Number of history lines (0 = visible pane only, default)ov tmux send — Send KeysSends keystrokes to a running session. For automation when you need to respond to prompts.
# Type text and press Enter
ov tmux send sway-browser-vnc -s oauth "yes" --enter
# Send literal text (disable tmux key name interpretation)
ov tmux send sway-browser-vnc -s oauth -l "C-c is not ctrl-c here"
# Send special keys
ov tmux send sway-browser-vnc -s oauth Enter
ov tmux send sway-browser-vnc -s oauth C-c
Flags:
--enter — Append Enter key after the text-l / --literal — Send keys literally (disable key name lookup)ov tmux kill — Kill Sessionov tmux kill sway-browser-vnc -s oauth
# Killed tmux session "oauth" in ov-sway-browser-vnc
The primary use case that motivated ov tmux. The openclaw models auth login TUI requires a real terminal to complete the post-callback token exchange. ov shell --tty piped through tee or backgrounded breaks the TUI event loop — the callback is received but tokens are never saved.
IMG=sway-browser-vnc
# 1. Start OAuth in a tmux session (real terminal)
ov tmux run $IMG -s oauth \
"openclaw models auth login --provider openai-codex --set-default"
# 2. Read the OAuth URL from tmux output
ov tmux capture $IMG -s oauth | grep -o 'https://auth.openai.com/[^ ]*'
# 3. Open URL in Chrome, complete OAuth via CDP
ov eval cdp open $IMG "<oauth-url>"
TAB=$(ov eval cdp list $IMG | grep -i "openai" | head -1 | awk '{print $1}')
ov eval cdp click $IMG $TAB 'button._buttonStyleFix_wvuha_65' --vnc # Continue with Google
sleep 5
ov eval cdp click $IMG $TAB 'button._primary_3rdp0_107' --vnc # Continue (consent)
# 4. Verify token exchange completed
sleep 10
ov tmux capture $IMG -s oauth | tail -5
# Should show: "OpenAI OAuth complete", "Default model set to openai-codex/gpt-5.4"
# 5. Clean up
ov tmux kill $IMG -s oauth
# Start a shell that survives disconnects
ov tmux shell jupyter
# Work inside the shell...
# pip install something, edit configs, run scripts
# Connection drops or terminal closes
# Just reconnect:
ov tmux shell jupyter
# → Everything is still there
The tmux layer must be included in the image. Check with:
ov shell <image> -c "which tmux"
If tmux is not installed, ov tmux returns: "tmux is not installed in container <name> (add the tmux layer to your image)".
The tmux layer is already a dependency of openclaw-full (and all derivative images). For other images, add tmux to the layers list in image.yml.
For users unfamiliar with tmux:
| Key | Action |
|-----|--------|
| Ctrl-b d | Detach from session (leaves it running) |
| Ctrl-b [ | Enter scroll mode (navigate with arrows, q to exit) |
| Ctrl-b c | Create new window |
| Ctrl-b n / Ctrl-b p | Next / previous window |
| Ctrl-b % | Split pane vertically |
| Ctrl-b " | Split pane horizontally |
Command execution follows a consistent naming pattern across ov:
| Interactive shell | Single command | Persistent session |
|-------------------|---------------|-------------------|
| ov shell | ov cmd | — |
| ov tmux shell | ov tmux cmd | ov tmux run |
ov cmd — runs command synchronously in running container, notifies on completionov tmux cmd — sends command to existing tmux session, notifies on dispatchov tmux run — creates new detached tmux session with commandov cmd — Single command execution with D-Bus notification (running containers only, no tmux)/ov-core:shell — ov shell for one-shot commands (no persistence) or ov shell -c (full container setup)/ov-eval:cdp — Chrome DevTools Protocol (used with tmux for OAuth flows)/ov-automation:openclaw-deploy — OpenClaw gateway config (OAuth requires tmux for token exchange)/ov-core:service — Supervisord service management (different scope: persistent services vs ad-hoc commands)/ov-infrastructure:tmux-layer — The tmux layer definition/ov-infrastructure:dbus-layer — D-Bus session bus (required for notifications)MUST be invoked when the task involves:
development
Claude Code multi-agent support in Overthink — sub-agents, dynamic workflows, and agent teams, and how each drives the existing `ov eval` disposable beds to test and verify. MUST be invoked before authoring or invoking an ov sub-agent / dynamic workflow / agent team, wiring agent-lifecycle hooks, or asking "which primitive should drive the R10 beds?".
tools
Mounts a virtiofs share tagged `workspace` at /workspace inside a VM guest via a systemd .mount unit. Use when a kind:vm entity shares a host directory into the guest and you need it auto-mounted (and re-mounted at every boot).
development
MUST be invoked before any work involving: the `kind: android` schema kind, a `target: android` deploy, the `apk:` layer package format (installing Android apps declaratively), AndroidDeployTarget, an in-pod emulator OR a remote/physical adb-endpoint device, or nested `pod → android` deployment. The first-class Android device + app surface that sits above `ov eval adb`/`appium`.
tools
Use when committing, branching, pushing, merging, tagging, creating PRs, or approving/merging PRs with gh — the feat/-branch, R10-gated, never-force-push landing workflow across the main repo + the plugins submodule + image/<distro> submodules. Covers sync-to-upstream, branch/worktree pruning, the fork+PR path for contributors without write access, and cross-repo @github landing order.