# How to Add a Custom Terminal Backend to SwarmForge: Complete Implementation Guide

> Learn how to add a custom terminal backend to SwarmForge by creating a Zsh adapter script and setting the SWARMFORGE_TERMINAL environment variable. Implement the necessary API functions for seamless integration.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: how-to-guide
- Published: 2026-08-10

---

**Adding a custom terminal backend to SwarmForge requires creating a Zsh adapter script in `swarmforge/scripts/terminal-adapters/` that implements six standard API functions, then selecting it via the `SWARMFORGE_TERMINAL` environment variable.**

SwarmForge abstracts terminal handling through *terminal adapters*—modular Zsh scripts that enable integration with any terminal emulator or remote UI. If you need to support a custom terminal that isn't covered by built-in adapters like iTerm2 or Windows Terminal, you can add a custom terminal backend to SwarmForge by conforming to the adapter interface defined in the core loader.

## Understanding the Terminal Adapter Architecture

The terminal abstraction layer lives in **[`swarmforge/scripts/swarm-terminal-adapter.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm-terminal-adapter.sh)**. This script provides three key functions that manage backend lifecycle:

- **`detect_terminal_backend`** – Automatically selects a backend based on the `SWARMFORGE_TERMINAL` environment variable or host capabilities (iTerm, macOS Terminal, Windows Terminal)
- **`normalize_terminal_backend`** – Maps user-friendly names (e.g., `iterm`, `terminal`, `wt`) to exact adapter filenames
- **`load_terminal_backend`** – Sources the adapter file from `swarmforge/scripts/terminal-adapters/<name>.sh`

When SwarmForge initializes, it calls `load_terminal_backend` with the normalized backend name, which sources your custom script and makes its functions available to the session manager.

## Required Terminal Adapter API

Every adapter must expose six public functions. SwarmForge calls these to manage terminal windows and tmux sessions:

- **`terminal_backend_label`** – Returns a human-readable name for logging purposes
- **`terminal_backend_can_open_sessions`** – Returns `0` if the backend can launch new tmux sessions, non-zero otherwise
- **`terminal_backend_tracks_windows`** – Returns `0` if the backend can query existing windows (used for cleanup operations), non-zero otherwise
- **`terminal_window_exists <window_id>`** – Returns `0` if the given window ID still exists
- **`terminal_open_session <session> <title>`** – Launches a new terminal window/tab, attaches the tmux session, and echoes the window ID
- **`terminal_close_window <window_id>`** – Closes the specific window identified by the ID

Reference implementations are available in the built-in adapters: **[`terminal-app.sh`](https://github.com/unclebob/swarm-forge/blob/main/terminal-app.sh)** (macOS Terminal) and **[`none.sh`](https://github.com/unclebob/swarm-forge/blob/main/none.sh)** (fallback no-op backend).

## Step-by-Step: Creating a Custom Backend

### 1. Create the Adapter Script

Create a new file in `swarmforge/scripts/terminal-adapters/` named after your backend (e.g., [`mybackend.sh`](https://github.com/unclebob/swarm-forge/blob/main/mybackend.sh)). The file must be executable Zsh.

### 2. Implement the Required Functions

Below is a complete example implementing a GNOME Terminal adapter. This script opens new GNOME Terminal windows and attaches them to tmux sessions:

```zsh
#!/usr/bin/env zsh

# File: swarmforge/scripts/terminal-adapters/mybackend.sh

terminal_backend_label() {
  echo "GNOME Terminal"
}

terminal_backend_can_open_sessions() {
  # Return 0 if gnome-terminal is available

  has_command gnome-terminal && return 0
  return 1
}

terminal_backend_tracks_windows() {
  # GNOME Terminal does not support reliable window querying

  return 1
}

terminal_window_exists() {
  # No tracking capability; assume window exists

  return 0
}

terminal_open_session() {
  local session="$1"
  local title="$2"
  
  # Launch GNOME Terminal, cd to working directory, and attach tmux

  gnome-terminal \
    --title="$title" \
    -- bash -c "cd \"$WORKING_DIR\" && exec tmux -S \"$TMUX_SOCKET\" attach-session -t \"$session\""
  
  # Echo placeholder ID since GNOME Terminal doesn't return window IDs

  echo "gnome-terminal"
}

terminal_close_window() {
  # No reliable method to close by ID; silently succeed

  return 0
}

```

Place this file at [`swarmforge/scripts/terminal-adapters/mybackend.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/terminal-adapters/mybackend.sh) and make it executable:

```bash
chmod +x swarmforge/scripts/terminal-adapters/mybackend.sh

```

### 3. Select Your Backend

Activate your custom backend by setting the environment variable before invoking SwarmForge:

```bash
export SWARMFORGE_TERMINAL=mybackend

```

SwarmForge will now load your adapter via `load_terminal_backend "mybackend"` and use your implementations for session management.

**Note:** Some legacy scripts in the codebase reference `SWARMFORGE_TERMINAL_BACKEND` (as seen in [`swarmforge/scripts/swarm-cleanup.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm-cleanup.sh)), but the primary variable for new implementations is `SWARMFORGE_TERMINAL`.

## Summary

- SwarmForge loads terminal adapters from **`swarmforge/scripts/terminal-adapters/`** via the loader in **[`swarmforge/scripts/swarm-terminal-adapter.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm-terminal-adapter.sh)**
- Custom backends must implement six standard functions: `terminal_backend_label`, `terminal_backend_can_open_sessions`, `terminal_backend_tracks_windows`, `terminal_window_exists`, `terminal_open_session`, and `terminal_close_window`
- Adapter scripts must be executable Zsh files placed in the terminal-adapters directory
- Activate custom backends using the **`SWARMFORGE_TERMINAL`** environment variable set to the script name without the `.sh` extension
- Reference built-in adapters like **[`terminal-app.sh`](https://github.com/unclebob/swarm-forge/blob/main/terminal-app.sh)** and **[`none.sh`](https://github.com/unclebob/swarm-forge/blob/main/none.sh)** for implementation patterns

## Frequently Asked Questions

### What programming language must I use for the adapter script?

You must write terminal adapters in **Zsh**. The SwarmForge loader sources these scripts directly into the main Zsh environment, so they must be compatible with Zsh syntax and have access to the shell functions and variables defined by the core system.

### Where does SwarmForge look for adapter files?

SwarmForge loads adapters from the **`swarmforge/scripts/terminal-adapters/`** directory relative to the repository root. The `load_terminal_backend` function constructs the path by appending the backend name and `.sh` extension to this directory.

### Can I use environment variables within my adapter script?

Yes. Your adapter has access to SwarmForge's internal variables including **`$WORKING_DIR`** and **`$TMUX_SOCKET`**, which you should use when launching terminal sessions to ensure proper tmux attachment and directory context.

### How do I handle terminals that cannot track window IDs?

If your terminal emulator cannot reliably track or query window IDs (like GNOME Terminal), implement `terminal_backend_tracks_windows` to return `1` (false) and `terminal_window_exists` to always return `0`. This tells SwarmForge to skip window cleanup operations for your backend, as demonstrated in the [`none.sh`](https://github.com/unclebob/swarm-forge/blob/main/none.sh) fallback adapter.