--- name: tmux-task-runner description: Run build processes, test suites, deployments, and development servers in monitored tmux sessions with persistent logging. Use when executing long-running tasks that need background execution with real-time monitoring, or when running commands like npm build, pytest, deployment scripts, or dev servers that should continue running while you work on other tasks. --- # Tmux Long-Running Task Skill ## Overview This skill provides a robust solution for running long-running tasks in tmux sessions, offering superior flexibility compared to standard background process execution. It enables: - **Detached execution**: Tasks run in isolated tmux sessions - **Real-time monitoring**: Capture and analyze logs via `tmux capture-pane` - **Developer control**: Attach to sessions for interactive debugging - **Persistent logging**: All output saved to timestamped log files (configurable via `LOG_DIR`) - **Status metadata**: Exit codes, timings, and environment details saved for later review - **Session management**: List, monitor, summarize, and clean up active sessions ## Critical Workflow When a user requests execution of a long-running task (builds, tests, deployments, servers, etc.): 1. **Detect task type**: Identify if the task is long-running (>30s expected duration) 2. **Create session**: Generate unique session name (e.g., `task-build-1729519263`) 3. **Execute in tmux**: Run command in detached tmux session with logging 4. **Monitor output**: Use `tmux capture-pane` to read session output 5. **Report status**: Inform user of session name, log/status file locations, and monitoring options 6. **Provide access**: Give user commands to tail logs, use the `tail` helper, or attach to the session **CRITICAL:** Always check if tmux is installed before proceeding. If not found, inform the user to install it first. ## How It Works 1. User requests a long-running task execution 2. Skill creates a tmux session with descriptive name 3. Task runs in a detached session with output captured to a timestamped log in `${LOG_DIR:-/tmp}` 4. Skill records status metadata (exit code, timings, command, overrides) in `${STATUS_DIR:-/tmp}` 5. User can monitor via log tailing, the built-in `tail` helper, the `status` summary, or by attaching 6. Session persists until task completes or user kills it ## Setup Instructions Ensure tmux is installed on your system: ```bash # macOS brew install tmux # Ubuntu/Debian sudo apt-get install tmux # Fedora/RHEL sudo dnf install tmux ``` Verify installation: ```bash tmux -V ``` ## Execution Pattern ### Step 1: Validate tmux availability ```javascript // Check if tmux is installed const { execSync } = require('child_process'); try { execSync('which tmux', { stdio: 'pipe' }); } catch (error) { throw new Error('tmux is not installed. Please install it first.'); } ``` ### Step 2: Prepare session metadata ```bash # Generate unique session name and resolve directories SESSION_NAME="task-${TASK_TYPE}-$(date +%s)" LOG_DIR="${LOG_DIR:-/tmp}" STATUS_DIR="${STATUS_DIR:-/tmp}" LOG_FILE="$LOG_DIR/${SESSION_NAME}.log" STATUS_FILE="$STATUS_DIR/${SESSION_NAME}.status" # Optional overrides WORKDIR="${WORKDIR:-$PWD}" # run command from a different folder ENV_OVERRIDES=("NODE_ENV=ci" "DEBUG=1") # repeatable KEY=VALUE pairs NOTIFY=1 # enable desktop notifications if available ``` ### Step 3: Launch tmux session with logging and status tracking ```bash tmux new-session -d -s "$SESSION_NAME" -c "$WORKDIR" bash -lc ' set -o pipefail # Export requested environment overrides export NODE_ENV=ci DEBUG=1 START_EPOCH=$(date +%s) START_ISO=$(date -u +"%Y-%m-%dT%H:%M:%SZ") your-command-here 2>&1 | tee "'"$LOG_FILE"'" exit_code=${PIPESTATUS[0]} END_EPOCH=$(date +%s) END_ISO=$(date -u +"%Y-%m-%dT%H:%M:%SZ") DURATION=$((END_EPOCH - START_EPOCH)) { printf "exit_code=%q\n" "$exit_code" printf "command=%q\n" "your-command-here" printf "started_at_iso=%q\n" "$START_ISO" printf "finished_at_iso=%q\n" "$END_ISO" printf "duration_seconds=%q\n" "$DURATION" printf "log_file=%q\n" "'"$LOG_FILE"'" printf "workdir=%q\n" "'"$WORKDIR"'" printf "env_vars=%q\n" "NODE_ENV=ci; DEBUG=1" } > "'"$STATUS_FILE"'" if [ '"$NOTIFY"' -eq 1 ]; then message="[$SESSION_NAME] " if [ "$exit_code" -eq 0 ]; then message+="completed successfully" else message+="failed (exit $exit_code)" fi command -v notify-send >/dev/null 2>&1 && notify-send "tmux-task-runner" "$message" fi exit "$exit_code" ' ``` ### Step 4: Provide monitoring and summary commands ```bash # Tail the log file directly tail -f "$LOG_FILE" # Poll output without attaching ./run.sh tail "$SESSION_NAME" --interval 5 --lines 80 # Summarize session metadata (exit status, duration, timestamps) ./run.sh status "$SESSION_NAME" # Attach to the session (interactive) tmux attach-session -t "$SESSION_NAME" ``` ## Common Patterns ### Build Tasks ```bash ./run.sh run build "npm run build" # Monitor tail: ./run.sh tail task-build-... --interval 5 # Summarize: ./run.sh status task-build-... ``` ### Test Suites ```bash ./run.sh run test --env NODE_ENV=ci "npm test -- --coverage" ``` ### Development Server ```bash ./run.sh run server --workdir ./services/web "npm run dev" ``` ### Deployment Scripts ```bash ./run.sh run deploy --notify "./deploy.sh production" ``` ## Run Script Enhancements ### Working Directory Overrides - Use `--workdir ` to run the command from a different directory without wrapping the command in `cd ... &&`. - The script attempts to use `tmux new-session -c` when available and falls back to an inline `cd` if necessary. ### Environment Variable Injection - Repeatable `--env KEY=VALUE` flags export additional environment variables for the task. - Variable names are validated to prevent invalid shell identifiers. ### Completion Notifications - `--notify` triggers a best-effort desktop notification (`notify-send`, `osascript`, or `terminal-notifier`) when the job ends. - Notifications include the session name and whether the command succeeded. ### Status Metadata and Summaries - Each run writes a status file to `${STATUS_DIR:-/tmp}` containing exit code, timestamps, duration, command, workdir, and env overrides. - `./run.sh status` lists recent runs; `./run.sh status ` prints detailed metadata and the latest log lines. - Status files enable tooling to expose job history without attaching to tmux directly. ### Tail Helper - `./run.sh tail [--interval N] [--lines M]` polls `tmux capture-pane` on a timer for lightweight monitoring. - Falls back to the log file if the session has already exited. ### Configurable Directories and Pruning - Override `LOG_DIR` and `STATUS_DIR` to store artifacts outside `/tmp`. - `PRUNE_RETENTION_DAYS` (default 7) automatically removes stale log/status files. - `STATUS_SUMMARY_LIMIT`, `TAIL_DEFAULT_LINES`, and `TAIL_DEFAULT_INTERVAL` tune command defaults without editing the script. ## Session Management ### List Active Sessions ```bash # List all tmux sessions tmux list-sessions # List only task sessions tmux list-sessions 2>/dev/null | grep "^task-" || echo "No active task sessions" ``` ### Monitor Session Output ```bash # Capture last 100 lines tmux capture-pane -t SESSION_NAME -p -S -100 # Capture entire scrollback buffer tmux capture-pane -t SESSION_NAME -p -S - # Save to file tmux capture-pane -t SESSION_NAME -p -S - > session-capture.txt ``` ### Kill Sessions ```bash # Kill specific session tmux kill-session -t SESSION_NAME # Kill all task sessions tmux list-sessions -F "#{session_name}" | grep "^task-" | xargs -I {} tmux kill-session -t {} ``` ## Helper Script Example Create a reusable helper for common operations: ```bash #!/bin/bash # tmux-task.sh - Tmux task runner helper run_task() { local task_type=$1 shift local command="$@" local session="task-${task_type}-$(date +%s)" local logfile="/tmp/${session}.log" # Create session tmux new-session -d -s "$session" "$command 2>&1 | tee $logfile" # Output info echo "✓ Task started in session: $session" echo " Log file: $logfile" echo "" echo "Monitoring commands:" echo " tail -f $logfile # Follow log output" echo " tmux attach-session -t $session # Attach to session" echo " tmux kill-session -t $session # Stop task" } check_session() { local session=$1 if tmux has-session -t "$session" 2>/dev/null; then echo "Session '$session' is running" echo "" echo "Recent output:" tmux capture-pane -t "$session" -p -S -20 else echo "Session '$session' has completed or doesn't exist" fi } list_tasks() { echo "Active task sessions:" tmux list-sessions 2>/dev/null | grep "^task-" || echo " No active tasks" } # Usage example case "$1" in run) run_task "$2" "${@:3}" ;; check) check_session "$2" ;; list) list_tasks ;; *) echo "Usage: $0 {run|check|list} [args...]" exit 1 esac ``` ## Tips - **CRITICAL:** Always use unique session names to avoid conflicts - **CRITICAL:** Include timestamps in session names for easy identification - **CRITICAL:** Always provide log file paths to users for monitoring - Use descriptive task type prefixes (build, test, deploy, server, etc.) - Use `LOG_DIR` (defaults to `/tmp`) to avoid cluttering project directories - Use `tmux capture-pane -p -S -100` to get reasonable output chunks - For very long output, save to file instead of displaying inline - Remind users they can attach to sessions for interactive debugging - Clean up completed sessions periodically to avoid clutter ## Troubleshooting **Problem:** "session not found" error - **Solution:** Session may have completed. Check if process finished in log file. **Problem:** Unable to capture pane output - **Solution:** Ensure session name is correct: `tmux list-sessions` **Problem:** Log file not updating - **Solution:** Verify command includes `2>&1 | tee $LOG_FILE` for proper output capture **Problem:** tmux not found - **Solution:** Install tmux using system package manager (brew, apt, dnf, etc.) **Problem:** Session already exists - **Solution:** Use unique names with timestamps or kill existing session first ## Example Usage **User:** "Run the full test suite in the background and let me monitor it" **Claude:** I'll run your test suite in a tmux session so you can monitor it easily. ```bash ./run.sh run test --env NODE_ENV=ci "npm test -- --runInBand" ``` Your tests are now running in the background. Here's how to monitor: **Monitor the logs:** ```bash ./run.sh tail task-test-1729519263 --interval 5 --lines 80 # or tail -f "$LOG_DIR"/task-test-1729519263.log ``` **Attach to the session:** ```bash tmux attach-session -t task-test-1729519263 ``` (Press `Ctrl+b` then `d` to detach without stopping the tests) **Check current status summary:** ```bash ./run.sh status task-test-1729519263 ``` The summary includes exit code, duration, timestamps, workdir, and environment overrides once the command finishes. --- ## Advanced Features ### Multi-Pane Monitoring Run multiple related tasks in split panes: ```bash SESSION="task-multiview-$(date +%s)" # Create session with first task tmux new-session -d -s "$SESSION" "npm run build" # Split horizontally and run tests tmux split-window -h -t "$SESSION" "npm test" # Split first pane vertically for logs tmux select-pane -t 0 tmux split-window -v -t "$SESSION" "tail -f /tmp/app.log" echo "Multi-pane session created: $SESSION" echo "Attach with: tmux attach-session -t $SESSION" ``` ### Persistent Sessions Configure tmux to save sessions across reboots (requires tmux-resurrect plugin): ```bash # Install tmux plugin manager (TPM) git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm # Add to ~/.tmux.conf echo "set -g @plugin 'tmux-plugins/tmux-resurrect'" >> ~/.tmux.conf echo "run '~/.tmux/plugins/tpm/tpm'" >> ~/.tmux.conf ``` ### Integration with CI/CD Use tmux sessions for local CI/CD simulation: ```bash SESSION="task-ci-$(date +%s)" LOG="/tmp/${SESSION}.log" tmux new-session -d -s "$SESSION" bash -c " echo '=== Linting ===' && npm run lint && echo '=== Testing ===' && npm test && echo '=== Building ===' && npm run build && echo '=== CI Complete ===' || echo '=== CI Failed ===' " 2>&1 | tee $LOG ``` ## Best Practices 1. **Always provide monitoring commands** to users after starting a session 2. **Use descriptive task types** in session names (build, test, deploy, etc.) 3. **Capture initial output** after starting to confirm task began successfully 4. **Use LOG_DIR (defaults to /tmp)** to keep project directories clean 5. **Include cleanup instructions** for when tasks complete 6. **Check session status** before attempting operations 7. **Provide both tail and attach options** for different monitoring preferences 8. **Use tee for logging** to enable both file and real-time capture