How SwarmForge Isolates tmux Sessions Using Custom Socket Paths

SwarmForge isolates tmux sessions by generating a unique Unix socket file per run and passing the -S <socket-path> flag to every tmux command, ensuring complete separation from any existing tmux servers on the host.

SwarmForge is a role-based orchestration tool for managing AI coding agents. According to the unclebob/swarm-forge source code, it achieves tmux session isolation through a carefully designed socket-based architecture that prevents interference with users' personal tmux configurations or other running projects.

How Socket Path Isolation Works in SwarmForge

SwarmForge's isolation strategy centers on three core mechanisms: generating unique socket identifiers, persisting socket paths for reuse, and scoping every tmux invocation to that private socket.

Generating Unique Socket Identifiers

When SwarmForge initializes its context, it creates a deterministic yet unique socket file name using a CRC-32 checksum of the absolute working directory. This ensures the same project always maps to the same socket, while different projects remain isolated.

The socket directory follows a portable temporary path pattern under /tmp to avoid platform-specific issues:

;; swarmforge/scripts/swarmforge.bb – lines 667-670
(let [socket-id (str (.getValue crc))
      tmux-socket-dir (fs/path "/tmp"
                        (str "swarmforge-" (or (System/getenv "UID")
                                              (System/getProperty "user.name"))))
      tmux-socket (str (fs/path tmux-socket-dir (str socket-id ".sock")))]

The UID environment variable takes precedence, falling back to user.name for broader compatibility. This produces paths like /tmp/swarmforge-joe/1234567890.sock.

Persisting the Socket Path

SwarmForge writes the computed socket path to .swarmforge/tmux-socket within the project root. All subsequent operations—including helper scripts and watchdog processes—read this file to locate the correct socket:

;; swarmforge/scripts/swarmforge.bb – line 316
(spit (str (:tmux-socket-file ctx)) (str (:tmux-socket ctx) "\n"))

This persistence enables inter-process coordination without hardcoding paths or relying on environment variable inheritance.

Creating Sessions on the Custom Socket

Every role's tmux session is bootstrapped with explicit -S flags. The create-role-session! function in swarmforge.bb demonstrates this pattern:

;; swarmforge/scripts/swarmforge.bb – lines 822-836
(defn create-role-session! [ctx session title]
  (sh "tmux" "-S" (:tmux-socket ctx) "new-session" "-d" "-s" session "-n" agent-window)
  (sh "tmux" "-S" (:tmux-socket ctx) "set-option" "-t" session "history-limit" (str pane-history-limit))
  (sh "tmux" "-S" (:tmux-socket ctx) "rename-window" "-t" (str session ":" agent-window) title)
  (sh "tmux" "-S" (:tmux-socket ctx) "set-window-option"
      "-t" (str session ":" title) "allow-rename" "off"))

Each sh invocation includes -S followed by the socket path, directing commands to SwarmForge's private tmux server rather than the default socket.

Scoping All tmux Queries and Control

Helper functions in swarm_window_watchdog.bb extend isolation to session introspection and cleanup:

;; swarmforge/scripts/swarm_window_watchdog.bb – lines 54-55
(defn tmux-session? [tmux-socket session]
  (zero? (:exit (process/sh {:continue true}
               "tmux" "-S" tmux-socket "has-session" "-t" session))))

Similarly, kill-session! and send-keys! operations all carry the -S flag. This guarantees that checking for session existence or terminating a role never affects unrelated tmux servers.

Verifying Portable Socket Directories

The SwarmForge test suite explicitly validates that socket paths remain platform-agnostic, particularly avoiding macOS's private /tmp alias:

;; test/swarmforge/script_test.clj – lines 124-128
(deftest swarmforge-uses-portable-tmux-socket-dir
  (let [socket-path (str/trim (slurp (str (fs/path root ".swarmforge/tmux-socket"))))]
    (is (str/starts-with? socket-path "/tmp/swarmforge-"))
    (is (not (str/starts-with? socket-path "/private/tmp/")))))

This test prevents regression on macOS, where /tmp symlinks to /private/tmp and some tmux operations behave differently with resolving versus non-resolving paths.

Manual Re-attachment to Isolated Sessions

Users can interact directly with SwarmForge's isolated tmux server using the printed socket path:


# Start SwarmForge (socket created automatically)

$ ./swarmforge.sh /path/to/project

# Output includes:

#   Tip: Reattach manually with 'tmux -S /tmp/swarmforge-joe/12345.sock attach-session -t swarmforge-coder'

# Manual operations using the custom socket

$ tmux -S /tmp/swarmforge-joe/12345.sock attach-session -t swarmforge-coder
$ tmux -S /tmp/swarmforge-joe/12345.sock send-keys -t swarmforge-coder:0 "git status" C-m
$ tmux -S /tmp/swarmforge-joe/12345.sock kill-session -t swarmforge-coder

The -S flag must precede all tmux subcommands. Omitting it connects to the default tmux server, which contains no SwarmForge sessions.

Key Implementation Files

File Responsibility
swarmforge/scripts/swarmforge.bb Socket generation, context initialization, session creation
swarmforge/scripts/swarm_window_watchdog.bb Session queries and lifecycle helpers with -S scoping
test/swarmforge/script_test.clj Assertions for portable /tmp/swarmforge-* paths
swarmforge/scripts/terminal-adapters/*.sh Terminal-specific wrappers passing TMUX_SOCKET environment variable
swarmforge/scripts/pack_*.bb Role-specific scripts that read .swarmforge/tmux-socket and send keys

Summary

SwarmForge isolates tmux sessions through a custom socket path architecture:

  • Unique socket generation: CRC-32 of working directory + user-specific /tmp directory
  • Path persistence: Stored in .swarmforge/tmux-socket for cross-script coordination
  • Universal -S flagging: Every tmux command targets the private socket
  • Platform portability: Explicitly tested to avoid macOS /private/tmp issues
  • User transparency: Socket path printed for manual re-attachment when needed

This design ensures multiple SwarmForge projects—and personal tmux usage—can coexist without conflict on the same host.

Frequently Asked Questions

What happens if I run SwarmForge from the same directory twice?

SwarmForge computes the same socket path because the CRC-32 depends only on the absolute working directory. The second invocation connects to the existing tmux server rather than creating a conflict, though role session names must be unique to avoid collisions.

Can I change where SwarmForge creates its socket files?

No—the socket directory is hardcoded to /tmp/swarmforge-<user> in swarmforge.bb. This limitation ensures the test suite's portability guarantees remain valid. Modify the source at lines 667-670 if you require a custom location.

Why does SwarmForge use CRC-32 instead of random identifiers?

Deterministic socket paths enable reconnection to an existing SwarmForge instance if the controlling process restarts. A random UUID would orphan running tmux servers and prevent recovery of in-flight agent sessions.

How do I troubleshoot "no server running on " errors?

Verify the socket file exists at the path printed in the startup tip. If missing, SwarmForge may have crashed during initialization or cleaned up on exit. Check permissions on /tmp/swarmforge-<user>/ and ensure no other user owns the directory.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →