# Restore

> Restore claude/codex agents from a resume-after-reboot JSON state file after tmux-resurrect reopens their windows. Use after a reboot when asked to restore, resume, or bring back tmux agents. For herdr instead of tmux, use the herdr-reboot plugin.

- Skill: `motlin/restore-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add motlin/restore-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/motlin/restore-2/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: motlin (https://skillmd.com/u/motlin)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/motlin/restore-2

---


# Restore Tmux Agents

After a reboot, tmux-resurrect reopens the windows and working directories. Resume the agents that
were running in them from the JSON snapshot written by `/tmux-reboot:snapshot`.

Preview the plan first:

```bash
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/restore.py .llm/resume-after-reboot-state.json
```

Show the user the list of windows and resume commands. Once they confirm, fire them:

```bash
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/restore.py .llm/resume-after-reboot-state.json --go
```

The state file is JSON, schema `resume-after-reboot/v1`. A file written with any other `schema`
value is rejected rather than guessed at, including the nested `resume-after-reboot/v2` that
`herdr-reboot` writes — its workspaces, tabs, and splits have no tmux equivalent here. The header
line of the
output echoes the `backend` and `captured` time so the user can see which plugin wrote the file and
how stale it is.

Rows are paired with live windows by `cwd`, not by position, because tmux-resurrect renumbers
windows. A row's `slot` is just a 1-based ordinal — pass `--skip SLOT` (repeatable) to leave one
row alone. The window running the script is fired last so the restore is not interrupted mid-run.
Each command is sent with a trailing Enter, so the user does not press return themselves — the
script both pastes and runs every resume line.

Rows with `"tool": "shell"` are idle panes with no command; they are skipped. Alongside
`claude`/`codex` agents, the snapshot may hold `command` rows — dev servers and watchers like
`just dev` (`restore_default: false`), and read-only viewers like `git log`, `less FILE`, or
`htop` (`restore_default: true`). This restore re-runs both the same way, unlike `herdr-reboot`,
which fires only the viewers unless asked. Point the dev-server rows out before firing, since
re-running one rebinds its port. Viewers re-run from the top: scroll position and search are not
restored.

Rows are only fired into windows sitting idle at a shell prompt with no live agent, so a repeated
run never types into a running program. Report the skipped rows to the user; "no live window with
this cwd" usually means tmux-resurrect has not finished restoring, or that pane's window is gone.

Verify rows whose `session_id` is `null` and whose command is `claude --continue` or
`codex resume --last`; those fallbacks mean the snapshot could not match an exact transcript. If a
resumed session opens the wrong conversation because one working directory held multiple agents or
an idle Codex transcript had a stale modification time, run `codex resume` or `claude --resume`
manually in that window and use the interactive picker.

