Set up and verify an OpenCode sandbox with Docker Sandboxes
Docker Sandboxes Clone Mode lets OpenCode work in a private clone without writing changes directly into the host repository. This runbook covers a single Linux path, pinned to sbx v0.39.0 and checked against the linked documentation on August 23, 2026. You will test workspace isolation, egress, credentials, and host integrations separately.
At the end, the OpenCode TUI should be running, while a controlled clone change remains absent from the host working tree. An approved and a blocked network destination should produce distinct policy outcomes, the provider credential should follow the intended proxy path, and unnecessary host integrations should be absent. Clone Mode does not hide repository contents from the agent. Whether these controls are sufficient still depends on your workload and threat model.
Check prerequisites and version
This path requires a Linux host running Ubuntu 24.04 or newer with KVM hardware virtualization. According to Docker's installation guide, a working host exposes a KVM module such as kvm_intel, kvm_amd, kvm_arm64, or kvm.
Before you begin, prepare:
sbxv0.39.0, installed from Docker's supported installation path;- a Docker account for
sbx login; - a clearly named, disposable test repository at
~/my-projectthat contains no secrets the agent should not read; - an OpenAI credential you are authorized to use;
- one destination that your sandbox policy explicitly allows and one destination it denies; and
- no required local stdio MCP server. If one is required, document it as a trusted host integration rather than treating it as covered by the sandbox boundary.
Check virtualization, authenticate, and diagnose the host before starting a sandbox:
lsmod | grep kvm sbx login sbx diagnose
Stop if the first command does not show a documented KVM module or if sbx diagnose reports unresolved virtualization trouble. The installation guide documents the Linux requirements. This runbook uses the v0.39.0 release.
Start OpenCode in Clone Mode
Docker Sandboxes makes credentials available only when you provide them explicitly. Store the OpenAI credential before launch:
sbx secret set openai
Start OpenCode in Clone Mode with shared host skills disabled:
sbx run --clone --no-share-skills opencode ~/my-project
A successful start opens the OpenCode TUI. Docker documents that OpenCode reads configuration from the project working directory, not the user's host-level OpenCode configuration. Review the project configuration before launch. Remove or disable local stdio MCP integrations unless you explicitly trust and need them.
Open another host terminal, list the running sandboxes, and record the name shown for this session:
sbx ls export SANDBOX="replace-with-the-name-from-sbx-ls"
Wait until the TUI is visible and sbx ls shows the sandbox. If launch fails, run sbx diagnose. For a network-related failure, inspect sbx policy log before changing policy.
Prove that the host working tree is unchanged
Clone Mode mounts the host repository read-only and gives the agent a private clone. This prevents direct modification of the host repository, but the agent can still inspect files in that repository, including sensitive files such as readable .env files.
Create a baseline on the host:
cd ~/my-project git status --short
In OpenCode, ask the agent to create a controlled file named sandbox-proof.txt in its workspace and show the resulting diff. Then repeat on the host:
git status --short test ! -e sandbox-proof.txt && printf 'PASS: clone change is absent on host\n'
OpenCode should be able to read the clone and create the controlled change there, while sandbox-proof.txt remains absent from the host working tree. Next, ask OpenCode to read a harmless path outside the project and any explicitly shared paths. That outside host path should be unreachable because access to the host filesystem outside mounted workspaces and shared skills is blocked.
If the controlled file appears on the host or an unshared host path is reachable, stop. Confirm that you created the session with --clone. Clone Mode is fixed at creation, so create a fresh sandbox instead of trying to convert the existing one.
Verify egress as its own control
Outbound TCP is blocked unless policy explicitly allows it. Replace the example hostnames below with one real destination your policy allows and one it denies. The documentation supports checking and observing policy, but not an invented rule-authoring command. Establish the allow rule through your approved Docker Sandboxes policy configuration before running this guide.
export ALLOWED_HOST="api.example.com" export BLOCKED_HOST="blocked.example.com" sbx policy check network --sandbox "$SANDBOX" "$ALLOWED_HOST" sbx policy check network --sandbox "$SANDBOX" "$BLOCKED_HOST" sbx policy log
The checks must return distinct Allowed and Denied outcomes. In the policy log, a blocked runtime request should show its block reason, such as default deny. An allowed request should show the matching rule and proxy mode. Docker documents that forward supports credential injection, while forward-bypass and transparent do not.
Stop if both destinations produce the same result, the allowed destination has no applicable rule, or the log cannot explain the observed request. Correct the policy outside the agent session, then rerun both checks. Do not broaden egress merely to make the test pass.
Verify credential scope as its own control
Bind the OpenAI credential to the named sandbox and inspect the mapping:
sbx secret set openai --sandbox "$SANDBOX" sbx secret ls sbx policy log
With proxy management, Docker documents that the real credential stays on the host and the sandbox receives a sentinel. The proxy selects the OpenCode credential by API endpoint and injects it on the forward path. Confirm in the policy log that the provider request used that intended path. The existence of this mapping does not establish that every credential is invisible.
Also check the documented Linux storage fallback. If Secret Service is unavailable, credential storage can fall back to a readable file. Treat that file as sensitive host material and stop if its permissions or handling do not meet your requirements.
This check passes only when the mapping exists, OpenCode's provider request succeeds through the intended proxy path, and the real credential is not deliberately copied into the project or prompt. If the request uses another proxy mode or has no explainable mapping, remove the unintended path, correct the configuration, and rerun the check.
Verify host integrations as their own control
The microVM is the primary trust boundary. The agent has broad control inside it, including sudo. Material transitions remain at the workspace, credentials, network, shared skills, and MCP traffic.
Because this run started with --no-share-skills, shared host skills should not be present. In OpenCode, confirm that no shared-skill directory or content expected from the host is available. Review the project-level OpenCode configuration once more and confirm that no local stdio MCP server is enabled. A sandbox has its own Docker Engine with no route to the host daemon, but that boundary does not automatically cover a local stdio MCP server.
OpenCode permissions can add interaction policy, but OpenCode's own security guidance says they are not security isolation. An ask or deny permission result therefore does not prove the microVM, filesystem, network, credential, or MCP boundary.
If shared skills appear despite the launch flag, or if an undocumented local MCP integration remains active, stop. Remove the integration or explicitly accept and document it as trusted. Create a fresh sandbox if necessary, then repeat this control check.
Evaluate the result and clean up
Proceed with the workload only if all four controls pass independently:
- Workspace isolation: the private clone is readable and writable inside the sandbox, while its controlled change does not directly reach the host and unshared host paths remain unreachable.
- Egress: the approved and blocked destinations show distinct
AllowedandDeniedresults, and the policy log explains both. - Credentials: the expected mapping exists and the provider request uses the intended credential-injecting proxy path, with the Linux storage fallback checked.
- Host integrations: shared skills are absent and no local stdio MCP integration is mistakenly treated as part of the microVM boundary.
If any control fails, start with sbx diagnose and sbx policy log. sbx daemon restart preserves sandbox data. sbx reset stops all VMs and deletes all sandbox data, so use reset only when you intend to delete that data.
When testing is complete, preserve any clone commits you need by fetching or pushing them before removal. Then list, stop, and remove the sandbox:
sbx ls sbx stop "$SANDBOX" sbx rm "$SANDBOX"
For a separate implementation path, see how to run Claude Code in a container with network and secret boundaries. That container route is not part of this OpenCode runbook.
Continue only when all four observed results meet the documented target for your workload and threat model. Otherwise, stop, correct the affected configuration, and rerun that control check.