docs: update Sandboxes documentation for v0.49.1 (#26387)

Update Sandboxes documentation for current kit validation and signing
behavior, host Git-ignore snapshots, cloud proxy support, and browser
and daemon logging settings. Correct SSH workspace, policy refresh,
automation, environment merging, and T3 toolchain guidance.

Keep offline checks alongside kit validation and inspection, consolidate
proxy explanations, and make toolchain installation conditional.
Preserve the upstream explanation of kit context files.

Regenerate the published v0.49.1 release notes and vendor the CLI YAML
from docker/sandboxes release/v0.49.

Each atomic change has its own commit. Rebased onto main. Scoped
Markdown and Vale checks, the Hugo build, and diff whitespace checks
passed. All 121 CLI YAML files parse and match upstream exactly.

Generated by Codex
This commit is contained in:
David Karlsson authored and GitHub committed 2026-10-21 13:20:55 +02:00
commit 6a06d3ec7a
43 files changed
+444 -700

No files matched your search

@@ -131,6 +131,9 @@ $ ssh sbx_01abc123@sbx_cloud
Replace the example with `ssh <sandbox-id>@sbx_cloud`, using the
`sbx_`-prefixed ID from `sbx --cloud ls`.
Cloud SSH honors your host's configured upstream proxy. If the proxy refuses
SSH connections, see [Cloud SSH proxy configuration](../configuration/upstream-proxy.md#cloud-ssh).
## Transfer files
Use `sbx --cloud cp` to copy files or directories between the client machine
@@ -362,6 +362,10 @@ replace earlier scalar values. In this example, the sandbox has four CPUs,
12 GB of memory, and both environment variables. Each relative workspace path
resolves from the directory of the file that declares it.
Each source file must contain valid fields and values before merging. A later
override can't repair an invalid value in an earlier file. This also applies
to [user defaults](#set-user-defaults) loaded from `~/.sbxenv.yaml`.
### Work across multiple repositories
Mount related repositories alongside the primary project when the agent needs
@@ -134,6 +134,19 @@ variable appears only when the setting has a direct equivalent. Use
### Agents and host access
#### browser.enabled {.wrap-anywhere}
{{< setting-metadata type="boolean" default="true" >}}
Set this to `false` to prevent sandboxed processes from opening URLs in your
host browser:
```console
$ sbx settings set browser.enabled false
```
This also prevents in-sandbox OAuth logins that redirect to localhost.
#### clipboard.imagePaste {.wrap-anywhere}
{{< setting-metadata type="boolean" default="false"
@@ -440,6 +453,49 @@ this setting. It doesn't override a gateway selected by organization governance.
Set it back to `false` and restart to return to automatic selection. See
[MCP gateway](../mcp-gateway.md) for server registration and agent setup.
### Daemon logging
These settings control rotation of `daemon.log`, not logs written by the CLI
or processes inside a sandbox. Changes take effect after `sbx daemon restart`.
The backup count and age limits apply together: a rotated log is removed when
it exceeds either limit.
#### daemon.log.maxSizeMB {.wrap-anywhere}
{{< setting-metadata type="integer" default="50" >}}
Set the size in MB at which the daemon log rotates. The minimum is `1`:
```console
$ sbx settings set daemon.log.maxSizeMB 100
$ sbx daemon restart
```
#### daemon.log.maxBackups {.wrap-anywhere}
{{< setting-metadata type="integer" default="3" >}}
Set the maximum number of rotated daemon logs to keep. The value must be zero
or greater. A value of `0` removes the count limit, but the age limit still
applies:
```console
$ sbx settings set daemon.log.maxBackups 5
$ sbx daemon restart
```
#### daemon.log.maxAgeDays {.wrap-anywhere}
{{< setting-metadata type="integer" default="0" >}}
Set how many days to keep rotated daemon logs, from `0` to `3650`. A value of
`0` removes the age limit, but the backup count limit still applies:
```console
$ sbx settings set daemon.log.maxAgeDays 30
$ sbx daemon restart
```
### Diagnostics
#### diagnostics.autoUpload {.wrap-anywhere}
@@ -534,8 +590,8 @@ updated value; existing sandbox proxies require a daemon restart.
{{< setting-metadata type="string" default="Empty string" >}}
Use this to route the daemon's requests, such as image pulls, separately from
sandbox traffic. Supported host CLI requests, including `sbx login` and
`sbx diagnose --upload`, also use this scope.
sandbox traffic. Host CLI connections, including connections to cloud sandboxes,
also use this scope. See [traffic scopes](upstream-proxy.md).
For example, keep a shared proxy for sandbox traffic while letting the daemon
connect directly:
@@ -548,6 +604,15 @@ $ sbx daemon restart
Unset this setting to inherit `proxy`. Supported CLI requests use changes on
the next invocation; the daemon's own requests require a restart.
#### proxy.sshDirect {.wrap-anywhere}
{{< setting-metadata type="boolean" default="false" >}}
Set this to `true` to bypass the upstream proxy for cloud SSH connections.
Other host CLI requests keep using the configured proxy. Changes apply on the
next SSH connection without a daemon restart. For setup, see
[Cloud SSH](upstream-proxy.md#cloud-ssh).
#### no_proxy {.wrap-anywhere}
{{< setting-metadata type="string" default="Empty string" >}}
@@ -1,15 +1,16 @@
---
title: Configure an upstream proxy
linkTitle: Upstream proxy
description: Route sandbox and daemon traffic through a corporate or upstream proxy, including PAC files, SOCKS5, and your OS system proxy.
description: Route local sandbox, daemon, and host CLI traffic through an upstream proxy, including cloud connections, PAC files, SOCKS5, and your OS system proxy.
keywords: docker sandboxes, sbx, upstream proxy, corporate proxy, pac, socks5, system proxy, no_proxy, egress, ntlm, kerberos
weight: 40
aliases:
- /ai/sandboxes/upstream-proxy/
---
This page describes proxy settings for local sandboxes and the local daemon.
For cloud sandbox egress controls, see
This page describes proxy settings for local sandboxes, the local daemon, and
host CLI connections to cloud sandboxes. These settings don't configure traffic
originating inside a cloud sandbox. For cloud sandbox egress controls, see
[Cloud network policy](../cloud/network-policy.md).
> [!IMPORTANT]
@@ -28,10 +29,10 @@ traffic reaches them.
Docker Sandboxes sends two kinds of outbound traffic, and you can proxy them
independently:
- Sandbox traffic — network access from inside your sandboxes.
- Daemon traffic — the `sbx` daemon's own access, including image pulls,
telemetry, and feature flags. CLI requests for `sbx login` and
`sbx diagnose --upload` also use this scope.
- Sandbox traffic — network access from inside your local sandboxes.
- Daemon and host CLI traffic — the daemon's own access, including image pulls,
telemetry, and feature flags, and host CLI requests, including `sbx login`,
`sbx diagnose --upload`, cloud commands, `sbx move`, the TUI, and cloud SSH.
## Default behavior
@@ -126,9 +127,8 @@ Proxy settings take effect at different times depending on the consumer:
- Daemon scope (`proxy.daemon`, `no_proxy.daemon`, and the daemon side of
`proxy` and `no_proxy`) is resolved once when the daemon starts. Changes to
the daemon's own traffic require `sbx daemon restart`.
- Supported CLI clients read daemon-scoped settings on each invocation,
including `sbx login` and `sbx diagnose --upload`. Changes apply on the next
invocation without a daemon restart.
- Host CLI clients read daemon-scoped settings on each invocation. Changes
apply on the next invocation without a daemon restart.
The `DOCKER_SANDBOXES_*` environment variables are a separate case. They control
sandbox traffic only, as described in
@@ -140,6 +140,21 @@ the variable and restart the daemon for the stored setting to take effect.
When a `system` or PAC proxy is in use, `sbx` still tracks OS-level proxy changes
(such as switching networks, connecting a VPN, or updated PAC contents) live.
## Cloud SSH
Cloud SSH uses the configured host proxy to connect to the SSH gateway. Some
proxies refuse connections to the gateway's SSH port. If your network permits
direct SSH connections, bypass the proxy for cloud SSH:
```console
$ sbx settings set proxy.sshDirect true
```
This setting skips the proxy entirely for cloud SSH, without trying it first.
Other host CLI requests keep using the configured proxy. The change applies on
the next SSH connection without a daemon restart. Set it to `false` to use the
proxy again.
## Authentication
If the upstream proxy requires you to authenticate to it, `sbx` supports two
@@ -25,7 +25,8 @@ To save and reuse an environment you've configured interactively, see
Docker's sandbox templates are published as
`docker/sandbox-templates:<variant>`. They are based on Ubuntu and run as a
non-root `agent` user with sudo access. Most variants include Git, Docker
CLI, and common development tools like Node.js, Python, Go, and Java.
CLI, and common development tools like Node.js, Python, Go, and Java. Full
templates also include a C/C++ compiler toolchain for building native code.
| Variant | Agent |
| --------------------- | -------------------------------------------------------------------- |
@@ -662,14 +662,21 @@ and OpenCode reads `OPENCODE_CONFIG`. Don't use `setup.startup` for settings
the agent must read during initialization; startup commands don't gate the
entrypoint.
## Packaging and distribution
## Validate and inspect kits
The `sbx kit` subcommands validate, inspect, and publish kits:
Use these commands to check a kit before sharing it:
- `sbx kit validate <path>` — check that a kit directory or ZIP is
well-formed.
- `sbx kit inspect <path>` — display kit details. Add `--json` for
machine-readable output.
Add `--offline` to validate or inspect a local directory or ZIP without starting
the daemon or signing in. Offline checks skip kit source and signature policies;
they don't establish whether the kit is permitted to load.
## Packaging and distribution
- `sbx kit pack <path> -o <file.zip>` — package a directory as a ZIP file
for sharing.
- `sbx kit push <path> <ref>` — publish to an OCI registry (for example,
@@ -708,8 +715,14 @@ $ sbx kit verify --key cosign.pub ./my-kit/
For a local directory, `sbx kit sign` writes a `kit.sig.bundle` file next to
`spec.yaml`. Commit this file so consumers can verify a kit loaded from the Git
repository. For an OCI kit, the signature is stored as an OCI referrer. You can
sign an OCI kit after pushing it, or push and sign it in one step:
repository.
Git line-ending conversion and clean filters can invalidate a source signature.
If `sbx kit sign` warns about these transformations, ensure Git preserves the
signed files unchanged before sharing the Git reference.
For an OCI kit, the signature is stored as an OCI referrer. You can sign an OCI
kit after pushing it, or push and sign it in one step:
```console
$ sbx kit push ./my-kit/ ghcr.io/myorg/my-kit:1.0 --sign
@@ -83,10 +83,13 @@ default network org all network: 38 allow, 4 deny
```
`Governance` shows which organization manages the policy, and `Sync` confirms
the daemon has pulled the latest rules. If the sync state shows an error or a
stale timestamp, the daemon may not have the most recent org policy. Run
`sbx policy reset` to force a fresh pull. `Hidden` reports how many inactive
rules are suppressed and how to reveal them.
the daemon has pulled the latest rules. `Hidden` reports how many inactive rules
are suppressed and how to reveal them.
If the sync state shows an error or a stale timestamp, run `sbx policy refresh`
to fetch and apply the latest policy without restarting the daemon or stopping
sandboxes. The policy applies to new connections. To close existing connections
that the updated policy denies, restart the sandbox.
If Docker can't determine which organization governs your account, policy
output shows `Governance: Unresolved`, and the dashboard shows the same
@@ -120,10 +120,10 @@ $ ssh demo.sbx
Connecting an app to a sandbox selects the remote environment, but it might not
open the primary workspace automatically. The initial folder depends on the
client. A remote folder picker might open at the sandbox user's home directory,
`/home/agent`, while an interactive `ssh` shell might start in
`/home/agent/workspace`. Select the intended folder explicitly instead of
relying on the initial location.
client. An interactive SSH shell starts in the sandbox workspace, matching
`sbx exec`. An editor's remote folder picker might open at the sandbox user's
home directory, `/home/agent`. Select the intended folder explicitly in the
editor instead of relying on its initial location.
For a sandbox with a primary workspace, each workspace path appears inside the
sandbox at the same absolute path as on the host. For example, if you pass
+71 -59
View File
@@ -16,6 +16,77 @@ the full release history, including pre-releases and downloads, see the
<!-- BEGIN GENERATED RELEASES -->
## 0.49.1
{{< release-date date="2026-10-20" >}}
[GitHub release](https://github.com/docker/sbx-releases/releases/tag/v0.49.1)
### Highlights
Docker Sandboxes v0.49.1 improves kit compatibility, proxy support for cloud connections, and sandbox shutdown reliability.
> [!NOTE]
> v0.49.0 was skipped. These release notes cover all changes since v0.48.0.
### What's new
#### Kits
- `sbx kit validate` and `sbx kit inspect` accept `--offline` to check a local directory or ZIP kit without starting the daemon or signing in.
- Creating sandboxes from local or Git v3 kits honors build-time `--kit-arg` values, including scoped overrides.
- Sandboxes combining multiple agent kits, such as Claude and Codex, start successfully and receive guidance in each agent's context file.
- On Windows, sandboxes can combine workload and mixin kits, including kits loaded through Windows junctions.
- Kits declaring multiple OAuth credentials authenticate every declared service.
- `sbx kit sign` warns when Git would change the signed file contents and invalidate signatures for `git+` references.
- Reading a kit directory rejects unsupported entries, such as named pipes and device nodes, instead of hanging. `sbx kit pack` rejects symlinks that would produce an archive Sandboxes cannot load.
#### Sandbox lifecycle and workspaces
- SSH sessions start in the sandbox workspace, matching `sbx exec`.
- SSH-agent access granted by a kit continues working in running sandboxes after the daemon restarts.
- In newly created local sandboxes, Git preserves the host's ignore decisions for paths already present in the primary workspace. This applies to primary workspaces mounted at a Git repository root.
- Sandbox startup waits for Docker to become ready without launching competing Docker daemons.
- Daemon shutdown and sandbox reset no longer hang indefinitely when Docker is unresponsive or a kit registry operation stalls.
- Sandbox reset handles concurrent operations more reliably, avoids false cleanup warnings, and identifies sandboxes it could not fully remove.
- Port changes fail cleanly during sandbox creation or deletion, avoiding stale host bindings.
- SSH connection attempts fail cleanly when the daemon is shutting down.
- Cursor sandboxes no longer show an unexpected Workspace Trust prompt for workspace paths containing characters such as `.` or `_`.
#### Networking and cloud sandboxes
- Explicit CIDR deny rules take precedence over matching domain allow rules when Sandboxes resolves the destination address.
- Cloud commands, `sbx move`, the TUI, and cloud SSH honor configured proxies, including system and PAC proxies. Set `proxy.sshDirect` to `true` to connect cloud SSH directly on networks that permit direct SSH connections.
- `sbx mcp add` completes OAuth discovery on networks that require an HTTP proxy, without needing `--skip-ssrf-check`.
- Fixed uploads stalling while waiting for HTTP 100 Continue through intercepted HTTPS connections.
- Fixed a Windows system-proxy watcher hang that could prevent the daemon from stopping.
- Image pulls from `public.ecr.aws` work under the `balanced` network policy.
- `sbx policy refresh` immediately refreshes policy, for example after an AI Governance change, instead of waiting for the next polling interval. Existing connections remain open.
- `sbx policy ls` continues showing `default-deny-all` after a kit adds network rules.
- Cloud connection and authentication errors include guidance for resolving the problem.
#### Authentication and MCP
- Custom secrets using `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` appear in the sandbox as expected.
- `sbx secret set-custom` warns before replacing a different host or environment-variable mapping under the same placeholder.
- `sbx secret rm` returns an error when no secret matches `--registry`, `--placeholder`, `--host`, or `--env-name`.
- MCP gateway code-mode tools work on Windows hosts.
#### CLI, settings, and diagnostics
- `sbx policy ls`, `sbx settings ls`, and `sbx policy approval ls` accept `-q` to print only rule IDs, setting keys, or approval IDs.
- Configure daemon log size and retention with `sbx settings set` using `daemon.log.maxSizeMB`, `daemon.log.maxBackups`, and `daemon.log.maxAgeDays`.
- The `browser.enabled` setting controls whether sandboxes can open the host browser.
- `sbx env` reports unknown keys and invalid values with their source file, line, column, and field. Invalid values in a base file must be fixed even if a later file overrides them; this also applies to `~/.sbxenv.yaml` and `sbx env rm`.
- `sbx settings set` rejects incorrectly structured values for `kit.allowedSources` and `kit.trustedSigners` before saving them.
- `sbx cp` clearly reports a missing destination directory without extra tar errors.
- `sbx diagnose` reports running CLI and shim processes, warns when global network policy is not initialized, and detects a ZFS setting that can make image builds unusually slow.
#### Templates and installation
- Full templates now include a C/C++ toolchain for compiling native code inside the sandbox.
- The Linux tarball installer works for regular users on systems with AppArmor.
## 0.48.0
{{< release-date date="2026-10-13" >}}
@@ -217,65 +288,6 @@ Docker Sandboxes v0.47.0 adds automatic cleanup after agent sessions with `sbx r
- Windows update notices appear only after WinGet confirms that the version is available in its catalog.
<!-- release-notes:end -->
## 0.46.0
{{< release-date date="2026-09-28" >}}
[GitHub release](https://github.com/docker/sbx-releases/releases/tag/v0.46.0)
### What's new
#### Breaking changes
- Secret commands configured with `sbx secret set --command`, `sbx secret set-custom --command`, or `secrets.<name>.command` in an environment file execute from a fresh temporary directory on the host. Relative paths such as `./credential-helper` no longer resolve from the project directory or the directory where you ran `sbx`. Store helpers and their dependencies outside writable sandbox mounts. Run helpers by name from an absolute directory on the host's `PATH`, use absolute paths, or explicitly change to their private directory in the command. For existing environments that declare secret commands, the next `sbx env run` asks you to approve a one-time plan change for the working directory. The execution change takes effect after upgrading and restarting the daemon, even before you approve that plan.
#### Cloud sandboxes
- `sbx --cloud create --on-timeout restart` accepts `restart` as the timeout action. When the sandbox reaches its time limit, it stops and immediately restarts instead of remaining stopped.
- `sbx --cloud create` passes `--kit-arg` and `--kit-args-file` values to kits supplied with `--kit`.
#### Kits and skills
- Kits can install files in the agent's skills directory when shared skills are read-only. The shared skills store remains read-only, while kit installation and startup commands can write their own skills without a read-only filesystem error.
- Kits added through the runtime API retain their network rules and applicable agent instructions when another kit addition recreates the sandbox container.
- `sbx kit add` warns if it cannot save the updated sandbox record. The warning explains which kit settings could be lost and whether a daemon restart or another container replacement would cause the loss.
#### Agents and models
- The local model server starts and stops with the Docker Sandboxes daemon and downloads its llama.cpp runtime when the daemon starts. The macOS and Windows bundles include llmman v0.1.418, which manages the runtime download instead of relying on a separately bundled `llama-server`.
- Image paste in WSL2 falls back to the Windows clipboard when Linux clipboard tools return no image. Requires `clipboard.imagePaste` to be enabled.
#### Sandbox lifecycle and workspaces
- Fixed a shutdown bug affecting templates that use dash as `/bin/sh`, including the built-in Ubuntu-based templates. The shutdown handler forwards `SIGTERM` correctly, giving sandbox processes a chance to exit gracefully instead of waiting five seconds for a forced shutdown.
- On Linux arm64 hosts, the default CPU allocation is capped at 16 CPUs per sandbox. This fixes startup failures with `VM did not connect within 15s` when several sandboxes start together on hosts with many CPU cores. Use `--cpus` to request a larger allocation.
- `sbx umount` can remove a saved mount from a stopped sandbox using the original host path even after that directory has been deleted.
- On macOS, mounting, unmounting, and restoring saved mounts consistently recognize host paths whose capitalization differs.
- If the runtime fails to mount the workspace, sandbox startup reports the mount failure and points to the daemon log for the cause instead of reporting a generic container startup error.
- Starting a second daemon against a state directory already in use fails with an error instead of disrupting the running daemon.
- `sbx reset` stops background feature-flag updates and log writes before deleting local state, preventing leftover files and recreated directories. On Windows, it also closes daemon log files before deleting them to avoid cleanup retries caused by open file handles.
#### Authentication and credentials
- Removing secrets in bulk revokes credentials from running sandboxes. Failed revocations can be retried even after the stored secrets have been deleted.
#### Networking and policy
- Sandboxes created with the `balanced` network policy preset can download Playwright browser binaries from `cdn.playwright.dev` over HTTPS. Existing sandboxes keep their saved policies. To use the updated preset, create a new sandbox with the `balanced` network policy.
#### CLI and diagnostics
- `sbx env` reports unrecognized environment-file keys with the file, line, and column where they were declared, including when multiple files are merged.
- Canceling a batch `sbx rm` or `sbx stop` stops processing the remaining sandboxes instead of printing a cancellation error for each one.
- `sbx diagnose --upload` returns a non-zero exit status if the requested diagnostics upload fails, so scripts can detect the failure.
- `sbx diagnose` reports the socket-path length limit used by the container runtime as `runtime_socket_limit_bytes` and clarifies the meaning of the reported socket-path values.
#### Packaging and installation
- Windows MSI installations include `llmman` and the guest kernel, fixing local model serving with `sbx run --model` and sandbox launches that failed with `No kernel specified`.
- Uninstalling Docker Sandboxes through the Windows MSI stops the daemon.
- Fixed the Linux static tarball failing to start on distributions with older glibc versions. The tarball is built against glibc 2.34.
<!-- END GENERATED RELEASES -->
## Earlier releases
@@ -66,7 +66,8 @@ script.
For repeatable cleanup, check which resources exist before removing them. For
example, use `sbx mcp ls` before `sbx mcp rm`, which fails for an unregistered
server even with `--force`.
server even with `--force`. Likewise, `sbx secret rm` fails if no secret matches
the selector; check for matches with `sbx secret ls` before removing secrets.
## Parse command output
@@ -85,6 +86,14 @@ $ sbx prune --dry-run --format yaml
are rejected. `sbx events --json` emits newline-delimited JSON, and
`sbx mcp auth --format text|json` uses command-specific formats.
For lists of identifiers without table headings, use `--quiet` or `-q`:
| Command | Output |
| --- | --- |
| `sbx policy ls -q` | Local rule IDs. With `--cloud`, network patterns instead. |
| `sbx settings ls -q` | Setting keys. |
| `sbx policy approval ls -q` | Approval IDs. |
### Update scripts for v0.48.0
{{< copy-as-prompt instruction="Update this repository's Docker Sandboxes CLI usage for v0.48.0 using the migration reference below. Inspect scripts and documentation, update affected commands and output parsers, and verify the changes. Preserve unrelated behavior." >}}
@@ -187,6 +187,20 @@ yourself after reviewing the changes.
$ gh pr create
```
## Git ignore rules
Git inside a local sandbox preserves host-specific ignore decisions for paths
that exist when you create the sandbox. This applies when the primary workspace
is at a Git repository root.
The sandbox receives a snapshot of ignored paths, not the host-specific patterns.
Those patterns don't apply to files created later, but ignored directories still
cover files added inside them. Additional repositories and primary workspaces
below a repository root don't receive this snapshot. Repository `.gitignore`
files continue to work as usual.
Git ignore rules don't restrict the agent's access to files in the workspace.
## Commit signing
SSH agent forwarding is enabled by default. When `SSH_AUTH_SOCK` is set,
+3
View File
@@ -88,6 +88,9 @@ options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+3
View File
@@ -95,6 +95,9 @@ inherited_options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+21 -212
View File
@@ -2,224 +2,33 @@ name: sbx env
synopsis: |
Manage sandboxes declaratively from an sbxenv.yaml file
experimental: true
description: |
Manage a sandbox environment declared in an sbxenv.yaml file.
description: |-
Manage a sandbox declared in an sbxenv.yaml file. The file selects the agent,
kits, workspace mounts, environment variables, secrets, and credential bindings.
The file describes the agent, optional mixin kits, workspace mounts,
environment variables, secrets to provision, and per-service credential
bindings. Secrets are provisioned at the environment's sandbox scope so
`sbx env rm` can remove everything it created.
Use create to provision the sandbox, run to start or join its agent session,
exec to run a command, and rm to remove it and its provisioned secrets.
Use plan to preview changes. Changes require approval; --force skips the prompt.
A secret with `command` or `ref` can set `snapshot: true` to resolve on
the host after approval and store the result as a literal. This works locally
and with --cloud. Snapshots do not refresh; recreate the environment to rotate
them. A snapshot cannot set refresh or noVerify.
Lifecycle commands and command-based secrets execute on the host with your
permissions. Keep secret helpers and their dependencies outside writable
sandbox mounts, and use absolute helper paths.
Command secrets run from a fresh temporary directory on the host during
verification and refresh. The host temporary directory must be absolute and must
remain outside writable sandbox mounts. Relative references such as ./helper or
cat token no longer resolve against the project or daemon working directory. Use an absolute
helper path outside shared workspaces. sbx does not copy helpers, inspect their
dependencies, or confine their execution. Helpers and any code or configuration
they load must remain outside writable sandbox mounts. Explicit paths into shared
workspaces and broad mounts exposing host configuration or the host temporary
directory remain unsafe, including mounts added later with sbx mount.
The environment file is mounted read-only by default when shared with the
sandbox. Set sandboxOptions.writableEnvFiles only when you trust the agent
to change what future invocations run on the host.
secrets:
github:
command: gh auth token
snapshot: true
With --cloud, manage a cloud sandbox from the same file. Host workspace mounts,
host port bindings, MCP definitions, registry credentials, and unsnapshotted
dynamic secret sources are unsupported. Clone the project inside the sandbox instead.
A file may declare its own inputs in an `args:` block, each with a default or
`required: true` and an optional description, enum, or pattern. Reference one
as `${{ env.args.NAME }}` anywhere a value appears and supply it with
`--env-arg NAME=VALUE`.
Secrets and bindings are provisioned at creation; changes require recreating
the sandbox. Removal deletes secrets provisioned by this environment; bindings
are retained unless --prune-bindings is passed. Use the same cloud target,
identity, and ordered files for subsequent commands.
A `kits:` entry is either a bare reference or a mapping carrying the
arguments that kit declares, which `--kit-arg` overrides per invocation:
kits:
- ./mixins/base
- source: ./mixins/tool
args:
version: ${{ env.args.channel }}
A kit source written as an explicit relative path — `./…`, `../…`, `.`, `..`, or one
ending in `.zip` — is resolved against the directory of the file that declares
it, so a checked-in file reaches the same kits from wherever `sbx` is run. Write a
local kit that way: a bare `kits/tool` is as much a registry reference as a
directory, so it is left as written and resolves from the current directory.
A `workspace:` names the directory mounted read/write into the sandbox. A
relative path resolves against the directory of the file that declares it — as
a relative kit source does — so `workspace: .` mounts the directory the file
sits in. ${{ env.projectDir }} names the project directory (the one holding the
first PATH, or the current directory when none is named) and ${{ env.fileDir }}
the declaring file's own, for a value that spells its anchor out. Declaring
none mounts nothing — as omitting PATH does for `sbx create` — and the agent
works in the container's own filesystem instead of on your files. Unless the file sets `name:` or --name overrides it,
the sandbox is named after the mounted directory, or after the project directory
when nothing is mounted, so an environment that mounts nothing is still the same
sandbox every time.
A `lifecycle:` block declares commands that run on the host — outside
the sandbox, with your own privileges — around the sandbox's life:
lifecycle:
initialize:
- command: test -d app || git clone https://github.com/acme/app
postCreate:
- command: ./scripts/seed-fixtures.sh
preRemove:
- command: ./scripts/archive-state.sh
Each runs through your shell from the project directory — the one holding the
first PATH, or the current directory when none is named; ${{ env.projectDir }}
names the same place, and commands merged in from a file elsewhere share it.
Change it per command with `workdir:`, and cap a command's runtime with
`timeout:`.
"initialize" runs on every "create" and every "run", including one that only
attaches, so it can produce the workspace the sandbox mounts; write it to be
repeatable. "postCreate" runs once the sandbox exists, and "preRemove" after
"sbx env rm" is confirmed but before it deletes anything. Whatever stops
preRemove is only a warning, so a teardown that cannot run still cannot make an
environment unremovable; what one adds to the environment instead — a stored
credential, an approved domain — stops the removal, since what follows would
delete it without a plan row ever naming it. "sbx env exec" runs no commands at
all.
Commands appear in the environment plan with the directory each runs in, and are
approved with it before the invocation does any work. An environment that declares
any of them asks on every invocation, whether or not this one is what runs them,
since approving a command also trusts whatever it invokes, including a script
whose contents change after the answer. Use --skip-host-commands to run none of
them.
Everything an environment sets up — host commands, credentials, bindings, MCP
registrations, directories, published ports, the sandbox itself and the
variables it runs with — is shown as a plan and approved before anything runs:
ENVIRONMENT
Name: claude-proj
File: /Users/me/proj/sbxenv.yaml
SECRETS
+ anthropic
ref: op://vault/anthropic/key
refresh: 55m
LIFECYCLE
~ initialize: make setup && make seed
command: make setup -> make setup && make seed
workdir: /Users/me/proj
1 to add · 1 to change · 0 to destroy
Approve this plan? (y/N)
The plan groups resources by the block of the file that declares them, in the
order the blocks are declared, so a row is looked up where it was written. The
mark in front of a row is what applying does to the resource, and the totals
name every mark a plan can carry: "+ to add" and "~ to change" above,
"- to destroy" for what "sbx env rm" takes away, "> to run" for a command that
runs again — a command converges to nothing, so it runs on every apply that
reaches it — and "! to forget" for a resource this environment applied and no
longer declares. Where the file has nothing to say, the text after the row's name does:
that a resource is missing, or that the work waits for the next create, since a
port, a credential, a kit or a postCreate command comes with the sandbox, so
attaching to one that already exists leaves it for the next one that is built. A
resource that is as it was, and already approved, is left out: what is on screen
is what there is to read.
The lines under a row are the attributes the environment declares, so an edited
kit argument or variable reads as what it was against what it becomes, and a
"command:" or "ref:" secret shows where the credential comes from — a command
that resolves one runs on this machine. A secret's literal "value:" is the one
exception: a plan is both shown here and written to state, so it is named and
stands in as a "sha256:" digest.
KITS
~ ./mixins/tool
args.version: 1.2.3 -> 1.2.4
ENV
~ GOFLAGS
value: -mod=mod -> -mod=readonly
What an attribute was is what this environment last applied here, or — for one it
approved and never applied, such as a binding or a port answered for while
attaching to a sandbox that already exists — what was approved. Either way an
edit shows the value the question is about, whatever the row itself does.
An environment file that a mount would hand over read-write — which is what
mounting the project directory holding it does — is bound read-only at its own
path inside that mount, leaving the rest of it writable. The file decides what a
later invocation runs on this machine, so an agent able to edit it decides what
the next plan asks about. Declare "sandboxOptions.writableEnvFiles: true" where an
agent is meant to edit it; the plan then says the file is writable, as it says
when a file sits below a mount's own directory, where renaming that directory
reaches it again.
What was approved is recorded per environment under sbx's state directory, not
next to the file, so a later invocation asks only about what moved — and applies
silently when nothing did. An environment that declares commands running on this
machine is asked about on every invocation, changed or not: the answer is about
the invocation, and what a command does depends on what the project holds when it
runs rather than on the text approved before. "sbx env plan" prints the plan and
changes nothing.
Use --force (-f) where there is no terminal to answer on. Where an
environment's commands are your own and run many times a day,
"sbx settings set env.rememberHostCommands true" asks about them only when
they change.
With --cloud, create, run, exec, rm and plan manage a cloud sandbox from the same
file. Supported declarations are agents and kits, sandbox environment variables,
CPU and memory sizing, literal or snapshot secrets and bindings for supported providers, and
host lifecycle commands. Kits can publish TCP ports through cloud endpoints.
Stored cloud secrets are inherited as with cloud create/run; sandbox-scoped secrets
override account defaults, and secrets declared in the file override both. The plan
shows inherited credentials. Removal deletes only secrets provisioned by this environment.
Bindings merge into the same global credentials.yaml as local environments and
are retained on removal unless --prune-bindings is passed. Cloud must advertise
kit credential support. Third-party kit domains must be approved by the binding;
creation refuses implicit provider-default routing for a bound secret. Bindings
and secrets are provisioned at creation; editing them requires recreating the sandbox.
Snapshot references use the host's supported CLI resolvers (such as op:// and AWS
Secrets Manager ARNs); the sdk backend is unsupported. An interrupted secret
upload reuses the saved value in the host credential store. If that value is
unavailable, resolution is not repeated: follow the recovery error before cleanup.
workspace, additionalWorkspaces and clone name host directories, which a cloud
sandbox cannot mount; remove them and clone the project inside the sandbox from a
kit instead. Host port bindings, registry credentials, MCP definitions, custom
credential providers, local sandbox options and dynamic secret sources are also
rejected before host commands or provisioning. Initialize commands may prepare
local kit sources; kit validation follows initialization and precedes cloud baking.
State belongs to this machine, the selected cloud endpoint, Docker identity and
ordered environment files. Use the same target and files for subsequent commands.
DOCKER_ACCESS_TOKEN uses a token-specific state scope: changing the token starts
with separate state. Use sbx login for state that survives token refresh.
If creation is interrupted, retry the same command and declaration within 23 hours.
Removal waits for unresolved writes to be recovered. Older unresolved attempts
retain their journal; the error names its path. Before deleting that journal,
confirm the original requests have finished and remove their sandbox and secrets
using ordinary cloud commands in the same account and endpoint. If the outcome
cannot be confirmed, retain the journal and contact support.
Lifecycle commands inherit the cloud endpoint and expose SBX_SANDBOX_ID after
creation. Sandbox env values apply to new sessions; rejoining a live agent keeps
that process's existing environment.
sbx --cloud env plan ./sbxenv.yaml
sbx --cloud env run --force --detach ./sbxenv.yaml
sbx --cloud env exec ./sbxenv.yaml -- git status
sbx --cloud env rm --force ./sbxenv.yaml
For file syntax and workflows, see:
https://docs.docker.com/ai/sandboxes/configuration/environment-files/
usage: sbx env COMMAND
options:
- name: help
+4 -17
View File
@@ -13,23 +13,10 @@ description: |-
supplied by --env-arg, plus ${{ env.projectDir }} and ${{ env.fileDir }}.
Nothing else is expanded, so a "$" is literal text.
A directory resolves to the sbxenv.yaml in it and to no other name; any
other file is read only when a PATH names it. The hidden .sbxenv.yaml was once
read as a directory's own environment too, so a project still holding one now
reads as having none.
With no PATH, an existing .sbxenv.yaml in your home directory is merged
underneath as a base layer for defaults shared across projects; naming any
PATH skips the layer. It may not set "name:", which identifies a single
project, and its "workspace:" must be rooted at ${{ env.projectDir }} — for
the base that is always the directory the invocation runs from, since naming
any PATH skips it — so the base mounts each project's own directory rather
than one directory under all of them. Changing its "agent:"
changes the derived <agent>-<directory-basename> sandbox name, leaving
sandboxes created under the previous name for "sbx env rm" to miss.
A list such as "ports" or "mcp.servers" concatenates across layers rather
than overriding, so an entry declared in both appears twice.
A directory PATH selects sbxenv.yaml; a file PATH selects that file.
With no PATH, ~/.sbxenv.yaml supplies shared defaults when present.
Explicit PATHs skip those defaults. Later files override earlier values;
lists such as ports and mcp.servers are concatenated.
usage: sbx env create [PATH...] [flags]
options:
- name: clone
+4 -17
View File
@@ -13,23 +13,10 @@ description: |-
argument forms the command and the environment file is read from the current
directory.
A directory resolves to the sbxenv.yaml in it and to no other name; any
other file is read only when a PATH names it. The hidden .sbxenv.yaml was once
read as a directory's own environment too, so a project still holding one now
reads as having none.
With no PATH, an existing .sbxenv.yaml in your home directory is merged
underneath as a base layer for defaults shared across projects; naming any
PATH skips the layer. It may not set "name:", which identifies a single
project, and its "workspace:" must be rooted at ${{ env.projectDir }} — for
the base that is always the directory the invocation runs from, since naming
any PATH skips it — so the base mounts each project's own directory rather
than one directory under all of them. Changing its "agent:"
changes the derived <agent>-<directory-basename> sandbox name, leaving
sandboxes created under the previous name for "sbx env rm" to miss.
A list such as "ports" or "mcp.servers" concatenates across layers rather
than overriding, so an entry declared in both appears twice.
A directory PATH selects sbxenv.yaml; a file PATH selects that file.
With no PATH, ~/.sbxenv.yaml supplies shared defaults when present.
Explicit PATHs skip those defaults. Later files override earlier values;
lists such as ports and mcp.servers are concatenated.
Flags match the behavior of "sbx exec".
usage: sbx env exec [flags] [PATH...] -- COMMAND [ARG...]
+4 -17
View File
@@ -17,23 +17,10 @@ description: |-
path to the environment file itself. Passing more than one PATH deep-merges them
in order, matching the other "sbx env" subcommands.
A directory resolves to the sbxenv.yaml in it and to no other name; any
other file is read only when a PATH names it. The hidden .sbxenv.yaml was once
read as a directory's own environment too, so a project still holding one now
reads as having none.
With no PATH, an existing .sbxenv.yaml in your home directory is merged
underneath as a base layer for defaults shared across projects; naming any
PATH skips the layer. It may not set "name:", which identifies a single
project, and its "workspace:" must be rooted at ${{ env.projectDir }} — for
the base that is always the directory the invocation runs from, since naming
any PATH skips it — so the base mounts each project's own directory rather
than one directory under all of them. Changing its "agent:"
changes the derived <agent>-<directory-basename> sandbox name, leaving
sandboxes created under the previous name for "sbx env rm" to miss.
A list such as "ports" or "mcp.servers" concatenates across layers rather
than overriding, so an entry declared in both appears twice.
A directory PATH selects sbxenv.yaml; a file PATH selects that file.
With no PATH, ~/.sbxenv.yaml supplies shared defaults when present.
Explicit PATHs skip those defaults. Later files override earlier values;
lists such as ports and mcp.servers are concatenated.
usage: sbx env plan [PATH...] [flags]
options:
- name: clone
+4 -17
View File
@@ -13,23 +13,10 @@ description: |-
in order (docker-compose `-f` semantics), so the same set used to create the
environment resolves to the same sandbox on removal.
A directory resolves to the sbxenv.yaml in it and to no other name; any
other file is read only when a PATH names it. The hidden .sbxenv.yaml was once
read as a directory's own environment too, so a project still holding one now
reads as having none.
With no PATH, an existing .sbxenv.yaml in your home directory is merged
underneath as a base layer for defaults shared across projects; naming any
PATH skips the layer. It may not set "name:", which identifies a single
project, and its "workspace:" must be rooted at ${{ env.projectDir }} — for
the base that is always the directory the invocation runs from, since naming
any PATH skips it — so the base mounts each project's own directory rather
than one directory under all of them. Changing its "agent:"
changes the derived <agent>-<directory-basename> sandbox name, leaving
sandboxes created under the previous name for "sbx env rm" to miss.
A list such as "ports" or "mcp.servers" concatenates across layers rather
than overriding, so an entry declared in both appears twice.
A directory PATH selects sbxenv.yaml; a file PATH selects that file.
With no PATH, ~/.sbxenv.yaml supplies shared defaults when present.
Explicit PATHs skip those defaults. Later files override earlier values;
lists such as ports and mcp.servers are concatenated.
usage: sbx env rm [PATH...] [flags]
options:
- name: env-arg
+4 -17
View File
@@ -14,23 +14,10 @@ description: |-
supplied by --env-arg, plus ${{ env.projectDir }} and ${{ env.fileDir }}.
Nothing else is expanded, so a "$" is literal text.
A directory resolves to the sbxenv.yaml in it and to no other name; any
other file is read only when a PATH names it. The hidden .sbxenv.yaml was once
read as a directory's own environment too, so a project still holding one now
reads as having none.
With no PATH, an existing .sbxenv.yaml in your home directory is merged
underneath as a base layer for defaults shared across projects; naming any
PATH skips the layer. It may not set "name:", which identifies a single
project, and its "workspace:" must be rooted at ${{ env.projectDir }} — for
the base that is always the directory the invocation runs from, since naming
any PATH skips it — so the base mounts each project's own directory rather
than one directory under all of them. Changing its "agent:"
changes the derived <agent>-<directory-basename> sandbox name, leaving
sandboxes created under the previous name for "sbx env rm" to miss.
A list such as "ports" or "mcp.servers" concatenates across layers rather
than overriding, so an entry declared in both appears twice.
A directory PATH selects sbxenv.yaml; a file PATH selects that file.
With no PATH, ~/.sbxenv.yaml supplies shared defaults when present.
Explicit PATHs skip those defaults. Later files override earlier values;
lists such as ports and mcp.servers are concatenated.
usage: sbx env run [PATH...] [flags]
options:
- name: clone
+12
View File
@@ -8,6 +8,11 @@ description: |-
Pass --kit-arg to preview how the kit resolves with a given set of
arguments; the output shows the substituted content.
--offline skips the daemon-backed kit policy (kit.allowedSources,
kit.allowLocalKits, kit.requireSignature) so the command needs neither
sandboxd nor a signed-in session; it only accepts a local directory or
ZIP reference, since those are the only ones this check applies to.
usage: sbx kit inspect REFERENCE [flags]
options:
- name: format
@@ -29,6 +34,10 @@ options:
experimental: true
usage: |
File of name=value kit arguments, one per line (can be repeated); --kit-arg overrides
- name: offline
default_value: "false"
usage: |
Skip the daemon-backed kit policy check; local directory or ZIP references only
inherited_options:
- name: cloud
default_value: "false"
@@ -44,5 +53,8 @@ example: |4-
# Machine-readable output
sbx kit inspect ghcr.io/myorg/my-kit:1.0 --format json
# Inspect without sandboxd running or a Docker sign-in
sbx kit inspect ./my-kit --offline
see_also:
- sbx kit - (Experimental) Manage kit artifacts
+6 -9
View File
@@ -2,18 +2,15 @@ name: sbx kit pull
synopsis: Pull a kit artifact from an OCI registry
experimental: true
description: |-
Pull a kit artifact from an OCI registry and save its layer payload to a file.
Pull a kit artifact from an OCI registry and save its payload to a file.
Use a registry/repo:tag or registry/repo@sha256:digest reference.
The reference should be in the format "registry/repo:tag" or
"registry/repo@sha256:digest" (e.g., "ghcr.io/myorg/my-plugin:1.0").
The file extension is chosen automatically based on the kit's format:
schemaVersion: "1" → <name>.zip (legacy ZIP archive)
schemaVersion: "2" → <name>.tar.gz (standard OCI tar+gzip layer)
The output extension follows the resolved artifact format: .zip for v1,
or .tar.gz for v2. Use --output to choose the file path.
For Docker Hub, the sbx login session takes priority. Other registries use
secrets set with sbx secret set --registry. Both fall back to Docker credentials.
The registry must support HTTPS.
Authentication: sbx registry secrets (sbx secret set --registry) take priority, falling back to the Docker credential store.
usage: sbx kit pull REFERENCE [flags]
options:
- name: help
+7 -23
View File
@@ -2,31 +2,15 @@ name: sbx kit push
synopsis: Push a kit artifact to an OCI registry
experimental: true
description: |-
Package and push a kit artifact directory to an OCI registry.
Package a kit directory containing spec.yaml and push it to an OCI registry.
Use a registry/repo:tag reference. The kit's schema selects the artifact format.
The directory must contain a valid spec.yaml. The reference should be
in the format "registry/repo:tag" (e.g., "ghcr.io/myorg/my-plugin:1.0").
Every push attaches provenance. Use --sign to also sign the manifest and
provenance; signing is keyless unless --key is supplied.
The OCI artifact format is selected from the kit's spec.yaml:
schemaVersion: "1" → legacy ZIP-based artifact
schemaVersion: "2" → v2 tar+gzip layer with the spec in the manifest
config blob and standard OCI annotations (so
distribution tooling can read kit metadata
without pulling layers)
With --sign, the pushed manifest is signed and the Sigstore bundle is
attached to the kit as an OCI referrer. Signing is keyless (Fulcio +
Rekor) unless --key is given for key-based signing.
Every push also attaches a SLSA provenance attestation as an OCI
referrer, recording the kit's content digests, the declared sandbox
image, and the source git commit when the directory is a working tree.
The provenance is unsigned unless --sign is given, in which case it is
signed as a DSSE in-toto attestation with the same identity or key.
Authentication: the Docker Hub session from sbx login and sbx registry
secrets (sbx secret set --registry) take priority, falling back to the
Docker credential store.
For Docker Hub, the sbx login session takes priority. Other registries use
secrets set with sbx secret set --registry. Both fall back to Docker credentials.
The registry must support HTTPS.
usage: sbx kit push DIRECTORY REFERENCE [flags]
options:
- name: help
+12
View File
@@ -9,6 +9,11 @@ description: |-
A kit that declares required arguments is invalid until they are
supplied, so pass the same --kit-arg values you would pass to sbx
create.
--offline skips the daemon-backed kit policy (kit.allowedSources,
kit.allowLocalKits, kit.requireSignature) so the command needs neither
sandboxd nor a signed-in session; it only accepts a local directory or
ZIP reference, since those are the only ones this check applies to.
usage: sbx kit validate REFERENCE [flags]
options:
- name: format
@@ -30,6 +35,10 @@ options:
experimental: true
usage: |
File of name=value kit arguments, one per line (can be repeated); --kit-arg overrides
- name: offline
default_value: "false"
usage: |
Skip the daemon-backed kit policy check; local directory or ZIP references only
inherited_options:
- name: cloud
default_value: "false"
@@ -45,5 +54,8 @@ example: |4-
# Supply the arguments a kit declares
sbx kit validate ./my-kit --kit-arg region=eu
# Validate without sandboxd running or a Docker sign-in
sbx kit validate ./my-kit --offline
see_also:
- sbx kit - (Experimental) Manage kit artifacts
+1 -1
View File
@@ -22,7 +22,7 @@ see_also:
- sbx mcp add - Register an MCP server
- sbx mcp auth - Authorize MCP servers
- sbx mcp inspect - Show MCP server details
- sbx mcp load - Load an already-registered MCP server into a running sandbox
- sbx mcp load - Load an already-registered MCP server into a sandbox
- sbx mcp ls - List MCP servers
- sbx mcp rm - Remove a registered MCP server
- sbx mcp unload - Unload an MCP server from a running sandbox
+15 -210
View File
@@ -1,220 +1,25 @@
name: sbx mcp add
synopsis: Register an MCP server
description: |-
Register an MCP server by name. The server is validated and its
specification is stored for use with sbx create/run --static-mcp.
Register an MCP server for use with sbx create/run --static-mcp.
To attach a registered server to a running sandbox, use sbx mcp load.
This command only registers the server. To attach an already-registered
server to a running sandbox, use 'sbx mcp load'.
Use --url for a remote MCP endpoint, a community-registry or server-manifest
URL, or a Docker Hardened Image reference. Other image references are unsupported.
Use --command for a local stdio server. Local servers run on the host with your
full permissions; use only trusted executables.
The --url flag accepts four input formats; the type is auto-detected:
OAuth metadata is discovered automatically for remote endpoints. Use --client-id
for a pre-registered client, or --oauth-authorization-server when the server
publishes no discovery metadata. Confidential clients need a secret stored as
mcp:NAME:client_secret; use sbx secret set without -t to read it from stdin.
- Remote MCP endpoint URL (https://host/mcp — talks MCP at the URL;
OAuth metadata is discovered via RFC 9728/8414).
- MCP community-registry URL (https://registry.modelcontextprotocol.io/v0/servers/<name>...)
— fetches the registry envelope and resolves the OCI image.
- Server-manifest URL (any URL returning a server.json or server.yaml
body shaped like the MCP community-registry schema — GitHub raw URLs,
internal HTTP servers, ad-hoc CDN links all work).
- Docker Hardened Images (DHI) image ref (dhi.io/<name>:<tag> or
dhi.io/<name>@sha256:... — the server.json manifest is extracted
from the image's in-toto attestation via the OCI Referrers API).
Use --header for custom headers on remote endpoints. Header values can reference
stored secrets; see the examples below. Header secrets come from this host's
secret store and require a locally connected server.
Other image refs (inputs without "://" that are not dhi.io, e.g.
docker.io/foo:tag) are no longer accepted. Use a server manifest instead.
SSRF guard and --skip-ssrf-check:
A --url whose host resolves to a private/RFC1918, loopback, link-local, or
cloud-metadata address is fetched anyway, but flagged: the add proceeds and
a warning naming the resolved address is printed (this protects against
manifest URLs that reach internal services, cloud metadata, or
DNS-rebinding targets by making them visible, not by blocking them). Some
legitimate servers live on private networks (split-horizon DNS, internal
load balancers, VPN-only endpoints, PrivateLink), so their public hostname
resolves to a private address and the warning is expected noise for them.
OAuth authorization-server metadata has a separate SSRF guard with the same
warn-and-proceed posture: a disallowed address is logged, not blocked. Pass
--skip-ssrf-check to disable both checks for this add, including OAuth
metadata redirects (silencing the warning too), when you trust the provider
and its discovery destinations; use it only for URLs you control.
OAuth for remote endpoints (--oauth-authorization-server / --client-id):
Two related options configure OAuth for a remote --url server (both are
only valid with --url):
--oauth-authorization-server hand-supplies the authorization-server
metadata for a server that publishes no well-known RFC 9728/8414 metadata
(e.g. Gmail). It is a local file path or an http(s) URL to a JSON document
conforming to the RFC 8414 oauth-authorization-server shape
(authorization_endpoint and token_endpoint are required). --client-id is
required alongside it UNLESS the metadata document itself advertises a
registration_endpoint, in which case a client is registered dynamically
(RFC 7591) and --client-id may be omitted.
--client-id supplies a PRE-REGISTERED OAuth client. It may be given WITHOUT
--oauth-authorization-server: the server's authorization metadata is then
discovered normally and the supplied client is attached to it. This is the
right mode for a server whose discoverable metadata exposes no
registration_endpoint (so Dynamic Client Registration is impossible) but
which accepts a client id the operator registered ahead of time.
Client secrets (confidential clients):
There is no --client-secret flag. The secret for a confidential client
lives in the secret store in the global scope under the
service name "mcp:<server>:client_secret", and is read from there
whenever the server is used:
sbx secret set mcp:<server>:client_secret
Run it with no -t so the value is read from stdin instead of landing in
your shell history. The secret is never written to the MCP registration
on disk. Remove it later with 'sbx secret rm mcp:<server>:client_secret'.
The stored secret is bound to the OAuth identity (client id, issuer and
token endpoint) that first used it. Re-registering the same server name
against a different client or authorization server therefore does NOT
reuse it — store the secret again for the new client. To let a new
identity claim the existing secret, drop the recorded binding with
'sbx secret rm mcp:<server>:client_secret:identity'.
Two rules apply on the discovered path (they do not affect a server that
advertises a registration_endpoint, the hand-supplied
--oauth-authorization-server path, or --command servers):
- If the discovered authorization metadata has NO registration_endpoint,
Dynamic Client Registration is impossible, so --client-id is REQUIRED;
the add fails without it. This is the Slack shape (discoverable metadata,
no DCR, a pre-registered client).
- A stored client secret is REQUIRED when the server's advertised
token_endpoint_auth_methods_supported (RFC 8414) does NOT include "none"
— i.e. it accepts only confidential clients (client_secret_basic /
client_secret_post). Registration still succeeds without one, but the
add-time authorization is skipped; store the secret and run
'sbx mcp auth <server>' to finish. When the list includes "none" a
public/PKCE client is allowed and --client-id alone is enough. If the
server advertises no token_endpoint_auth_methods_supported at all (the
field is optional in RFC 8414), the requirement cannot be determined and
the add proceeds as usual.
Default OAuth scopes (--scope / --no-scope):
--scope records the DEFAULT set of scopes to request at consent time for a
remote --url OAuth server (repeatable). Precedence at authorization time is
--no-scope > an explicit 'sbx mcp auth --scope' > the set recorded here > the
scope set the RESOURCE itself says it requires (from its RFC 9728
protected-resource metadata or its WWW-Authenticate challenge) > whichever of
openid, email, profile, and offline_access are advertised. Other advertised
scopes are excluded from this fallback. If no scopes are selected, the scope
parameter is omitted so the authorization server can apply its own default
grant (RFC 6749 §3.3).
A resource that publishes a required set therefore gets it requested with no
flag at all, and the consent block marks that set as derived rather than
chosen. --no-scope suppresses all scope fallbacks and requests the server's
default grant.
When using recorded defaults or resource scopes, sbx also requests offline_access
if the authorization server advertises it, allowing refresh tokens. To request
an exact set without this addition, use 'sbx mcp auth <server> --scope ...'.
Scopes you name are checked against the union of two documents a server can
publish: the authorization server's RFC 8414 scopes_supported and the
resource's own RFC 9728 protected-resource metadata (some servers, e.g.
GitHub, document their real scopes on the resource and advertise almost
nothing over RFC 8414). A scope in neither prints a warning naming the
offender but is still requested — a mismatch is often the server's own
documentation gap, not a typo, and either document is allowed to be
non-exhaustive. This is a recognition check, not a promise: a recognized
scope can still be refused at consent time.
Scope values may be URN-shaped (urn:ietf:params:oauth:scope:mail) or
URL-shaped (https://www.fastmail.com/dev/mcp). Neither needs quoting — a scope
token cannot contain a space or a quote — and both are percent-encoded
normally on the wire. --scope applies both to a hand-supplied override and to
a plain --url server whose OAuth metadata is discovered.
RFC 8707 resource indicator (--resource):
Every authorization request, code exchange and token refresh names the server
the token is for, in the 'resource' parameter the MCP authorization
specification requires (RFC 8707). That value is normally DERIVED, and you do
not need this flag: it comes from the server's own RFC 9728 protected-resource
metadata when it publishes some, and otherwise from the --url endpoint
(lowercased scheme/host, path kept, fragment dropped).
--resource replaces that derivation with a value you supply. Use it when the
derived one is wrong — most often a server whose published identifier is its
bare origin (https://api.example.com) while its endpoint has a path
(https://api.example.com/mcp), which is indistinguishable from publishing
nothing, so the endpoint URL is what gets sent. An authorization server
entitled to reject an unknown target answers 'invalid_target'.
The value must be an absolute URI with a scheme and a host, and RFC 8707 §2
forbids a fragment; a bad value fails the add rather than being repaired or
dropped later. It is sent VERBATIM — nothing is lowercased and no path or
trailing slash is adjusted, because the string names a server and changing it
could name a different one. Only one value is accepted: a gateway backend
connects to exactly one MCP endpoint.
It outranks both the published value and the URL derivation, and also an
authorization server advertising resource_indicators_supported=false (the add
says so when that happens). It is recorded on the registration, so there is no
'sbx mcp auth --resource': one value is used by the add-time authorization,
every later 'sbx mcp auth', and every token refresh — a resource that differed
between them is the audience mismatch this parameter exists to prevent. To
change it, 'sbx mcp rm' the server and add it again; the existing token was
minted for the old resource anyway.
Not 'audience': RFC 8707 'resource' is what the MCP specification requires, and
an 'audience' parameter on an authorization-code request is an Auth0/Okta
vendor extension that sbx does not send. See 'sbx mcp inspect <name>' for the
effective value and where it came from.
Scope limit: this governs the OAuth flow sbx itself runs — a local data plane
(SBX_MCP_URL=none), and any server registered with
--oauth-authorization-server/--client-id. For a plain remote in hosted mode the
control-plane gateway is the OAuth client and does not carry the field yet, so
the value is recorded and the add warns that it is not sent for that server.
Custom request headers for remote endpoints (--header):
--header adds an HTTP header to every request sent to a remote --url
endpoint, written in the curl convention 'Header-Name: header value'.
Repeat the flag for more headers; each header name may be given once.
Headers the transport owns (Host, Content-Length, Connection, Proxy-*, …)
are rejected.
Only a remote endpoint can carry them: --header is refused with --command
and --local, and an add whose --url resolves to a stdio server (a registry
or manifest URL naming an OCI image) fails rather than dropping them.
A header value may reference a secret with ${placeholder}. The placeholder is
stored in the registration exactly as typed and the secret itself never is;
the value is read from the encrypted secret store and substituted when a
sandbox connects to the server. Store it with:
sbx secret set mcp:<server>:<placeholder>
For example:
sbx mcp add acme --url https://mcp.acme.com/mcp --header 'Authorization: Bearer ${api-key}'
sbx secret set mcp:acme:api-key
On an OAuth-protected server an explicit Authorization header takes
precedence over the OAuth access token.
Header secrets are read from the LOCAL secret store, so a header-bearing
server only works where this host connects it. Adding one while your MCP
gateway is the hosted (SaaS) one is rejected rather than registered with
headers that would be silently dropped — unless the server carries a
hand-supplied OAuth override (--oauth-authorization-server), which this
host connects directly in every gateway mode.
Alternative input — local stdio command (--command + --args):
The command runs as a subprocess on the HOST, outside the sandbox.
WARNING: Local servers are for ad-hoc development only. They have
no identity, no verifiable supply chain, and no sandboxing. The
process runs with your host user's full permissions — it can read
your filesystem, access your network, and call any API your user
can. Do not use --command with untrusted executables.
For registration and authorization workflows, see:
https://docs.docker.com/ai/sandboxes/mcp-gateway/
usage: sbx mcp add NAME (--url URL | --command COMMAND) [flags]
options:
- name: args
+5 -4
View File
@@ -1,9 +1,10 @@
name: sbx mcp load
synopsis: Load an already-registered MCP server into a running sandbox
synopsis: Load an already-registered MCP server into a sandbox
description: |-
Attach a previously-registered MCP server to a running sandbox's gateway.
Connected agents see the new server's tools immediately via the standard MCP
tools/list_changed notification — no agent restart required.
Attach a previously-registered MCP server to a sandbox's gateway.
In a running sandbox, connected agents see the new server's tools immediately
via the standard MCP tools/list_changed notification — no agent restart
required. A stopped sandbox gets the server the next time it starts.
The server must already exist in the local MCP store (register first with
'sbx mcp add'). Both remote/hosted and local-stdio servers are supported.
+1
View File
@@ -30,5 +30,6 @@ see_also:
- sbx policy inspect - Show policy or rule details
- sbx policy log - Show sandbox policy logs
- sbx policy ls - List sandbox policies
- sbx policy refresh - Force an immediate policy refresh
- sbx policy reset - Reset policies to defaults
- sbx policy rm - Remove a policy rule
+9 -14
View File
@@ -1,23 +1,18 @@
name: sbx policy init
synopsis: Initialize the global network policy
description: |-
Initialize the global network policy that applies to all sandboxes.
Initialize the global network policy before starting a sandbox or adding
custom rules. Per-sandbox rules apply on top of this policy.
This sets the initial global network policy and must be run before adding
custom allow/deny rules or starting a sandbox for the first time. It is a
one-time setup: once initialized, use "sbx policy reset" to start over.
Choose a policy:
This is the initial global policy, not a per-sandbox default; you can change
it later. Per-sandbox rules, including those added by kits such as the
built-in agent kits, apply on top for individual sandboxes.
- allow-all: Allow all outbound network traffic.
- balanced: Allow typical development traffic, including AI services and package registries.
- deny-all: Block all outbound network traffic.
Available policies:
allow-all All outbound network traffic is allowed
balanced Typical development traffic is allowed, such as AI services and package registries
deny-all All outbound network traffic is blocked
After initializing, use "sbx policy allow/deny/rm" to change the global policy.
Use "sbx policy reset" to clear all policies and start over.
After initialization, use sbx policy allow/deny/rm to change the rules.
Initialization is a one-time setup. Use sbx policy reset to clear all policies
and start over.
With --cloud:
Set the default network mode of the cloud policy.
+7
View File
@@ -37,6 +37,10 @@ options:
usage: Output in JSON format
- name: protocol
usage: 'Filter network rules by protocol: tcp or udp'
- name: quiet
shorthand: q
default_value: "false"
usage: Only display rule IDs (network patterns with --cloud)
- name: source
usage: 'Filter policies by source: "local", "org", or "kit"'
- name: type
@@ -68,6 +72,9 @@ example: |4-
# Output filtered rules as JSON
sbx policy ls --json
# List only rule IDs
sbx policy ls -q
# List only network policies
sbx policy ls --type network
+32
View File
@@ -0,0 +1,32 @@
name: sbx policy refresh
synopsis: Force an immediate policy refresh
description: |-
Force sandboxd to fetch and apply governance policy immediately.
The daemon normally polls for policy changes on a regular interval. Use this
after changing an org policy setting (for example, toggling AI Governance) so
the change takes effect without waiting for the next poll. This also
invalidates the cached registry credential; it never restarts the daemon or
stops running sandboxes.
The refreshed policy applies to new connections only. Connections a sandbox
opened while the previous policy allowed them stay open even if the new
policy denies them; restart the sandbox to drop them.
usage: sbx policy refresh [flags]
options:
- name: help
shorthand: h
default_value: "false"
usage: help for refresh
inherited_options:
- name: cloud
default_value: "false"
usage: |
Dispatch to Docker Cloud Sandboxes API instead of local sandboxd (supported by a growing set of verbs — run 'sbx --cloud --help' for the current list)
- name: debug
shorthand: D
default_value: "false"
usage: Enable debug logging
example: ' sbx policy refresh'
see_also:
- sbx policy - Manage sandbox policies
+3
View File
@@ -116,6 +116,9 @@ options:
- name: on-timeout
usage: |
What happens when --ttl lapses: 'stop' stops the sandbox in place so it can be started again later, 'restart' keeps it running by stopping and immediately starting it, or 'delete' removes it. Omit the flag and the server stops the sandbox when it can be started again later, and deletes it otherwise. With 'restart' a supplied --ttl must be at least 1h (cloud only).
- name: platform
usage: |
Target platform: linux/amd64 or linux/arm64 (cloud only). With --image-ref, omitting it lets the server resolve the platform from the image and the CLI sends the local CPU as a hint for multi-platform images. With --template, omitting it inherits the template platform. With a sandbox kit, the kit's template is built for this platform and cached apart from other platforms; omitting it keeps the server's choice.
- name: publish
shorthand: p
default_value: '[]'
+7
View File
@@ -22,6 +22,10 @@ options:
- name: no-trunc
default_value: "false"
usage: Show full values and descriptions, one setting per block
- name: quiet
shorthand: q
default_value: "false"
usage: Only display setting keys
inherited_options:
- name: cloud
default_value: "false"
@@ -37,5 +41,8 @@ example: |4-
# List settings as JSON
sbx settings ls --format json
# List only setting keys
sbx settings ls -q
see_also:
- sbx settings - Manage Docker Sandboxes settings
+5 -12
View File
@@ -1,21 +1,14 @@
name: sbx settings set
synopsis: Set a setting override
description: |-
Set a user override for a setting.
Administrator constraints apply to saved overrides. A conflicting value is rejected.
The value is parsed according to the setting's type:
bool "true" or "false"
int integer value
float floating-point value
string plain text
json raw JSON
Set a user override for a setting. Values are parsed according to the
setting's type: bool (true or false), int, float, string, or raw JSON.
Administrator constraints apply; conflicting values are rejected.
Environment variables take precedence over user overrides.
Most changes take effect within about five seconds. If a daemon restart is
required, this command tells you to run 'sbx daemon restart'.
Most changes take effect within about five seconds. This command reports
when a daemon restart is required.
usage: sbx settings set KEY VALUE [flags]
options:
- name: help
+11 -21
View File
@@ -2,29 +2,19 @@ name: sbx skills import
synopsis: Import skills from supported agent directories
experimental: true
description: |-
Import skills already installed for supported coding agents on this
machine.
Import skills installed for supported coding agents on this machine.
Directories are checked in order:
The following directories are checked in order:
~/.agents/skills
~/.claude/skills
~/.config/opencode/skills
~/.copilot/skills
~/.cursor/skills
~/.factory/skills
1. ~/.agents/skills
2. ~/.claude/skills
3. ~/.config/opencode/skills
4. ~/.copilot/skills
5. ~/.cursor/skills
6. ~/.factory/skills
When the same skill appears in more than one directory, the first copy is used
and the others are skipped with a warning.
Importing a skill that is already installed replaces it completely, including
removing files that are no longer present. You will be prompted before a skill
is replaced; use --force to skip all prompts.
Symlinks at the top level are followed if they point to a directory. Symlinks
within skill folders and loose files at the top level are skipped.
Imported skills are available to Claude, Codex, Copilot, Cursor, Droid, and
OpenCode.
The first copy of each skill is used. Importing replaces an existing skill
completely, including removing obsolete files; --force skips confirmation.
Top-level directory symlinks are followed; symlinks within skills are skipped.
usage: sbx skills import [flags]
options:
- name: dry-run
+12 -15
View File
@@ -7,22 +7,19 @@ description: |-
Tar files are typically created with: sbx template save SANDBOX TAG --output FILE
With --cloud:
The tar is uploaded to the cloud template registry as a new template.
Takes two arguments (FILE, NAME). NAME must be unique per account.
--cpus and --memory-mib are required, and together must name one of the
billable sandbox shapes:
micro (1 vCPU / 2048 MiB)
small (2 vCPU / 4096 MiB)
medium (4 vCPU / 8192 MiB)
large (8 vCPU / 16384 MiB)
xl (16 vCPU / 32768 MiB)
--capture-mode controls what gets captured for the template: "disk" (default)
is faster to load and cold-boots from the filesystem; "all" captures memory +
disk + microVM checkpoint so subsequent runs resume in sub-second time at the
cost of a slower load.
Upload a tar file as a cloud template. Takes FILE and NAME; NAME must be
unique per account. Uploads can take several minutes.
Cloud loads upload your full tar to the registry; multi-GB uploads can
take several minutes. See https://docs.docker.com/ai/sandboxes/ for the snapshot/load model.
--cpus and --memory-mib are required and must match a billable sandbox shape:
- micro (1 vCPU / 2048 MiB)
- small (2 vCPU / 4096 MiB)
- medium (4 vCPU / 8192 MiB)
- large (8 vCPU / 16384 MiB)
- xl (16 vCPU / 32768 MiB)
Use --capture-mode disk for a filesystem snapshot, or all to capture memory,
disk, and the microVM checkpoint for faster resume.
usage: sbx template load FILE [NAME] [flags]
options:
- name: capture-mode
+7 -9
View File
@@ -1,16 +1,11 @@
name: sbx template save
synopsis: Save a snapshot of the sandbox as a template
description: |-
Save a snapshot of the sandbox as a template.
Save a sandbox snapshot as a template in the local image store.
Use --pull never when creating a sandbox from the saved template.
The saved image is stored in the sandbox runtime's image store and can be
used as a template for new sandboxes with:
sbx run --pull never -t TAG AGENT [WORKSPACE]
Use --pull never to use the saved image without trying to pull it from a registry.
Use --output to also export the image to a tar file that can be shared
and loaded on another host with: sbx template load FILE
Use --output to export a tar file for loading on another host with
sbx template load.
With --cloud:
Snapshot a running cloud sandbox into a cloud-managed template. The
@@ -52,6 +47,9 @@ example: |4-
# Save as a template for new sandboxes on this host
sbx template save my-sandbox myimage:v1.0
# Create a sandbox from the saved template
sbx run --pull never -t myimage:v1.0 claude ./project
# Also export to a shareable tar file
sbx template save my-sandbox myimage:v1.0 --output /tmp/myimage.tar