# How `window-invisible` vs `window` Lines in `swarmforge.conf` Control the Terminal Surface

> Learn how window-invisible vs window lines in swarmforge.conf control your terminal surface. Run agents invisibly or create visible, tracked terminal sessions with ease.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: deep-dive
- Published: 2026-08-30

---

**`window-invisible` runs agents in tmux without a visible Terminal window, while `window` creates both a tmux session and a tracked Terminal surface for the role.**

The [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) configuration file in [unclebob/swarm-forge](https://github.com/unclebob/swarm-forge) defines one line per role in your swarm. The first token on each line determines whether SwarmForge opens a **Terminal surface**—a visible window or tab that tracks the agent's session. Understanding how `window-invisible` and `window` control this behavior is essential for configuring headless automation versus interactive monitoring.

## How the Directive Controls Terminal Surface Creation

The `visible-window?` function in `swarmforge/scripts/swarmforge.bb` implements the core logic:

```clojure
(defn visible-window? [directive line-no]
  (case directive
    "window"          true
    "window-invisible" false
    (config-fail! (str "Unknown config directive on line " line-no ": " directive))))

```

This function returns a boolean that flows through the parsing pipeline:

- **`window`** → returns `true` → triggers Terminal surface creation
- **`window-invisible`** → returns `false` → suppresses external window creation

## The Complete Flow from Configuration to Terminal

### Step 1: Configuration Parsing

When `parse-window-line` processes a [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf) entry, it stores the `visible-window?` result in the `:visible?` field of the `window-row` description.

### Step 2: Terminal Backend Dispatch

The [`swarmforge/scripts/swarm-terminal-adapter.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm-terminal-adapter.sh) script acts as the dispatcher. It reads the `:visible?` flag and either:

- **Invokes a terminal adapter** from `swarmforge/scripts/terminal-adapters/` (e.g., [`windows-terminal.sh`](https://github.com/unclebob/swarm-forge/blob/main/windows-terminal.sh), [`ghostty.sh`](https://github.com/unclebob/swarm-forge/blob/main/ghostty.sh), [`terminal-app.sh`](https://github.com/unclebob/swarm-forge/blob/main/terminal-app.sh)) when `:visible?` is `true`
- **Falls back to [`none.sh`](https://github.com/unclebob/swarm-forge/blob/main/none.sh)** behavior—attaching the cleanup tmux session in the current shell—when `:visible?` is `false`

Both paths still run the agent inside tmux; only the external window creation differs.

## Practical Configuration Examples

### Invisible Window (Default for Pack Branches)

```conf
window-invisible coder grok coder

```

**Result:** The `coder` role executes within tmux with no external Terminal window. The adapter skips window creation entirely.

### Visible Window with Tracked Surface

```conf
window architect claude wt-arch task --dangerously-skip-permissions

```

**Result:** The `architect` role runs in tmux **and** opens a Terminal window or tab via the detected backend. The watchdog can reopen this surface if it closes unexpectedly.

## Programmatic Visibility Check

You can verify the behavior in Clojure:

```clojure
;; Inside swarmforge.bb during configuration parsing
(let [directive "window"
      visible? (visible-window? directive 1)]
  ;; visible? => true, so swarm-terminal-adapter.sh will invoke
  ;; a terminal-adapter script like ghostty.sh or terminal-app.sh
  )

```

## Key Files and Their Roles

| File | Purpose |
|------|---------|
| `swarmforge/scripts/swarmforge.bb` | Parses [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf); defines `visible-window?` to distinguish directives |
| [`swarmforge/scripts/swarm-terminal-adapter.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm-terminal-adapter.sh) | Dispatches to terminal adapters based on `:visible?` flag |
| `swarmforge/scripts/terminal-adapters/*.sh` | Platform-specific Terminal surface creation scripts |
| [`README.md`](https://github.com/unclebob/swarm-forge/blob/main/README.md) (lines 11-12, 78-81) | Documents directive semantics and pack branch defaults |

According to the swarm-forge source code, pack branches deliberately use `window-invisible` to avoid window proliferation, while visible `window` lines enable trackable terminal surfaces through the small terminal backend adapter.

## Summary

- **`window-invisible`** creates a tmux session only—no external Terminal surface appears
- **`window`** creates both a tmux session and a visible, tracked Terminal window/tab
- The `visible-window?` function in `swarmforge.bb` implements this two-state logic
- Terminal adapter scripts in `terminal-adapters/` are conditionally invoked based on the `:visible?` flag
- Pack branches default to `window-invisible` for streamlined, headless operation

## Frequently Asked Questions

### Can I mix `window` and `window-invisible` in the same [`swarmforge.conf`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge.conf)?

Yes. Each line is parsed independently, so you can configure some roles with visible Terminal surfaces for monitoring while others run headless. The `visible-window?` function evaluates each directive separately during the `parse-window-line` phase.

### What happens if I use an unknown directive instead of `window` or `window-invisible`?

The `visible-window?` function calls `config-fail!` with a descriptive error message including the line number and unknown directive. SwarmForge will exit with a configuration error before attempting to launch any agents.

### Does `window-invisible` completely disable terminal output?

No. The agent still runs inside tmux with full I/O capabilities through the tmux session. You can attach to it manually with `tmux attach-session`. The "invisible" designation only prevents automatic creation of external Terminal windows or tabs through the adapter layer.