> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ctrlnode.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Bridge configuration

> BASE_PATH, .env precedence, all providers loaded, Hermes env vars, and timeouts

Configure the Bridge with environment variables or `~/.ctrlnode/.env`. The runtime reads config at **startup**; installers (`install.ps1` / `install.sh`) create the initial file.

<Note>
  Interactive setup belongs in **install scripts**, not in the Bridge binary. After install, edit `~/.ctrlnode/.env` or your shell profile.
</Note>

## Where settings live

**`.env` search order** (first existing file wins; keys already in the process environment are not overwritten from file, except installer overrides — see below):

1. `{BASE_PATH}/.ctrlnode/.env` (recommended — written by installers)
2. `./.env` (current working directory)
3. `~/.env` (home directory)

For keys `PAIRING_TOKEN`, `SAAS_URL`, and `BASE_PATH`, values in **`~/.ctrlnode/.env` from the installer override** stale shell exports so a random `PAIRING_TOKEN=test` in your profile does not break production pairing.

Example:

```env theme={null}
PAIRING_TOKEN=your_token_from_bridge_setup
SAAS_URL=wss://api.ctrlnode.ai/ws/bridge
BASE_PATH=C:\Users\you
```

On disk, Bridge data lives under:

```text theme={null}
{BASE_PATH}/.ctrlnode/
  tasks/              # per-task output folders (OUTPUT ONLY mode)
  agents/             # Hermes only: optional AGENTS.md + .meta.json
  .hermes-sessions/   # Hermes CLI conversation resume
  .codex-agents/      # Codex per-agent CODEX_HOME
```

## Core connection

| Variable        | Required | Default                           | Description                            |
| --------------- | -------- | --------------------------------- | -------------------------------------- |
| `PAIRING_TOKEN` | **Yes**  | —                                 | Token from **Bridge Setup** in the app |
| `SAAS_URL`      | No       | `wss://api.ctrlnode.ai/ws/bridge` | Control plane WebSocket URL            |

## Workspace: `BASE_PATH` (replaces `AGENTS_FOLDER`)

| Variable    | Required | Default             | Description                                  |
| ----------- | -------- | ------------------- | -------------------------------------------- |
| `BASE_PATH` | No       | User home directory | Parent directory for `{BASE_PATH}/.ctrlnode` |

Installers set **`BASE_PATH`** (not `AGENTS_FOLDER`). This is the “workspace parent” you choose at install time — where task folders and Bridge metadata are stored.

<Warning>
  **`AGENTS_FOLDER` is legacy.** Do not document or set it for new installs. Use **`BASE_PATH`** only.
</Warning>

**Project work directory** is separate: it is configured per **project** in the web app (`repositoryPaths`), not via a Bridge env var. See [Tasks — work modes](/tasks/task-work-modes).

## Providers: no `PROVIDERS` env var

The Bridge **always loads all built-in providers**:

```text theme={null}
openclaw, claude, claude-sdk, copilot, gemini, codex, cursor, hermes
```

| Variable    | Effect today                                        |
| ----------- | --------------------------------------------------- |
| `PROVIDERS` | **Ignored** (kept only for backwards compatibility) |
| `PROVIDER`  | **Ignored**                                         |

**Routing** is driven by CtrlNode: on connect the server sends `sync_{provider}_agents` for each CLI type. The Bridge maps each agent id → provider. Install only the CLIs you use; missing tools fail tasks with clear errors instead of silent mis-routing.

<Note>
  If `openclaw.json` is missing, OpenClaw is skipped at runtime with a warning — other providers still work.
</Note>

Per-provider setup: [Providers](/bridge/providers).

## OpenClaw paths

| Variable                                                        | Default                  | Description                      |
| --------------------------------------------------------------- | ------------------------ | -------------------------------- |
| `OPENCLAW_GATEWAY_URL`                                          | `http://localhost:18789` | Gateway HTTP base                |
| `OPENCLAW_GATEWAY_TOKEN`                                        | —                        | Bearer token for `/tools/invoke` |
| `OPENCLAW_HOME` / `OPENCLAW_CONFIG_PATH` / `OPENCLAW_STATE_DIR` | resolved                 | See OpenClaw provider page       |

## Provider credentials (summary)

| Provider id  | Primary setup                                                                                     |
| ------------ | ------------------------------------------------------------------------------------------------- |
| `openclaw`   | `OPENCLAW_GATEWAY_TOKEN`, gateway URL                                                             |
| `claude`     | Claude Code CLI login                                                                             |
| `claude-sdk` | `ANTHROPIC_API_KEY` or subscription / `claude login`                                              |
| `copilot`    | `copilot login` or `COPILOT_GITHUB_TOKEN`                                                         |
| `gemini`     | `GEMINI_API_KEY` / `GOOGLE_API_KEY` or `gemini auth login`                                        |
| `codex`      | `CODEX_API_KEY` or `codex auth login`; optional `CODEX_BIN_PATH`                                  |
| `cursor`     | `CURSOR_API_KEY` (required)                                                                       |
| `hermes`     | `pip install "hermes-agent[acp]"`, `hermes` on PATH; optional `HERMES_USE_ACP=false` for CLI-only |

## Hermes-specific

| Variable                 | Default | Description                                                                              |
| ------------------------ | ------- | ---------------------------------------------------------------------------------------- |
| `HERMES_HOME`            | —       | Emergency global override only; normally each agent uses `~/.hermes/profiles/{agentId}/` |
| `HERMES_TIMEOUT_MINUTES` | `15`    | Task timeout                                                                             |
| `HERMES_USE_ACP`         | ACP on  | Set `false` or `0` to force `hermes chat` CLI instead of `hermes acp`                    |

See [Hermes provider](/bridge/providers/hermes).

## Timers and watcher

| Variable                             | Default |
| ------------------------------------ | ------- |
| `HEARTBEAT_MS`                       | `30000` |
| `RECONNECT_MS`                       | `5000`  |
| `CONNECTION_TIMEOUT_MS`              | `10000` |
| `POLL_CONFIG_MS`                     | `60000` |
| `AGENT_IDLE_RESET_MS`                | `15000` |
| `SESSION_HISTORY_POLL_MS`            | `5000`  |
| `SESSION_INACTIVITY_TIMEOUT_MINUTES` | `5`     |
| `WATCHER_USE_POLLING`                | `false` |
| `WATCHER_POLL_INTERVAL`              | `1000`  |

Per-provider `*_TIMEOUT_MINUTES` default to **10** (Hermes **15**).

## Debugging

| Variable                    | Description                                               |
| --------------------------- | --------------------------------------------------------- |
| `BRIDGE_INCOMING_DUMP_PATH` | Optional directory to dump raw inbound WebSocket payloads |

Run `ctrlnode` in a terminal and watch stderr for `handshake_sent`, `sync_*_agents`, and provider warnings.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Bridge disconnected">
    Confirm `ctrlnode` is running, `PAIRING_TOKEN` in `~/.ctrlnode/.env` is current, and shell `PAIRING_TOKEN` is unset.
  </Accordion>

  <Accordion title="Wrong provider ran the task">
    Match the agent's **agent type** in Team to the installed CLI. Do not set `PROVIDERS` — it has no effect. Reconnect Bridge after creating agents.
  </Accordion>

  <Accordion title="Tasks write outside the repo in WORK DIRECTORY mode">
    Ensure the project has a **Project work directory** configured and the task mode is **WORK DIRECTORY**. See [Task work modes](/tasks/task-work-modes).
  </Accordion>
</AccordionGroup>

## Related

* [Install](/bridge/install)
* [Providers](/bridge/providers)
* [Overview](/bridge/overview)
