Configuration and persistence
Every setting lives in one .env file next to the Compose project, and every
one of them has a default — the workspace starts with only an API key and a
console password. This page covers what the rest do, and the more important
question underneath them: which of your work survives what.
Copy .env.example to .env and set CMDOP_API_KEY and
CMDOP_ADMIN_PASSWORD. Host directories survive everything; named volumes
survive rebuilds but not down --volumes; the image is replaced by every
rebuild. Put anything you care about in a host directory.
Required
| Variable | Purpose |
|---|---|
CMDOP_API_KEY | Your platform key. Used for inference and, in public relay mode, to register the address. |
CMDOP_ADMIN_PASSWORD | The first console password. Mounted as a secret file and read only when the relay’s database has no admin credential yet. |
Reachability
| Variable | Default | Purpose |
|---|---|---|
CMDOP_RELAY_MODE | auto | auto picks public when a subdomain is set, otherwise LAN. |
CMDOP_PUBLIC_SUBDOMAIN | (empty) | The cmdop.dev label to claim. Empty with public reuses the address already provisioned for the key’s organization. |
HOST_BIND_ADDRESS | 127.0.0.1 | Which host interface the published ports bind to. Change to 0.0.0.0 only deliberately. |
DEMO_HOST_PORT | 8080 | Host port for the site. |
CMDOP_HOST_PORT | 63141 | Host port for the console. |
Naming the subdomain explicitly matters when an organization already has a relay address: without a label, the container adopts the existing one and two machines end up contending for a single address.
The agent’s boundary
| Variable | Default | Purpose |
|---|---|---|
CMDOP_AGENT_CWD | /workspace/demo | The directory inbound chats can reach. |
CMDOP_PERMISSIONS_MODE | default | Keep default for normal approval prompts. |
CMDOP_GIT_AUTHOR_NAME | Cmdop Agent | Identity for commits made in the demo repository. |
CMDOP_GIT_AUTHOR_EMAIL | [email protected] | As above. |
CMDOP_PERMISSIONS_MODE=bypass removes approval prompts. Use it only in a
disposable, isolated environment you are about to throw away — a recording, a
scratch VM — never on a machine holding anything you would miss.
Build-time options
These are build arguments, so changing one requires a rebuild rather than a restart.
| Variable | Default | Purpose |
|---|---|---|
CMDOP_BROWSER | 1 | Install headless Chromium for the agent’s browser tools. 0 builds a slimmer image; the agent then runs without those tools. |
CMDOP_CLAUDE_CODE | 1 | Install Claude Code into the image. |
CMDOP_CODEX | 1 | Install Codex into the image. |
HOST_UID / HOST_GID | 1000 | Match your host user so bind-mounted files stay writable on Linux. Run id -u and id -g. |
CMDOP_CODEX_SANDBOX is a runtime setting and is covered in
coding agents.
What survives what
This is the part worth internalizing before you put real work in a container.
| Where it lives | Survives restart | Survives rebuild | Survives down --volumes |
|---|---|---|---|
| Host directories (the project, coding-agent logins) | Yes | Yes | Yes |
| Named volumes (relay state, Git history, dependencies) | Yes | Yes | No |
| Image contents (the binaries) | Yes | Replaced | Replaced |
Two consequences follow, and both have bitten people:
An executable installed into a volume goes stale. A named volume is seeded from the image once, when it is first created, and then survives every later build. Anything installed into a path backed by a volume therefore keeps the version from the day the volume was created, no matter how many times you rebuild. Executables belong in the image; only state belongs in a volume.
down --volumes does not reach host directories. It resets the relay’s
identity and history, which is often what you want, and it leaves your project
and your coding-agent logins alone, which is also what you want. Know which of
the two a given file is in before assuming a reset cleared it.