tmux Use for existing interactive tmux sessions. For one-shot commands, use normal shell. For new non-interactive background jobs, use background execution. Basics Target format: , e.g. . Send input Literal text, then Enter: Special keys: Use for arbitrary text. Split text and Enter to avoid paste/newline surprises. Sessions Prompt checks Approve/select only when the prompt is understood: Helpers - : discover sessions. - : wait until captured pane contents contain text. searches echoed input and scrollback as well as process output. For command completion, use a unique marker whose full text…

#{session_name}\\t#{session_attached}\\t#{t:session_created}'\n\n if ! sessions=\"$(\"${tmux_cmd[@]}\" list-sessions -F \"$session_format\" 2>/dev/null)\"; then\n echo \"No tmux server found on $label\" >&2\n return 1\n fi\n\n if [[ -n \"$query\" ]]; then\n sessions=\"$(printf '%s\\n' \"$sessions\" | grep -i -- \"$query\" || true)\"\n fi\n\n if [[ -z \"$sessions\" ]]; then\n echo \"No sessions found on $label\"\n return 0\n fi\n\n echo \"Sessions on $label:\"\n printf '%s\\n' \"$sessions\" | while IFS=

tmux Use for existing interactive tmux sessions. For one-shot commands, use normal shell. For new non-interactive background jobs, use background execution. Basics Target format: , e.g. . Send input Literal text, then Enter: Special keys: Use for arbitrary text. Split text and Enter to avoid paste/newline surprises. Sessions Prompt checks Approve/select only when the prompt is understood: Helpers - : discover sessions. - : wait until captured pane contents contain text. searches echoed input and scrollback as well as process output. For command completion, use a unique marker whose full text…

\\t' read -r name attached created; do\n attached_label=$([[ \"$attached\" == \"1\" ]] && echo \"attached\" || echo \"detached\")\n printf ' - %s (%s, started %s)\\n' \"$name\" \"$attached_label\" \"$created\"\n done\n}\n\nif [[ \"$scan_all\" == true ]]; then\n if [[ ! -d \"$socket_dir\" ]]; then\n echo \"Socket directory not found: $socket_dir\" >&2\n exit 1\n fi\n\n shopt -s nullglob\n sockets=(\"$socket_dir\"/*)\n shopt -u nullglob\n\n if [[ \"${#sockets[@]}\" -eq 0 ]]; then\n echo \"No sockets found under $socket_dir\" >&2\n exit 1\n fi\n\n exit_code=0\n for sock in \"${sockets[@]}\"; do\n if [[ ! -S \"$sock\" ]]; then\n continue\n fi\n list_sessions \"socket path '$sock'\" -S \"$sock\" || exit_code=$?\n done\n exit \"$exit_code\"\nfi\n\ntmux_cmd=(tmux)\nsocket_label=\"default socket\"\n\nif [[ -n \"$socket_name\" ]]; then\n tmux_cmd+=(-L \"$socket_name\")\n socket_label=\"socket name '$socket_name'\"\nelif [[ -n \"$socket_path\" ]]; then\n tmux_cmd+=(-S \"$socket_path\")\n socket_label=\"socket path '$socket_path'\"\nfi\n\nlist_sessions \"$socket_label\" \"${tmux_cmd[@]:1}\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2983,"content_sha256":"8df6ac8e5824b0fa4d791235bd944ce86b0d12dcbf98af7abeb6d6de50e96823"},{"filename":"scripts/wait-for-text.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\n\nusage() {\n cat \u003c\u003c'USAGE'\nUsage: wait-for-text.sh -t target -p pattern [options]\n\nPoll a tmux pane for text and exit when found.\n\nThe search includes echoed input and scrollback. For command completion, use a\nunique marker whose full text does not appear in the command sent to tmux.\n\nOptions:\n -t, --target tmux target (session:window.pane), required\n -p, --pattern regex pattern to look for, required\n -F, --fixed treat pattern as a fixed string (grep -F)\n -T, --timeout seconds to wait (integer, default: 15)\n -i, --interval poll interval in seconds (default: 0.5)\n -l, --lines number of history lines to inspect (integer, default: 1000)\n -h, --help show this help\nUSAGE\n}\n\ntarget=\"\"\npattern=\"\"\ngrep_flag=\"-E\"\ntimeout=15\ninterval=0.5\nlines=1000\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n -t|--target) target=\"${2-}\"; shift 2 ;;\n -p|--pattern) pattern=\"${2-}\"; shift 2 ;;\n -F|--fixed) grep_flag=\"-F\"; shift ;;\n -T|--timeout) timeout=\"${2-}\"; shift 2 ;;\n -i|--interval) interval=\"${2-}\"; shift 2 ;;\n -l|--lines) lines=\"${2-}\"; shift 2 ;;\n -h|--help) usage; exit 0 ;;\n *) echo \"Unknown option: $1\" >&2; usage; exit 1 ;;\n esac\ndone\n\nif [[ -z \"$target\" || -z \"$pattern\" ]]; then\n echo \"target and pattern are required\" >&2\n usage\n exit 1\nfi\n\nif ! [[ \"$timeout\" =~ ^[0-9]+$ ]]; then\n echo \"timeout must be an integer number of seconds\" >&2\n exit 1\nfi\n\nif ! [[ \"$lines\" =~ ^[0-9]+$ ]]; then\n echo \"lines must be an integer\" >&2\n exit 1\nfi\n\nif ! command -v tmux >/dev/null 2>&1; then\n echo \"tmux not found in PATH\" >&2\n exit 1\nfi\n\n# End time in epoch seconds (integer, good enough for polling)\nstart_epoch=$(date +%s)\ndeadline=$((start_epoch + timeout))\n\nwhile true; do\n # -J joins wrapped lines, -S uses negative index to read last N lines\n pane_text=\"$(tmux capture-pane -p -J -t \"$target\" -S \"-${lines}\" 2>/dev/null || true)\"\n\n if printf '%s\\n' \"$pane_text\" | grep $grep_flag -- \"$pattern\" >/dev/null 2>&1; then\n exit 0\n fi\n\n now=$(date +%s)\n if (( now >= deadline )); then\n echo \"Timed out after ${timeout}s waiting for pattern: $pattern\" >&2\n echo \"Last ${lines} lines from $target:\" >&2\n printf '%s\\n' \"$pane_text\" >&2\n exit 1\n fi\n\n sleep \"$interval\"\ndone\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2294,"content_sha256":"b7efb785d3f2a4f1194e2ae18d7191135ad5a2fff4f08e6a4c7ad8412f3a7309"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"tmux","type":"text"}]},{"type":"paragraph","content":[{"text":"Use for existing interactive tmux sessions. For one-shot commands, use normal shell. For new non-interactive background jobs, use background execution.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Basics","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux ls\ntmux list-windows -t shared\ntmux list-panes -t shared:0\ntmux capture-pane -t shared:0.0 -p\ntmux capture-pane -t shared:0.0 -p -S -","type":"text"}]},{"type":"paragraph","content":[{"text":"Target format: ","type":"text"},{"text":"session:window.pane","type":"text","marks":[{"type":"code_inline"}]},{"text":", e.g. ","type":"text"},{"text":"shared:0.0","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Send input","type":"text"}]},{"type":"paragraph","content":[{"text":"Literal text, then Enter:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux send-keys -t shared:0.0 -l -- \"Please continue\"\ntmux send-keys -t shared:0.0 Enter","type":"text"}]},{"type":"paragraph","content":[{"text":"Special keys:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux send-keys -t shared:0.0 C-c\ntmux send-keys -t shared:0.0 C-d\ntmux send-keys -t shared:0.0 Escape","type":"text"}]},{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"-l --","type":"text","marks":[{"type":"code_inline"}]},{"text":" for arbitrary text. Split text and Enter to avoid paste/newline surprises.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Sessions","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux new-session -d -s worker\ntmux rename-session -t old new\ntmux kill-session -t worker","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prompt checks","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux capture-pane -t worker-3 -p | tail -20\ntmux capture-pane -t worker-3 -p | rg \"proceed|permission|Yes|No|❯\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Approve/select only when the prompt is understood:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"tmux send-keys -t worker-3 -l -- \"y\"\ntmux send-keys -t worker-3 Enter","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Helpers","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/find-sessions.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":": discover sessions.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"scripts/wait-for-text.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":": wait until captured pane contents contain text.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"wait-for-text.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" searches echoed input and scrollback as well as process output. For command completion, use a unique marker whose full text is split across arguments in the command sent to tmux:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"nonce=\"$(od -An -N8 -tx1 /dev/urandom | tr -d ' \\n')\"\nmarker=\"OPENCLAW_DONE_${nonce}\"\ntmux send-keys -t shared:0.0 -l -- \"sleep 4; printf '%s%s\\n' 'OPENCLAW_DONE_' '$nonce'\"\ntmux send-keys -t shared:0.0 Enter\nscripts/wait-for-text.sh -t shared:0.0 -p \"$marker\" -F -T 30","type":"text"}]},{"type":"paragraph","content":[{"text":"The echoed command never contains the complete marker, and the nonce prevents an older completion line from matching.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Notes","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"capture-pane -p","type":"text","marks":[{"type":"code_inline"}]},{"text":" prints to stdout for scripts.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"-S -","type":"text","marks":[{"type":"code_inline"}]},{"text":" captures full scrollback.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"tmux sessions persist across SSH disconnects.","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"tmux","author":"@skillopedia","source":{"stars":393736,"repo_name":"openclaw","origin_url":"https://github.com/openclaw/openclaw/blob/HEAD/skills/tmux/SKILL.md","repo_owner":"openclaw","body_sha256":"8aeaa6f3dfe06d58e09721778b8c9e654bcbd47590f26f442c4dc87c9349c572","cluster_key":"0236ee7ba9883fdace76040c2283e822b5cfcc8df4e0fb8b0605f255ee947dc0","clean_bundle":{"format":"clean-skill-bundle-v1","source":"openclaw/openclaw/skills/tmux/SKILL.md","text_bytes":5277,"source_commit":"4c451a77c68be7e6e24b4900bf22ef1022ef3a9a","skills_sh_rank":3854,"attachment_count":2,"text_attachments":2,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/tmux/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"software-engineering","category_label":"Engineering"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"software-engineering","metadata":{"openclaw":{"os":["darwin","linux"],"emoji":"🧵","install":[{"id":"brew","bins":["tmux"],"kind":"brew","label":"Install tmux (brew)","formula":"tmux"}],"requires":{"bins":["tmux"]}}},"import_tag":"skills-sh-top20k-2026-11","description":"Control tmux sessions/panes for interactive CLIs: list, capture output, send keys, paste text, monitor prompts."}},"renderedAt":1793671662782}

tmux Use for existing interactive tmux sessions. For one-shot commands, use normal shell. For new non-interactive background jobs, use background execution. Basics Target format: , e.g. . Send input Literal text, then Enter: Special keys: Use for arbitrary text. Split text and Enter to avoid paste/newline surprises. Sessions Prompt checks Approve/select only when the prompt is understood: Helpers - : discover sessions. - : wait until captured pane contents contain text. searches echoed input and scrollback as well as process output. For command completion, use a unique marker whose full text…