Workflows
Loom workflows are defined in .loom/workflow.yml and describe what to run, in what order, and how to diagnose failures when they happen.
The v1 workflow format is designed to be familiar to anyone who has used modern CI systems: stages, jobs, variables, includes/templates, secrets, and cache configuration — paired with Loom's pointer-first diagnostics model (receipts, manifests, structured events) so you can follow pointers to the exact failing unit instead of hunting through console output.
If you're new to Loom, start with Getting Started → Hello Loom first, then come back here for the full syntax and patterns.
If you need runtime defaults such as Docker workspace mount mode or provider
alias wiring, see Runtime config. .loom/workflow.yml remains
the executable workflow source of truth.
Choose the right surface
Workflow definition, runtime defaults, and env-based overrides live in different places on purpose:
| Surface | Use it for |
|---|---|
.loom/workflow.yml | Jobs, stages, scripts, variables, cache, and secrets references |
.loom/config.yml | Repo-scoped runtime defaults for local execution |
~/.config/loom/config.yml | User-scoped runtime defaults on one machine |
| Environment variables | Secret values and one-off runtime overrides |
If you are deciding what the pipeline does, stay in the workflow docs. If you are deciding what local defaults Loom should assume before a run starts, go to Runtime config.
Runtime config is runtime-only. It is not a second workflow language.
Minimal workflow (copy/paste)
A schema-valid "hello workflow" you can paste into .loom/workflow.yml and run locally:
version: v1
stages: [ci]
check:
stage: ci
target: linux
script: ["echo hello from Loom"]
- For the full keyword reference, see Syntax (v1).
- For how to run locally, see CLI
loom run.
Why Loom workflows
Loom workflows make failures diagnosable without log archaeology. After every run, Loom produces deterministic artifacts — receipts, manifests, and structured events — so you follow pointers to the exact failing unit instead of scrolling through raw console output.
| Traditional CI | Loom |
|---|---|
| Scroll through combined stdout/stderr to find the error | Follow pointer chain: receipt → manifest → failing step events.jsonl |
Re-run with set -x to reproduce | Inspect structured events captured during the original run |
| Grep logs for "error" across jobs | Read summary.json for status + exit code, then drill into the one failing job |
- Start with the Diagnostics ladder to learn the pointer chain.
- See canonical layouts: Runtime logs contract and Receipts contract.
What's supported today
- Workflow file:
.loom/workflow.yml(or--workflow <path>). - Local execution:
loom run --local(Linux target only in the current release). - Jobs:
- Jobs run on the host shell by default, or in Docker when an
image:is set. - Job scripts are an ordered list of command strings (
script:).
- Jobs run on the host shell by default, or in Docker when an
- Secrets: jobs can declare secrets that are resolved at runtime and injected securely. See Secrets.
- Strict schema: workflows are validated via
loom check(schema v1).
Platform support
-
Linux-only local execution: the local runner supports
target: linux. If you're on macOS or Windows, run Loom inside a Linux environment (VM, container, or CI runner). -
Docker is optional: you only need Docker if your workflow uses job
image:(see Docker provider).- Docker prerequisites (daemon reachable, image pullable): see Docker provider → Prerequisites.
-
Provider routing is per job:
Job configuration Provider used No image:Host provider image:setDocker provider
What's enforced vs what's planned
Loom has two layers to keep separate:
| Layer | What it means | Examples |
|---|---|---|
Enforced (schema validation via loom check) | The workflow is schema v1 compliant: required keys, allowed shapes, naming rules | version, stages, stage, target, script, variables, cache, secrets |
| Schema-accepted, runtime evolving | Keywords are accepted so workflows can be written future-compatible, but may not change execution behavior yet | needs (DAG scheduling), runner_pool (remote execution), invariant (policy checkpoints) |
When in doubt, treat the "What's supported today" section as the behavior you can rely on. Planned sections signal direction, not commitment.
Runtime config boundary
The current layered runtime config surface is consumed only by:
loom config showloom run --local
loom check and loom compile still read workflow inputs rather than layered
runtime config.
Planned
- Remote execution (runner pools + leases).
- Richer job sections (
before_script,after_script) and expanded step semantics. - Full DAG scheduling via
needs. - Runner pool capability/constraint enforcement.
- Invariant policy checkpoints with decision capture in receipts/events.
Next steps
- Full keyword reference: Syntax (v1)
- Variables: Workflows → Variables and Concepts → Variables
- Caching: Workflows → Cache and Concepts → Cache
- Secrets: Workflows → Secrets and Concepts → Secrets
- Runtime defaults: Runtime config
- Workflow/runtime boundary: Runtime config vs workflow YAML
- Providers: Host vs Docker
- Real example: Examples → Stage 0
- Predefined variables: CI/CD variables (Loom)