Skip to main content

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:

ConditionProvider
Job has a non-empty image: valueDocker — 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.buildHost — 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.image applies to every job that doesn't override it.
  • Template inheritance: extends or imported templates can contribute image:.

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:

  1. Open .loom/.runtime/logs/<run_id>/pipeline/manifest.json and locate the job pointer.
  2. Open .loom/.runtime/logs/<run_id>/jobs/<job_id>/manifest.json and check system_sections.
  3. The system/provider/events.jsonl section records the selected provider, image (if Docker), and execution details.
  4. If cache was active, look for cache_restore and cache_save system sections alongside the provider section.

For the full file layout, see the Runtime logs contract.

Prerequisites

  • loom run --local execution.
  • 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

DimensionHostDocker
IsolationRuns in your local shell; inherits the process environmentRuns in a container; environment is explicit
Startup speedNo container overheadContainer pull + startup adds latency
ReproducibilityDepends on local machine stateImage pins a known environment
Tool availabilityWhatever is in your PATHOnly what the image provides
Security boundaryJobs see local environment variables and filesystemContainer 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

Troubleshooting

SymptomLikely causeWhat to do
Job unexpectedly ran on hostMissing image:Run loom compile and verify the resolved job has a non-empty image:
Job unexpectedly ran in DockerInherited image:Check for image: from default, extends, or templates
"Cannot connect to the Docker daemon"Docker daemon downConfirm the daemon is running, then re-run
Image pull failsAuth / not found / rate limitConfirm the image name/tag and registry access; check provider system events for the exact error
Docker job fails before script startsDocker setup issueCheck Docker daemon status and image availability
Cache restore "miss" or no cache sectionsCache misconfigurationConfirm 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: