Ephemeral worktree isolation for Loop Engineering. Divert agent execution into an isolated git worktree, capture their changes as a reviewable .patch file, and instantly destroy the sandbox.
Unattended AI agents (loops) running directly in your main working tree can cause damage, overwrite untracked files, or make it incredibly tedious to untangle failed execution attempts.
loop-sandbox solves this by providing ephemeral worktree isolation:
- It automatically creates an isolated git worktree for the agent to run in.
- The agent runs its command, interacting with the codebase completely naturally.
- When the command finishes,
loop-sandboxautomatically captures the agent's edits (including new untracked files) into a clean.patchfile. - It nukes the worktree, keeping your main repo completely clean.
A human can then safely review the patch and apply it with one keystroke.
Warning
Isolation Limits: This is not a containerized air-gap. The agent process retains full filesystem and network access. It can escape the worktree (e.g. ../../), and changes outside the worktree or to .gitignored files will not be captured in the patch. This tool is complementary to docs/safety.md and does not replace OS-level sandboxing for hostile code.
npm install -g @cobusgreyling/loop-sandbox
# or run directly via npx
npx @cobusgreyling/loop-sandbox run -- <command>Important
Required Gitignores: You must add the following to your project's .gitignore to prevent patches and worktree manifests from being committed:
.loop-sandbox/
.loop-worktrees/
loop-sandbox <command> [options]| Command | Description |
|---|---|
run [opts] -- <cmd> |
Run an agent command inside the isolated sandbox |
review / list |
List isolated patches ready for human review |
| Option | Description |
|---|---|
--shell |
Forces shell: true (for bash -c, etc.). On Windows, npm-installed .cmd shims (npx, tsc, ...) that fail with ENOENT are automatically retried through a shell, so this is rarely needed there. |
--base <branch> |
The base branch for the worktree (defaults to current HEAD) |
--lock-paths <globs> |
Comma-separated globs to hold a loop-worktree advisory lock on for the run's duration, so a scheduled loop can't touch the same paths concurrently. Off by default -- see Multi-loop safety below. |
--lock-owner <name> |
Lock owner name (defaults to the run's generated id) |
--lock-ttl <dur> |
e.g. 30m -- passed through to loop-worktree's --ttl |
--lock-wait <dur> |
e.g. 5m -- passed through to loop-worktree's --wait |
Running a tool via an agent:
# Safely let an agent run your linter/formatter without polluting your working tree
npx @cobusgreyling/loop-sandbox run -- npx my-agentRunning a shell command:
npx @cobusgreyling/loop-sandbox run --shell -- bash -c "echo 'hello' > test.txt"Running alongside a scheduled loop that touches the same files:
npx @cobusgreyling/loop-sandbox run --lock-paths "src/**,docs/**" -- npx my-agentReviewing and applying patches:
# List all patches the sandbox caught
npx @cobusgreyling/loop-sandbox review
# Example output:
# === Loop Sandbox Patches ===
# 📄 sandbox-82f1e394.patch (1.2 KB)
# Apply: git apply .loop-sandbox/patches/sandbox-82f1e394.patchUnder the hood, loop-sandbox leverages @cobusgreyling/loop-worktree and native git worktree primitives. It creates a temporary branch from your current HEAD, spawns your process with its cwd set to the isolated tree, runs git diff --cached to generate the patch, and uses git worktree remove --force to clean up.
A sandbox run is not, by itself, protected against a scheduled loop editing
the same files at the same time -- --lock-paths opts a run into
loop-worktree's advisory lock (acquired before the worktree is created,
released once the run finishes) so a colliding scheduled loop's own lock
call fails loudly instead of racing silently. See
docs/multi-loop.md for the wider convention this
follows.