From 7fdd0d95e15020a7979cd4497af6d28bfe3c67ed Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Thu, 21 May 2026 19:37:28 +0200 Subject: [PATCH 1/6] sandboxes: document --clone, in-container clone and source-repository isolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the `--branch[=NAME]` documentation with `--clone` (boolean) on both `sbx create` and `sbx run`, matching the CLI rename in docker/sandboxes#3055. Clone mode is now strictly about running the agent on a private in-container `git clone --reference` of the host repository; no host-side branch is created on the user's behalf — the user instructs the agent to `git checkout -b ...` inside the sandbox if a dedicated working branch is needed. Key documentation changes: - usage.md: "Branch mode" section is renamed to "Clone mode" and rewritten end-to-end. Drops the `.sbx/-worktrees/...` directory mention (no longer created), the host-side branch creation/checkout step, the `--branch=auto` flow, and the legacy "Multiple branches per sandbox" section. Adds: * an explicit note that clone mode is fixed at create time; * the forge-remote propagation behaviour (origin/upstream propagated from host into the in-container clone, local-path remotes skipped); * a Cleanup warning about lost in-container commits when running `sbx rm` (mirrors the runtime warning). - security/isolation.md: adds the "Source-repository isolation" section introduced in #25007. Same content, but uses `--clone` and "clone mode" terminology throughout, plus a clarifying note that `sbx rm` warns before dropping unfetched/unpushed commits. - security/workspace.md: the existing "Branch mode" stub (claiming the old `--branch` was a "workflow convenience, not a security boundary") is replaced with a "Clone mode" section that explicitly calls out the isolation guarantee — clone mode IS a security boundary, the host's `.git` cannot be touched. - security/_index.md: source-repository isolation is added to the five-layer model (was four). Wording aligned with isolation.md. Migration: callers that scripted `sbx create --branch=feature/x` now pass `--clone` and tell the agent to create the branch. This PR is an alternative to docker/docs#25007, written against the post-rename CLI. Signed-off-by: Nicolas De loof --- .../manuals/ai/sandboxes/security/_index.md | 5 +- .../ai/sandboxes/security/isolation.md | 68 ++++++- .../ai/sandboxes/security/workspace.md | 21 ++- content/manuals/ai/sandboxes/usage.md | 174 ++++++++++-------- 4 files changed, 177 insertions(+), 91 deletions(-) diff --git a/content/manuals/ai/sandboxes/security/_index.md b/content/manuals/ai/sandboxes/security/_index.md index ef6048e4446..3c326736723 100644 --- a/content/manuals/ai/sandboxes/security/_index.md +++ b/content/manuals/ai/sandboxes/security/_index.md @@ -41,7 +41,7 @@ and ICMP are blocked at the network layer. ## Isolation layers -The sandbox security model has four layers. See +The sandbox security model has five layers. See [Isolation layers](isolation/) for technical details on each. - **Hypervisor isolation:** separate kernel per sandbox. No shared memory or @@ -50,6 +50,9 @@ The sandbox security model has four layers. See [Deny-by-default policy](defaults/). Non-HTTP protocols blocked entirely. - **Docker Engine isolation:** each sandbox has its own Docker Engine with no path to the host daemon. +- **Source-repository isolation (clone mode):** the agent works on a private + in-VM clone with your `.git` mounted read-only. Even an unconstrained + agent cannot corrupt your host repository. - **Credential isolation:** API keys are injected into HTTP headers by the host-side proxy. Credential values never enter the VM. diff --git a/content/manuals/ai/sandboxes/security/isolation.md b/content/manuals/ai/sandboxes/security/isolation.md index ab220ad26ba..0dda1b70450 100644 --- a/content/manuals/ai/sandboxes/security/isolation.md +++ b/content/manuals/ai/sandboxes/security/isolation.md @@ -1,13 +1,14 @@ --- title: Isolation layers weight: 10 -description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, and credential boundaries. -keywords: docker sandboxes, isolation, hypervisor, network, credentials +description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, source-repository, and credential boundaries. +keywords: docker sandboxes, isolation, hypervisor, network, credentials, git --- AI coding agents need to execute code, install packages, and run tools on -your behalf. Docker Sandboxes run each agent in its own microVM with four -isolation layers: hypervisor, network, Docker Engine, and credential proxy. +your behalf. Docker Sandboxes run each agent in its own microVM with five +isolation layers: hypervisor, network, Docker Engine, source-repository +(in clone mode), and credential proxy. ## Hypervisor isolation @@ -71,6 +72,65 @@ Host system └── [VM] Containers created by agent ``` +## Source-repository isolation + +When you start a sandbox with `--clone` (see the +[clone-mode workflow](../usage.md#clone-mode)), the agent never works +directly against your host repository. Even with full root inside the VM, +it cannot corrupt your local Git state. + +The boundary works like this: + +- Your repository's Git root is bind-mounted into the sandbox at + `/run/sandbox/source` as a read-only mount. The agent — and anything it + spawns — cannot write to your `.git` directory, your working tree, or + any tracked file via that mount. +- The agent's working copy is a private `git clone --reference` populated + on the sandbox's overlay filesystem. The clone has its own index, its + own refs, and its own working tree. Object storage is shared via + `.git/objects/info/alternates`, so the clone is space-efficient and + full history is walkable, but writes to the clone never reach your + host's object database. +- Your host pulls the agent's commits over a `git-daemon` exposed by the + sandbox on `127.0.0.1:`. The CLI registers it as a + `sandbox-` remote on your host repository. Fetching from + that remote uses the same trust model as fetching from any third-party + remote: nothing is integrated until you explicitly merge or check out + the fetched refs. + +```plaintext +Host repository Sandbox VM + .git/ /run/sandbox/source/ (RO bind mount) + objects/ ◄─────── alternates ───────── clone/.git/objects/ + refs/ clone/.git/refs/ (private) + HEAD clone/.git/HEAD (private) + working tree clone/working tree (overlay FS) + remote sandbox- ──── git:// ────► git-daemon :9418 + (published 127.0.0.1:) +``` + +The practical guarantees: + +- Index and ref corruption can't happen — concurrent `git` commands on the + host and inside the sandbox don't race on a shared `.git/index` or shared + refs because there is no shared writable state. +- The agent can't write back to your working tree. A compromised or buggy + agent can't drop a `.git/hooks/pre-commit`, modify `.github/workflows/`, + or edit any other tracked file in a way that affects your host until you + fetch and merge from the `sandbox-` remote. +- Credentials, signing keys, and global settings declared in your + repository's `.git/config` stay on the host. The agent's clone has its + own independent configuration. +- Cleanup is automatic: `sbx rm` deletes the clone, the published port, + and the `sandbox-` remote on your host. Any in-container commits + that have not been fetched or pushed to an upstream remote are dropped + with the sandbox — `sbx rm` prints a warning before doing so. + +In direct mode (no `--clone`), the agent edits your working tree directly +and this isolation does not apply. Use clone mode whenever you want a +strong boundary between the agent's Git activity and your host +repository. + ## Credential isolation Most agents need API keys for their model provider. Rather than passing keys diff --git a/content/manuals/ai/sandboxes/security/workspace.md b/content/manuals/ai/sandboxes/security/workspace.md index e6cb792bfa0..4f3d0e00094 100644 --- a/content/manuals/ai/sandboxes/security/workspace.md +++ b/content/manuals/ai/sandboxes/security/workspace.md @@ -33,11 +33,18 @@ includes: > building, or opening the project in an IDE. Review these files after any agent > session before performing those actions. -## Branch mode +## Clone mode -The `--branch` flag lets the agent work on a separate branch. This is a -workflow convenience, not a security boundary: the agent still mounts the full -repository. See the [usage guide](../usage.md) for details. +The `--clone` flag isolates the agent from your host repository: it works +on a private clone inside the sandbox, with your `.git` directory +bind-mounted as a read-only reference. This means the agent cannot modify +any tracked file or any byte under `.git/` on your host, no matter how +unconstrained the agent runs. You see the agent's commits only after +explicitly running `git fetch sandbox-`. + +See [Source-repository isolation](isolation.md#source-repository-isolation) +for the full boundary, and the [usage guide](../usage.md#clone-mode) for +the workflow. ## Reviewing changes @@ -50,10 +57,12 @@ With the default direct mount, changes are in your working tree: $ git diff ``` -If you used `--branch`, the agent's changes are on a separate branch: +If you used `--clone`, the agent's changes are on the `sandbox-` +remote until you fetch and merge them: ```console -$ git diff main..my-feature +$ git fetch sandbox-my-sandbox +$ git diff main..sandbox-my-sandbox/ ``` Pay particular attention to: diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index c8fa2e8f757..274e297f627 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -77,117 +77,131 @@ When your workspace is a Git repository, the agent edits your working tree directly by default. Changes appear in your working tree immediately, the same as working in a normal terminal. -If you run multiple agents on the same repository at once, use [branch -mode](#branch-mode) to give each agent its own branch and working directory. +If you want the agent to work in isolation from your host repository — for +example to run multiple agents in parallel, or to prevent any chance of an +agent rewriting your local Git state — use [clone mode](#clone-mode). The +agent runs against a private Git clone inside the sandbox; your host repository +sees the agent's commits only after you explicitly fetch them. ### Direct mode (default) The agent edits your working tree directly. Stage, commit, and push as you normally would. If you run multiple agents on the same repository at the same time, they may step on each other's changes. See -[branch mode](#branch-mode) for an alternative. - -### Branch mode - -Pass `--branch ` to give the agent its own -[Git worktree](https://git-scm.com/docs/git-worktree) and branch. This -prevents conflicts when multiple agents, or you and an agent, write to the -same files at the same time. You can set `--branch` on `create`, `run`, or -both. - -The CLI creates worktrees under `.sbx/` in your repository root. The -worktree is a separate working directory, so the agent doesn't touch your main -working tree. This means: - -- The worktree branches off your latest commit when you create it. - Uncommitted changes in your working tree are not included (`sbx` warns you - if it detects any). -- Files you add or change in your main working tree won't be visible to the - agent, and vice versa. The two directories are independent. - -#### Starting a branch +[clone mode](#clone-mode) for an alternative. + +### Clone mode + +Pass `--clone` to run the agent on a private Git clone living entirely +inside the sandbox, instead of bind-mounting your working tree. Your host +repository is mounted read-only as the clone's reference, so the agent — even +with full root inside the VM — cannot modify any byte of your `.git` +directory or working tree. You can set `--clone` on `create` or, equivalently, +on `run` at create time. + +When `--clone` is active: + +- The agent works on a private clone populated by + `git clone --reference` from your repository, on the sandbox's overlay + filesystem. The clone has its own index, refs, and working tree. + Object storage is shared via `.git/objects/info/alternates`, so the + clone is space-efficient and full history is walkable, but writes to + the clone never reach your host's object database. +- Your repository's Git root is bind-mounted at `/run/sandbox/source` as a + read-only mount. The agent's `git clone --reference` reads from this + mount; nothing on the host is writable from inside the sandbox. +- The clone follows whatever HEAD your host repository is on at create time. + No branch is created automatically — if you want the agent to work on a + dedicated branch, instruct the agent to `git checkout -b my-feature` + inside the sandbox before it starts editing. +- The sandbox runs a `git-daemon` over a `127.0.0.1`-bound ephemeral port + that exports the in-container clone. The CLI registers it as a Git remote + named `sandbox-` on your host repository, so you can pull + the agent's commits with `git fetch`. +- Forge remotes you have on the host (`origin`, `upstream`, …) are + propagated into the in-container clone with their existing URLs, so the + agent can `git push origin …` to your GitHub fork as you would on the + host. Local-path remotes (`file://`, paths) are skipped because they + aren't reachable from inside the sandbox. + +See [Source-repository isolation](security/isolation.md#source-repository-isolation) +for the security boundary. + +#### Starting a sandbox in clone mode ```console -$ sbx run claude --branch my-feature # agent works on the my-feature branch +$ sbx run --clone claude # private clone of the current repository ``` -Use `--branch auto` to let the CLI generate a branch name for you: +You can also create the sandbox first and attach later: ```console -$ sbx run claude --branch auto +$ sbx create --clone --name my-sandbox claude . +$ sbx run my-sandbox # resumes in the in-container clone ``` -You can also create the sandbox first and add a branch at run time: +> [!NOTE] +> Clone mode is fixed at create time. Recreate the sandbox with +> `sbx create --clone ...` to switch an existing sandbox into clone mode. -```console -$ sbx create --name my-sandbox claude . -$ sbx run --branch my-feature my-sandbox -``` - -Or set the branch at create time and reuse it on subsequent runs: - -```console -$ sbx create --name my-sandbox --branch my-feature claude . -$ sbx run my-sandbox # resumes in the my-feature worktree -$ sbx run --branch my-feature my-sandbox # same — reuses the existing worktree -``` - -#### Multiple branches per sandbox +#### Reviewing and pushing changes -You can run multiple worktrees in the same sandbox by passing different branch -names: +The CLI wires the agent's in-container clone as a `sandbox-` +Git remote on your host repository. Review the agent's work with the same +commands you'd use for any other remote — no extra tooling, no `cd` into +a separate directory: ```console -$ sbx run --branch feature-a my-sandbox -$ sbx run --branch feature-b my-sandbox +$ git fetch sandbox-my-sandbox # pull the agent's commits +$ git log sandbox-my-sandbox/ # see what the agent did +$ git diff main..sandbox-my-sandbox/ +$ git checkout -b my-feature sandbox-my-sandbox/ +$ git push -u origin my-feature +$ gh pr create ``` -#### Reviewing and pushing changes +If the agent committed on a dedicated branch (because you asked it to +`git checkout -b ...`), that branch name appears on the `sandbox-` +remote. If it stayed on the HEAD it inherited at create time, its commits +extend that branch instead — you'll see them by fetching and diffing. -To review the agent's work, find the worktree with `git worktree list`, then -push or open a PR from there: +Some agents don't commit automatically. If `git log sandbox-/...` +shows nothing new, open a shell in the sandbox and commit from there +before fetching. `sbx exec` drops you into the in-container clone: ```console -$ git worktree list # find the worktree path -$ cd .sbx/-worktrees/my-feature -$ git log # see what the agent did -$ git push -u origin my-feature -$ gh pr create +$ sbx exec -it my-sandbox bash +$ git commit -am "save work" ``` -Some agents don't commit automatically and leave changes uncommitted in the -worktree. If that happens, commit from the worktree directory before pushing. - See [Workspace trust](security/workspace.md) for security considerations when reviewing agent changes. #### Cleanup -`sbx rm` removes the sandbox and all of its worktrees and branches. - -#### Ignoring the `.sbx/` directory +`sbx rm` deletes the sandbox, its in-container clone, the published Git +port, and the `sandbox-` remote on your host repository. -Branch mode stores worktrees under `.sbx/` in your repository root. To keep -this directory out of `git status`, add it to your project's `.gitignore`: +> [!WARNING] +> Any commits the agent made inside the sandbox that you have not yet +> fetched (via `git fetch sandbox-`) or pushed to an upstream +> remote will be lost — the in-container clone lives on the sandbox's +> overlay filesystem and is dropped with it. `sbx rm` prints a warning +> for clone-mode sandboxes; review it before confirming the removal. -```console -$ echo '.sbx/' >> .gitignore -``` - -Or, to ignore it across all repositories, add `.sbx/` to your global gitignore: - -```console -$ echo '.sbx/' >> "$(git config --global core.excludesFile)" -``` +#### Restrictions -> [!TIP] -> If `git config --global core.excludesFile` is empty, set one first: -> `git config --global core.excludesFile ~/.gitignore`. +A few configurations are incompatible with clone mode and are rejected at +create time: -You can also create Git worktrees yourself and run an agent directly in one, -but the sandbox won't have access to the `.git` directory in the parent -repository. This means the agent can't commit, push, or use Git. `--branch` -solves this by setting up the worktree so that Git works inside the sandbox. +- `--clone` together with `--workspace-volume`: the source-repository + isolation relies on bind-mounting your Git root, which is incompatible + with a volume-backed workspace. +- `--clone` from inside a host Git worktree: the bind mount can't resolve + the worktree's `.git` pointer file. Run `sbx create --clone ...` from + the main repository instead. +- `--clone` on a non-Git workspace: clone mode requires a Git repository. + Run `sbx create` without `--clone` for non-Git workspaces. ### Signed commits @@ -251,7 +265,7 @@ $ sbx create claude . ``` Unlike `run`, `create` requires an explicit workspace path. It uses direct -mode by default, or pass `--branch` for [branch mode](#branch-mode). Attach +mode by default, or pass `--clone` for [clone mode](#clone-mode). Attach later with `sbx run`: ```console @@ -262,8 +276,8 @@ $ sbx run claude-my-project You can mount extra directories into a sandbox alongside the main workspace. The first path is the primary workspace — the agent starts here, and the -sandbox's Git worktree is created from this directory if you use `--branch`. -Extra workspaces are always mounted directly. +sandbox's in-container Git clone is populated from this directory if you +use `--clone`. Extra workspaces are always mounted directly. All workspaces appear inside the sandbox at their absolute host paths. Append `:ro` to mount an extra workspace read-only — useful for reference material or From 755405eeb8cbf22403042e539db3d5083fe2426a Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 26 May 2026 14:29:42 +0200 Subject: [PATCH 2/6] sandboxes: restructure clone-mode docs around workflow and consolidate isolation - Move boundary description for both direct and clone modes onto the isolation page; snip the separate workspace trust page. - Rewrite the usage.md Clone mode section workflow-first: mental model, setup, reviewing/merging via the sandbox- remote, pushing to forge remotes propagated from the host, parallel branches inside one sandbox, daemon lifecycle and ephemeral port, cleanup, restrictions. - Drop the --workspace-volume restriction (hidden, non-functional flag). - Restore the user-created worktree caveat. - Update cross-references that pointed at workspace.md. --- content/manuals/ai/sandboxes/_index.md | 4 +- content/manuals/ai/sandboxes/get-started.md | 3 +- .../manuals/ai/sandboxes/security/_index.md | 35 +-- .../manuals/ai/sandboxes/security/defaults.md | 3 +- .../ai/sandboxes/security/isolation.md | 147 +++++++----- .../ai/sandboxes/security/workspace.md | 81 ------- content/manuals/ai/sandboxes/usage.md | 210 ++++++++++-------- 7 files changed, 235 insertions(+), 248 deletions(-) delete mode 100644 content/manuals/ai/sandboxes/security/workspace.md diff --git a/content/manuals/ai/sandboxes/_index.md b/content/manuals/ai/sandboxes/_index.md index 00cd87d0134..7e32f3b9055 100644 --- a/content/manuals/ai/sandboxes/_index.md +++ b/content/manuals/ai/sandboxes/_index.md @@ -72,8 +72,8 @@ the [usage guide](usage.md) for common patterns. extending or tailoring sandboxes - [Architecture](architecture.md) — microVM isolation, workspace mounting, networking -- [Security](security/) — isolation model, credential handling, network - policies, workspace trust +- [Security](security/) — isolation model, credential handling, and + network policies - [CLI reference](/reference/cli/sbx/) — full list of `sbx` commands and options - [Troubleshooting](troubleshooting.md) — common issues and fixes - [FAQ](faq.md) — login requirements, telemetry, etc diff --git a/content/manuals/ai/sandboxes/get-started.md b/content/manuals/ai/sandboxes/get-started.md index 2e1d97d380a..160db21dcdd 100644 --- a/content/manuals/ai/sandboxes/get-started.md +++ b/content/manuals/ai/sandboxes/get-started.md @@ -268,5 +268,6 @@ working tree are unaffected. - [Customize](customize/) — build reusable templates or declare capabilities with kits - [Credentials](security/credentials.md) — credential storage and management -- [Workspace trust](security/workspace.md) — review agent changes safely +- [Workspace isolation](security/isolation.md#workspace-isolation) — what + the agent can affect on your host, and how to review changes - [Policies](security/policy.md) — control outbound access diff --git a/content/manuals/ai/sandboxes/security/_index.md b/content/manuals/ai/sandboxes/security/_index.md index 3c326736723..120270ec9c9 100644 --- a/content/manuals/ai/sandboxes/security/_index.md +++ b/content/manuals/ai/sandboxes/security/_index.md @@ -18,9 +18,10 @@ anything on your host except what is explicitly shared. What crosses the boundary into the VM: -- **Workspace directory:** mounted into the VM with read-write access. With - the default direct mount, changes the agent makes appear on your host - immediately. +- **Workspace directory:** mounted into the VM. The default direct mount is + read-write — the agent edits your working tree in place. With + [`--clone`](../usage.md#clone-mode), your repository is mounted read-only + and the agent works on a private clone. - **Credentials:** the host-side proxy injects authentication headers into outbound HTTP requests. The raw credential values never enter the VM. - **Network access:** HTTP and HTTPS requests to @@ -50,9 +51,10 @@ The sandbox security model has five layers. See [Deny-by-default policy](defaults/). Non-HTTP protocols blocked entirely. - **Docker Engine isolation:** each sandbox has its own Docker Engine with no path to the host daemon. -- **Source-repository isolation (clone mode):** the agent works on a private - in-VM clone with your `.git` mounted read-only. Even an unconstrained - agent cannot corrupt your host repository. +- **Workspace isolation:** with `--clone`, the agent works on a private + in-VM clone and your repository is mounted read-only. In direct mode + (default), the agent edits your working tree directly — no boundary + applies. - **Credential isolation:** API keys are injected into HTTP headers by the host-side proxy. Credential values never enter the VM. @@ -69,13 +71,15 @@ permitted and what is blocked. The sandbox isolates the agent from your host system, but the agent's actions can still affect you through the shared workspace and allowed network channels. -**Workspace changes are live on your host.** The agent edits the same files you -see on your host. This includes files that execute implicitly during normal -development: Git hooks, CI configuration, IDE task configs, `Makefile`, -`package.json` scripts, and similar build files. Review changes before running -any modified code. Note that Git hooks live inside `.git/` and do not appear in -`git diff` output. Check them separately. -See [Workspace trust](workspace/). +**Workspace changes are live on your host in direct mode.** With the default +direct mount, the agent edits the same files you see on your host. This +includes files that execute implicitly during normal development: Git hooks, +CI configuration, IDE task configs, `Makefile`, `package.json` scripts, and +similar build files. Review changes before running any modified code. Note +that Git hooks live inside `.git/` and do not appear in `git diff` output — +check them separately. See +[Workspace isolation](isolation/#workspace-isolation) for the full list and +for the alternative clone-mode boundary. **Default allowed domains include broad wildcards.** Some defaults like `*.googleapis.com` cover many services beyond AI APIs. Run `sbx policy ls` to @@ -96,12 +100,11 @@ See [Organization governance](governance/) for details. ## Learn more -- [Isolation layers](isolation/): how hypervisor, network, Docker, and - credential isolation work +- [Isolation layers](isolation/): how hypervisor, network, Docker, + workspace, and credential isolation work - [Default security posture](defaults/): what a fresh sandbox permits and blocks - [Credentials](credentials/): how to provide and manage API keys - [Policies](policy/): how to customize network access rules - [Organization governance](governance/): centrally manage policies across an organization -- [Workspace trust](workspace/): what to review after an agent session diff --git a/content/manuals/ai/sandboxes/security/defaults.md b/content/manuals/ai/sandboxes/security/defaults.md index 8c8a1f9a175..fe698245648 100644 --- a/content/manuals/ai/sandboxes/security/defaults.md +++ b/content/manuals/ai/sandboxes/security/defaults.md @@ -28,7 +28,8 @@ working tree directly, and changes appear on your host immediately. The agent can read, write, and delete any file within the workspace directory, including hidden files, configuration files, build scripts, and Git hooks. -See [Workspace trust](workspace.md) for what to review after an agent session. +See [Workspace isolation](isolation.md#workspace-isolation) for what to +review after an agent session. ## Credential defaults diff --git a/content/manuals/ai/sandboxes/security/isolation.md b/content/manuals/ai/sandboxes/security/isolation.md index 0dda1b70450..e1d620dd3c2 100644 --- a/content/manuals/ai/sandboxes/security/isolation.md +++ b/content/manuals/ai/sandboxes/security/isolation.md @@ -1,14 +1,14 @@ --- title: Isolation layers weight: 10 -description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, source-repository, and credential boundaries. -keywords: docker sandboxes, isolation, hypervisor, network, credentials, git +description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, workspace, and credential boundaries. +keywords: docker sandboxes, isolation, hypervisor, network, credentials, workspace, git --- AI coding agents need to execute code, install packages, and run tools on -your behalf. Docker Sandboxes run each agent in its own microVM with five -isolation layers: hypervisor, network, Docker Engine, source-repository -(in clone mode), and credential proxy. +your behalf. Docker Sandboxes run each agent in its own microVM. Five +isolation layers protect your host: hypervisor, network, Docker Engine, +workspace, and credential proxy. ## Hypervisor isolation @@ -72,64 +72,97 @@ Host system └── [VM] Containers created by agent ``` -## Source-repository isolation - -When you start a sandbox with `--clone` (see the -[clone-mode workflow](../usage.md#clone-mode)), the agent never works -directly against your host repository. Even with full root inside the VM, -it cannot corrupt your local Git state. - -The boundary works like this: - -- Your repository's Git root is bind-mounted into the sandbox at - `/run/sandbox/source` as a read-only mount. The agent — and anything it - spawns — cannot write to your `.git` directory, your working tree, or - any tracked file via that mount. -- The agent's working copy is a private `git clone --reference` populated - on the sandbox's overlay filesystem. The clone has its own index, its - own refs, and its own working tree. Object storage is shared via - `.git/objects/info/alternates`, so the clone is space-efficient and - full history is walkable, but writes to the clone never reach your - host's object database. -- Your host pulls the agent's commits over a `git-daemon` exposed by the - sandbox on `127.0.0.1:`. The CLI registers it as a - `sandbox-` remote on your host repository. Fetching from - that remote uses the same trust model as fetching from any third-party - remote: nothing is integrated until you explicitly merge or check out - the fetched refs. +## Workspace isolation + +A sandbox mounts your workspace one of two ways. The mount mode determines +whether there is a security boundary between the agent's edits and your +host filesystem. The mode is fixed at create time; see +[Git workflow](../usage.md#git-workflow) for the workflow side of each. + +### Direct mount (default) + +By default, the sandbox bind-mounts your workspace read-write into the VM. +The agent and the host see the same files, and changes the agent makes +appear on your host as soon as they're written. + +There is no isolation between the agent and your workspace in this mode. +The agent can create, modify, or delete any file in the workspace, +including: + +- Source code and configuration files +- Build files (`Makefile`, `package.json`, `Cargo.toml`) +- Git hooks (`.git/hooks/`) +- CI configuration (`.github/workflows/`, `.gitlab-ci.yml`) +- IDE configuration (`.vscode/tasks.json`, `.idea/` run configurations) +- Hidden files, shell scripts, and executables + +Some of these files execute code when you trigger normal development +actions — committing, pushing, building, or opening the project in an IDE. +Review them after any agent session before performing those actions: + +- **Git hooks** (`.git/hooks/`) run on commit, push, and other Git actions. + These are inside `.git/` and **do not appear in `git diff` output** — + check them separately with `ls -la .git/hooks/`. +- **CI configuration** (`.github/workflows/`, `.gitlab-ci.yml`) runs on + push. +- **Build files** (`Makefile`, `package.json` scripts, `Cargo.toml`) run + during build or install steps. +- **IDE configuration** (`.vscode/tasks.json`, `.idea/`) can run tasks + when you open the project. + +Treat sandbox-modified workspace files the same way you would treat a pull +request from an untrusted contributor: review before you trust them on +your host. + +### Clone mode + +When you start a sandbox with [`--clone`](../usage.md#clone-mode), the agent +never works directly against your host repository. Even with full root +inside the VM, it cannot modify your `.git` directory, your working tree, +or any tracked file on your host. ```plaintext -Host repository Sandbox VM - .git/ /run/sandbox/source/ (RO bind mount) - objects/ ◄─────── alternates ───────── clone/.git/objects/ - refs/ clone/.git/refs/ (private) - HEAD clone/.git/HEAD (private) - working tree clone/working tree (overlay FS) - remote sandbox- ──── git:// ────► git-daemon :9418 - (published 127.0.0.1:) +Host repository Sandbox VM + .git/ (untouched) private clone (RW, in VM) + working tree (untouched) ↑ agent edits here + │ + /run/sandbox/source (RO bind mount) ←──────┘ + (read-only view of your repo) + + remote sandbox- ──── git fetch ───► git-daemon (inside VM) ``` +How the boundary is enforced: + +- Your repository's Git root is bind-mounted at `/run/sandbox/source` as + read-only. Nothing the agent does inside the VM can write back through + that mount. +- The agent works on a private clone that lives inside the sandbox. The + clone has its own index, its own refs, and its own working tree. Writes + to the clone never reach your host. +- The sandbox publishes the clone over a Git daemon bound to localhost on + the host. The CLI wires it up as a `sandbox-` Git remote on + your host repository. Fetching from that remote uses the same trust + model as fetching from any third-party remote — nothing is integrated + until you explicitly merge or check out the fetched refs. + The practical guarantees: -- Index and ref corruption can't happen — concurrent `git` commands on the - host and inside the sandbox don't race on a shared `.git/index` or shared - refs because there is no shared writable state. -- The agent can't write back to your working tree. A compromised or buggy - agent can't drop a `.git/hooks/pre-commit`, modify `.github/workflows/`, - or edit any other tracked file in a way that affects your host until you - fetch and merge from the `sandbox-` remote. -- Credentials, signing keys, and global settings declared in your - repository's `.git/config` stay on the host. The agent's clone has its - own independent configuration. -- Cleanup is automatic: `sbx rm` deletes the clone, the published port, - and the `sandbox-` remote on your host. Any in-container commits - that have not been fetched or pushed to an upstream remote are dropped - with the sandbox — `sbx rm` prints a warning before doing so. - -In direct mode (no `--clone`), the agent edits your working tree directly -and this isolation does not apply. Use clone mode whenever you want a -strong boundary between the agent's Git activity and your host -repository. +- The agent cannot modify any tracked file or any byte under `.git/` on + your host. A compromised or buggy agent cannot drop a + `.git/hooks/pre-commit`, alter `.github/workflows/`, or sneak changes + into your working tree. +- Concurrent `git` commands on the host and inside the sandbox cannot + race on a shared `.git/index` or shared refs — there is no shared + writable state. +- Credentials, signing keys, and any settings in your repository's + `.git/config` stay on the host. The agent's clone has its own + independent configuration. + +Use clone mode whenever you want a strong boundary between the agent's +Git activity and your host repository — for example when running an +unfamiliar agent, running multiple agents on the same repository at once, +or keeping your working tree clean while the agent works. ## Credential isolation diff --git a/content/manuals/ai/sandboxes/security/workspace.md b/content/manuals/ai/sandboxes/security/workspace.md deleted file mode 100644 index 4f3d0e00094..00000000000 --- a/content/manuals/ai/sandboxes/security/workspace.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Workspace trust -weight: 40 -description: | - How sandboxed agents interact with your workspace files and what to review - after an agent session. -keywords: docker sandboxes, workspace trust, file access, review, sbx ---- - -Agents running in sandboxes have full access to the workspace directory without -prompting. With the default direct mount, changes the agent makes appear on -your host immediately. Treat sandbox-modified workspace files the same way -you would treat a pull request from an untrusted contributor: review before -you trust them on your host. - -## What the agent can modify - -The agent can create, modify, and delete any file in the workspace. This -includes: - -- Source code files -- Configuration files (`.eslintrc`, `pyproject.toml`, `.env`, etc.) -- Build files (`Makefile`, `package.json`, `Cargo.toml`) -- Git hooks (`.git/hooks/`) -- CI configuration (`.github/workflows/`, `.gitlab-ci.yml`) -- IDE configuration (`.vscode/tasks.json`, `.idea/` run configurations) -- Hidden files and directories -- Shell scripts and executables - -> [!CAUTION] -> Files like Git hooks, CI configuration, IDE task configs, and build scripts -> execute code when triggered by normal development actions such as committing, -> building, or opening the project in an IDE. Review these files after any agent -> session before performing those actions. - -## Clone mode - -The `--clone` flag isolates the agent from your host repository: it works -on a private clone inside the sandbox, with your `.git` directory -bind-mounted as a read-only reference. This means the agent cannot modify -any tracked file or any byte under `.git/` on your host, no matter how -unconstrained the agent runs. You see the agent's commits only after -explicitly running `git fetch sandbox-`. - -See [Source-repository isolation](isolation.md#source-repository-isolation) -for the full boundary, and the [usage guide](../usage.md#clone-mode) for -the workflow. - -## Reviewing changes - -After an agent session, review changes before executing any code the agent -touched. - -With the default direct mount, changes are in your working tree: - -```console -$ git diff -``` - -If you used `--clone`, the agent's changes are on the `sandbox-` -remote until you fetch and merge them: - -```console -$ git fetch sandbox-my-sandbox -$ git diff main..sandbox-my-sandbox/ -``` - -Pay particular attention to: - -- **Git hooks** (`.git/hooks/`): run on commit, push, and other Git actions. - These are inside `.git/` and **do not appear in `git diff` output**. Check - them separately with `ls -la .git/hooks/`. -- **CI configuration** (`.github/workflows/`, `.gitlab-ci.yml`): runs on push -- **Build files** (`Makefile`, `package.json` scripts, `Cargo.toml`): run - during build or install steps -- **IDE configuration** (`.vscode/tasks.json`, `.idea/`): can run tasks when - you open the project -- **Executable files and shell scripts**: can run directly - -These files execute code without you explicitly running them. Review them before -committing, building, or opening the project in an IDE. diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index 274e297f627..10fb37fa9b0 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -73,135 +73,165 @@ hosts, and add custom network rules. Press `?` to see all keyboard shortcuts. ## Git workflow -When your workspace is a Git repository, the agent edits your working tree -directly by default. Changes appear in your working tree immediately, the same -as working in a normal terminal. - -If you want the agent to work in isolation from your host repository — for -example to run multiple agents in parallel, or to prevent any chance of an -agent rewriting your local Git state — use [clone mode](#clone-mode). The -agent runs against a private Git clone inside the sandbox; your host repository -sees the agent's commits only after you explicitly fetch them. +When your workspace is a Git repository, a sandbox mounts it one of two +ways. The mode is set at create time and determines how the agent interacts +with your repository: + +- **Direct mode (default)** — the sandbox bind-mounts your working tree + read-write. The agent edits your files in place; changes appear on your + host immediately. Best when you're collaborating turn-by-turn with the + agent on a single repository. +- **[Clone mode](#clone-mode) (`--clone`)** — the agent works on a private + Git clone inside the sandbox, and your host repository is mounted + read-only. The sandbox exposes its clone as a Git remote on your host, so + you fetch the agent's commits the same way you'd fetch from any other + remote. Best when you want the agent isolated from your host repository — + for running multiple agents in parallel, working with untrusted code, or + keeping your working tree clean while the agent works. + +See [Workspace isolation](security/isolation.md#workspace-isolation) for the +security model behind each mode. ### Direct mode (default) The agent edits your working tree directly. Stage, commit, and push as you -normally would. If you run multiple agents on the same repository at the same -time, they may step on each other's changes. See -[clone mode](#clone-mode) for an alternative. +normally would. If you run multiple agents on the same repository at the +same time, they may step on each other's changes — use +[clone mode](#clone-mode) to give each agent its own isolated workspace. ### Clone mode -Pass `--clone` to run the agent on a private Git clone living entirely -inside the sandbox, instead of bind-mounting your working tree. Your host -repository is mounted read-only as the clone's reference, so the agent — even -with full root inside the VM — cannot modify any byte of your `.git` -directory or working tree. You can set `--clone` on `create` or, equivalently, -on `run` at create time. - -When `--clone` is active: - -- The agent works on a private clone populated by - `git clone --reference` from your repository, on the sandbox's overlay - filesystem. The clone has its own index, refs, and working tree. - Object storage is shared via `.git/objects/info/alternates`, so the - clone is space-efficient and full history is walkable, but writes to - the clone never reach your host's object database. -- Your repository's Git root is bind-mounted at `/run/sandbox/source` as a - read-only mount. The agent's `git clone --reference` reads from this - mount; nothing on the host is writable from inside the sandbox. -- The clone follows whatever HEAD your host repository is on at create time. - No branch is created automatically — if you want the agent to work on a - dedicated branch, instruct the agent to `git checkout -b my-feature` - inside the sandbox before it starts editing. -- The sandbox runs a `git-daemon` over a `127.0.0.1`-bound ephemeral port - that exports the in-container clone. The CLI registers it as a Git remote - named `sandbox-` on your host repository, so you can pull - the agent's commits with `git fetch`. -- Forge remotes you have on the host (`origin`, `upstream`, …) are - propagated into the in-container clone with their existing URLs, so the - agent can `git push origin …` to your GitHub fork as you would on the - host. Local-path remotes (`file://`, paths) are skipped because they - aren't reachable from inside the sandbox. - -See [Source-repository isolation](security/isolation.md#source-repository-isolation) -for the security boundary. - -#### Starting a sandbox in clone mode +In clone mode, the sandbox becomes a Git remote on your host. The agent +commits inside the sandbox; you pull its work back out by fetching from +that remote. ```console -$ sbx run --clone claude # private clone of the current repository +$ sbx run --clone claude ``` -You can also create the sandbox first and attach later: +You can also create the sandbox in the background and attach later: ```console $ sbx create --clone --name my-sandbox claude . -$ sbx run my-sandbox # resumes in the in-container clone +$ sbx run my-sandbox ``` +The clone follows whichever ref your host repository has checked out at +create time. No new branch is created automatically. If you want the agent +to work on a dedicated branch, instruct it (or open a shell with `sbx exec` +yourself) to run `git checkout -b my-feature` inside the sandbox before it +starts editing. + > [!NOTE] -> Clone mode is fixed at create time. Recreate the sandbox with -> `sbx create --clone ...` to switch an existing sandbox into clone mode. +> Clone mode is fixed at create time. To switch an existing sandbox to +> clone mode, remove it and recreate it with `sbx create --clone`. -#### Reviewing and pushing changes +#### Reviewing and merging the agent's commits -The CLI wires the agent's in-container clone as a `sandbox-` -Git remote on your host repository. Review the agent's work with the same -commands you'd use for any other remote — no extra tooling, no `cd` into -a separate directory: +The CLI wires the in-sandbox clone as a `sandbox-` Git remote +on your host. Pull the agent's commits the same way you'd fetch any other +remote — no `cd` into a separate directory, no extra tooling: ```console -$ git fetch sandbox-my-sandbox # pull the agent's commits -$ git log sandbox-my-sandbox/ # see what the agent did -$ git diff main..sandbox-my-sandbox/ -$ git checkout -b my-feature sandbox-my-sandbox/ +$ git fetch sandbox-my-sandbox +$ git log sandbox-my-sandbox/ +$ git diff main..sandbox-my-sandbox/ +$ git checkout -b my-feature sandbox-my-sandbox/ $ git push -u origin my-feature $ gh pr create ``` -If the agent committed on a dedicated branch (because you asked it to -`git checkout -b ...`), that branch name appears on the `sandbox-` -remote. If it stayed on the HEAD it inherited at create time, its commits -extend that branch instead — you'll see them by fetching and diffing. +If you asked the agent to work on a dedicated branch, `` is that +branch name. Otherwise it's whatever ref your host repository was on at +create time. -Some agents don't commit automatically. If `git log sandbox-/...` -shows nothing new, open a shell in the sandbox and commit from there -before fetching. `sbx exec` drops you into the in-container clone: +Some agents don't commit automatically. If `git log sandbox-/` +shows nothing new, open a shell in the sandbox and commit from there: ```console $ sbx exec -it my-sandbox bash $ git commit -am "save work" ``` -See [Workspace trust](security/workspace.md) for security considerations when -reviewing agent changes. +#### Pushing to your fork from inside the sandbox + +When the sandbox starts, the CLI copies the Git remotes from your host +repository (`origin`, `upstream`, and so on) into the in-sandbox clone with +their existing URLs. The agent can push to your fork on GitHub the same way +you would on the host: + +```console +$ sbx exec -it my-sandbox bash +$ git push origin my-feature +$ gh pr create +``` + +This is interchangeable with fetching to your host first and pushing from +there. Pick whichever fits your workflow — or do both. + +Local-path remotes (`file://` URLs, filesystem paths) aren't copied, since +they aren't reachable from inside the sandbox. + +#### Running multiple branches in parallel + +To work on several branches with one sandbox, have the agent create them +inside the sandbox: + +```console +$ sbx exec -it my-sandbox bash +$ git checkout -b feature-a +# ...agent works on feature-a, commits... +$ git checkout -b feature-b main +# ...agent works on feature-b, commits... +``` + +Each branch appears on the `sandbox-` remote, and you can pull them +independently: + +```console +$ git fetch sandbox-my-sandbox +$ git log sandbox-my-sandbox/feature-a +$ git log sandbox-my-sandbox/feature-b +``` + +The sandbox is one VM with one working tree, so checking out a different +branch inside it changes what the agent sees. Committed branches stay on +the remote regardless of which branch the sandbox is currently on. -#### Cleanup +#### Sandbox lifecycle and the Git remote -`sbx rm` deletes the sandbox, its in-container clone, the published Git -port, and the `sandbox-` remote on your host repository. +The Git daemon that exposes the in-sandbox clone runs as part of the +sandbox itself. It's only reachable while the sandbox is running: + +- `sbx stop` shuts down the daemon. `git fetch sandbox-` fails until + the sandbox starts again. +- Restarting the sandbox assigns a new ephemeral port to the daemon. The + CLI updates the `sandbox-` remote URL in your host repository's + Git config automatically, so fetching continues to work without manual + reconfiguration. +- `sbx rm` removes the sandbox, the daemon, the published port, and the + `sandbox-` remote entry from your host repository. > [!WARNING] -> Any commits the agent made inside the sandbox that you have not yet -> fetched (via `git fetch sandbox-`) or pushed to an upstream -> remote will be lost — the in-container clone lives on the sandbox's -> overlay filesystem and is dropped with it. `sbx rm` prints a warning -> for clone-mode sandboxes; review it before confirming the removal. +> Removing a clone-mode sandbox drops the in-sandbox clone along with it. +> Any commits you haven't fetched (`git fetch sandbox-`) or pushed +> to an upstream remote are lost. `sbx rm` prints a warning before +> deleting a clone-mode sandbox — review it before confirming. #### Restrictions -A few configurations are incompatible with clone mode and are rejected at -create time: - -- `--clone` together with `--workspace-volume`: the source-repository - isolation relies on bind-mounting your Git root, which is incompatible - with a volume-backed workspace. -- `--clone` from inside a host Git worktree: the bind mount can't resolve - the worktree's `.git` pointer file. Run `sbx create --clone ...` from - the main repository instead. -- `--clone` on a non-Git workspace: clone mode requires a Git repository. - Run `sbx create` without `--clone` for non-Git workspaces. +Clone mode requires a Git repository as the primary workspace, and is +rejected at create time in two cases: + +- `--clone` on a non-Git workspace. Omit `--clone` for non-Git workspaces. +- `--clone` from inside a Git worktree (other than the main one). The + read-only bind mount can't resolve the worktree's `.git` pointer file. + Run `sbx create --clone` from the main repository checkout instead. + +You can also create a Git worktree yourself and run an agent inside it +without `--clone`, but the sandbox won't have access to the `.git` +directory in the parent repository, so the agent can't use Git at all. +Clone mode is the supported alternative for working on a separate branch. ### Signed commits From e8564f0c2296732d8366b2a08fa5eeb42a802707 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 26 May 2026 14:48:35 +0200 Subject: [PATCH 3/6] sandboxes: refine clone-mode docs phrasing and prompting framing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Name both mounting modes upfront in the isolation page intro instead of teasing "two ways" and burying the detail in subsections. - Reword "a sandbox mounts it one of two ways" to put the user in control of the choice. - Soften "bind-mount" terminology — the workspace is shared into a VM, not a container. - Reframe the multiple-branches and pushing-to-fork sections around prompting and agent orchestration patterns instead of manual sbx exec invocations. The agent (or the agent setup) should be driving Git inside the sandbox, not the user via a shell. --- .../ai/sandboxes/security/isolation.md | 20 +++-- content/manuals/ai/sandboxes/usage.md | 76 +++++++++---------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/content/manuals/ai/sandboxes/security/isolation.md b/content/manuals/ai/sandboxes/security/isolation.md index e1d620dd3c2..f5f0dcdd3fa 100644 --- a/content/manuals/ai/sandboxes/security/isolation.md +++ b/content/manuals/ai/sandboxes/security/isolation.md @@ -74,14 +74,22 @@ Host system ## Workspace isolation -A sandbox mounts your workspace one of two ways. The mount mode determines -whether there is a security boundary between the agent's edits and your -host filesystem. The mode is fixed at create time; see -[Git workflow](../usage.md#git-workflow) for the workflow side of each. +When you create a sandbox, you choose one of two ways to share your +workspace with it: + +- **Direct mount** (the default): the agent has read-write access to + your working tree. There is no boundary between the agent's edits and + your host filesystem. +- **Clone mode** (`--clone`): your repository is mounted read-only into + the VM and the agent works on a private clone inside the VM. The + agent's edits never reach your host until you fetch them. + +See [Git workflow](../usage.md#git-workflow) for the workflow side of +each. ### Direct mount (default) -By default, the sandbox bind-mounts your workspace read-write into the VM. +By default, your workspace is shared into the VM as a read-write mount. The agent and the host see the same files, and changes the agent makes appear on your host as soon as they're written. @@ -134,7 +142,7 @@ Host repository Sandbox VM How the boundary is enforced: -- Your repository's Git root is bind-mounted at `/run/sandbox/source` as +- Your repository's Git root is mounted at `/run/sandbox/source` as read-only. Nothing the agent does inside the VM can write back through that mount. - The agent works on a private clone that lives inside the sandbox. The diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index 10fb37fa9b0..81f169e5b78 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -73,21 +73,22 @@ hosts, and add custom network rules. Press `?` to see all keyboard shortcuts. ## Git workflow -When your workspace is a Git repository, a sandbox mounts it one of two -ways. The mode is set at create time and determines how the agent interacts -with your repository: - -- **Direct mode (default)** — the sandbox bind-mounts your working tree - read-write. The agent edits your files in place; changes appear on your - host immediately. Best when you're collaborating turn-by-turn with the - agent on a single repository. +When your workspace is a Git repository, you can choose one of two ways +to share it with a sandbox. You make the choice when you create the +sandbox: + +- **Direct mode (default)** — the agent has read-write access to your + working tree. Changes the agent makes appear on your host immediately. + Best when you're collaborating turn-by-turn with the agent on a single + repository. - **[Clone mode](#clone-mode) (`--clone`)** — the agent works on a private - Git clone inside the sandbox, and your host repository is mounted - read-only. The sandbox exposes its clone as a Git remote on your host, so - you fetch the agent's commits the same way you'd fetch from any other - remote. Best when you want the agent isolated from your host repository — - for running multiple agents in parallel, working with untrusted code, or - keeping your working tree clean while the agent works. + Git clone inside the sandbox, with your host repository mounted + read-only. The sandbox exposes its clone as a Git remote on your host, + so you fetch the agent's commits the same way you'd fetch from any + other remote. Best when you want the agent isolated from your host + repository — for running multiple agents in parallel, working with + untrusted code, or keeping your working tree clean while the agent + works. See [Workspace isolation](security/isolation.md#workspace-isolation) for the security model behind each mode. @@ -156,37 +157,38 @@ $ git commit -am "save work" #### Pushing to your fork from inside the sandbox When the sandbox starts, the CLI copies the Git remotes from your host -repository (`origin`, `upstream`, and so on) into the in-sandbox clone with -their existing URLs. The agent can push to your fork on GitHub the same way -you would on the host: +repository (`origin`, `upstream`, and so on) into the in-sandbox clone +with their existing URLs. The agent can push to your fork on GitHub +directly — for example, by prompting: -```console -$ sbx exec -it my-sandbox bash -$ git push origin my-feature -$ gh pr create -``` +> Commit these changes and push them to a new branch on `origin`. -This is interchangeable with fetching to your host first and pushing from -there. Pick whichever fits your workflow — or do both. +The push uses the same `git push origin ...` invocation the agent would +run on the host. This is interchangeable with fetching the commits to +your host first and pushing from there. Local-path remotes (`file://` URLs, filesystem paths) aren't copied, since they aren't reachable from inside the sandbox. #### Running multiple branches in parallel -To work on several branches with one sandbox, have the agent create them -inside the sandbox: +To work on several branches with one sandbox, the agent — not you — +should create them inside the sandbox. How depends on how your agent is +set up: -```console -$ sbx exec -it my-sandbox bash -$ git checkout -b feature-a -# ...agent works on feature-a, commits... -$ git checkout -b feature-b main -# ...agent works on feature-b, commits... -``` +- **Orchestrators that delegate to subagents** can have each subagent + create its own worktree and branch inside the clone. Claude Code's + [agents view](https://code.claude.com/docs/en/agent-view) is one + example. With clone mode, those worktrees live entirely inside the + sandbox. +- **Persistent agent instructions** — an agent-level `CLAUDE.md`, an + orchestration skill, or a system prompt — can tell the agent to start + each task on a fresh branch before editing. +- **Ad-hoc prompting** works for one-off tasks: ask the agent to switch + to a new branch before it starts. -Each branch appears on the `sandbox-` remote, and you can pull them -independently: +Each branch the agent commits to appears on the `sandbox-` remote +on your host. Fetch them independently: ```console $ git fetch sandbox-my-sandbox @@ -194,10 +196,6 @@ $ git log sandbox-my-sandbox/feature-a $ git log sandbox-my-sandbox/feature-b ``` -The sandbox is one VM with one working tree, so checking out a different -branch inside it changes what the agent sees. Committed branches stay on -the remote regardless of which branch the sandbox is currently on. - #### Sandbox lifecycle and the Git remote The Git daemon that exposes the in-sandbox clone runs as part of the From 10f67714b5d24aa827f16f34c2e4c212052df4f6 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 26 May 2026 14:51:00 +0200 Subject: [PATCH 4/6] sandboxes: rewrite parallel-branches section to drop preachy framing --- content/manuals/ai/sandboxes/usage.md | 31 ++++++++++++--------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index 81f169e5b78..4509af5bf43 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -172,23 +172,9 @@ they aren't reachable from inside the sandbox. #### Running multiple branches in parallel -To work on several branches with one sandbox, the agent — not you — -should create them inside the sandbox. How depends on how your agent is -set up: - -- **Orchestrators that delegate to subagents** can have each subagent - create its own worktree and branch inside the clone. Claude Code's - [agents view](https://code.claude.com/docs/en/agent-view) is one - example. With clone mode, those worktrees live entirely inside the - sandbox. -- **Persistent agent instructions** — an agent-level `CLAUDE.md`, an - orchestration skill, or a system prompt — can tell the agent to start - each task on a fresh branch before editing. -- **Ad-hoc prompting** works for one-off tasks: ask the agent to switch - to a new branch before it starts. - -Each branch the agent commits to appears on the `sandbox-` remote -on your host. Fetch them independently: +A single sandbox can hold several branches at once. Each branch the +agent commits to appears as a separate ref on the `sandbox-` +remote, so you can fetch them independently from the host: ```console $ git fetch sandbox-my-sandbox @@ -196,6 +182,17 @@ $ git log sandbox-my-sandbox/feature-a $ git log sandbox-my-sandbox/feature-b ``` +A few common ways to have the agent start each task on its own branch: + +- A subagent orchestrator such as Claude Code's + [agents view](https://code.claude.com/docs/en/agent-view) dispatches + each task to a subagent that creates its own worktree inside the + clone. +- Agent-level instructions in `CLAUDE.md`, an orchestration skill, or a + system prompt include a rule to start each task on a new branch. +- For one-off tasks, ask the agent to switch to a new branch before it + starts. + #### Sandbox lifecycle and the Git remote The Git daemon that exposes the in-sandbox clone runs as part of the From 31d5fc715318231e25f99a7b99e143ffdd0577e2 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 26 May 2026 15:10:06 +0200 Subject: [PATCH 5/6] sandboxes: document Claude Code agents view + clone mode recipe --- .../ai/sandboxes/agents/claude-code.md | 23 +++++++++++++++++++ content/manuals/ai/sandboxes/usage.md | 5 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/content/manuals/ai/sandboxes/agents/claude-code.md b/content/manuals/ai/sandboxes/agents/claude-code.md index 8bc52aae25c..ab2dc4afcb7 100644 --- a/content/manuals/ai/sandboxes/agents/claude-code.md +++ b/content/manuals/ai/sandboxes/agents/claude-code.md @@ -72,6 +72,29 @@ $ sbx run claude -- --dangerously-skip-permissions -c See the [Claude Code CLI reference](https://code.claude.com/docs/en/cli-reference) for available options. +## Agents view + +Claude Code's [agents view](https://code.claude.com/docs/en/agent-view) +dispatches tasks to subagents that work in parallel, each in its own +Git worktree. Pair it with [clone mode](../usage.md#clone-mode) for an +isolated multi-agent workflow: + +```console +$ sbx run --clone claude -- agents +``` + +The subagents' worktrees live inside the sandbox's private clone — none +of them touches your host repository. Each subagent commits to its own +branch, and you review the work from the host by fetching the +`sandbox-` remote: + +```console +$ git fetch sandbox- +$ git diff main..sandbox-/ +``` + +See [Git workflow](../usage.md#git-workflow) for clone-mode details. + ## Base image The sandbox uses `docker/sandbox-templates:claude-code`. See diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index 4509af5bf43..861c52f459c 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -185,9 +185,8 @@ $ git log sandbox-my-sandbox/feature-b A few common ways to have the agent start each task on its own branch: - A subagent orchestrator such as Claude Code's - [agents view](https://code.claude.com/docs/en/agent-view) dispatches - each task to a subagent that creates its own worktree inside the - clone. + [agents view](agents/claude-code.md#agents-view) dispatches each task + to a subagent that creates its own worktree inside the clone. - Agent-level instructions in `CLAUDE.md`, an orchestration skill, or a system prompt include a rule to start each task on a new branch. - For one-off tasks, ask the agent to switch to a new branch before it From e926b527c2ded9a7b8f1e1a1b5aed997f7b2652d Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 26 May 2026 15:16:09 +0200 Subject: [PATCH 6/6] sandboxes: note bypass-permissions gotcha for agents view recipe --- content/manuals/ai/sandboxes/agents/claude-code.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/content/manuals/ai/sandboxes/agents/claude-code.md b/content/manuals/ai/sandboxes/agents/claude-code.md index ab2dc4afcb7..2043649de2d 100644 --- a/content/manuals/ai/sandboxes/agents/claude-code.md +++ b/content/manuals/ai/sandboxes/agents/claude-code.md @@ -83,6 +83,17 @@ isolated multi-agent workflow: $ sbx run --clone claude -- agents ``` +This invocation replaces the +[default startup command](#default-startup-command), so it doesn't +include `--dangerously-skip-permissions` and you can't switch to +bypass-permissions mode inside the sandbox. Either pass the flag too: + +```console +$ sbx run --clone claude -- --dangerously-skip-permissions agents +``` + +or use Claude Code's auto mode. + The subagents' worktrees live inside the sandbox's private clone — none of them touches your host repository. Each subagent commits to its own branch, and you review the work from the host by fetching the