# coma.yaml

A `coma.yaml` makes a project directory a workspace: which machine and engine it uses, what to sync and which ports to forward. It is meant to be committed. Full reference: https://coma.sh/docs/reference/coma-yaml

## Commands

| Command | Does |
| --- | --- |
| `coma workspace init --json` | Writes a minimal `coma.yaml` for the current directory, naming the Compose file it finds. Refuses to overwrite without `--force` |
| `coma workspace validate --json` | Checks the file. Problems are in `error.details.diagnostics` with line, column and YAML path |
| `coma workspace plan --json` | What `up` would do (machine, engine, sync, ports), changing nothing |
| `coma workspace up --json` | Connects, starts the endpoint and syncs. Does not start containers |
| `coma workspace status --json` | Health and drift since the last `up` |
| `coma workspace down --json` | Stops syncing. Containers and the machine's copy stay |

Workspace commands find `coma.yaml` (or `coma.yml`) in the current directory or a parent, stopping at the repository root. `--file` picks one explicitly.

## Example

```yaml
apiVersion: coma.sh/v1alpha1
kind: Workspace
metadata:
  name: shop                 # lower-case letters, digits, dashes; max 63
spec:
  source:
    path: .                  # relative to coma.yaml; must be a directory
  runtime:
    engine: docker           # or podman
    compose:
      projectName: shop      # where `service` ports find their containers
  sync:
    mode: one-way-safe       # the default
    gitignore: true          # apply .gitignore files (default)
    ignore:
      - node_modules/
    include:
      - .env.development
  ports:
    - name: web
      remote: 3000           # forwarded to localhost:3000
    - name: db
      remote: 5432
      local: 15432           # a different local number
    - service: api
      remote: 8080           # the container's port in the Compose project
      local: auto            # any free local port, kept across ups
```

## Rules worth knowing

- **Do not write `spec.target.machine` unless the user asks.** Machine names are per user and the file is committed. Without it, `up` uses `--machine` or the current context's machine.
- **Engine** resolves as `--engine`, then `spec.runtime.engine`, then the context's preference or the machine's only working engine.
- **COMA does not run Compose.** After `up`, run `docker compose up`. `compose.files`, `profiles`, `envFiles` and `removeOrphans` are checked but not passed to Compose. `projectName` matters for `service` ports; without it COMA uses Compose's default (the source directory's name, lower-cased).
- **Sync modes:**

  | Mode | Effect | Who can enable it |
  | --- | --- | --- |
  | `none` | No sync; bind mounts of the source are refused | `coma.yaml` |
  | `one-way-safe` | Local changes go to the machine; files changed on the machine are never overwritten (conflict instead) | Default |
  | `one-way-mirror` | The machine's copy is made identical to local, deleting and overwriting files there | `coma.yaml`, plus a confirmation (`--yes`) on first sync. Ask the user |
  | `bidirectional` | Changes flow both ways | Only the user's own config (`sync.allowBidirectional: true`) or `COMA_SYNC_ALLOW_BIDIRECTIONAL=1`. Never set this for them |

  Both opt-in modes need the Mutagen sync engine.
- **Ignore order**, later wins: built-in (`.git/`, `.coma/`), `.comaignore`, root `.gitignore`, `ignore`, `include`, nested `.gitignore`. As in Git, `include` cannot re-add a path inside an excluded directory. `coma sync explain <path> --json` says which rule decided.
- **Ports:** `remote` is 1–65535 (the machine's host port, or with `service`, the container port). `local` is a number, `auto`, or `disabled`. `visibility` is `local` (default) or `none`; `public` is refused because COMA never opens public ingress. `container` and `host` are refused. Names, explicit local ports and targets must be unique. A declared port replaces the automatic mirror of the same remote port while the workspace is up.
- **Not supported yet:** `spec.target.pool` / `cluster` (fail with `workspace_target_kind_unsupported`), `remotePath` other than `auto`, `delete`, `watch`. Reserved sections (`requirements`, `environment`, `secrets`, `persistence`, `caches`, `lifecycle`, `idle`, `budget`, `policy`, `extensions`) are accepted and reported as ignored.
- `apiVersion` must be `coma.sh/v1alpha1`. Unknown keys are errors. Labels may not use the `coma.sh/` prefix. The file may be at most 1 MiB.
