Localsetup localsetup-tmux-shared-session-workflow
Server/ops in tmux; use tmux_ops tool to pick session (idle = prompt on current line) and probe sudo; run commands only in chosen session. Supports REMOTE_TMUX_HOST for VMs/remote/Docker.
git clone https://github.com/CruxExperts/localsetup
T=$(mktemp -d) && git clone --depth=1 https://github.com/CruxExperts/localsetup "$T" && mkdir -p ~/.claude/skills && cp -r "$T/_localsetup/skills/localsetup-tmux-shared-session-workflow" ~/.claude/skills/cruxexperts-localsetup-localsetup-tmux-shared-session-workflow && rm -rf "$T"
_localsetup/skills/localsetup-tmux-shared-session-workflow/SKILL.mdtmux shared session workflow (ops)
Rule: Any request that involves running commands on the host uses this workflow. Sudo is always assumed required. Use the tmux_ops tool to pick session and probe; do not infer busy from
tmux ls or parse raw capture yourself.
Tool (use this)
- Entrypoint: From repo root run
(or set./_localsetup/tools/tmux_ops
to run the same tool on a remote host via SSH; see Remote below).REMOTE_TMUX_HOST - Pick session:
→ JSON e.g../_localsetup/tools/tmux_ops pick
or{"session": "ops", "reason": "idle"}
or{"reason": "created"}
. Use that{"reason": "waiting_sudo"}
for the whole run.session - Probe sudo:
→ JSON./_localsetup/tools/tmux_ops probe -t <session>
or{"sudo": "ready"}
.{"sudo": "password_required"} - Send command:
sends the command and applies a short pylon-guard delay (default 0.5 s) to prevent commands racing ahead of output on high-latency links. Does not wait for the command to finish unless./_localsetup/tools/tmux_ops send -t <session> '...'
is passed.--wait - Send and wait:
sends and then polls for idle. Returns the moment the prompt reappears. Use for commands expected to finish in < 30 s../_localsetup/tools/tmux_ops send -t <session> --wait '...' - Wait (standalone):
polls pane for idle. Use after./_localsetup/tools/tmux_ops wait -t <session> [--timeout N]
(withoutsend
) for long-running ops. Returns--wait
or{"idle": true, "elapsed_s": X, "polls": N}
.{"idle": false, "timed_out": true, "cursor_line": "..."} - Idle definition: Idle = cursor line matches a shell prompt (
or$
) AND cursor Y moved from its pre-send position (cursor-delta guard prevents false positives).#
Subcommand reference
| Subcommand | Key args | Returns |
|---|---|---|
| | |
| | |
| , , , | |
| , , | |
Optional:
--idle-re PATTERN overrides the prompt regex (also env TMUX_OPS_IDLE_RE). --pre-cursor-y N enables the cursor-delta guard on standalone wait calls.
Sequence (follow exactly)
-
Pick session. Run
. Parse JSON; use the returned./_localsetup/tools/tmux_ops pick
for the whole run. If the tool errors, report and stop.session -
Show attach command immediately. Right after pick (whether the session was created or already existed), display the join command in a copy-paste code block so the user can attach at any time. Do not wait for the user to confirm they joined.
- Put this in a fenced code block:
tmux new-session -A -s <session> - If pick returned
: cancel any abandoned command first: sendreason: "waiting_sudo"
, wait ~0.5 s, then run the probe.tmux send-keys -t <session> C-c - Then run the probe.
- Put this in a fenced code block:
-
Gate on probe only. If the probe returns
: stop. Ask the user to attach to the session, enter the password in that pane, and reply "sudo ready". Only after they reply may you send the first command. If"sudo": "password_required"
, continue to step 4."sudo": "ready" -
Send one step at a time. Send one logical step at a time.
- Short command (< 30 s expected): use
. Returns the moment idle is confirmed; no sleep needed.send --wait - Long command (builds, installs, deploys): use
(nosend
), then call--wait
where N is your best estimate.wait --timeout N
→ continue to next step.idle=true
→ inspecttimed_out=true
field; extend wait, read log, or escalate.cursor_line
- Never use arbitrary
calls as a completion signal.sleep - Use a log:
(e.g./tmp/agent-<session>-YYYYmmdd-HHMMSS.log
). Read the log yourself.|& tee -a $LOG
- Short command (< 30 s expected): use
-
Run. Commands go via
. Use a log path. Never run those commands in the agent shell../_localsetup/tools/tmux_ops send -t <session> '...' -
Re-gate if sudo expires. If a later command fails (e.g. sudo timeout), run the probe again; if
, stop and ask for "sudo ready"; only then continue.password_required
Waiting strategy
After send, choose: Command expected in < 30 s? YES → send --wait Returns idle=true the moment done. Continue immediately. Command expected in > 30 s or unknown? → send (no --wait), then wait --timeout N idle=true → continue timed_out=true → inspect cursor_line; extend wait, read log, or escalate Need exact latency, zero polling (advanced)? → append "; tmux wait-for -S done-$$" to command then run: tmux wait-for done-<PID> Blocks until shell signals completion. Use only when you fully control the command string.
Sentinel PS1 (advanced, zero false positives)
If you want completely unambiguous idle detection, inject a known prompt right after
pick:
tmux_ops send -t ops 'export PS1="__OPS__\$ "' # Then pass --idle-re '^__OPS__[$#]\s*$' to all subsequent wait calls
This makes the prompt unique and removes any chance of a false match on command output.
Remote (VMs, remote SSH, Docker)
When the tmux server runs on a different host (e.g. Cursor on laptop, tmux on VM or remote server):
- Set REMOTE_TMUX_HOST to that host (e.g.
). Optionally REMOTE_TMUX_CWD to the repo path on the remote (defaultexport REMOTE_TMUX_HOST=sh0t
)./opt/devzone/devops - Run
,tmux_ops pick
,probe
, andsend
as usual; the wrapper runs the tool over SSH and returns the same JSON.wait
Checklist
| Step | Do | Do not |
|---|---|---|
| 1 | Run ; use returned session for whole run. | Infer session from or "(attached)". |
| 2 | Right after pick, show attach in code block. If , send C-c first, then probe. | Wait for "I joined"; skip cancel when . |
| 3 | If probe says , stop and ask user; only then send commands. If ready, continue. | Send commands before user says "sudo ready" when probe said . |
| 4 (short cmd) | ; continue on . | Sleep then assume done. |
| 4 (long cmd) | , then ; handle . | Guess a sleep duration. |
| 5 | Run in chosen session via ; tee to log; read log. | Run in agent shell; skip log. |
| 6 | If sudo expired, probe again; if , stop. | Assume sudo still valid. |
Session and log
- Session: the one returned by
(e.g.tmux_ops pick
orops
).ops1 - Log:
. Commands:/tmp/agent-<session>-YYYYmmdd-HHMMSS.log
. After run: read log (e.g.... |& tee -a $LOG
that file).tail -n 200
Hard rules
- Server/ops commands run only in tmux. Use
to pick session and probe; never in the agent shell.tmux_ops - If probe returns ready, continue immediately; do not stop for a chat "sudo ready". Only stop when probe returns
.password_required - If
: ask user to enter password in the ops pane and reply "sudo ready"; then proceed.password_required - Right after pick, display the attach command in a copy-paste code block; do not wait for user to confirm join before probing.
- Capture output to the log path; the agent reads the log. State what you are about to do before running commands.
- Never use
as a completion signal. Usesleep
orsend --wait
.wait --timeout N