Isolated workspace
During setup, loom run --local creates an isolated workspace: a disposable, on-disk snapshot where jobs execute. It separates execution from your live checkout and excludes ignored files. It does not isolate host processes or guarantee the same result as CI.
If a command fails, use the printed isolated workspace path to reproduce the command against the exact source snapshot. Use the receipt path in the live checkout to inspect persistent logs and published artifacts.
Why it exists
The snapshot lets you inspect and rerun commands against the source used by the run. Missing ignored files can expose dependencies on local state. Host tools, environment variables, user config, secrets, and external services can still affect the result.
When comparing with CI, match the source, tool versions or image digest and platform, variables, services, secrets, and external inputs. Uncommitted source in a local snapshot may differ from the source checked out in CI.
What gets snapshotted
Loom starts from HEAD and includes your uncommitted source changes:
| Source | Included? | Details |
|---|---|---|
HEAD commit | Yes | Loom clones the repo and checks out HEAD in detached mode |
| Modified tracked files | Yes | Dirty changes to tracked files are copied into the snapshot |
| Added/renamed tracked files | Yes | Staged additions and renames are applied |
| Deleted tracked files | Yes | Tracked deletions are removed from the snapshot |
| Untracked, non-ignored files | Yes | Files visible to git status (not in .gitignore) are copied |
| Gitignored files | No | Files matched by .gitignore are excluded |
| Symlinks | Preserved | Symlinks are copied as symlinks (targets are not dereferenced) |
| Non-regular files | No | Devices, sockets, and other special files are not supported |
If a command behaves differently in the snapshot, check whether it depends on an ignored file that Loom excluded.
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 when you need to inspect or rerun against the source snapshot.
2. Inspect the snapshot
The snapshot looks like a normal repo checkout. It is the execution workspace, not the persistent runtime-artifact destination:
/tmp/loom-run-local-<run_id>-*/
apps/
libs/
packages/
.git/ # real git clone (detached HEAD)
3. Check run artifacts
After the run completes, start debugging from .loom/.runtime/ in the live checkout. Loom publishes runtime outputs there so they survive independently of the disposable snapshot:
| Artifact | Path | What it tells you |
|---|---|---|
| Receipt | .loom/.runtime/receipts/<receipt>.json | Run metadata, status, pointers to logs |
| Pipeline summary | .loom/.runtime/logs/<run_id>/pipeline/summary.json | Overall pass/fail, job statuses |
| Job manifest | .loom/.runtime/logs/<run_id>/jobs/<job_id>/manifest.json | Pointers to the failing step's events |
| Step events | .loom/.runtime/logs/<run_id>/jobs/<job_id>/user/execution/script/<NN>/events.jsonl | Detailed output for a specific step |
| Job artifacts | .loom/.runtime/logs/<run_id>/jobs/<job_id>/artifacts/ | Published files when artifacts: is configured |
The pointer fields form the stable diagnostic structure; concrete receipt names, run IDs, timestamps, and absolute paths are specific to each run. For a failed user step, follow the receipt's logs_dir to pipeline/manifest.json, then follow failing_job_manifest_path to the job manifest and failing_step_events_path to the existing user/execution/script/<NN>/events.jsonl file.
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 starts another run from that source snapshot. Environment variables, tools, configuration, and external services can still differ. Check those inputs as well as files when reproducing a failure.
Disk usage and cleanup
Because each snapshot is a full copy of your repo, it can use significant disk space for large repositories.
| Behavior | Details |
|---|---|
| Location | OS temp directory (e.g., /tmp/loom-run-local-<run_id>-*) |
| On preparation failure | Snapshot directory is cleaned up automatically |
| On run success or failure | Snapshot is preserved for debugging |
| Manual cleanup | Delete the directory when done — it is fully disposable |
Deleting the snapshot does not delete receipts, structured logs, or published job artifacts in the live checkout's .loom/.runtime/ directory.
Common pitfalls
| Pitfall | Fix |
|---|---|
| Debugging in your original checkout instead of the snapshot | Always 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 execution | The snapshot is for local reproducibility only — it does not imply remote execution |
Referencing ~/... paths during debugging | Stay within the snapshot directory to reproduce what Loom actually ran |
Example: gitignored file causes failure
A common "it works on my machine" scenario:
- You have a gitignored config file (e.g.,
.env.local) in your checkout. - Your script reads it implicitly (directly, or via tooling that auto-loads it).
- 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 command-generated files.
- The live checkout's
.loom/.runtime/may contain logs and published artifacts with environment details, commands, and error output. - Loom redacts exact secret matches in supported console, log, and receipt output. Transformed values and raw artifacts are outside that protection; review them 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. Artifact matching reads that snapshot after execution.ephemeral_volume(default) — a Docker volume is created and seeded with the snapshot. Candidate artifact roots are exported to private staging before the volume is removed; Loom then applies includes and excludes and publishes only selected files to the persistent destination.
Configure with the --docker-workspace-mount flag, LOOM_DOCKER_WORKSPACE_MOUNT environment variable, or runtime.docker.workspaceMount in repo or user config, in that precedence order. See Docker provider for details.
What to read next
- Runtime logs — how to navigate the persistent structured log tree in the live checkout
- Receipts — run metadata and pointers to recorded evidence
- 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