Providers
A provider determines where and how a Loom job executes — on your local machine's shell or inside a Docker container. Provider selection is automatic: if your job specifies an image, it runs in Docker; otherwise, it runs on the host.
Why providers matter
Provider selection changes four things about your job's execution environment:
| Concern | Host provider | Docker provider |
|---|---|---|
| Isolation | None — inherits your local process environment | Process and filesystem isolation via containers |
| Available tools | Whatever is installed on your machine | Whatever is in the container image |
| Environment variables | Your shell env + Loom variables | Only Loom variables + image defaults |
| Failure debugging | Failures reference local paths and tools | Failures reference container paths; check Docker daemon first |
Host jobs use local tooling without starting a container. Docker jobs use image-defined tooling, which reduces dependencies on the host environment. Results can still vary with source, image content and platform, variables, and external services.
How Loom selects a provider
Provider selection is per-job and automatic. The rule is:
Does the job have image:? | Provider used | What happens |
|---|---|---|
| No (omitted or empty) | Host | Job runs directly in your local shell |
| Yes (non-empty string) | Docker | Job runs inside a container using the specified image |
There is no manual provider override. If you want a job to run in Docker, set image:. If you want it on the host, remove image:.
The provider name is available at runtime as the LOOM_PROVIDER variable (host or docker), which you can read in your scripts or use for conditional logic.
Host job example
version: v1
stages: [ci]
lint:
stage: ci
target: linux
script:
- golangci-lint run ./...
No image: key — Loom uses the host provider. The golangci-lint binary must be available on your machine.
Docker job example
version: v1
stages: [ci]
test:
stage: ci
target: linux
image: golang:1.22
script:
- go test ./...
The image: golang:1.22 key triggers the Docker provider. Loom pulls the image (if needed), creates a container, mounts your workspace, and runs the script inside it.
Running workflows with providers
Both host and Docker jobs are triggered the same way:
loom run --local --workflow .loom/workflow.yml
Loom inspects each job definition in the compiled graph and routes it to the correct provider automatically. To confirm the selected runtime from an executed command, print the nonsecret LOOM_PROVIDER variable and read its output with loom logs <run_id> --json. Provider diagnostics share .loom/.runtime/runs/<run_id>/events.jsonl; use job_id to match them with job state. MCP clients can filter loom_read_events by that job ID.
Docker workspace mount modes
When a job uses the Docker provider, Loom mounts the workspace into the container using one of two strategies:
| Mode | How it works | When to use |
|---|---|---|
bind_mount | Bind-mounts the host workspace directory directly into the container | Use when container writes should be visible in the snapshot |
ephemeral_volume (default) | Seeds a per-job volume from the snapshot, exports declared artifacts and cache paths, then removes the volume; other changes are discarded | Keep container writes separate from the snapshot |
Configuring the mount mode
| Method | Example | Priority |
|---|---|---|
| CLI flag | loom run --local --docker-workspace-mount bind_mount | Highest |
| Environment variable | LOOM_DOCKER_WORKSPACE_MOUNT=bind_mount loom run --local | 2 |
| Repo config | runtime.docker.workspaceMount in .loom/config.yml | 3 |
| User config | runtime.docker.workspaceMount in ~/.config/loom/config.yml | 4 |
| Default | ephemeral_volume | Lowest |
The flag always wins. If you set both, the flag takes priority:
LOOM_DOCKER_WORKSPACE_MOUNT=ephemeral_volume loom run --local --docker-workspace-mount bind_mount
# → uses bind_mount (flag takes priority)
Isolation and security model
Host provider
- Runs with local tools without container startup or image pulls.
- Weakest isolation — the job inherits your full local environment, including credentials, shell configuration, and machine-specific paths.
- Best for: quick local validation, jobs that need local toolchain access.
Docker provider
- Stronger isolation — process and filesystem isolation via containers.
- Your workspace is mounted into the container, so the job can read and write project files.
- You are still trusting your local Docker daemon and the images you reference.
- Best for: reproducible builds, testing against specific runtimes, isolating job environments from each other.
| Host | Docker | |
|---|---|---|
| Startup work | Starts a local shell | Image lookup or pull, then container creation |
| Environment | Full local shell env | Only Loom variables + image defaults |
| Filesystem isolation | None | Container filesystem with workspace mount |
| Reproducibility | Depends on local machine | Depends on image, platform, and external inputs |
| When to choose | Local iteration, native toolchain | Image-defined toolchains, multi-runtime testing |
Host jobs inherit your local environment, which may include credentials or sensitive paths. When sharing state or event excerpts for help, follow What to share and redact sensitive values.
Common pitfalls
Docker daemon not reachable
- Symptom: Jobs with
image:fail immediately with errors like "cannot connect to Docker daemon" or "pull access denied". - Fix: Verify Docker is running and accessible from your shell (
docker info). Then retry. If the failure persists, read the job's state and diagnostic messages withloom logs <run_id> --stateandloom logs <run_id> --json.
Job ran on host but you expected Docker
- Symptom: The job seems to use host tooling; container-only tools aren't present.
- Cause:
image:is missing, empty, or removed by template resolution. - Fix: Ensure the job's resolved definition has a non-empty
image:value. If you use templates ordefault, inspect the resolved workflow vialoom compileto confirm the image is present.
Different behavior between host and Docker jobs
- Symptom: A job works on host but fails in Docker (or the opposite).
- Cause: Host jobs inherit your shell environment; Docker jobs only get Loom's workflow/job variables plus the image defaults.
- Fix: Make all inputs explicit using workflow or job
variables:(see Variables). Don't assume your shell environment is available inside a container.
Planned
- Remote providers and runner pools (planned)
What to read next
- Provider details: Host provider, Docker provider, Cache provider
- Environment configuration: Variables
- CLI reference:
loom run - Failure triage: Diagnostics ladder, Common failures