Docker
Two different questions bring people here, and they have different answers.
“Do I need Docker to run Cmdop?” No. The relay is embedded in the cmdop
binary, so a normal deployment is one process on one host — no Compose file, no
database server, no cache, no separate relay service.
“Can I put Cmdop inside a container I already ship?” Yes, and that is the common case. Two lines in your Dockerfile add the agent beside your own application; your process keeps PID 1 and the container joins your fleet as one more machine.
FROM your-image # unchanged
COPY --from=markolofsen/cmdop:latest /cmdop /usr/local/bin/cmdop
ENTRYPOINT ["cmdop", "sidecar", "--"]
CMD ["your-app", "--your", "flags"] # unchangedAdding Cmdop to a container is two lines plus a join key — see
add Cmdop to a container. Docker is optional
for Cmdop itself. The cmdop-docker
repository holds both a minimal example and a larger demo stand that runs at
demo.cmdop.com .
Start here
The two lines, the settings that are not optional, and what sidecar does to PID 1.
The public demo: an agent editing a live project, with a preview and Git history.
The two examples
The public repository carries opposite ends of the same idea, and it helps to know which one you are looking at.
| What it shows | |
|---|---|
examples/simple | The two lines above, on an ordinary app. About fifteen lines of Dockerfile and nothing else. Start here. |
examples/original | Everything by hand and without a registry: the container hosts its own relay, and an entrypoint supervises three processes — a coding agent editing a live project, a dev server, and Git history. This is what runs at demo.cmdop.com . |
The rest of this section documents the demo stand, because that is the arrangement with settings worth explaining. If you only want an agent beside your own application, the sidecar page is the whole story.
Quick start — the demo stand
You need Docker Engine with Compose v2 and a Cmdop API key.
git clone https://github.com/commandoperator/cmdop-docker.git
cd cmdop-docker/examples/original
cp .env.example .envSet two values in .env:
CMDOP_API_KEY=your_api_key
CMDOP_ADMIN_PASSWORD=choose_at_least_12_charactersThen start it:
docker compose up --build| Surface | Address | Container port |
|---|---|---|
| The demo site | http://localhost:8080 | 5173 |
| The web console | http://localhost:63141 | 63141 |
Open the console, pick the connected machine, and ask for a change. The site updates as the agent writes files.
What runs inside the demo stand
That container supervises three processes that form a single feedback loop. An
agent riding along beside your own application
(examples/simple)
has none of these moving parts.
| Process | Responsibility |
|---|---|
| Relay | The browser console, authenticated sessions, and machine connections |
| Machine agent | Agent work, scoped to the project directory |
| Dev server | Immediate preview of the same writable files |
The project directory is a host bind mount, so the files the agent edits are the files you can read, diff, and commit yourself. Relay state, Git history, and installed dependencies live in named volumes, so recreating the container keeps your work while a rebuild picks up the current Cmdop release.
Both published surfaces bind to 127.0.0.1 by default. The agent reaches the
relay outbound, so nothing needs an inbound port opened for the normal path.
In this section
The two lines, the join key, and the settings that are not optional.
Configuration and persistenceEnvironment variables, what survives a rebuild, and what does not.
Claude Code and CodexBoth ship in the image. How to sign in, and where the login is stored.
MessagingDrive the container’s agent from Telegram, Slack, or Discord.
TroubleshootingThe failures this setup actually produces, and what each one means.
Running only the relay in a container
If you do not want the demo stand and only need the relay containerized, run the
cmdop binary as the container’s process and publish its ports — HTTP 63141
and gRPC 63142 in LAN mode. cmdop server carries flags for exactly this case:
| Flag | Purpose |
|---|---|
--initial-admin-password-file <path> | Seed the first console password from a mounted secret. Ignored once initialized. |
--no-banner | Suppress the startup banner, which would otherwise print the join key into container logs. |
--no-open | Do not try to open a browser on startup. |
--cwd <directory> | Root the relay’s own agent filesystem tools at an explicit directory. |
Use --no-banner anywhere logs are collected.
Common questions
Do I need Docker Compose to run Cmdop?
No. The product deployment unit is one binary that contains both the agent and the relay. Compose appears here because the examples need something to start; adding the agent to a container you already ship needs no Compose file at all.
Do I need a separate container for Cmdop?
No, and that is the point of the sidecar page: the agent goes into the container you already have, as a binary the entrypoint starts before your own command. There is nothing to deploy alongside it — no database server, no cache, no broker, no second service.
Is the demo stand a production deployment?
It is a starter workspace, and it is honest about that: the console and site bind to loopback, the demo project is meant to be rewritten, and the defaults favour a fast local loop. It is a sound base for a real deployment once you change the bind address, permissions mode, and project directory deliberately — see configuration and public deployment.
Which ports do I publish?
A container that only joins a fleet publishes nothing — the agent dials the
relay outbound. The demo stand publishes 5173 for the site and 63141 for the console. A
relay-only container in LAN mode publishes HTTP 63141 and gRPC 63142. Public
and own-domain relay modes terminate at the relay’s own TLS door, so decide the
reachability mode before turning a container recipe into an operational
contract.
Should the join key appear in container logs?
No. Use --no-banner anywhere logs are collected, and seed the first console
password from a mounted secret with --initial-admin-password-file. The Compose
project already does both.