Providers
Providers control where each job executes during loom run --local. Your choice of provider determines isolation level, reproducibility, and available tooling.
Provider selection
Loom picks a provider for each job based on the resolved job definition:
| Condition | Provider |
|---|---|
Job has a non-empty image: value | Docker — runs in a container |
Job has image.build (build spec) | Docker — builds an image, then runs in a container |
Job has neither image: nor image.build | Host — runs on the local shell |
Job includes cache: | Cache wrapper around whichever provider above applies |
Cache is always a wrapper — it restores/saves around the base provider (host or Docker).
Inherited configuration matters
Provider selection happens after Loom resolves the full job definition. A job can inherit image: from sources you don't see inline:
- Workflow defaults:
default.imageapplies to every job that doesn't override it. - Template inheritance:
extendsor imported templates can contributeimage:.
If a job unexpectedly runs in Docker (or on host), inspect the resolved configuration:
loom compile --workflow .loom/workflow.yml
Quick example
stages: [ci]
host-job:
stage: ci
target: linux
script:
- echo "runs on host — no image set"
docker-job:
stage: ci
target: linux
image: alpine:3.20
script:
- echo "runs in a container"
cached-docker-job:
stage: ci
target: linux
image: alpine:3.20
cache:
paths: [.pnpm-store]
script:
- pnpm i --frozen-lockfile
Confirming which provider ran
Don't guess from the workflow YAML — confirm from runtime artifacts:
- Open
.loom/.runtime/logs/<run_id>/pipeline/manifest.jsonand locate the job pointer. - Open
.loom/.runtime/logs/<run_id>/jobs/<job_id>/manifest.jsonand checksystem_sections. - The
system/provider/events.jsonlsection records the selected provider, image (if Docker), and execution details. - If cache was active, look for
cache_restoreandcache_savesystem sections alongside the provider section.
For the full file layout, see the Runtime logs contract.
Prerequisites
loom run --localexecution.- Linux is the supported local target in the current MVP.
- For Docker jobs: Docker must be installed and the daemon must be reachable.
Choosing between host and Docker
| Dimension | Host | Docker |
|---|---|---|
| Isolation | Runs in your local shell; inherits the process environment | Runs in a container; environment is explicit |
| Startup speed | No container overhead | Container pull + startup adds latency |
| Reproducibility | Depends on local machine state | Image pins a known environment |
| Tool availability | Whatever is in your PATH | Only what the image provides |
| Security boundary | Jobs see local environment variables and filesystem | Container limits implicit host access (workspaces, secrets, and mounts still apply) |
For sensitive workflows, minimize secrets and mounts regardless of provider. Validate what a job can access by reviewing the provider's runtime events.
Provider pages
- Host provider — default when no
image:is set - Docker provider — activated by
image:orimage.build - Cache provider — wraps host or Docker with cache restore/save
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Job unexpectedly ran on host | Missing image: | Run loom compile and verify the resolved job has a non-empty image: |
| Job unexpectedly ran in Docker | Inherited image: | Check for image: from default, extends, or templates |
| "Cannot connect to the Docker daemon" | Docker daemon down | Confirm the daemon is running, then re-run |
| Image pull fails | Auth / not found / rate limit | Confirm the image name/tag and registry access; check provider system events for the exact error |
| Docker job fails before script starts | Docker setup issue | Check Docker daemon status and image availability |
| Cache restore "miss" or no cache sections | Cache misconfiguration | Confirm cache: is in the resolved job; check run logs for cache_restore / cache_save system sections |
If the failure is in a provider or system section (not your script:), follow the pointer-first approach in the job manifest: