import { pageMetadata } from '@/lib/page-metadata';

export const metadata = pageMetadata('configuration');

# Configuration

Create an `agent-browser.json` file to set persistent defaults instead of repeating flags on every command.

In this fork, default launch behavior auto-attaches to an existing browser by trying `localhost:9333` (CDP) first, then auto-discovery. If both fail, commands exit instead of launching a managed browser.

## Config File Locations

agent-browser checks two locations, merged in priority order:

<table>
  <thead>
    <tr>
      <th>Priority</th>
      <th>Location</th>
      <th>Scope</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1 (lowest)</td>
      <td>
        <code>~/.agent-browser/config.json</code>
      </td>
      <td>User-level defaults</td>
    </tr>
    <tr>
      <td>2</td>
      <td>
        <code>./agent-browser.json</code>
      </td>
      <td>Project-level overrides</td>
    </tr>
    <tr>
      <td>3</td>
      <td>
        <code>AGENT_BROWSER_*</code> env vars
      </td>
      <td>Override config values</td>
    </tr>
    <tr>
      <td>4 (highest)</td>
      <td>CLI flags</td>
      <td>Override everything</td>
    </tr>
  </tbody>
</table>

Project-level values override user-level values. Environment variables override both. CLI flags always win.

Use `--config <path>` or the `AGENT_BROWSER_CONFIG` environment variable to load a specific config file instead of the default locations:

```bash
agent-browser --config ./ci-config.json open example.com
AGENT_BROWSER_CONFIG=./ci-config.json agent-browser open example.com
```

## Example Config

```json
{
  "headed": true,
  "proxy": "http://localhost:8080",
  "userAgent": "my-agent/1.0",
  "ignoreHttpsErrors": true
}
```

## All Options

Most CLI flags can be set in the config file using their camelCase equivalents (`--resident` is CLI-only):

<table>
  <thead>
    <tr>
      <th>Config Key</th>
      <th>CLI Flag</th>
      <th>Type</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <code>headed</code>
      </td>
      <td>
        <code>--headed</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>json</code>
      </td>
      <td>
        <code>--json</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>full</code>
      </td>
      <td>
        <code>--full, -f</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>debug</code>
      </td>
      <td>
        <code>--debug</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>sessionName</code>
      </td>
      <td>
        <code>--session-name</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>parallel</code>
      </td>
      <td>
        <code>--parallel</code>
      </td>
      <td>string (isolated runtime channel name)</td>
    </tr>
    <tr>
      <td>
        <code>executablePath</code>
      </td>
      <td>
        <code>--executable-path</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>extensions</code>
      </td>
      <td>
        <code>--extension</code>
      </td>
      <td>string[]</td>
    </tr>
    <tr>
      <td>
        <code>state</code>
      </td>
      <td>
        <code>--state</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>proxy</code>
      </td>
      <td>
        <code>--proxy</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>proxyBypass</code>
      </td>
      <td>
        <code>--proxy-bypass</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>args</code>
      </td>
      <td>
        <code>--args</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>userAgent</code>
      </td>
      <td>
        <code>--user-agent</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>provider</code>
      </td>
      <td>
        <code>-p, --provider</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>device</code>
      </td>
      <td>
        <code>--device</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>ignoreHttpsErrors</code>
      </td>
      <td>
        <code>--ignore-https-errors</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>allowFileAccess</code>
      </td>
      <td>
        <code>--allow-file-access</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>cdp</code>
      </td>
      <td>
        <code>--cdp</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>autoConnect</code>
      </td>
      <td>
        <code>--auto-connect</code>
      </td>
      <td>boolean</td>
    </tr>
    <tr>
      <td>
        <code>colorScheme</code>
      </td>
      <td>
        <code>--color-scheme</code>
      </td>
      <td>
        string (<code>dark</code>, <code>light</code>, <code>no-preference</code>)
      </td>
    </tr>
    <tr>
      <td>
        <code>downloadPath</code>
      </td>
      <td>
        <code>--download-path</code>
      </td>
      <td>string</td>
    </tr>
    <tr>
      <td>
        <code>tabGroup</code>
      </td>
      <td>
        <code>--tab-group</code>
      </td>
      <td>string (base title for session tab grouping via CDP plugin handshake)</td>
    </tr>
    <tr>
      <td>
        <code>tabGroupPluginId</code>
      </td>
      <td>
        <code>--tab-group-plugin-id</code>
      </td>
      <td>string (expected extension ID for tab-group plugin handshake)</td>
    </tr>
    <tr>
      <td>
        <code>riskMode</code>
      </td>
      <td>
        <code>--risk-mode</code>
      </td>
      <td>
        string (<code>off</code>, <code>warn</code>, <code>block</code>)
      </td>
    </tr>
    <tr>
      <td>
        <code>headers</code>
      </td>
      <td>
        <code>--headers</code>
      </td>
      <td>string (JSON)</td>
    </tr>
  </tbody>
</table>

`riskMode` defaults to `warn` when unset.

For tab grouping in CDP mode, grouping is best-effort through the extension handshake:
extension available => grouped by session; extension missing/unavailable => silent no-op.

With the `agent-browser-stealth` extension installed, the side panel also exposes
session window isolation controls, activation guard toggles, empty-group cleanup, per-session allowlist policy editing, browser action controls, developer signal panels (console/network/DOM), and workflow automation (recording, shortcuts, and scheduled runs).

## Common Configurations

### Local Development

```json
{
  "headed": true,
  "sessionName": "local-dev"
}
```

### Behind a Proxy

```json
{
  "proxy": "http://proxy.corp.example.com:8080",
  "proxyBypass": "localhost,*.internal.com",
  "ignoreHttpsErrors": true
}
```

### CI / Devcontainer

```json
{
  "args": "--no-sandbox,--disable-gpu",
  "ignoreHttpsErrors": true
}
```

### iOS Testing

```json
{
  "provider": "ios",
  "device": "iPhone 16 Pro"
}
```

### Parallel Stateless Worker

```json
{
  "parallel": "worker-a"
}
```

Use this for stateless throughput tasks. For authenticated flows, prefer a stable `sessionName`.

## CLI-only daemon lifecycle flag

`--resident` is a CLI-only flag (not a config/env key). It keeps the daemon alive and disables the default 10-minute idle auto-shutdown.

```bash
agent-browser --resident open example.com
agent-browser close
```

## Overriding Boolean Options

Boolean flags accept an optional `true`/`false` value to override config settings:

```bash
agent-browser --headed false open example.com
```

A bare flag is equivalent to passing `true`:

```bash
agent-browser --headed open example.com       # same as --headed true
agent-browser --headed true open example.com  # explicit
```

This applies to all boolean flags: `--headed`, `--debug`, `--json`, `--ignore-https-errors`, `--allow-file-access`, `--auto-connect`, `--resident`.

## Extensions Merging

Extensions from user-level and project-level configs are **concatenated**, not replaced. For example, if `~/.agent-browser/config.json` specifies `["/ext1"]` and `./agent-browser.json` specifies `["/ext2"]`, the result is `["/ext1", "/ext2"]`.

The `AGENT_BROWSER_EXTENSIONS` environment variable and CLI `--extension` flags follow the standard priority rules (env replaces config, CLI appends).

## Environment Variables

These environment variables configure additional daemon and runtime behavior:

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Description</th>
      <th>Default</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <code>AGENT_BROWSER_AUTO_CONNECT</code>
      </td>
      <td>Auto-discover and connect to a running Chrome instance.</td>
      <td>(disabled)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_ALLOW_FILE_ACCESS</code>
      </td>
      <td>
        Allow <code>file://</code> URLs to access local files.
      </td>
      <td>(disabled)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_COLOR_SCHEME</code>
      </td>
      <td>
        Color scheme preference (<code>dark</code>, <code>light</code>, <code>no-preference</code>).
      </td>
      <td>(none)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_DOWNLOAD_PATH</code>
      </td>
      <td>Default directory for browser downloads.</td>
      <td>(temp directory)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_TAB_GROUP</code>
      </td>
      <td>Base title for tab grouping. Session suffix is appended automatically in CDP mode.</td>
      <td>
        <code>Agent Browser Stealth</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_TAB_GROUP_PLUGIN_ID</code>
      </td>
      <td>Expected extension ID for CDP tab-group plugin handshake.</td>
      <td>
        <code>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_RISK_MODE</code>
      </td>
      <td>
        Verification/captcha handling mode (<code>off</code>, <code>warn</code>, <code>block</code>
        ).
      </td>
      <td>
        <code>warn</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_DEFAULT_TIMEOUT</code>
      </td>
      <td>Default Playwright timeout in ms. Keep below 30000 to avoid IPC timeouts.</td>
      <td>
        <code>25000</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_SESSION_NAME</code>
      </td>
      <td>
        Auto-save/load state persistence name (defaults to <code>default</code> when unset).
      </td>
      <td>
        <code>default</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_PARALLEL</code>
      </td>
      <td>
        Isolated runtime channel name for parallel AI runs (maps to <code>parallel-&lt;name&gt;</code>).
      </td>
      <td>(none)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_STATE_EXPIRE_DAYS</code>
      </td>
      <td>Auto-delete saved session states older than N days.</td>
      <td>
        <code>30</code>
      </td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_ENCRYPTION_KEY</code>
      </td>
      <td>64-char hex key for AES-256-GCM session encryption.</td>
      <td>(none)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_STREAM_PORT</code>
      </td>
      <td>
        Enable WebSocket streaming on the specified port (e.g., <code>9223</code>).
      </td>
      <td>(disabled)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_IOS_DEVICE</code>
      </td>
      <td>
        Default iOS device name for the <code>ios</code> provider.
      </td>
      <td>(none)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_IOS_UDID</code>
      </td>
      <td>
        Default iOS device UDID for the <code>ios</code> provider.
      </td>
      <td>(none)</td>
    </tr>
    <tr>
      <td>
        <code>AGENT_BROWSER_DEBUG</code>
      </td>
      <td>
        Enable debug output (<code>1</code> to enable).
      </td>
      <td>(disabled)</td>
    </tr>
  </tbody>
</table>

## Error Handling

- **Auto-discovered config files** (`~/.agent-browser/config.json`, `./agent-browser.json`) that are missing are silently ignored.
- **`--config <path>`** with a missing or malformed file exits with an error.
- **Malformed JSON** in auto-discovered files prints a warning to stderr and continues without that file.
- **Unknown keys** are silently ignored for forward compatibility.

> **Tip:** If your project-level `agent-browser.json` contains environment-specific values (paths, proxies), consider adding it to `.gitignore`.
