Skip to main content

Isolated workspace

Every loom run --local execution creates an isolated workspace — a disposable, on-disk snapshot of your repository that serves as the execution context for all jobs in the run. This is what makes local runs behave like CI: your jobs run against a known, reproducible state rather than whatever happens to be on your machine.

If a run fails, the fastest debugging path is: copy the isolated workspace path from the output, cd into it, and inspect from there.

Why it exists

The isolated workspace solves the "works on my machine" problem for local runs:

  • Reproducibility — jobs run against a consistent snapshot of your repo, not your live working tree with its accumulated local state.
  • CI parity — the snapshot mimics what a CI system would check out, so failures you see locally are the same failures CI would catch.
  • Safe experimentation — you can inspect, modify, and re-run inside the snapshot without affecting your main checkout.

What gets snapshotted

The snapshot is designed to reflect "what CI would see" while still including your uncommitted work:

SourceIncluded?Details
HEAD commitYesLoom clones the repo and checks out HEAD in detached mode
Modified tracked filesYesDirty changes to tracked files are copied into the snapshot
Added/renamed tracked filesYesStaged additions and renames are applied
Deleted tracked filesYesTracked deletions are removed from the snapshot
Untracked, non-ignored filesYesFiles visible to git status (not in .gitignore) are copied
Gitignored filesNoFiles matched by .gitignore are excluded
SymlinksPreservedSymlinks are copied as symlinks (targets are not dereferenced)
Non-regular filesNoDevices, sockets, and other special files are not supported

Key takeaway: if your run behaves differently in the isolated workspace than in your checkout, ask: "Was I depending on a gitignored file?" That's the most common cause.

How to use it

1. Find the path

Local runs print the isolated workspace path near the start of output:

isolated workspace: /tmp/loom-run-local-1772666574190575000-3847261095

Copy this path. It's your entry point for all debugging.

2. Inspect the snapshot

The snapshot looks like a normal repo checkout with a .loom/.runtime/ directory for run artifacts:

/tmp/loom-run-local-<run_id>-*/
apps/
libs/
packages/
.git/ # real git clone (detached HEAD)
.loom/
.runtime/
logs/ # structured run logs
receipts/ # run receipt JSON

3. Check run artifacts

After the run completes, start debugging from .loom/.runtime/:

ArtifactPathWhat it tells you
Receipt.loom/.runtime/receipts/<receipt>.jsonRun metadata, status, pointers to logs
Pipeline summary.loom/.runtime/logs/<run_id>/pipeline/summary.jsonOverall pass/fail, job statuses
Job manifest.loom/.runtime/logs/<run_id>/jobs/<job_id>/manifest.jsonPointers to the failing step's events
Step events.loom/.runtime/logs/<run_id>/jobs/<job_id>/user/script/<NN>/events.jsonlDetailed output for a specific step
Job artifacts.loom/.runtime/logs/<run_id>/jobs/<job_id>/artifacts/Extracted files when artifacts: is configured

For the full navigation flow, see Runtime logs and Receipts.

4. Reproduce failures

Before changing anything in your main checkout, try reproducing from inside the isolated workspace:

cd /tmp/loom-run-local-<run_id>-*
loom run --local --workflow .loom/workflow.yml

This ensures you're testing against the exact same snapshot context. Avoid "fixing" problems by accidentally relying on files outside the snapshot (local configs, untracked files, environment-specific state).

Disk usage and cleanup

Because each snapshot is a full copy of your repo, it can use significant disk space for large repositories.

BehaviorDetails
LocationOS temp directory (e.g., /tmp/loom-run-local-<run_id>-*)
On preparation failureSnapshot directory is cleaned up automatically
On run success or failureSnapshot is preserved for debugging
Manual cleanupDelete the directory when done — it is fully disposable
caution

Deleting the snapshot also deletes the .loom/.runtime/ artifacts inside it (logs, receipts). Copy any artifacts you need before removing the directory.

Common pitfalls

PitfallFix
Debugging in your original checkout instead of the snapshotAlways cd into the printed isolated workspace path first
Depending on a gitignored file (e.g., .env.local)Commit the file, pass values via variables:, or generate it in a script: step
Assuming "snapshot" means remote executionThe snapshot is for local reproducibility only — it does not imply remote execution
Referencing ~/... paths during debuggingStay within the snapshot directory to reproduce what Loom actually ran

Example: gitignored file causes failure

A common "it works on my machine" scenario:

  1. You have a gitignored config file (e.g., .env.local) in your checkout.
  2. Your script reads it implicitly (directly, or via tooling that auto-loads it).
  3. The isolated workspace does not include that file, so the job runs with different configuration and fails.

Fix options:

  • Commit the config if it's not sensitive.
  • Pass values explicitly via workflow or job variables: — see Variables.
  • Generate the file inside the job as an explicit script: step (avoid printing secrets).

Privacy and secrets

Treat the isolated workspace as potentially sensitive:

  • It contains your source code and generated artifacts.
  • .loom/.runtime/ may contain logs with environment details, commands, and error output.
  • Secrets should not appear in logs (Loom redacts them), but review before sharing externally.

See Receipts for guidance on what's safe to share.

Docker workspace mount modes

When Docker jobs execute inside the isolated workspace, the workspace is mounted into the container using one of two modes:

  • bind_mount — the isolated workspace directory is bind-mounted directly into the container at /workspace. Fast, zero copy overhead.
  • ephemeral_volume (default) — a Docker volume is created and seeded with the workspace contents. After execution, changes are synced back. Provides stronger isolation from the host filesystem.

Configure via --docker-workspace-mount flag or LOOM_DOCKER_WORKSPACE_MOUNT environment variable. See Docker provider for details.

  • Runtime logs — how to navigate the structured log tree inside .loom/.runtime/
  • Receipts — the stable JSON pointer document for every run
  • Variables — pass configuration into jobs without relying on local files
  • Cache — cached outputs are restored inside the isolated workspace
  • Docker provider — workspace mount modes and container behavior
  • CLI loom run — full flag reference for local runs