Snapshot Herdr Workspaces
Capture the live herdr session so /herdr-reboot:restore can rebuild it after a reboot. Nothing
survives the reboot — not the workspaces, not the tabs, not the agents inside them.
Run:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.py --output .llm/resume-after-reboot-state.json
Then show the user the tree and confirm it looks right before the reboot. The state file holds
session ids personal to this machine, so keep it in the gitignored .llm/ directory.
The state file is JSON, schema resume-after-reboot/v2, and mirrors the session's own shape:
workspaces (with label, number, and active tab) hold tabs (with label, number, zoom, and focused
pane), and each tab holds a layout tree of split nodes — direction and ratio — bottoming
out in pane leaves. The document also records which workspace, tab, and pane held focus. It is
herdr-shaped, so the tmux-reboot plugin, which speaks the flat resume-after-reboot/v1, neither
reads nor writes it.
Each pane is one leaf, and slot numbers them by workspace order, then tab order, then layout
order, so a slot follows the visual layout. Review these caveats with the user when they affect
the panes:
claude panes carry the session id herdr itself reports, so they need no guessing and are exact.
Two ids are rejected before they reach the state file, because claude --resume would answer
No conversation found for both: a uuid v5 (claude mints v4 for a real session, so a v5 is a
derived placeholder) and an id whose transcript exists but is empty (the session never took a
turn). Those panes fall back to claude --continue and say so in their note. A missing
transcript is not held against the id — a pane sitting in a git worktree derives a different
project slug than the one the session was written under.
claude-rc panes are Remote Control — claude rc, the server hosting sessions driven from
claude.ai/code and the phone. herdr reports one as a claude pane carrying the id of the
placeholder session RC pre-creates on startup, which is never resumable and changes every launch,
so these are restored by relaunching with --continue instead. That reattaches the session last
recorded for the directory; past its ~4h window it errors and leaves the pane at a prompt, which
beats a fresh server that looks restored but is attached to nothing. Conversation state lives
server-side, so relaunching by hand loses none of it.
codex panes are only exact when herdr reported a session. herdr's codex integration reports
nothing until that pane takes a turn, so a codex pane that has been idle since launch falls back
to matching its working directory against recent rollout files on disk. Those panes say
herdr reported no session in their note — point them out, since the id is a best guess and
should be verified after restoration.
codex resume --last means no rollout matched the working directory at all.
command panes carry no session state, so restoring one just re-runs the command line. Their
restore_default field says whether restore replays it unasked:
false — long-lived dev servers and watchers (just dev, npm run dev, vite). Skipped by
default, because these frequently survive the reboot and still hold their ports.
true — read-only viewers (git log, git show, less FILE, man, htop, tig,
lazygit). None of these outlives the reboot, so restore replays them by default.
git panes are judged by subcommand, not by program, so git push and git rebase are never
captured. An alias is judged by what it expands to and restored as the alias you typed, so
git la comes back as git la.
- A pager is captured only when it names a file. A bare
less is draining a pipe whose writer
dies with the reboot, and re-running it would hang the pane on stdin.
shell panes are panes with nothing worth restoring; the restore just recreates the pane.
- Editors and REPLs with in-memory state (
vim, psql, ssh) are intentionally recorded as
shell panes rather than re-run.
tig and lazygit are captured as viewers, but both can stage, commit, and push from inside
the TUI — a restored one is only as safe as what you then type at it.
Regenerate immediately before rebooting so the session ids are current. Keep refresh manual unless
the user asks to automate it with cron or launchd.
Expect the file to go stale between reboots; the session keeps moving. It only has to be right just
before one, so don't chase drift or nag the user about refreshing.
1---2name: snapshot-23description: Snapshot running herdr workspaces, tabs, pane splits, and their claude/codex agents immediately before a reboot so they can be rebuilt afterward. Use when asked to snapshot, save, or capture herdr sessions before rebooting. For tmux instead of herdr, use the tmux-reboot plugin.4---56# Snapshot Herdr Workspaces78Capture the live herdr session so `/herdr-reboot:restore` can rebuild it after a reboot. Nothing9survives the reboot — not the workspaces, not the tabs, not the agents inside them.1011Run:1213```bash14python3 ${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.py --output .llm/resume-after-reboot-state.json15```1617Then show the user the tree and confirm it looks right before the reboot. The state file holds18session ids personal to this machine, so keep it in the gitignored `.llm/` directory.1920The state file is JSON, schema `resume-after-reboot/v2`, and mirrors the session's own shape:21workspaces (with label, number, and active tab) hold tabs (with label, number, zoom, and focused22pane), and each tab holds a `layout` tree of `split` nodes — `direction` and `ratio` — bottoming23out in `pane` leaves. The document also records which workspace, tab, and pane held focus. It is24herdr-shaped, so the `tmux-reboot` plugin, which speaks the flat `resume-after-reboot/v1`, neither25reads nor writes it.2627Each pane is one leaf, and `slot` numbers them by workspace order, then tab order, then layout28order, so a slot follows the visual layout. Review these caveats with the user when they affect29the panes:3031- `claude` panes carry the session id herdr itself reports, so they need no guessing and are exact.32 Two ids are rejected before they reach the state file, because `claude --resume` would answer33 `No conversation found` for both: a **uuid v5** (claude mints v4 for a real session, so a v5 is a34 derived placeholder) and an id whose transcript exists but is empty (the session never took a35 turn). Those panes fall back to `claude --continue` and say so in their note. A _missing_36 transcript is not held against the id — a pane sitting in a git worktree derives a different37 project slug than the one the session was written under.38- `claude-rc` panes are Remote Control — `claude rc`, the server hosting sessions driven from39 claude.ai/code and the phone. herdr reports one as a claude pane carrying the id of the40 placeholder session RC pre-creates on startup, which is never resumable and changes every launch,41 so these are restored by relaunching with `--continue` instead. That reattaches the session last42 recorded for the directory; past its ~4h window it errors and leaves the pane at a prompt, which43 beats a fresh server that looks restored but is attached to nothing. Conversation state lives44 server-side, so relaunching by hand loses none of it.45- `codex` panes are only exact when herdr reported a session. herdr's codex integration reports46 nothing until that pane takes a turn, so a codex pane that has been idle since launch falls back47 to matching its working directory against recent rollout files on disk. Those panes say48 `herdr reported no session` in their note — point them out, since the id is a best guess and49 should be verified after restoration.50- `codex resume --last` means no rollout matched the working directory at all.51- `command` panes carry no session state, so restoring one just re-runs the command line. Their52 `restore_default` field says whether restore replays it unasked:53 - `false` — long-lived dev servers and watchers (`just dev`, `npm run dev`, `vite`). Skipped by54 default, because these frequently survive the reboot and still hold their ports.55 - `true` — read-only viewers (`git log`, `git show`, `less FILE`, `man`, `htop`, `tig`,56 `lazygit`). None of these outlives the reboot, so restore replays them by default.57- `git` panes are judged by subcommand, not by program, so `git push` and `git rebase` are never58 captured. An alias is judged by what it expands to and restored as the alias you typed, so59 `git la` comes back as `git la`.60- A pager is captured only when it names a file. A bare `less` is draining a pipe whose writer61 dies with the reboot, and re-running it would hang the pane on stdin.62- `shell` panes are panes with nothing worth restoring; the restore just recreates the pane.63- Editors and REPLs with in-memory state (`vim`, `psql`, `ssh`) are intentionally recorded as64 `shell` panes rather than re-run.65- `tig` and `lazygit` are captured as viewers, but both can stage, commit, and push from inside66 the TUI — a restored one is only as safe as what you then type at it.6768Regenerate immediately before rebooting so the session ids are current. Keep refresh manual unless69the user asks to automate it with cron or launchd.7071Expect the file to go stale between reboots; the session keeps moving. It only has to be right just72before one, so don't chase drift or nag the user about refreshing.