Skip to content
COMA

Coding agents

Let Codex, Claude Code and Cursor run containers on a remote machine through COMA, and let them check COMA's state with JSON output.

A coding agent that runs docker compose up and a test suite on your laptop competes with everything else for its memory. With COMA, the same commands run on a machine, and the coding agent does not need to know.

How it works

coma connect switches the Docker CLI's context to coma. The Docker CLI reads its current context on every run, so every new shell uses the machine, including the shells that Codex, Claude Code and Cursor start. The coding agent keeps running docker compose up, npm test and curl localhost:3000; the containers, and the memory they use, are on the machine.

Connect, or bring up the project's workspace:

coma connect dev

Start the coding agent in the project as usual. Codex's sandbox needs two settings, described under the pitfalls below.

Check what happened while it worked:

coma doctor

If your docker is an alias for podman, connect with --engine podman instead. See Podman.

Commands a coding agent can use

Every COMA command takes --json. The result goes to stdout as one JSON envelope with a stable kind; errors go to stderr with a stable code and exit code. See JSON output and Exit codes.

coma workspace status --json

WorkspaceStatus reports conditions, each true, false or unknown: ManifestValid, CompatibilityEndpointReady, SyncReady and PortsReady. The command exits 0 even when a condition is false, so read the conditions. A coma.yaml changed since the last workspace up shows up in warnings.

coma doctor --json

DoctorReport has checks and a summary of counts. Each check has id, status (PASS, WARN or FAIL), message and, when there is one, remediation. The exit code is 10 when any check fails.

{
  "id": "docker-compose",
  "status": "WARN",
  "message": "Compose v1 cannot read compose.yaml: /opt/homebrew/bin/docker-compose (1.25.5), first on PATH",
  "remediation": "remove the old docker-compose (podman compose and a `docker compose` alias for it run whichever comes first on PATH)",
  "details": {
    "composes": [
      { "path": "/opt/homebrew/bin/docker-compose", "version": "1.25.5" },
      { "path": "/usr/local/bin/docker-compose", "version": "2.39.3" }
    ]
  }
}

Other useful commands:

CommandAnswers
coma port list --jsonWhich localhost ports reach which containers, and their state
coma sync status --jsonWhether sync is current, and any conflicts
coma endpoint list --jsonWhether the endpoint is ready, reconnecting or degraded
coma workspace plan --jsonWhat workspace up would do, without changing anything

A short note in the project's AGENTS.md or CLAUDE.md helps a coding agent use these, for example:

Containers run on a remote machine through COMA. If docker commands fail or
seem to run locally, run `coma doctor --json` and `coma workspace status --json`
and report the result instead of working around it.

Prompts never wait

COMA asks a question only when stdin is a real terminal and --no-input is not set. A coding agent's shell usually has no terminal on stdin (often /dev/null), so COMA never waits for an answer there. A command that would ask fails at once and names the flag to use instead:

CommandWithout a terminalUse
coma machine add (first connection)ssh_host_key_unknown; the message shows the fingerprint--host-key SHA256:…
coma machine bootstrapconfirmation_required--yes
coma workspace up (first sync in one-way-mirror)confirmation_required--yes
coma workspace deleteconfirmation_required--yes

To forbid prompts even in a terminal, pass --no-input or set COMA_NO_INPUT=1.

Pitfalls found in testing

COMA was dogfooded with Claude Code and Codex on real Compose projects. These came up along the way. Most are not specific to COMA, but each is easy to miss, and several let a coding agent report success while its containers ran on the laptop.

Check for local fallback

While you are connected, COMA watches the local engines it can find (Docker Desktop, a Podman machine, rootless Podman, Colima, OrbStack and /var/run/docker.sock) for new containers. After a coding agent's run, coma doctor reports any container created on a local engine in its local-fallback check, with its name, image and time. coma daemon logs lists each one. COMA cannot stop a tool from using another socket, but the fallback no longer goes unseen.

On this page