How SwarmForge Uses tmux: Session Management, Transcript Capture, and Role Isolation
SwarmForge uses tmux as the core infrastructure for orchestrating isolated terminal sessions per role, capturing interactive output to scrollback, and enabling clean teardown when swarms complete.
In the unclebob/swarm-forge repository, tmux is not merely a convenience tool—it is the deliberate architectural choice for managing the lifecycle of multi-role swarms. The codebase demonstrates precise control over tmux socket creation, per-role session spawning, output persistence, and server shutdown. This article examines the implementation details found in the test suite and supporting files.
Tmux Socket Creation and Portability
Every swarm begins with a dedicated tmux socket. This socket file enables multiple processes to coordinate against the same tmux server without relying on default system paths.
The socket path is written to .swarmforge/tmux-socket for discoverability:
(let [sock (str (fs/path root "tmux.sock"))]
(write-file (fs/path root ".swarmforge/tmux-socket") (str sock "\n"))
;; Subsequent tmux commands use -S sock
...)
This pattern appears in test/swarmforge/script_test.clj at lines 110 and 893, where the test suite verifies socket file existence and persistence. The socket-based approach ensures that:
- SwarmForge can run multiple swarms concurrently without socket collisions
- Any subprocess can locate and communicate with the correct tmux server
- The entire tmux state is scoped to the swarm's working directory
Per-Role Session Spawning
Each role in a swarm receives its own isolated tmux window. The helper start-tmux! in test/swarmforge/pack_ui_test.clj (line 195) encapsulates this logic:
;; From pack_ui_test.clj - starts tmux session for each role
(doseq [role roles]
(run {:dir root}
"tmux" "-S" sock "new-session" "-d"
"-s" (str "swarmforge-" role)
"sleep" "120"))
The session naming convention swarmforge-{role} creates predictable targets for subsequent commands. The -d flag ensures sessions detach immediately, running in the background while SwarmForge continues orchestration.
Commands are dispatched to specific windows using the -t target flag:
(run {:dir root}
"tmux" "-S" sock "send-keys"
"-t" "swarmforge-specifier:Specifier.0"
"-l" "your command here" "C-m")
This direct addressing enables SwarmForge to route tasks to the appropriate role without complex process management.
Transcript Capture in Scrollback
A critical requirement for swarm observability is retaining complete output history. SwarmForge leverages tmux's native scrollback buffer for this purpose.
The test launch-command puts transcript in scrollback at line 447 of test/swarmforge/script_test.clj explicitly validates this behavior. After a command executes, its full output remains accessible through tmux's history—enabling:
- Post-hoc debugging of failed role executions
- Replay of interactive sessions
- Audit trails without separate log file management
This design choice avoids the complexity of external log aggregation while ensuring no output is lost during role execution.
Graceful Shutdown and Cleanup
When a swarm terminates, SwarmForge ensures complete tmux server teardown. The close-swarm logic at line 886 of test/swarmforge/script_test.clj demonstrates the pattern:
;; Kill the tmux server and all associated sessions
(run {:dir "." :ok? false} "tmux" "-S" sock "kill-server")
The :ok? false parameter acknowledges that the command may fail if the server already exited—an acceptable condition that prevents error propagation during cleanup. This approach guarantees:
- No orphaned tmux processes persist after swarm completion
- The socket file becomes invalid, preventing accidental reconnection
- System resources are promptly released
Summary
- Socket-based coordination: Each swarm creates a dedicated tmux socket stored at
.swarmforge/tmux-socket, enabling portable multi-process access - Per-role isolation: Every role runs in a named tmux session (
swarmforge-{role}), with commands targeted via explicit window addresses - Built-in output persistence: Tmux scrollback buffers capture complete transcripts without additional logging infrastructure
- Clean resource management:
kill-serverensures deterministic teardown of all sessions and the socket on swarm completion
Frequently Asked Questions
Why does SwarmForge use tmux instead of Docker or raw subprocesses?
Tmux provides lightweight terminal multiplexing without containerization overhead. As implemented in unclebob/swarm-forge, it offers interactive session persistence, scrollback capture, and clean signal propagation—capabilities that raw subprocess management would require significant custom code to replicate.
Where is the tmux socket path stored in a swarm project?
The socket path is written to .swarmforge/tmux-socket in the swarm root directory. This convention appears in test/swarmforge/script_test.clj (lines 110, 893) and enables any component to locate the active tmux server for that swarm.
How does SwarmForge prevent tmux session name collisions?
Session names follow the pattern swarmforge-{role} combined with a unique socket path per swarm. Since each swarm operates on its own socket, identical role names across different swarms do not conflict—demonstrated in test/swarmforge/pack_ui_test.clj (line 195).
Can I inspect a running swarm's tmux sessions manually?
Yes. With the socket path from .swarmforge/tmux-socket, run tmux -S /path/to/socket list-sessions to view active role windows. The test suite at test/swarmforge/script_test.clj shows this pattern used for verification during automated testing.
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 →