A terminal operations manual for long-running tasks on POSIX shells, macOS, and Linux. It does not falsely claim native Windows compatibility; Windows users should use it in WSL or another POSIX environment.
Customer-readable description
What this skill can do
| Customer wants | Skill will do | Customer can see |
|---|---|---|
| Start or observe a long-running task | Start a tmux/background task with parameterized session, log directory, and command | command, workdir, session/PID, log path, and current status |
| Determine whether a task is stalled | Cross-check logs, CPU, and network/subprocess progress within the user-specified observation window | Evidence for each signal and a conclusion of "running/suspected stalled/unable to determine" |
| Recover or terminate a task | First confirm the target and data risk, then proceed in the order TERM→recheck→KILL | Each signal, confirmation point, exit status, and follow-up recovery recommendation |
How customers use it
Provide the following inputs; if inputs that would change the termination target or log destination are missing, ask first and do not guess:
- The command to run or diagnose, and the working directory;
- An existing PID or tmux session (if applicable);
session_name、log_dir、stall_window_seconds、term_grace_seconds;- Optional
fallback_command, and whether termination of the target process is pre-authorized.
This skill is not needed when only viewing short command output or file contents.
Dependencies and installation
Install this skill:
npx skills add soia-team/soia-open-dev-coding-skills -g -a '*' -s soia-dev-terminal-ops -y
Hard dependencies: POSIX shell,ps、kill. The tmux workflow requires tmux. Network connectivity checks optionally use lsof; when missing, mark it as "network signal not checked" and do not use that to conclude a deadlock.
Optional configuration:
~/.config/soia-skills/soia-dev-terminal-ops/config.yml
SOIA_DEV_TERMINAL_OPS_CONFIG_FILE=<custom-config-path>
Recommended configuration structure:
schema_version: 2
env:
TERMINAL_OPS_LOG_DIR: "<user-log-dir>"
TERMINAL_OPS_SESSION_NAME: "<session-name>"
TERMINAL_OPS_STALL_WINDOW_SECONDS: "<seconds>"
TERMINAL_OPS_TERM_GRACE_SECONDS: "<seconds>"
TERMINAL_OPS_FALLBACK_COMMAND: "<optional-command>"
Priority: this user input/CLI parameters → process environment → configuration file. Only when no log directory is given, use ${TMPDIR}; if TMPDIR is also not set, first ask the user to specify a directory.
Logs and completion receipts
For each report:
完成:<启动、诊断、恢复或终止结果>。
日志摘要:
- command/workdir: <命令与目录>
- session/pid: <会话名或 PID>
- log: <日志路径或“纯 stdout”>
- signals: <日志/CPU/网络/子进程证据>
- status: running / suspected-stall / inconclusive / completed / terminated / killed
验证:<退出码、复查命令和最后输出摘要>
问题与下一步:<fallback 或待确认项;没有则写“无”>
Trigger conditions
- Start or monitor a command expected to run for more than 30 seconds;
- Manage tmux sessions, background builds/tests, or continuous logs;
- Diagnose a process with no output, a hanging tool call, or an unrecoverable terminal;
- Terminate or downgrade a long-running task under an explicit confirmation gate.
Parameter parsing
Parse and echo non-secret parameters before execution:
SESSION_NAME="${TERMINAL_OPS_SESSION_NAME:?set session name}"
LOG_DIR="${TERMINAL_OPS_LOG_DIR:-${TMPDIR:?set TERMINAL_OPS_LOG_DIR or TMPDIR}}"
STALL_WINDOW_SECONDS="${TERMINAL_OPS_STALL_WINDOW_SECONDS:?set observation window}"
TERM_GRACE_SECONDS="${TERMINAL_OPS_TERM_GRACE_SECONDS:?set TERM grace period}"
FALLBACK_COMMAND="${TERMINAL_OPS_FALLBACK_COMMAND:-}"
Verify that the session name contains only letters, digits, dots, underscores, or hyphens; show the resolved absolute path before creating directories. Do not hard-code agent names, executor states, timeout values, or log file names in the skill.
Command risk classification
Default read-only/idempotent:
tmux list-sessions
ps -o pid,ppid,stat,etime,time,command -p <PID>
tail -n <LINES> <LOG_FILE>
lsof -nP -p <PID> -i # 可选
High-impact actions must first explain the target, rationale, and data risk, and obtain user confirmation (or cite explicit pre-authorization in this request):
kill -TERM <PID>;kill -KILL <PID>;tmux kill-session -t <SESSION_NAME>;- Execute
FALLBACK_COMMAND, because it may incur costs, remote state changes, or duplicate work.
After confirming the PID, read the full command and parent PID again to avoid PID reuse or selecting the wrong process. Do not use broad pkill/killall Instead of exact PID.
Background session management
The log name is specified by the caller and is not derived from the product name or agent name:
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/<log-name>.log"
tmux new-session -d -s "$SESSION_NAME" \
"cd '<workdir>' && <command> 2>&1 | tee '$LOG_FILE'"
tmux list-sessions
tmux capture-pane -p -t "$SESSION_NAME" -S -50
tail -n 50 "$LOG_FILE"
When commands, directories, or paths contain user input, use host tools to pass parameters safely; do not directly concatenate unchecked shell fragments. If a compound command must be run, first show the final command to the user exactly as it is.
Multi-signal stall diagnosis
S only indicates interruptible sleep; being in it for a long time S may also be normal waiting. Elapsed time or a single timeout is never a kill condition.
In STALL_WINDOW_SECONDS check at least two sampling points covered:
- Log progress: whether the log mtime, size, or last business progress entry has changed; when there is no log, explicitly record the gap.
- CPU progress: whether cumulative CPU time has increased; a single low CPU reading only indicates idleness at that moment.
- Network/IPC progress: if the task depends on the network, check whether the connection exists and whether its state changes;
lsofwhen unavailable, do not fabricate conclusions. - Child process progress: check whether the child process is still working, has exited, or is producing new output.
- Task-specific heartbeat: whether test counts, build targets, downloaded bytes, or queue counts, etc., have changed.
Only when "the observation window has exceeded the threshold" and at least two independent progress signals have continuously shown no change, and there is no reasonable normal-waiting explanation, mark it as suspected-stall. When signals are insufficient, mark it as inconclusive, continue observing, or ask the user to judge.
Example sampling (column names for commands on macOS/Linux may differ slightly; interpret according to actual output):
ps -o pid,ppid,stat,etime,time,command -p <PID>
wc -c < "$LOG_FILE"
tail -n 20 "$LOG_FILE"
lsof -nP -p <PID> -i 2>/dev/null || true
TARGET_PID=<PID>
ps -o pid,ppid,stat,etime,time,command -ax | awk -v p="$TARGET_PID" '$2 == p'
After waiting for the user-configured observation window, resample and diff. Do not mistakenly write "the command has not exited" as "no progress."
Safe termination and recovery
- Show the PID, full command, parent PID, working directory (when obtainable), and multi-signal evidence.
- Explain that TERM may interrupt writes, and KILL gives no chance to clean up; obtain confirmation.
- Send TERM.
- Within
TERM_GRACE_SECONDSrepeatedly recheck whether the process has exited, and check the log/disk-write status. - If it is still alive, show the recheck evidence and potential data loss, and obtain KILL confirmation again.
- Send KILL only to the same rechecked PID; then confirm that the process has disappeared, the session state, and output integrity.
- If a fallback is configured, first explain how context is passed, whether side effects and costs will be duplicated, and then execute after obtaining confirmation.
kill -TERM <PID>
# 按 TERM_GRACE_SECONDS 轮询:
ps -p <PID> >/dev/null 2>&1 || echo "terminated"
# 仍存活且再次确认后:
kill -KILL <PID>
ps -p <PID> >/dev/null 2>&1 && echo "still alive" || echo "killed"
Five output file categories
| Category | Examples in this skill | Destination |
|---|---|---|
| A Temporary | This round's build/test logs, sampling snapshots | User-specified log directory; otherwise ${TMPDIR}/soia-dev-terminal-ops/ |
| B Audit | Records of high-impact actions such as kill, session cleanup, and fallback | User-specified state directory or ${XDG_STATE_HOME}/soia-dev-terminal-ops/; if not configured, ask first |
| C Deliverable | The complete diagnostic package the user requested to keep | User explicitly specified path |
| D Product functionality as logs | Task logs defined by the target project | Only follow conventions already recorded by the target project; do not invent them in this skill |
| E Pure stdout | Short status checks, summaries that need not be retained | Do not write to disk |
The relative cwd must not be used as the default log directory. Class A may be rotated; Class B must not be deleted before the retention policy is confirmed.