coma.yaml
Every field of the workspace manifest, apiVersion coma.sh/v1alpha1, with its values, defaults and validation rules.
A coma.yaml makes a project directory a workspace: it names the machine, the engine, what to sync and which ports to forward. It is meant to be committed. coma workspace init writes a minimal one; coma workspace validate checks it.
Complete example
apiVersion: coma.sh/v1alpha1
kind: Workspace
metadata:
name: shop
description: Storefront and its database
labels:
team: web
spec:
source:
path: .
target:
machine: dev
runtime:
engine: docker
compose:
files:
- compose.yaml
projectName: shop
sync:
mode: one-way-safe
gitignore: true
ignore:
- node_modules/
- "*.log"
include:
- .env.development
ports:
- name: web
remote: 3000
- name: db
remote: 5432
local: 15432
- service: web
remote: 80
local: auto
- name: redis
remote: 6379
local: disabledFinding the file
Workspace commands use --file when given. Otherwise they look for coma.yaml or coma.yml in the current directory, then in each parent, and stop at the repository root (a directory containing .git) or the filesystem root. A directory with both names is an error (workspace_manifest_ambiguous). A manifest may be at most 1 MiB, and each list at most 256 entries.
Validation
Unknown keys and wrong types are errors, reported with the file and line. Once the file decodes, every field error is reported together, with its line, column and YAML path:
coma workspace validateError: ./coma.yaml is not a valid workspace manifest:
./coma.yaml:4:9 metadata.name: "Bad_Name" must be lower-case letters, digits and dashes (at most 63)
./coma.yaml:6:5 metadata.labels: label "coma.sh/x" uses the reserved coma.sh/ prefix
./coma.yaml:13:19 spec.ports.0.visibility: public visibility is not supported: COMA never opens public ingress (workspace_manifest_invalid)An invalid manifest exits with 2 (workspace_manifest_invalid). With --json, each problem is in error.details.diagnostics with file, line, column, path and message.
coma workspace status reports drift when coma.yaml changed after the last coma workspace up.
Top level
| Field | Required | Value |
|---|---|---|
apiVersion | yes | coma.sh/v1alpha1 |
kind | yes | Workspace |
metadata | yes | See below |
spec | no | See below |
The older name coma.dev/v1alpha1 is still read, with a warning to change it. Any other apiVersion fails with workspace_api_version_unsupported (exit 8).
metadata
| Field | Required | Value |
|---|---|---|
name | yes | Lower-case letters, digits and dashes; starts and ends with a letter or digit; at most 63 characters |
description | no | Free text |
labels | no | Map of string keys to string values. Keys may not start with coma.sh/, which COMA reserves |
coma workspace init derives the name from the directory's name.
spec.source
| Field | Default | Value |
|---|---|---|
path | . | The source directory, relative to the directory holding coma.yaml. It must exist and be a directory; absolute paths are refused |
spec.target
| Field | Value |
|---|---|
machine | The name of a machine in your COMA inventory |
pool, cluster | Accepted by the schema, but plan and up fail with workspace_target_kind_unsupported (exit 8) |
Set at most one of the three. Machine names are per user, so coma workspace init writes machine only when you pass --machine.
The machine is chosen in this order: --machine, then spec.target.machine, then the current context's machine. With none of them, plan and up fail with workspace_target_required. coma workspace plan shows which one was used.
spec.runtime
| Field | Value |
|---|---|
engine | docker or podman |
workingDirectory | A directory relative to the source; used for the Compose project's default name |
compose.files | Compose files, relative and inside the source. plan warns when one does not exist |
compose.projectName | The Compose project name |
compose.profiles | List of Compose profiles |
compose.envFiles | Env files, relative and inside the source |
compose.removeOrphans | true or false |
The engine is chosen in this order: --engine, then spec.runtime.engine, then the current context's preference or the machine's only working engine.
COMA does not start Compose: you run docker compose up after coma workspace up. files, profiles, envFiles and removeOrphans are accepted and their paths checked, but COMA does not pass them to Compose. projectName matters now: it is the project in which spec.ports entries with service find their containers. Without it, COMA uses Compose's default, the name of the source directory (or workingDirectory), lower-cased, keeping letters, digits, - and _.
spec.sync
| Field | Default | Value |
|---|---|---|
mode | one-way-safe | none, one-way-safe, one-way-mirror or bidirectional |
ignore | none | Git-style patterns to leave out |
include | none | Git-style patterns to bring back in |
gitignore | true | false stops applying .gitignore files |
Sync modes
| Mode | What it does | Who can turn it on |
|---|---|---|
none | Nothing is synced; bind mounts of the source are refused | coma.yaml |
one-way-safe | Your changes go to the machine; a file changed on the machine is never overwritten (a conflict instead) | Default |
one-way-mirror | The machine's copy is made identical to yours: files created or changed there, outside ignored paths, are overwritten or deleted | coma.yaml, and a confirmation before the first sync (--yes without a terminal) |
bidirectional | Changes on either side are copied to the other; a file changed on both is left as a conflict | coma.yaml plus your own sync.allowBidirectional: true in COMA's config, or COMA_SYNC_ALLOW_BIDIRECTIONAL=1 |
A repository's coma.yaml alone cannot make changes on the machine flow back to your computer: without your setting, bidirectional blocks up with workspace_plan_blocked. Both opt-in modes need the Mutagen sync engine; otherwise up fails with sync_mode_unsupported. coma workspace up --no-sync skips sync for one run. See Source sync.
Ignore rules
ignore and include entries are Git-style patterns relative to the source directory. Each must be one line of at most 1,024 bytes, not empty, not a comment, and must not leave the source directory (..).
Rules apply in this order, later rules winning: the built-in rules (.git/ and .coma/), .comaignore, the root .gitignore, ignore, include, then nested .gitignore files. As in Git, include cannot bring back a path inside a directory that is excluded. gitignore: false drops the .gitignore files; the built-in rules and .comaignore still apply.
coma sync explain <path> says whether a path is synced and which rule decided.
Fields reported as unsupported
| Field | What happens |
|---|---|
remotePath | Any value other than auto is reported as unsupported. COMA keeps the copy at ~/.coma/workspaces/<id>/source on the machine |
delete, watch | Reported as unsupported. COMA always watches, and the mode decides what is deleted |
spec.ports
Each entry forwards a port on the machine to your computer, possibly at another number. While the workspace is up, a declared port replaces the automatic mirror of the same remote port. See Ports.
| Field | Required | Value |
|---|---|---|
remote | yes | 1 to 65535. The machine's host port, or with service, the container's port |
local | no | A port number, auto (a free port, kept across ups when still free) or disabled (nothing forwarded, and the mirror of that port is turned off). Default: the remote number |
name | no | Lower-case letters, digits and dashes. Default: <service>-<remote>, or port-<remote> |
service | no | A Compose service in the workspace's project |
protocol | no | tcp, the only one forwarded |
visibility | no | local (default) or none, which acts like local: disabled. public is refused: COMA never opens public ingress |
container | no | Refused: not supported yet; use service |
host | no | Refused: ports are forwarded from the machine itself |
Names, explicit local ports and forwarded targets must each be unique within the file. A local port that is busy on your computer, or declared by another workspace, is reported as local_port_in_use; coma port list shows the state of each port.
Reserved sections
These spec sections are accepted with any content but not implemented yet. coma workspace validate and plan list each one as "not implemented yet, ignored", so nothing is silently dropped:
requirements, environment, secrets, persistence, caches, lifecycle, idle, budget, policy, extensions.