# How to Configure the Freebuff CLI Terminal Command Broker for Headless Operation

> Configure the Freebuff CLI terminal command broker for headless operation by setting FREEBUFF_HEADLESS=1. Bypass UI detection in CI pipelines and Docker containers.

- Repository: [Codebuff/freebuff](https://github.com/CodebuffAI/freebuff)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Set `FREEBUFF_HEADLESS=1` to force the Freebuff CLI's terminal command broker into headless mode, bypassing terminal UI detection in CI pipelines, Docker containers, and other display-less environments.**

The **terminal command broker** is a core component of the Freebuff CLI that manages how external commands are spawned and executed. By default, it attempts to attach to an interactive terminal for richer output handling. In headless environments—such as continuous integration systems, containerized deployments, or remote servers—the broker must be explicitly configured to operate without a display.

## Understanding the Terminal Command Broker Architecture

The broker implementation resides in **[[`cli/src/utils/terminal-command-broker.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)**. This module handles command execution lifecycle, including process spawning, output streaming, and error aggregation.

Before executing commands, the broker checks whether it can run in interactive mode. The detection logic lives in **[[`cli/src/utils/env.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/env.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/env.ts)** (lines 22–30), which examines:

- Presence of `DISPLAY` environment variable (X11)
- Presence of `WAYLAND_DISPLAY` environment variable (Wayland)
- The explicit override `FREEBUFF_HEADLESS`

When no display environment is detected, the broker automatically initializes in headless mode. However, automatic detection occasionally fails—particularly in nested containers or SSH sessions with forwarded X11. The `FREEBUFF_HEADLESS` variable provides deterministic control.

## Method 1: Environment Variable Configuration (Recommended)

Setting **`FREEBUFF_HEADLESS=1`** is the standard approach for configuring terminal command broker headless operation. This method works across all invocation patterns and overrides any automatic detection.

### Shell Export Pattern

```bash

# Unix/Linux/macOS

export FREEBUFF_HEADLESS=1
freebuff run my-agent --target production

```

```powershell

# Windows PowerShell

$env:FREEBUFF_HEADLESS=1
freebuff run my-agent --target production

```

```batch

# Windows Command Prompt

set FREEBUFF_HEADLESS=1
freebuff run my-agent --target production

```

### Docker Container Pattern

```dockerfile
FROM node:20-alpine

ENV FREEBUFF_HEADLESS=1

RUN npm install -g @codebuffai/freebuff

CMD ["freebuff", "run", "my-agent"]

```

Or via compose:

```yaml
services:
  freebuff-agent:
    image: codebuff/freebuff-cli:latest
    environment:
      - FREEBUFF_HEADLESS=1
    command: ["freebuff", "run", "my-agent"]

```

## Method 2: Disabling the Broker Entirely

For scenarios where you want the CLI to spawn processes directly without any broker mediation, pass the **`--no-terminal-command-broker`** flag. This flag is defined via `TERMINAL_COMMAND_BROKER_FLAG` in **[[`cli/src/utils/terminal-command-broker.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)**.

```bash
freebuff run my-agent --no-terminal-command-broker

```

**Trade-off:** Disabling the broker removes output buffering, structured error handling, and retry logic. Use this only when the broker itself causes compatibility issues.

## Method 3: Programmatic SDK Configuration

When using the Freebuff SDK directly, instantiate the broker with headless mode enforced through environment injection:

```typescript
// src/runner.ts
import { createTerminalCommandBroker } from 'freebuff/cli/src/utils/terminal-command-broker';
import { runTerminalCommand } from 'freebuff/sdk/src/tools/run-terminal-command.ts';

const broker = createTerminalCommandBroker({
  env: {
    ...process.env,
    FREEBUFF_HEADLESS: '1'
  },
  headless: true  // Explicit option if available in your version
});

const result = await runTerminalCommand({
  executable: ' terraform',
  args: ['apply', '-auto-approve'],
  broker  // Inject configured broker
}, {
  timeout: 300000
});

```

The SDK's **[[`sdk/src/tools/run-terminal-command.ts`](https://github.com/CodebuffAI/freebuff/blob/main/sdk/src/tools/run-terminal-command.ts)](https://github.com/CodebuffAI/freebuff/blob/main/sdk/src/tools/run-terminal-command.ts)** accepts an optional broker instance, falling back to default initialization if omitted.

## Verifying Headless Operation

Confirm your configuration is active by checking broker initialization logs. When `FREEBUFF_HEADLESS=1` is respected, logs contain entries such as:

```

[terminal-command-broker] Initializing in headless mode
[terminal-command-broker] Skipping terminal UI attachment (FREEBUFF_HEADLESS=1)
[terminal-command-broker] Command spawned without PTY allocation

```

Enable verbose logging if messages are suppressed:

```bash
FREEBUFF_HEADLESS=1 FREEBUFF_LOG_LEVEL=debug freebuff run my-agent

```

## Key Source Files Reference

| File | Responsibility |
|------|--------------|
| **[[`cli/src/utils/terminal-command-broker.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/terminal-command-broker.ts)** | Broker implementation, flag definitions (`--terminal-command-broker`, `--no-terminal-command-broker`) |
| **[[`cli/src/utils/env.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/env.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/env.ts)** | Headless detection logic (`DISPLAY`, `WAYLAND_DISPLAY`, `FREEBUFF_HEADLESS` parsing) |
| **[[`sdk/src/tools/run-terminal-command.ts`](https://github.com/CodebuffAI/freebuff/blob/main/sdk/src/tools/run-terminal-command.ts)](https://github.com/CodebuffAI/freebuff/blob/main/sdk/src/tools/run-terminal-command.ts)** | Public API for command execution with broker injection support |
| **[[`cli/src/utils/codebuff-client.ts`](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/codebuff-client.ts)](https://github.com/CodebuffAI/freebuff/blob/main/cli/src/utils/codebuff-client.ts)** | High-level client that wires broker into CLI commands |

## Summary

- **Preferred method:** Export `FREEBUFF_HEADLESS=1` to configure the terminal command broker for headless operation without code changes
- **Alternative:** Use `--no-terminal-command-broker` to bypass the broker entirely (sacrifices reliability features)
- **Detection:** The broker auto-detects headless environments via `DISPLAY` and `WAYLAND_DISPLAY` absence, but explicit configuration is more reliable
- **SDK usage:** Pass environment configuration or headless flag to `createTerminalCommandBroker`
- **Verification:** Check initialization logs for "headless mode" confirmation messages

## Frequently Asked Questions

### What happens if I don't configure headless mode in a CI environment?

The terminal command broker attempts to allocate a pseudo-terminal (PTY), which fails with "inappropriate ioctl for device" or similar errors. The CLI may hang waiting for terminal input or crash during initialization. Setting `FREEBUFF_HEADLESS=1` prevents PTY allocation and forces streaming output handling.

### Can I use `FREEBUFF_HEADLESS` with the VS Code extension or other IDE integrations?

Yes. The environment variable is respected regardless of how the CLI is invoked. Configure it in your IDE's terminal settings, task definitions, or launch configurations. For VS Code tasks, add `"options": { "env": { "FREEBUFF_HEADLESS": "1" } }` to your task definition.

### Does headless mode affect command output formatting?

Output remains fully captured and streamed. What changes is the *presentation layer*—progress bars become line-based logs, interactive prompts are bypassed or fail fast, and color codes may be suppressed unless `FORCE_COLOR` is also set. The underlying command execution and exit code handling are unchanged.

### Is there a performance difference between headless mode and disabled broker?

Headless mode maintains the broker's process supervision, retry logic, and structured output parsing with minimal overhead (typically <5ms per command). Disabling the broker (`--no-terminal-command-broker`) removes this overhead but also loses resilience features. For most CI pipelines, headless mode is the optimal balance.