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

# Configuration Overview

> The cordon.toml config file controls which routes are proxied and how credentials are injected.

Cordon is configured via **`cordon.toml`**. Prefer the CLI over hand-editing this file: `cordon setup` creates it, and `cordon route` / `cordon listener` commands validate changes and write the safer defaults for you. The file format is documented here for review, troubleshooting, and automation when a CLI command does not cover your use case.

See [setup](/cli/setup#project-setup-and-services) for details.

## Scopes

Cordon is project-first — most integrations default to project scope, giving each repository its own config, credentials, and proxy instance. A **user** scope is also available for tools that span projects. The two scopes are independent: each runs its own daemon with its own config file, TLS certificates, and optional OS service. They are not merged or layered.

| Resource         | Project scope                                               | User scope                            |
| ---------------- | ----------------------------------------------------------- | ------------------------------------- |
| Config file      | `$CWD/cordon.toml`                                          | `$XDG_CONFIG_HOME/cordon/cordon.toml` |
| TLS certificates | `$XDG_CONFIG_HOME/cordon/projects/<dirname>-<hash8>/certs/` | `$XDG_CONFIG_HOME/cordon/user/certs/` |
| Service name     | `<dirname>-<hash8>`                                         | `user`                                |

`<dirname>-<hash8>` is the project directory basename plus the first 8 hex characters of the SHA-256 of the absolute CWD path, so two projects with the same directory name never collide.

On macOS (launchd) and Linux (systemd user units) these names are automatically namespaced. The launchd label becomes `io.codezero.cordon.<name>`.

### Directory layout

<Note>
  Cordon follows the [XDG Base Directory spec](https://specifications.freedesktop.org/basedir-spec/latest/) for its config location. `$XDG_CONFIG_HOME` defaults to `~/.config` on both Linux and macOS — cordon intentionally uses `~/.config/cordon/` on macOS for consistency with cross-platform dev tools like git and VS Code. Set `XDG_CONFIG_HOME=/custom/path` to override; cordon will then use `/custom/path/cordon/`.
</Note>

```
~/.config/cordon/                         # base directory
├── cordon.toml                           # user-scope config
├── user/
│   └── certs/                            # user-scope TLS material
│       ├── ca-cert.pem
│       └── ca-key.pem
└── projects/
    └── myapp-a1b2c3d4/                   # <dirname>-<hash8>
        └── certs/                        # project-scope TLS material
            ├── ca-cert.pem
            └── ca-key.pem

<project>/
└── cordon.toml                           # project-scope config (one per project)
```

Project-scope configs live beside your code. Everything else — user-scope config and all TLS certificates — lives under the user's cordon config directory. The `<dirname>-<hash8>` naming uses SHA-256 of the absolute project path so two projects sharing the same directory name never collide.

### Port allocation

Each `cordon setup` invocation — project or user scope — asks the OS for a free port and writes it into `cordon.toml` at setup time. In practice this avoids collisions between concurrent projects and rapid successive `cordon setup` invocations. There is no base port to configure.

The allocated port is not reserved: `cordon setup` binds to port 0, reads the port the OS assigned, then releases the socket before writing the number into `cordon.toml`. Between setup and `cordon start`, another process could theoretically claim the port. If that happens, `cordon start` will fail to bind and you can rerun `cordon setup` to pick a new port. Persistent port reservation and re-allocation at start time is future work.

### Per-integration defaults

| Integration   | Default scope | Rationale                                                              |
| ------------- | ------------- | ---------------------------------------------------------------------- |
| `claude-code` | `project`     | Editor configs are typically per-repo                                  |
| `codex`       | `project`     | Project-specific Codex env isolates credentials                        |
| `hermes`      | `user`        | Hermes operates across projects; user scope avoids per-repo repetition |

### Overriding the scope

Pass `--scope user` or `--scope project` to override the default for `claude-code` or `codex`:

```bash theme={null}
# Configure Claude Code globally (one config for all projects)
cordon setup claude-code --scope user
```

Hermes only supports user scope — `cordon setup hermes --scope project` is rejected by the CLI.

### When to choose which scope

* **Project scope** — the right default for most tools. Each repo gets its own credentials, port, and service. No cross-project interference.
* **User scope** — best for tools like Hermes that naturally span multiple projects, or when you want a single cordon instance shared across repos. One cordon process handles all requests.

### `cordon start` and scope

`cordon start` with no flags uses `./cordon.toml` (project scope). To start the user-scope instance explicitly:

```bash theme={null}
cordon start --scope user
```

### `cordon service` and scope

`cordon service install/start/stop --scope <project|user>` derives the service name and config path from the scope automatically:

```bash theme={null}
cordon service install --scope project   # installs <dirname>-<hash8>
cordon service install --scope user      # installs user
```

After setup, use commands like `cordon route add`, `cordon route edit`, `cordon listener add`, and `cordon listener edit` to modify credential rules. For automation, prefer non-interactive CLI flags (for example, `cordon setup --yes` or fully-flagged `cordon route add`) instead of maintaining a hand-written config.

[`cordon service install`](/cli/service) does **not** write `cordon.toml` — it points an OS service at an existing file, typically the project-local file setup produced.

Paths in `cordon.toml` are literal strings: Cordon does **not** expand `$HOME`, `~`, or other environment variables. Use the absolute paths written by `cordon setup`, or substitute placeholders like elsewhere in these docs (`/path/to/...`). If `ca_cert_path` or `ca_key_path` are relative, they are resolved against the config file's directory (not the working directory), so hand-edited configs work correctly under service managers where the working directory is `/`.

## Minimal example

The `listen` port is assigned automatically by `cordon setup` — the `6790` shown in the example is illustrative; your actual port is OS-assigned and typically in the ephemeral range. Check the `listen = ...` line in your generated `cordon.toml` to find the port in use.

```toml theme={null}
listen = 6790  # illustrative — your setup may allocate a different port

[tls]
enabled = true
# Substitute paths from your real `cordon.toml` (typically under ~/.config/cordon/projects/<namespace>/certs/).
ca_cert_path = "/path/to/ca-cert.pem"
ca_key_path = "/path/to/ca-key.pem"

[[routes]]
name = "stripe"

[routes.match]
host = "api.stripe.com"

[routes.auth]
type = "header"
header_name = "Authorization"
scheme = "Bearer"

[routes.auth.secret]
source = "1password"
vault = "Engineering"
item = "Stripe API Key"
field = "secret_key"
```

## Top-level fields

| Field       | Type    | Required | Description                                                                                                                                                                                                                                               |
| ----------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `listen`    | integer | Yes      | Port number to listen on. The proxy always binds to `127.0.0.1` (loopback) — this is not configurable because binding to a non-loopback address would expose injected credentials to the network.                                                         |
| `tls`       | object  | No       | TLS interception settings. Required only when you enable HTTPS MITM or require PostgreSQL client TLS.                                                                                                                                                     |
| `secrets`   | object  | No       | Secret provider configuration. Use to specify an explicit path to the `op` binary when it's not on `PATH` (common for background services). See [Secret Sources — Provider configuration](/configuration/secret-sources#provider-configuration-optional). |
| `routes`    | array   | No       | List of HTTP credential route definitions. Matched routes are explicit trust decisions; see [Routes](/configuration/routes#how-matching-works).                                                                                                           |
| `listeners` | array   | No       | List of PostgreSQL listener definitions. See [Listeners](/configuration/listeners).                                                                                                                                                                       |

## TLS settings

| Field              | Type    | Required    | Description                                                                                                          |
| ------------------ | ------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
| `tls.enabled`      | boolean | No          | Enable HTTPS interception via TLS MITM. Defaults to `false` if omitted.                                              |
| `tls.ca_cert_path` | string  | Conditional | Path to the CA certificate file. Required when HTTPS MITM is enabled or PostgreSQL `client_tls = "require"` is used. |
| `tls.ca_key_path`  | string  | Conditional | Path to the CA private key file. Required when HTTPS MITM is enabled or PostgreSQL `client_tls = "require"` is used. |

When TLS is enabled, cordon performs MITM on HTTPS connections for matched routes. It generates per-host certificates signed by the local CA. See [TLS](/configuration/tls) for details.

Route and listener names share one namespace and must be unique. Listener ports must also be unique and cannot equal the HTTP proxy `listen` port.

## Extended examples

Keep this page as the map of `cordon.toml`. Use the focused references for complete examples:

* [Routes](/configuration/routes) for HTTP credential injection, auth types, provider examples, and route matching.
* [Listeners](/configuration/listeners) for PostgreSQL listener configuration.
* [Secret Sources](/configuration/secret-sources) for 1Password, keyring, rotation, and platform behavior.

## Config file location

`cordon start` resolves the config file based on scope:

* **Project scope** (default) — `./cordon.toml`
* **User scope** (`--scope user`) — `$XDG_CONFIG_HOME/cordon/cordon.toml` (or `~/.config/cordon/cordon.toml` if `XDG_CONFIG_HOME` is not set)

`cordon setup` writes the config to the scope-appropriate path automatically. See [Scopes](#scopes) above for the full scope path table.

You can bypass scope resolution entirely with the `--config` flag:

```bash theme={null}
cordon start --config /path/to/cordon.toml
```

<Note>
  `cordon.toml` typically contains project-specific secret references and should be gitignored.
</Note>
