ssh-long-running-job
Launch a multi-hour command in a detached tmux session, record it in host-notes, and poll for completion across sessions
Skill by Nightreaver
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/nightreaver-ssh-long-running-job
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: productivity
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/ssh-long-running-job
What's inside
- Skill name
ssh-long-running-job- Description
- Launch a multi-hour command in a detached tmux session, record it in host-notes, and poll for completion across sessions
- License
- GPL-3.0
- Instructions
- 331 lines in SKILL.md · view on GitHub
Agent Skills spec issues
- name: missing
Files (1)
- SKILL.md
SKILL.md (first lines)
# SSH Long-Running Job
Workflow runbook for "this command will run for hours and must survive
the MCP server, my conversation, and a flaky link". Pattern: run the
command in a detached `tmux` session on the remote, record the session
name + log path in [agent host-notes](../../skills/ssh-host-notes-append/SKILL.md),
poll until done. The motivating case is a multi-TB `rsync`, but the
same shape fits long `restic` backups, big `pg_dump`/`pg_restore`, mass
`apt` upgrades on slow boxes, dataset downloads, etc.
`ssh_exec_run_streaming` covers "minutes, not seconds" -- this runbook
covers "hours-to-days", where the job MUST be decoupled from the SSH
channel and the MCP process.
## Default-on cheatsheet rejection (since v1.9.0)
`ssh_exec_run` refuses commands that have a native MCP tool -- see
`skills/ssh-exec-run/SKILL.md`. The native-tool flow below avoids
that. Composite scripts (where the script IS the artefact) opt out
via `SSH_EXEC_ALLOW_CHEATSHEET_PATTERNS=true` at the operator level.
Every `ssh_exec_run` call in this runbook is a `tmux` / `tail` /
`grep` / `cat` / `command -v` invocation -- none of those have
native MCP wrappers and none are cheatsheet-matched. The launch
command (Section 2) wraps the long-running job inside `tmux new -d`;
that wrapper IS the long-job artefact (its detachment + rc-file
contract is what makes resume possible), so it intentionally runs
as a single exec under one audit correlation id.
## Why tmux and not the streaming tool
| Concern | `ssh_exec_run_streaming` | This runbook (tmux + notes) |
|---|---|---|
| Per-call timeout | bounded by `timeout` arg | none -- job outlives every call |
| Survives MCP restart | only with Redis docket | yes, unconditionally |
| Survives network blip | no (`ConnectError` aborts the stream) | yes |
| Resumable | no | yes (rsync `--partial`, restic checkpoints) |
| Future conversation can find it | no | yes (notes auto-injected on `ssh_host_ping`) |
| Live progress to the client | streaming chunks | poll `tail` of the log |
If any row in column 3 doesn't matter for your case, use the streaming
tool -- it's simpler.
## Sequence
1. Precheck source host (read)
2. Launch in detached tmux + log to disk (dangerous: `ssh_exec_run`)
3. Record job in host-notes (low-access: `ssh_host_notes_append`)
4. Poll until tmux session is gone (read)
5. Resume from a future session (read + low-access)
6. Verify exit code + finalize note (low-access)
7. Failure recovery (dangerous)
## 1. Precheck source host
The "host" the MCP server connects to is wherever the long-running
command *runs from* -- for an rsync push, that's the source. Confirm:
```python
# tmux installed?
ssh_exec_run(host="nas01", command="command -v tmux", timeout=10)
# disk for the log file
ssh_host_disk_usage(host="nas01")
# nothing already in flight under the same name (avoid clobbering a
# prior run)
ssh_host_notes(host="nas01") # look for an existing [long-run] line
ssh_exec_run(host="nas01", command="tmux ls 2>/dev/null", timeout=10)
```
If tmux isn't installed, stop and ask the operator -- this runbook
does not silently fall back to `nohup` or `screen` because the
polling commands below are tmux-specific. (Replace the launch +
poll lines if you really need `screen`; the rest of the shape is
identical.)
## 2. Launch in detached tmux
Pick a stable, dated session name -- it doubles as the handle for
every subsequent poll AND the slug the future-you will grep for in
host-notes. Format: `<task>-<UTC-date>-<short-tag>`.
```python
from shlex import quote as shlex_quote
job = "xfer-2026-05-19-rsync-nas-to-dst" # session name + log slug
log = f"/var/log/{job}.log"
rc = f"/var/log/{job}.rc"
# wrap the command so its exit code lands in a known file when the
# session exits. without this you can tell "it's done" but not
# "it succeeded".
inner = (
f"rsync -aP --partial --append-verify --log-file={log} "
f"/data/ user@dst01:/data/ ; echo $? > {rc}"
)
ssh_exec_run(
host="nas01",
command=f"tmux new -d -s {job} {shlex_quote(inner)}",
timeout=15,
)
```
Key flags:
- `tmux new -d -s <name>` -- detached; returns immediately, tmux owns
the process. No PID juggling needed; the session name IS the handle.
- `--partial --append-verify` (rsync) -- a network blip or full restart
resumes from the last good byte instead of retransferring TB.
- `--log-file=...` (rsync) -- progress is preserved even if no one is
watching. Don't rely on `tmux capture-pane` for completeness; the
scrollback is bounded.
- `echo $? > <rc>` -- the success signal. `tmux has-session` only
tells you the session is GONE, not whether the job succeeded; an
rsync that aborted with rc=23 (partial transfer) and one that
finished cleanly look identical from tmux's perspective.
The MCP `ssh_exec_run` call returns in milliseconds because tmux
detached. The rsync is now uncoupled from the MCP channel.From Nightreaver/python-ssh-mcp, GPL-3.0.
More from Nightreaver/python-ssh-mcp
- 0.529score
ssh-host-snapshot
Nightreaver
Capture a structured point-in-time inventory of a host (packages, systemd, network, storage, docker) for later diff or rollback reference
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-apt-list
Nightreaver
List APT packages on a remote host, filtered by mode and optional pattern
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-apt-show
Nightreaver
Show combined apt-cache show + policy details for one package
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-disk-cleanup
Nightreaver
Investigate a disk-full host and recover space safely -- find before prune, never volume-prune from the LLM
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-container-rollout
Nightreaver
Roll a single standalone Docker container to a new image tag with pre-pull, health verification, and rollback
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-deploy-verify
Nightreaver
Upload an artifact, verify the remote hash, bring the stack up, and tail logs to confirm health
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-docker-incident-response
Nightreaver
Diagnose a Docker container or compose stack that's failing, looping, or unresponsive
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-host-healthcheck
Nightreaver
Standard "is this host OK right now" pass combining identity, alerts, disk, processes, and uptime
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-integrity-audit
Nightreaver
Confirm a host's identity, file integrity, artifact signatures, and surface SUID / world-writable oddities
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-verify-signature
Nightreaver
Verify the signature of a remote artifact (GPG, cosign, minisign) via ssh_exec_run
SkillCFreshness: C★ 8Claude Code +9 - 0.523score
ssh-apt-install
Nightreaver
Install one or more APT packages on a remote host
SkillCFreshness: C★ 8Claude Code +9 - 0.523score
ssh-apt-mark
Nightreaver
Hold or unhold APT packages on a remote host (pin / unpin)
SkillCFreshness: C★ 8Claude Code +9
Signals
- Stars
- 8
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Jun 1, 2026 (4 months ago)
- Last release
- Jun 2, 2026 (4 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- GPL-3.0
- Repository
- github.com/Nightreaver/python-ssh-mcp
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from Nightreaver
- 0.529score
ssh-host-snapshot
Nightreaver
Capture a structured point-in-time inventory of a host (packages, systemd, network, storage, docker) for later diff or rollback reference
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-apt-list
Nightreaver
List APT packages on a remote host, filtered by mode and optional pattern
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-apt-show
Nightreaver
Show combined apt-cache show + policy details for one package
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-disk-cleanup
Nightreaver
Investigate a disk-full host and recover space safely -- find before prune, never volume-prune from the LLM
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-container-rollout
Nightreaver
Roll a single standalone Docker container to a new image tag with pre-pull, health verification, and rollback
SkillCFreshness: C★ 8Claude Code +9 - 0.526score
ssh-deploy-verify
Nightreaver
Upload an artifact, verify the remote hash, bring the stack up, and tail logs to confirm health
SkillCFreshness: C★ 8Claude Code +9
Cite this page
ssh-long-running-job skill. Agent Mart. https://agentmart.dev/skills/nightreaver-ssh-long-running-job (last updated 2026-10-24)