How SwarmForge Adapts to Different Terminal Backends: The Adapter Pattern Explained
SwarmForge decouples its core logic from terminal emulators by sourcing modular shell scripts at runtime that implement a standardized API for session management and window tracking.
SwarmForge, the open-source automation framework maintained by Uncle Bob (Robert C. Martin), enables developers to adapt to different terminal backends through a lightweight plugin architecture. Rather than hard-coding support for specific emulators, the system isolates terminal-specific operations—such as spawning windows and tracking lifecycle events—behind a thin abstraction layer. This design allows the Babashka-based core to support diverse environments from iTerm2 to Windows Terminal without modification.
The Terminal Adapter Architecture
SwarmForge implements a terminal-adapter plugin system that treats each backend as a standalone shell script. These adapters reside in swarmforge/scripts/terminal-adapters/ and expose a minimal, well-defined API that the core orchestration logic consumes uniformly.
Script Location and Naming Convention
Each backend is represented by a single executable shell script following the naming pattern <backend>.sh. The repository includes reference implementations such as windows-terminal.sh, iterm2.sh, ghostty.sh, and none.sh. According to the unclebob/swarm-forge source code, these scripts contain platform-specific implementations of common terminal operations while presenting a consistent interface to the Clojure runtime.
The Standardized API Contract
Every adapter must implement a core set of functions that SwarmForge queries to determine capabilities and trigger actions:
terminal_backend_label() # Returns human-readable name
terminal_backend_can_open_sessions() # Exit 0 if can launch, 1 if not
terminal_backend_tracks_windows() # Exit 0 if tracks windows, 1 if launch-only
terminal_window_exists() # Optional: verify window state
terminal_open_session <id> <title> # Launch new session/window
terminal_close_window <id> # Close session (if supported)
For example, the Windows Terminal adapter implements these functions in swarmforge/scripts/terminal-adapters/windows-terminal.sh (lines 3-13), returning exit code 0 for session creation capabilities but 1 for window tracking, indicating it operates in launch-only mode.
Adapter Selection and Loading Mechanism
SwarmForge determines which terminal backend to use through a hierarchical decision process that prioritizes explicit configuration over auto-detection.
Environment Variable Override
The system checks for the SWARMFORGE_TERMINAL environment variable first. When set, SwarmForge normalizes the value to match a script name in the adapters directory:
export SWARMFORGE_TERMINAL=iterm2
./swarmforge.sh
This setting bypasses auto-detection and forces the system to load iterm2.sh regardless of the host environment.
Auto-Detection Logic
If the environment variable is unset, SwarmForge executes the detect_terminal_backend function defined in swarmforge/scripts/swarm-terminal-adapter.sh (around lines 27-50). This logic examines the running environment—checking for $TERM_PROGRAM or platform-specific indicators—to identify the current terminal emulator and map it to the appropriate adapter script.
Runtime Loading in Babashka
Once identified, the selected adapter is dynamically sourced at runtime. In swarmforge/scripts/swarmforge.bb at line 290, the core executes:
(let [path (fs/path (:script-dir ctx) "terminal-adapters" helper)]
(load-file path))
This (load-file) call injects the adapter's function definitions into the Babashka runtime, making them available for subsequent capability queries and session management operations.
Unified Execution Through Wrapper Functions
Rather than calling adapter functions directly, SwarmForge routes all backend interactions through two thin wrappers defined in swarmforge.bb (lines 651-681):
terminal-call-ok?– Checks whether a function exists and returns a successful exit status (exit code 0)terminal-call-out– Captures and returns the stdout of an adapter function
These wrappers enable safe, conditional execution. For instance, the core queries window tracking support before attempting to monitor lifecycle events:
(when (terminal-call-ok? ctx "terminal_backend_tracks_windows")
(println "Active backend:" (terminal-call-out ctx "terminal_backend_label")))
Capability-Based Behavior Adaptation
SwarmForge adapts its behavior based on the adapter's reported capabilities, specifically interpreting the exit codes of terminal_backend_can_open_sessions and terminal_backend_tracks_windows.
Launch-Only Backends
When terminal_backend_can_open_sessions returns 0 but terminal_backend_tracks_windows returns 1—as seen in the Windows Terminal adapter—SwarmForge treats the backend as launch-only. It opens separate surfaces for each session but disables the watchdog process that would otherwise monitor and manage window lifecycles. This mode is suitable for terminals that expose limited scripting APIs.
Full-Tracking Backends
Backends like iTerm2 (iterm2.sh) return exit code 0 for both capability checks. This signals that the adapter supports full window lifecycle management, enabling SwarmForge to maintain a persistent mapping of window IDs, execute terminal_close_window commands, and run cleanup watchdogs when sessions terminate.
Creating Custom Terminal Adapters
Extending SwarmForge to support new terminal emulators requires only a new shell script in the adapters directory. The minimal implementation must define the three core capability functions and at least a stub for terminal_open_session:
#!/usr/bin/env bash
terminal_backend_label() { echo "MyTerm"; }
terminal_backend_can_open_sessions() { return 0; }
terminal_backend_tracks_windows() { return 0; }
terminal_open_session() {
local session=$1 title=$2
myterm --new-session "$session" --title "$title"
}
Save this as swarmforge/scripts/terminal-adapters/myterm.sh, then invoke SwarmForge with the custom backend:
SWARMFORGE_TERMINAL=myterm ./swarmforge.sh
Contributors can find detailed guidelines in the "Terminal Back-ends" section of README.md (lines 401-447), which documents the expected function signatures and testing procedures for new adapters.
Summary
- SwarmForge isolates terminal-specific code in modular shell scripts located at
swarmforge/scripts/terminal-adapters/ - The system selects backends via the
SWARMFORGE_TERMINALenvironment variable or auto-detection logic inswarmforge/scripts/swarm-terminal-adapter.sh - Adapters implement a minimal API including
terminal_backend_label(),terminal_backend_can_open_sessions(), andterminal_open_session() - Babashka loads the selected adapter dynamically at runtime using
load-fileat line 290 ofswarmforge.bb - Capability flags determine whether SwarmForge runs a watchdog process for window lifecycle management or operates in launch-only mode
- Adding support for new emulators requires only a new shell script following the
<backend>.shnaming convention
Frequently Asked Questions
What environment variable controls the terminal backend in SwarmForge?
Set SWARMFORGE_TERMINAL to the base name of your desired adapter script (e.g., iterm2, ghostty, or windows-terminal). SwarmForge normalizes this value and sources the corresponding file from swarmforge/scripts/terminal-adapters/ before executing any session management commands.
How do I create a custom terminal adapter for SwarmForge?
Create a new file named <your-backend>.sh in the swarmforge/scripts/terminal-adapters/ directory. Implement the required functions: terminal_backend_label(), terminal_backend_can_open_sessions(), and terminal_backend_tracks_windows(). Optionally implement terminal_open_session() and terminal_close_window() if your terminal supports programmatic control. Launch SwarmForge with SWARMFORGE_TERMINAL=<your-backend> to test your implementation.
What is the difference between launch-only and window-tracking terminal backends?
Launch-only backends (where terminal_backend_tracks_windows returns 1) can spawn new windows via terminal_open_session() but cannot detect when those windows close. SwarmForge disables its watchdog and window cleanup logic for these backends. Window-tracking backends (returning 0) support full lifecycle management, allowing SwarmForge to monitor session status and execute terminal_close_window() commands.
Which file contains the auto-detection logic for terminal backends?
The auto-detection logic resides in swarmforge/scripts/swarm-terminal-adapter.sh, specifically within the detect_terminal_backend and load_terminal_backend functions around lines 27-50. This script examines environment variables like $TERM_PROGRAM to determine which adapter to load when SWARMFORGE_TERMINAL is not explicitly set.
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 →