How the SwarmForge Window Watchdog Prevents Data Loss in Tmux Sessions
The SwarmForge window watchdog prevents data loss by continuously monitoring the window-state file for missing tmux windows, automatically respawning any window that remains missing for three consecutive checks, and executing a full session cleanup if the cleanup owner window itself disappears.
The unclebob/swarm-forge repository provides a resilient terminal session management system built around tmux. At its heart, the SwarmForge window watchdog ensures that transient terminal crashes or window closures never leave user data in an orphaned state by maintaining a persistent monitoring loop over every tracked window.
The Three-Stage Protection Loop
The watchdog operates from swarmforge/scripts/swarm-window-watchdog.bb as a Babashka process that executes a continuous recur loop with a 2000-millisecond pause. Each iteration performs three critical safety checks to guarantee session integrity.
Stage 1: Detecting Missing Windows
For every entry in the window-state file, the watchdog queries the terminal backend via terminal_window_exists to verify the window ID remains present in the graphical environment. If the check fails, the watchdog increments a missing-count for that specific row index.
(if (terminal-ok? … "terminal_window_exists" window-id)
(assoc counts index 0) ; window present → reset counter
(let [count (inc (get counts index 0))]
…)) ; window missing → bump counter
Source: swarmforge/scripts/swarm-window-watchdog.bb (lines 94-101)
This counter-based approach prevents the watchdog from reacting to transient rendering delays or momentary window manager hiccups.
Stage 2: Recovering Lost Windows
When a window's missing-count reaches the configurable missing-threshold (defaulting to 3), the watchdog initiates recovery. It calls terminal_open_session to spawn a new terminal window with the original session name and title, attaches it to the cleanup window, and atomically updates the state files with the new window ID via rewrite-window-id!.
(when (< count missing-threshold)
(assoc counts index count)
…)
(let [new-window-id (terminal-out … "terminal_open_session" session title cleanup-window-id)]
(rewrite-window-id! window-state-file window-ids-file index new-window-id))
Source: swarmforge/scripts/swarm-window-watchdog.bb (lines 101-107)
This "re-spawning" mechanism ensures that even if a terminal emulator crashes or is accidentally closed, the tmux session resumes inside a fresh window without data loss.
Stage 3: Fail-Safe Termination
If the cleanup owner window—the special window designated as the recovery anchor—disappears and its own missing-count reaches the threshold, the watchdog assumes catastrophic failure of the tmux environment. It immediately invokes kill-all-sessions! to terminate every tracked session and close all terminal windows, ensuring no stale state persists on disk.
(if (>= count missing-threshold)
(kill-all-sessions! script-dir window-state-file working-dir tmux-socket backend)
…)
Source: swarmforge/scripts/swarm-window-watchdog.bb (lines 112-118)
This final safeguard prevents the system from entering an undefined state where windows exist but cannot be managed or recovered.
File Structure and Integration
The watchdog relies on three core components in the swarmforge/scripts/ directory:
swarm-window-watchdog.sh— A thin Bash wrapper that launches the Babashka script with the correct classpath and arguments.swarm-window-watchdog.bb— The core Clojure implementation containing the monitoring loop, state parsing, and recovery logic.swarm-terminal-adapter.sh— The abstraction layer used by the watchdog to communicate with specific terminal backends (e.g., iTerm2, GNOME Terminal).
The main swarmforge.sh launcher starts the watchdog automatically alongside other Swarm Forge components, passing the window-state file, IDs file, cleanup owner index, tmux socket path, working directory, and backend identifier as positional arguments.
Running and Configuring the Watchdog
While typically invoked by swarmforge.sh, you can run the watchdog manually for debugging or custom deployments:
# Standard invocation
swarm-window-watchdog.sh \
/tmp/window-state.tsv \
/tmp/window-ids.txt \
0 \
/tmp/tmux.sock \
"$(pwd)" \
terminal-app
To force-update a window ID after manual session recovery:
swarm-window-watchdog.sh --rewrite-window-id \
/tmp/window-state.tsv \
/tmp/window-ids.txt \
3 \
abcdef1234567890
Programmatic invocation from Clojure uses Babashka's process library:
(require '[babashka.process :as process])
(process/sh ["bb" "swarmforge/scripts/swarm-window-watchdog.bb"
"/tmp/window-state.tsv"
"/tmp/window-ids.txt"
"0"
"/tmp/tmux.sock"
"/home/user/project"
"terminal-app"])
Summary
- The SwarmForge window watchdog monitors the
window-statefile every 2000 milliseconds to verify all tmux windows remain accessible viaterminal_window_exists. - It tracks missing windows using a counter system that tolerates up to three detection failures (
missing-threshold) before triggering recovery. - Lost windows are automatically recreated via
terminal_open_sessionand reattached to the cleanup window, with new IDs persisted throughrewrite-window-id!. - If the cleanup owner window itself disappears, the watchdog executes
kill-all-sessions!to prevent orphaned processes and data corruption. - The implementation resides primarily in
swarmforge/scripts/swarm-window-watchdog.bband is invoked throughswarm-window-watchdog.sh.
Frequently Asked Questions
What triggers the SwarmForge window watchdog to recreate a window?
The watchdog recreates a window when its internal missing-count for that window reaches the missing-threshold value (default 3). This count increments each time the watchdog loop detects—via terminal_window_exists—that the window ID no longer exists in the terminal backend, indicating the window was closed or crashed.
How does the watchdog decide when to kill all sessions?
The watchdog kills all sessions only when the cleanup owner window—the designated recovery anchor—disappears and its own missing-count reaches the threshold. This behavior, implemented in the kill-all-sessions! function, assumes that if the cleanup owner is gone, the entire tmux environment is unrecoverable, making a full shutdown safer than leaving stale state.
Can I configure the detection threshold or polling interval?
Yes. The missing-threshold variable controls how many consecutive detection failures are allowed before recovery triggers (default 3). While the polling interval is hardcoded to 2000 milliseconds (Thread/sleep 2000) in swarm-window-watchdog.bb, both values can be modified in the source before deployment to trade off between reaction speed and tolerance for transient window manager delays.
What files does the window watchdog monitor and modify?
The watchdog reads from the window-state file (TSV format listing sessions and titles) and the window-ids file (containing terminal window IDs) passed as the first two arguments. During recovery, it modifies both files via rewrite-window-id! to persist new window IDs after respawning lost sessions, ensuring the state remains synchronized with the actual terminal environment.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →