documentation
Install and setup
Everything below is drawn from the shipped CLI — command output, defaults, and behavior as implemented. For the threat model, read SECURITY.md.
Getting started
You need Node ≥ 20.12, on macOS, Linux or Windows. A multiplexer — tmux ≥ 3.2, Zellij, herdr or cmux — gives you pane-level watching; without one unsnooze runs headless and still catches and resumes stops.
$ npm install -g unsnooze $ unsnooze setup
The setup wizard asks which agents to guard and which toggles you want, then wires everything up:
- Shell wrappers into
~/.zshrc/~/.bashrc,~/.config/fish/config.fishfor fish, or PowerShell's$PROFILE— after this, typingclaudeorcodexruns the CLI inside a watched multiplexer pane. You never call unsnooze directly to be protected. - The Claude
StopFailurehook — the authoritative limit-stop signal, carrying the session id. - Optionally the daemon (a launchd agent on macOS, a systemd user unit on Linux, a logon Scheduled Task on Windows) for GUI-surface watching and pre-wall usage warnings.
~/.unsnooze/config.jsonwith your choices — see Settings.
Fish wrappers are added when fish is your login shell or its config file already exists. An absolute XDG_CONFIG_HOME changes the location to $XDG_CONFIG_HOME/fish/config.fish. After upgrading, run unsnooze setup and open a new shell to load the wrappers.
Every file it touches is backed up first (*.unsnooze-orig pristine, *.unsnooze-bak rolling), and unsnooze uninstall removes every change. Verify the install any time with unsnooze doctor — it reports problems, not a checklist, so a healthy install is a one-liner:
$ unsnooze doctor unsnooze doctor: all clear — install is healthy. · resumer/daemon: running (pid 4821)
Anything wrong comes back as a ✗ finding with a suggested fix, and doctor --fix repairs what it safely can. One nuance on requirements: tmux version isn't checked — any tmux runs, but reviving dead sessions uses env flags that need tmux ≥ 3.2.
Supported terminals
unsnooze drives four terminal multiplexers — and works without one. Pick one explicitly with unsnooze config set multiplexer tmux|zellij|herdr|cmux|headless. On auto it uses the multiplexer you are currently inside; failing that, the only one installed (tmux breaks ties); failing that, headless.
| tmux ≥ 3.2 | Zellij | herdr ≥ 0.8 | cmux | headless | |
|---|---|---|---|---|---|
| Detect a limit stop | pane + hook + transcript | pane + hook + transcript | pane + hook + transcript | pane + hook + transcript | hook + transcript |
| Resume a live session in place | ✅ | ✅ | ✅ | ✅ | — |
| Answer Claude's limit menu | ✅ | ✅ | ✅ | ✅ | — |
| Revive a session whose pane died | ✅ | ✅ | ✅ 1 | ✅ 2 | ✅ 3 |
Wrap a bare claude into a managed session | ✅ | ✅ | ✅ | — | n/a 4 |
unsnooze reap idle sessions | ✅ | ✅ | ✅ | — | — |
attach: hint in unsnooze status | ✅ | ✅ | ✅ | — | — |
| OSC notifications to your terminal | ✅ | — | — | — | — |
- As a new tab in whichever workspace herdr already has open on that directory — a workspace is the project, not the window — and into a fresh session name (
unsnooze-2), never by restarting the stopped one, since herdr restores saved agent panes itself and a revival on top would resume the same conversation twice. - Into a fresh workspace; cmux has no joinable named-session model.
- As a detached process. Its output goes to
~/.unsnooze/headless/<session>.log, since there is no scrollback to read it out of later. - Nothing to wrap into — your own terminal is the session.
Install: brew install tmux or brew install zellij on macOS, sudo apt install tmux on Linux/WSL. herdr comes from herdr.dev — Homebrew still ships 0.7.3, which unsnooze refuses, so take the release binary.
Day to day
Run your agents like always. When one hits its limit, unsnooze records the stop in ~/.unsnooze/state.json — agent, session id, working directory, pane, and the reset time parsed from the banner — and wakes it when the limit lifts.
$ unsnooze status
[STOPPED ] f3a1c2d4 claude 5h /Users/you/work/payments
mux tmux · pane %12 · session unsnooze · via hook · resets 19/7/2026, 3:00:00 am (2h 41m) (absolute, from hook) · attempts 0/5 · ctx ~152k tok
[RESUMED ] 92d6f63d claude 5h /Users/you/oss/unsnooze
mux tmux · pane %7 · session unsnooze · via cli · resets 18/7/2026, 4:11:00 pm (due now) (absolute, from scrape) · attempts 1/5 · attach: tmux attach -t unsnoozeEach session is two lines: a header (status, 8-char id, agent, limit window, working directory) and a detail line (pane, how the stop was detected, the reset time with countdown and its provenance, attempts out of 5, plus ctx ~152k tok on stopped sessions and an attach hint on live ones). Statuses are stopped, resuming, resumed, cancelled, and failed.
On an interactive terminal, status, usage, and sessions open the live dashboard instead; pipes, CI, NO_COLOR, and --json stay plain. The common interventions:
$ unsnooze message f3a1 "Run the tests first, then continue." $ unsnooze resume-now f3a1 # don't wait for the reset time $ unsnooze cancel --all # stop tracking everything
Not sure what it's about to do? unsnooze preview is a true dry-run: it prints exactly what would be typed, where, and why — or what's holding it back — and sends nothing. It shares its decision code with the real dispatcher, so it cannot drift from what dispatch actually does. It exits 2 when a wake is actionable right now, 0 otherwise — scriptable.
The rest of the docs
Setup is the whole of the required reading. Everything else is here when you need it:
- Command reference — every command with real output, the
unsnooze usageforecast that tells you when the wall arrives, and the prompt queue that starts the next piece of work as a fresh session. - Settings and guards — every key in
~/.unsnooze/config.json, the guards that decide when not to wake a session, and how notifications reach you. - SSH multi-host fleet — watch limit-stopped sessions on every machine you code on, plus GUI surfaces and platform support.
- Troubleshooting and security — when a wake did not happen, what
unsnooze doctorreports, and the threat model.
Shipped releases and the reasoning behind each change live in the changelog; anything missing or wrong is worth reporting.