Agent skill
tmux-task-runner
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.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/tmux-task-runner
SKILL.md
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.):
- Detect task type: Identify if the task is long-running (>30s expected duration)
- Create session: Generate unique session name (e.g.,
task-build-1729519263) - Execute in tmux: Run command in detached tmux session with logging
- Monitor output: Use
tmux capture-paneto read session output - Report status: Inform user of session name, log/status file locations, and monitoring options
- Provide access: Give user commands to tail logs, use the
tailhelper, 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
- User requests a long-running task execution
- Skill creates a tmux session with descriptive name
- Task runs in a detached session with output captured to a timestamped log in
${LOG_DIR:-/tmp} - Skill records status metadata (exit code, timings, command, overrides) in
${STATUS_DIR:-/tmp} - User can monitor via log tailing, the built-in
tailhelper, thestatussummary, or by attaching - Session persists until task completes or user kills it
Setup Instructions
Ensure tmux is installed on your system:
# macOS
brew install tmux
# Ubuntu/Debian
sudo apt-get install tmux
# Fedora/RHEL
sudo dnf install tmux
Verify installation:
tmux -V
Execution Pattern
Step 1: Validate tmux availability
// 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
# 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
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
# 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
./run.sh run build "npm run build"
# Monitor tail: ./run.sh tail task-build-... --interval 5
# Summarize: ./run.sh status task-build-...
Test Suites
./run.sh run test --env NODE_ENV=ci "npm test -- --coverage"
Development Server
./run.sh run server --workdir ./services/web "npm run dev"
Deployment Scripts
./run.sh run deploy --notify "./deploy.sh production"
Run Script Enhancements
Working Directory Overrides
- Use
--workdir <path>to run the command from a different directory without wrapping the command incd ... &&. - The script attempts to use
tmux new-session -cwhen available and falls back to an inlinecdif necessary.
Environment Variable Injection
- Repeatable
--env KEY=VALUEflags export additional environment variables for the task. - Variable names are validated to prevent invalid shell identifiers.
Completion Notifications
--notifytriggers a best-effort desktop notification (notify-send,osascript, orterminal-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 statuslists recent runs;./run.sh status <session>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 <session> [--interval N] [--lines M]pollstmux capture-paneon a timer for lightweight monitoring.- Falls back to the log file if the session has already exited.
Configurable Directories and Pruning
- Override
LOG_DIRandSTATUS_DIRto store artifacts outside/tmp. PRUNE_RETENTION_DAYS(default 7) automatically removes stale log/status files.STATUS_SUMMARY_LIMIT,TAIL_DEFAULT_LINES, andTAIL_DEFAULT_INTERVALtune command defaults without editing the script.
Session Management
List Active Sessions
# 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
# 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
# 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:
#!/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 -100to 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_FILEfor 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.
./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:
./run.sh tail task-test-1729519263 --interval 5 --lines 80
# or tail -f "$LOG_DIR"/task-test-1729519263.log
Attach to the session:
tmux attach-session -t task-test-1729519263
(Press Ctrl+b then d to detach without stopping the tests)
Check current status summary:
./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:
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):
# 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:
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
- Always provide monitoring commands to users after starting a session
- Use descriptive task types in session names (build, test, deploy, etc.)
- Capture initial output after starting to confirm task began successfully
- Use LOG_DIR (defaults to /tmp) to keep project directories clean
- Include cleanup instructions for when tasks complete
- Check session status before attempting operations
- Provide both tail and attach options for different monitoring preferences
- Use tee for logging to enable both file and real-time capture
Didn't find tool you were looking for?