From d7cd0ad38f1a114579ec6fc436eafa13c66322cd Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:03:40 +0200 Subject: [PATCH 1/2] docs(sandboxes): add workflow patterns page Adds workflows.md to the sandboxes manual covering git strategies (single-agent feature branch, multi-agent parallel branches, direct mode), commit signing via SSH agent forwarding, authenticated CLI tools (gh, Docker registry, 1Password), and CI/headless use. Co-Authored-By: Claude Sonnet 4.6 --- content/manuals/ai/sandboxes/usage.md | 125 +-------- content/manuals/ai/sandboxes/workflows.md | 301 ++++++++++++++++++++++ 2 files changed, 313 insertions(+), 113 deletions(-) create mode 100644 content/manuals/ai/sandboxes/workflows.md diff --git a/content/manuals/ai/sandboxes/usage.md b/content/manuals/ai/sandboxes/usage.md index 8160b7f3be4a..0dfc665c785b 100644 --- a/content/manuals/ai/sandboxes/usage.md +++ b/content/manuals/ai/sandboxes/usage.md @@ -79,19 +79,16 @@ 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, 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. + other remote. -See [Workspace isolation](security/isolation.md#workspace-isolation) for the -security model behind each mode. +For a comparison of approaches and step-by-step recipes, see +[Workflow patterns](workflows.md#git-workflows). For the security model +behind each mode, see +[Workspace isolation](security/isolation.md#workspace-isolation). ### Direct mode (default) @@ -123,79 +120,17 @@ $ 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 to run `git checkout -b -my-feature` inside the sandbox before it starts editing. Alternatively, -open a shell with `sbx exec` and create the branch yourself. +create time. No new branch is created automatically. > [!NOTE] > 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 merging the agent's commits - -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 -$ 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 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: - -```console -$ sbx exec -it my-sandbox bash -$ 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 -directly — for example, by prompting: - -> Commit these changes and push them to a new branch on `origin`. - -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 - -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 -$ 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](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 - starts. +The CLI copies the Git remotes from your host repository (`origin`, +`upstream`, and so on) into the in-sandbox clone. The agent can push to +your fork directly using the same remote names. Local-path remotes +(`file://` URLs, filesystem paths) aren't copied, since they aren't +reachable from inside the sandbox. #### Sandbox lifecycle and the Git remote @@ -230,43 +165,7 @@ rejected at create time in two cases: 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 - -Sandboxes can sign Git commits with SSH keys from your host agent. The private -key stays on your host. - -On the host, load the key into your SSH agent: - -```console -$ ssh-add ~/.ssh/id_ed25519 -``` - -Inside the sandbox, check that the forwarded agent exposes the key: - -```console -$ ssh-add -L -``` - -Configure Git globally inside the sandbox to use SSH commit signing. This -writes to the sandbox user's Git config, not your repository's `.git/config`. -Use an inline public key instead of a key file path, because host paths such as -`~/.ssh/id_ed25519.pub` might not exist in the sandbox: - -```console -$ git config --global gpg.format ssh -$ git config --global user.signingkey "key::$(ssh-add -L | head -n 1)" -``` - -Then commit as usual: - -```console -$ git commit -S -``` - -For common signing failures, see -[Sandbox commits aren't signed](troubleshooting.md#sandbox-commits-arent-signed). +See [Host worktree](workflows.md#host-worktree) in Workflow patterns. ## Reconnecting and naming diff --git a/content/manuals/ai/sandboxes/workflows.md b/content/manuals/ai/sandboxes/workflows.md new file mode 100644 index 000000000000..a5c5132d494c --- /dev/null +++ b/content/manuals/ai/sandboxes/workflows.md @@ -0,0 +1,301 @@ +--- +title: Workflow patterns +linkTitle: Workflows +weight: 30 +description: Common workflow patterns for Docker Sandboxes, covering git strategies, authenticated tools, commit signing, and CI integration. +keywords: docker sandboxes, sbx, workflows, clone mode, git, branches, commit signing, github cli, ci, headless +--- + +## Git workflows + +Sandboxes support three approaches for working with Git repositories. The +right choice depends on whether you want branch isolation and whether you +plan to run tasks in parallel: + +| | Direct mode | Clone mode (`--clone`) | Host worktree | +|---|---|---|---| +| Branch management | You, on the host | Agent, inside the clone | You, on the host | +| Changes visible on host | Immediately | After fetch or agent push | Immediately | +| Agent can use Git | Yes | Yes | No | +| Parallelism | No | Multiple agents, one sandbox | One sandbox per parallel task | +| Mode fixed at create time | No | Yes | — | + +### Direct mode + +The simplest approach. The sandbox mounts your host working tree directly — +the agent edits files in place and changes appear immediately. You manage +branches yourself. + +1. Check out the branch you want to work on: + + ```console + $ git checkout -b feat/my-feature + ``` + +2. Start the sandbox. No special flags needed: + + ```console + $ sbx run claude + ``` + +3. The agent edits files in your working tree. Review diffs, stage, and + commit as you normally would: + + ```console + $ git diff + $ git add -p + $ git commit + $ git push -u origin feat/my-feature + ``` + +Because the sandbox mounts your working tree, switching branches on the host +also changes what the agent sees. This makes direct mode well-suited for +focused, single-branch work where you're collaborating with the agent +turn-by-turn. + +### Clone mode + +In clone mode, the sandbox gets a private Git clone. The agent manages its +own branches and commits inside that clone; your host working tree is never +touched. When the agent is done, you either fetch its branches to the host or +ask the agent to push directly to your fork. + +Clone mode is designed for parallelism: a single clone-mode sandbox can hold +many branches at once, and subagent orchestrators (such as Claude Code's +[agents view](agents/claude-code.md#agents-view)) can dispatch independent +tasks to separate agents, each working on its own branch or worktree inside +the clone. + +> [!NOTE] +> `--clone` is a create-time flag and cannot be changed on an existing +> sandbox. If you need to run additional non-clone sandboxes for the same +> repository, you would have to remove the clone-mode sandbox first. +> Keep a clone-mode sandbox running across multiple tasks rather than +> recreating it per task. + +#### Single task + +1. Start a clone-mode sandbox: + + ```console + $ sbx run --clone claude + ``` + +2. Ask the agent to create a branch before it starts editing: + + > Create a branch `feat/my-feature` and make the changes. + +3. Fetch the agent's branch when it's done: + + ```console + $ git fetch sandbox- + $ git log sandbox-/feat/my-feature + $ git diff main..sandbox-/feat/my-feature + ``` + +4. Pull the branch to the host and push, or ask the agent to push directly: + + ```console + # Pull to host, then push + $ git checkout -b feat/my-feature sandbox-/feat/my-feature + $ git push -u origin feat/my-feature + $ gh pr create + + # Or ask the agent + # "Push feat/my-feature to origin and open a PR." + ``` + +#### Parallel tasks + +1. Start a clone-mode sandbox and open the + [agents view](agents/claude-code.md#agents-view): + + ```console + $ sbx run --clone claude + ``` + +2. Dispatch each independent task to a separate subagent. Claude Code handles + branch isolation for subagents automatically in agents view. For other + agents (such as Codex), add an instruction to `AGENTS.md` to get the same + behavior: + + ```markdown + Always start each task on a new git branch before making changes. + ``` + +3. Fetch all branches when the agents are done: + + ```console + $ git fetch sandbox- + $ git log sandbox-/feat/task-a + $ git log sandbox-/feat/task-b + ``` + +4. Check out the branches you want to keep and open PRs as normal. + +### Host worktree + +You can create a Git worktree on your host and point the sandbox at it. The +agent edits files directly in the worktree — but because the sandbox mounts +only the worktree directory (not the parent repository), it can't resolve the +`.git` pointer file and has no Git access. The agent can read and write files, +but can't commit, branch, or check status. + +This is useful when you want branch isolation without the create-time +commitment of clone mode, and you're comfortable committing from the host +yourself after reviewing the changes. + +1. Create the worktree on the host: + + ```console + $ git worktree add -b feat/my-feature ../my-feature-work + ``` + +2. Start the sandbox with the worktree as the workspace: + + ```console + $ sbx run claude ../my-feature-work + ``` + +3. The agent edits files. When it's done, commit and push from the host: + + ```console + $ cd ../my-feature-work + $ git diff + $ git add -p && git commit + $ git push -u origin feat/my-feature + $ gh pr create + ``` + +## Commit signing + +Sandboxes forward your host SSH agent into the sandbox, so the agent can +sign commits with your SSH key without the private key ever leaving your +host. + +1. On your host, make sure the signing key is loaded in your SSH agent: + + ```console + $ ssh-add ~/.ssh/id_ed25519 + $ ssh-add -L # confirm the key appears + ``` + +2. Inside the sandbox, configure Git to sign with SSH. Use the forwarded key + directly rather than a file path, since host paths don't exist inside the + sandbox: + + ```console + $ git config --global gpg.format ssh + $ git config --global user.signingkey "key::$(ssh-add -L | head -n 1)" + ``` + +3. Sign commits as usual: + + ```console + $ git commit -S -m "feat: my change" + ``` + +To apply this configuration automatically to every sandbox, put the `git +config` commands in a [kit](customize/kits.md) init script rather than +running them by hand each time. + +For troubleshooting, see +[Sandbox commits aren't signed](troubleshooting.md#sandbox-commits-arent-signed). + +## Authenticated CLI tools + +The sandbox proxy handles API credentials for model providers automatically, +but agents often also need credentials for tools like `gh`, `docker`, or a +secrets manager. The pattern is the same in each case: configure the +credential on your host once, and the sandbox either forwards it via the +proxy or via SSH agent forwarding. + +> [!NOTE] +> The `-g` flag stores a secret globally so all future sandboxes can use it. +> Sandboxes that already exist when you run `sbx secret set -g` do not +> receive the new value. To update a running sandbox, scope the secret to +> it directly: `sbx secret set `. + +### GitHub CLI + +Store your GitHub token as a sandbox secret. The proxy injects it into +outbound requests, so `gh` works inside the sandbox without any additional +configuration: + +```console +$ echo "$(gh auth token)" | sbx secret set -g github +``` + +The agent can then create pull requests, open issues, comment on PRs, and +interact with the GitHub API the same way it would from your host: + +```console +# Inside the sandbox +$ gh pr create --title "feat: my feature" --body "..." +$ gh issue list +``` + +The token is never stored in plaintext inside the sandbox. See +[GitHub token](security/credentials.md#github-token) for details. + +### Docker registry + +To let the agent push images it builds to a private registry, store registry +credentials on your host. The agent can then run `docker build` and +`docker push` without any extra authentication: + +```console +$ gh auth token | sbx secret set --registry ghcr.io --password-stdin +$ echo "$ACR_PASSWORD" | sbx secret set --registry myregistry.azurecr.io \ + --username myuser --password-stdin +``` + +Images and containers built inside the sandbox run on the sandbox's private +Docker daemon, not your host's. They're deleted when the sandbox is removed. +See [Registry credentials](security/credentials.md#registry-credentials) for +the full reference. + +### Sourcing credentials from 1Password + +If you store credentials in 1Password, use `op read` to populate `sbx` secrets +without pasting values manually: + +```console +$ op read "op://Work/GitHub/token" | sbx secret set -g github +$ op read "op://Work/Anthropic/credential" | sbx secret set -g anthropic +``` + +The real value stays on your host; the sandbox sees the proxy-managed +placeholder as usual. + +## CI and headless use + +For CI environments and scripts where a browser isn't available, authenticate +with a Docker Personal Access Token (PAT): + +```console +$ echo "$DOCKER_PAT" | sbx login --username --password-stdin +``` + +Generate a PAT from your +[Docker account settings](https://app.docker.com/settings/personal-access-tokens) +with at least **Read** scope. + +From there, the rest of the `sbx` workflow is the same as interactive use. +Create the sandbox in the background with `sbx create`, run agent tasks with +`sbx exec`, and clean up with `sbx rm`: + +```console +$ sbx create --name ci-task --clone claude . +$ sbx run ci-task # attach and give instructions, or use sbx exec for one-off commands +$ git fetch sandbox-ci-task +$ sbx rm ci-task +``` + +Agent credentials (API keys, GitHub token) can be pre-configured as global +secrets so they're available to any sandbox the CI runner creates: + +```console +$ echo "$ANTHROPIC_API_KEY" | sbx secret set -g anthropic +$ echo "$GITHUB_TOKEN" | sbx secret set -g github +``` From a6b6ef268e439f3fa51b5d384fe5ec8aef9a7ee1 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:51:53 +0200 Subject: [PATCH 2/2] fix(sandboxes): address review feedback on workflows page Add missing --username flag to GHCR registry secret example, and remove erroneous trailing `.` from sbx create CI example to match other clone-mode examples. Co-Authored-By: Claude Sonnet 4.6 --- content/manuals/ai/sandboxes/workflows.md | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/content/manuals/ai/sandboxes/workflows.md b/content/manuals/ai/sandboxes/workflows.md index a5c5132d494c..a8c8426ac50b 100644 --- a/content/manuals/ai/sandboxes/workflows.md +++ b/content/manuals/ai/sandboxes/workflows.md @@ -12,13 +12,13 @@ Sandboxes support three approaches for working with Git repositories. The right choice depends on whether you want branch isolation and whether you plan to run tasks in parallel: -| | Direct mode | Clone mode (`--clone`) | Host worktree | -|---|---|---|---| -| Branch management | You, on the host | Agent, inside the clone | You, on the host | -| Changes visible on host | Immediately | After fetch or agent push | Immediately | -| Agent can use Git | Yes | Yes | No | -| Parallelism | No | Multiple agents, one sandbox | One sandbox per parallel task | -| Mode fixed at create time | No | Yes | — | +| | Direct mode | Clone mode (`--clone`) | Host worktree | +| ------------------------- | ---------------- | ---------------------------- | ----------------------------- | +| Branch management | You, on the host | Agent, inside the clone | You, on the host | +| Changes visible on host | Immediately | After fetch or agent push | Immediately | +| Agent can use Git | Yes | Yes | No | +| Parallelism | No | Multiple agents, one sandbox | One sandbox per parallel task | +| Mode fixed at create time | No | Yes | — | ### Direct mode @@ -195,9 +195,10 @@ host. $ git commit -S -m "feat: my change" ``` -To apply this configuration automatically to every sandbox, put the `git -config` commands in a [kit](customize/kits.md) init script rather than -running them by hand each time. +To apply this configuration automatically to every sandbox, use the +[`git-ssh-sign`](https://github.com/docker/sbx-kits-contrib/tree/main/git-ssh-sign) +community kit, which handles all of the above setup. See [Kits](customize/kits.md) +if you want to package it alongside other sandbox customizations. For troubleshooting, see [Sandbox commits aren't signed](troubleshooting.md#sandbox-commits-arent-signed). @@ -245,7 +246,8 @@ credentials on your host. The agent can then run `docker build` and `docker push` without any extra authentication: ```console -$ gh auth token | sbx secret set --registry ghcr.io --password-stdin +$ gh auth token | sbx secret set --registry ghcr.io \ + --username --password-stdin $ echo "$ACR_PASSWORD" | sbx secret set --registry myregistry.azurecr.io \ --username myuser --password-stdin ``` @@ -286,7 +288,7 @@ Create the sandbox in the background with `sbx create`, run agent tasks with `sbx exec`, and clean up with `sbx rm`: ```console -$ sbx create --name ci-task --clone claude . +$ sbx create --name ci-task --clone claude $ sbx run ci-task # attach and give instructions, or use sbx exec for one-off commands $ git fetch sandbox-ci-task $ sbx rm ci-task