restart-resume
Skill2 starsChanged 6 months agoMITView on GitHub
Restore every tmux Claude session captured by /restart-process — recreates the original tmux layout (sessions, windows, panes with correct geometry via window_layout strings) and spawns FRESH claude processes (NOT --resume) with each pane's captured handoff as the first user message. Use when you say '/restart-resume', 'resume sessions after reboot', 'restore my tmux setup', 'bring back my claudes', 'I just rebooted - restore', or when a SessionStart hook surfaces a pending restart manifest banner. Reads the manifest at `$RESTART_HANDOFFS_DIR/latest/manifest.json` (default `~/.cache/claude-restart/latest/manifest.json`) — verifies checksum + schema before doing anything. Pairs with /restart-process — that skill captures, this restores.
In this repository10 other files it gives its agents.
- chrome-validateSkill
- clarifySkill
- datavizSkill
- delegateSkill
- fresh-eyesSkill
- plan-archiveSkill
- pre-sendSkill
- respond-htmlSkill
- restart-processSkill
- second-opinionSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
Verify a manifest exists at ${RESTART_HANDOFFS_DIR:-$HOME/.cache/claude-restart}/latest/manifest.json.
- Distinctive: line 96
Window renaming only applies to freshly-created sessions: If the session already existed (per the limitation above), its windows are NOT …
- Very specific: line 97
Layout strings include a tmux checksum prefix: If you hand-edit a manifest, recompute the layout string via tmux list-windows -F …
- Very specific: line 102
If a different /restart-process was triggered after the manifest you're trying to restore — only latest is restored.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/restart-resume — Rebuild every session post-reboot
Reads the most recent restart manifest produced by /restart-process, recreates the tmux layout (sessions, windows, pane geometry), and spawns fresh claude processes per Claude pane with the captured handoff as the first user message.
Why fresh, not --resume: the whole point of /restart-process + /restart-resume is to take advantage of an updated claude binary, new MCP versions, fresh memory, no stale connections. --resume reuses old session state including the binary version. We deliberately discard that.
Where the manifest lives
By default, $HOME/.cache/claude-restart/latest/manifest.json (a symlink to the most recent archive dir). Override the root via the RESTART_HANDOFFS_DIR env var if /restart-process was configured to write elsewhere.
When to invoke
- A fresh terminal opens post-reboot and a SessionStart hook surfaces a pending manifest banner
- The user says
/restart-resumeor any of the trigger phrases in the description above - Auto-invocation via the SessionStart-hook mechanism — wire your hook to emit
additionalContextreferencing this skill; the model will then invoke without asking
Pre-flight
- Verify a manifest exists at
${RESTART_HANDOFFS_DIR:-$HOME/.cache/claude-restart}/latest/manifest.json. If missing, abort with: "no pending manifest — was /restart-process actually run?". - Print a summary BEFORE any destructive tmux mutation:
import json, os root = os.environ.get("RESTART_HANDOFFS_DIR") or os.path.expanduser("~/.cache/claude-restart") m = json.load(open(f"{root}/latest/manifest.json")) n_sessions = len({w["session"] for w in m["windows"]}) n_claude = sum(1 for w in m["windows"] for p in w["panes"] if p.get("is_claude")) n_panes = sum(len(w["panes"]) for w in m["windows"]) print(f'Manifest from {m["captured_at"]}: {n_claude} claude panes across ' f'{n_sessions} sessions ({n_panes} total panes).') print(f'Orchestrator was at: {m["orchestrator_pane"]}') - Confirm intent to the user: "About to recreate
<N>tmux sessions. Existing sessions with the same names will be reused (their first windows may be renamed to manifest names). Proceeding."
Invocation
~/.claude/skills/restart-process/scripts/restore.sh \
"${RESTART_HANDOFFS_DIR:-$HOME/.cache/claude-restart}/latest"restore.sh is the shared engine (lives in the sibling /restart-process skill dir since that's where the rest of the family lives). It performs seven phases:
- R1. Reads
manifest.json; validatesschema_version: 1; validates sha256 checksum against canonical re-serialization; verifies every referencedhandoff_path,launcher_path,pane_state_pathexists. Exits2on any mismatch. Symlink path arguments are resolved viarealpathup-front (see Failure modes #7). - R2. For each session in the manifest: if it doesn't exist,
tmux new-session -d -s <name> -c <first_pane_cwd>. If it does exist (e.g. a scheduled task or shell startup recreated it between/restart-processand/restart-resume), log and proceed. Handoffs are not lost to silent collisions — the own-pane case (the typical collision) is handled by displaced-spawn in R7. Other collisions are documented under "Known limitations". - R3. For each window:
tmux new-window -t <session>:<idx> -n <name> -c <cwd>(skips windows that already exist after R2). The explicit-t session:idxis load-bearing — it preserves non-contiguous indices (e.g.{1, 3, 6}) the manifest captured. - R4. EXPLICIT ORDER per window:
- (i)
tmux split-windowuntil pane count matches manifest - (ii)
tmux select-layout '<window_layout>'to restore exact geometry - (iii)
sleep 0.3then per pane:send-keys- Claude pane: send
cd <cwd> && claude "$(cat <abs-handoff-path>)"+ Enter — claude boots with the handoff as the first user message - Non-Claude pane: send the captured
argv— NO Enter (user reviews before executing)
- Claude pane: send
- (i)
- R5. Own-pane skip: whichever pane is running
/restart-resumeis the de facto orchestrator for this run and is skipped unconditionally (not just whenis_orchestrator == Truein the manifest). If the skipped pane has a Claude handoff in the manifest, the handoff is queued for displaced-spawn in R7 — it does NOT get orphaned on disk. - R6. Mark manifest consumed: write a
restored_atmarker file inside the archive dir + remove thelatestsymlink. This prevents a SessionStart banner from firing on subsequent sessions. - R7. Displaced-spawn queue: for each handoff queued in R5, find the next free window index in the same session and create a new window there named
<original-name> (resumed). Sendcd <cwd> && claude "$(cat <abs-handoff>)"+ Enter so Claude boots with the handoff as its first user message. This lets you invoke/restart-resumefrom a pre-existing session (e.g. a fresh post-reboot terminal that automatically opened a session matching one in the manifest) without losing the Claude that was supposed to land at the orchestrator's pane.
Post-restoration
Tell the user:
- N panes restored (includes any displaced)
- M panes skipped (own-pane skips that had no Claude handoff to displace)
- D panes displaced (own-pane Claude handoffs spawned at
<session>:<next-free-idx>instead of the manifest's original target — JSON listsorig_target_pane,new_target_pane,window_name) - Any errors
- Manifest archived at
<ts>/(no longer thelatestsymlink target)
Failure modes
| # | Failure | Behavior |
| 1 | No latest/ symlink | Abort; no destructive action |
| 2 | Checksum mismatch | Abort with stated vs computed hashes |
| 3 | Schema version mismatch | Abort — restore engine needs to be updated for new schema |
| 4 | Per-pane file missing | Abort — manifest references a file that's not on disk |
| 5 | select-layout fails | Non-fatal: tmux falls back to default tiling for that window |
| 6 | send-keys fails for one pane | Logged, continue with other panes |
| 7 | restore.sh invoked with a symlink path (the typical case) | Resolved via realpath() BEFORE composing any send-keys command — otherwise R6's symlink removal would race the slow-to-init pane shells, causing cat <symlink>/handoff-*.md to fail and Claude to boot with no context |
| 8 | Restore runs in a tmux pane the manifest claims existed (own-pane collision) | Skipped at the original target via R5; the Claude handoff is displaced-spawned at <session>:<next-free-idx> by R7 (zero info loss) |
| 9 | Non-own-pane collision in a pre-existing session (rare) | Existing windows are reused; send-keys lands in them. See "Known limitations" |
Known limitations
- Non-own-pane collisions in pre-existing sessions reuse the existing windows. If a scheduled task or your shell startup created a session with the same name as one in the manifest AND that session also has windows at the same indices the manifest specifies (a rarer case than the own-pane variant, which R7 handles), restore will send-keys into those existing windows. Workaround: kill the conflicting session before invoking
/restart-resume, or pass an alternate manifest dir directly. - Window renaming only applies to freshly-created sessions. If the session already existed (per the limitation above), its windows are NOT renamed — to avoid clobbering user windows.
- Layout strings include a tmux checksum prefix. If you hand-edit a manifest, recompute the layout string via
tmux list-windows -F '#{window_layout}'— otherwiseselect-layoutfails (non-fatal, but the geometry won't match exactly).
When NOT to use
- Mid-task —
restoremutates tmux globally. Don't run if you have active work that conflicts with the manifest's expected sessions. - If a different
/restart-processwas triggered after the manifest you're trying to restore — onlylatestis restored. Older manifests can be restored manually by passing their dir path directly.
Files
This skill is intentionally thin — all the logic lives in the sibling /restart-process skill's scripts/restore.sh. Tests for restore.sh (including regression coverage for #7 above) live in /restart-process/tests/restore.bats.
SKILL.md— this file (just the contract + invocation)- Engine:
../restart-process/scripts/restore.sh - Tests:
../restart-process/tests/restore.bats
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

