Docker Sandboxes Env
DockerOfficialPublished by Docker
- Skill
- Tool integration
- Automation and integrations
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The docker-sandboxes-env skill provides a declarative approach to managing Docker Sandbox environments. By using an sbxenv.yaml file, users can define agents, kits, workspace mounts, environment variables, secrets, and host-side lifecycle commands. This replaces manual, long-form command-line invocations with a version-controlled, reproducible configuration that supports deep-merging, parameterization via arguments, and secure lifecycle hooks.
What it does
- Defines sandbox environments declaratively using sbxenv.yaml.
- Supports multi-file deep merging for modular configurations.
- Manages host-side lifecycle commands (initialize, postCreate, preRemove).
- Parameterizes environments using named arguments.
- Provides secure, scoped provisioning for secrets, registries, and bindings.
- Enforces read-only protection for environment files within the sandbox.
When to use it
- When you need a reproducible, checked-in definition for a sandbox environment.
- When you require host-side setup or teardown tasks tied to the sandbox lifecycle.
- When you want to parameterize shared sandbox configurations.
- When debugging sandbox creation, planning, or approval workflows.
Advantages
- Eliminates complex, error-prone command-line flag sequences.
- Enables version control for environment definitions.
- Ensures consistent sandbox setup across different users or machines.
- Provides clear visibility into changes via the planning and approval model.
- Enhances security by isolating secrets and protecting configuration files.
Usage examples
- “Create a sandbox environment based on my sbxenv.yaml file.”
- The agent reads the sbxenv.yaml file, generates an execution plan for approval, and provisions the sandbox with the specified kits, mounts, and variables.
- “How do I run a setup script every time I attach to my sandbox?”
- The agent explains how to add an initialize hook to the lifecycle block in your sbxenv.yaml, ensuring the script runs idempotently on every create or run.
- “Define a shared environment that takes a custom version argument.”
- The agent demonstrates how to define an args block in sbxenv.yaml and use the ${{ env.args.NAME }} syntax to inject values at runtime.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/docker/docker-sandboxes-env/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip docker-sandboxes-env.zip -d .agents/skills
Documentation by Docker
Docker Sandboxes: Declarative sbxenv.yaml Environments
Overview
sbxenv.yaml (schemaVersion "1", EXPERIMENTAL) declaratively describes one
sandbox environment — agent, mixin kits, workspace mounts, environment
variables, secrets/registries/bindings to provision, MCP servers, ports, and
host-side lifecycle commands — so sbx env create|run|plan|exec|rm can stand
it up and tear it down reproducibly instead of a long flag invocation. This
skill owns that file format end to end. It delegates the sandbox lifecycle
semantics it wraps, the credential/network model it provisions into, and the
kit schema its kits: entries reference, to their own skills.
When to use this skill
Activate this skill when:
The user wants a checked-in, reproducible definition of a sandbox environment instead of a long
sbx create/sbx runcommand line.The user wants host-side setup/teardown commands (cloning a repo, seeding fixtures, archiving state) tied to a sandbox's create/attach/remove lifecycle.
The user wants to parameterize a shared environment file with named arguments (
args:+--env-arg).The user is debugging why
sbx env create/runis asking for approval, or why a file, kit, or secret it declares was skipped or flagged.
Do not use this skill when
Do not use this skill when:
The task is the underlying
sbx create/run/rmflag-based workflow with nosbxenv.yamlfile involved — usedocker-sandboxes-lifecycle.The task is choosing network policy or storing a secret/registry credential independent of any environment file — use
docker-sandboxes-network-credentials(this skill'ssecrets:/registries:/bindings:blocks provision into that same store, but do not redefine its rules here).The task is authoring the kit
spec.yamlakits:entry points at — usedocker-sandboxes-kits.
Core guidance
File resolution and required fields
The file
sbx envreads from a directory is exactlysbxenv.yaml— no other name, and a directory-named.sbxenv.yamlat the project level is not read as a project's own file (only the home-directory base layer uses that hidden name; see below).Every environment file requires
schemaVersion: "1"andagent:(a built-in agent name or the manifest name of an agent kit supplied viakits:). Everything else is optional.agent: shellneeds no credentials and is the simplest way to validate a file's mechanics.sbx env create|run|plan|exec|rmaccept one or morePATHarguments. EachPATHis either a directory (resolved to<PATH>/sbxenv.yaml) or the file itself. Passing more than one deep-merges them in declaration order —docker compose -f-style semantics: later files override earlier ones, mappings merge key-by-key, sequences concatenate.sbx env create sbxenv.yaml override.yaml
Naming, workspace, and the .sbxenv.yaml user base layer
Unless the file sets
name:or--nameoverrides it, the sandbox is named after the mounted directory (or the project directory when nothing is mounted) — so an environment that mounts nothing is still the same sandbox every time it is applied. Two different environment files in the same directory derive the same sandbox name and collide unless each sets its ownname:(or you pass a distinct--nameper invocation) — always give each environment its own explicitname:when more than one may exist in the same directory.workspace:names the read/write mount, exactly likesbx create's omitted-path behavior: omittingworkspace:mounts nothing at all. A relativeworkspace:path resolves against the directory of the file that declares it —workspace: .mounts the directory the file sits in.${{ env.projectDir }}names the project directory (the one holding the firstPATH, or cwd when none is named);${{ env.fileDir }}names the declaring file's own directory. Nothing else is expanded — a bare$is literal text, so a value written for the container (PATH: $PATH:/opt/bin) reaches it unchanged.workspace: . # mounts the directory this file sits in # workspace: ${{ env.projectDir }} # mounts the project directory explicitlyRelative kit sources follow the same file-directory anchoring rule as
workspace:(seedocker-sandboxes-kitsfor kit reference syntax).Files within a mounted workspace get default read-only masking, and that protection is complete only when the file sits directly at the mount's own root. A read-only bind at the mount point cannot be renamed by the sandbox — there is nothing above it inside the mount to rename. But an environment file in a subdirectory of a read-write mount is protected only at its current path: the sandbox can rename the containing directory (which it can write to) and then recreate the original path itself, landing a sandbox-controlled file back where the read-only bind no longer applies.
sbx env plancalls this gap out explicitly for a file that is not at a mount's root. Do not claim renaming the containing directory creates no gap — for anything but the mount root, it does.With no
PATHgiven, an.sbxenv.yamlin the home directory is merged underneath as a base layer for defaults shared across projects; naming anyPATHskips this layer entirely. The base layer may not setname:(which identifies one project) and itsworkspace:must be rooted at${{ env.projectDir }}— any other value would mount one fixed directory under every project that merges it.
args: — parameterizing a shared file
Declare named inputs under
args:, each with adefault(making it optional,default: ""counts as a real default) orrequired: true(mutually exclusive), plus optionaldescription,enum, orpattern.Reference one as
${{ env.args.NAME }}anywhere a value appears in the file, and supply it with--env-arg NAME=VALUE(repeatable) or--env-args-file PATH.
lifecycle: — host commands and the approval plan
lifecycle:declares shell commands that run on the host, outside the sandbox, with your own privileges — not inside the container. Three phases, run in this order per invocation:initialize— runs on everycreateandrun, including one that only attaches to an existing sandbox. It is the one phase that can produce what the environment needs to exist (a cloned workspace, a generated file), so it must be idempotent — it reruns on every reattach.postCreate— runs once, after the sandbox exists, before an interactive attach takes the terminal.preRemove— runs beforesbx env rmdeletes the sandbox, whilesbx env execcan still reach it. A failingpreRemoveis only a warning — the failure itself does not block removal. After the hook, removal rechecks the approved destroy plan and sandbox identity. A new credential or changed binding not covered by that approval, or a replacement sandbox under the same name, stops removal before deletion. Review the new destroy plan before retrying.sbx env execruns no lifecycle commands at all, and requires the sandbox to already exist — it does not create one. Runsbx env create/sbx env runfirst.
lifecycle: initialize: - command: test -d app || git clone https://github.com/acme/app postCreate: - command: ./scripts/seed-fixtures.sh preRemove: - command: ./scripts/archive-state.shEvery command runs through the shell from the project directory by default (override per-command with
workdir:; bound its runtime withtimeout:).A file that declares any lifecycle command is asked about on every invocation that reaches it, whether or not this particular invocation changed anything — approving a command also trusts whatever it invokes, including a script whose contents can change after the answer, so the question is repeated rather than remembered by default. The one exception:
sbx settings set env.rememberHostCommands truemakes it ask again only when the commands actually change. Never treat an untrusted file's or an untrusted kit's lifecycle commands as pre-approved, and never enablerememberHostCommandsfor a file whose commands you have not reviewed. An environment that declares no host commands at all, and whose config is otherwise unchanged from what was last approved, applies silently with no prompt. Use--skip-host-commandsto run none of the declared commands for one invocation.
The environment plan: what it is and is not
sbx env plan [PATH...]prints everything applying the file would set up — host commands, credentials/bindings, MCP registrations, directories, published ports, the sandbox itself, and its variables — compared against what was last applied/approved. It changes nothing.sbx env create/sbx env runshow the same plan and require approval before doing any work (--auto-approve/-yskips the prompt for non-interactive use — never default to-yfor a file or kit you have not reviewed). A secret's literalvalue:is the one field shown both in the plan and recorded to state as asha256:digest rather than in the clear; aref:/command:secret shows where the credential comes from, not its resolved value.
Secrets, registries, and bindings scoped to the environment
secrets:andregistries:provision into the same credential storesbx secret setuses, at this environment's sandbox scope, sosbx env rmcan remove exactly what it created. Each entry uses the samevalue/ref/commandshape assbx secret set(exactly one of the three) — seedocker-sandboxes-network-credentialsfor what those mean at runtime and why a literal secret value should not otherwise appear in a checked-in file.bindings:are per-service credential bindings merged into the user's globalcredentials.yaml; unlikesecrets:/registries:, they are left in place by default bysbx env rm(they are user-wide and may be shared with other sandboxes/environments) — pass--prune-bindingsto also remove them.Never write a literal secret value directly into a checked-in
sbxenv.yaml. Useref:(1Password/AWS Secrets Manager) orcommand:so the value never lives in the file at all; if a literalvalue:is used transiently, both the plan and state show only its digest, but the original environment file still contains the plaintext secret. See the labeledsecrets:fragment below for the shape — it is intentionally not part of the minimal asset, which needs no credentials at all to validate.# OPTIONAL fragment — add only if this environment actually needs a # credential; the minimal asset omits this entirely. secrets: anthropic: ref: op://Private/Anthropic/api-key # never a literal `value:` in a checked-in file refresh: 55m
kits:, additionalWorkspaces:, mcp:, ports:, and sandboxOptions:
kits:composes mixin kits (and, exactly once, an agent kit whose name matchesagent:) onto the base agent; a relative source anchors to the declaring file's own directory, the same rule asworkspace:.additionalWorkspaces:mounts extra directories beyond the primaryworkspace:(a file cannot declare one without the other) — thesbxenv.yamlequivalent ofsbx run's extra positional workspace arguments with:ro.mcp.servers:registers MCP servers on the host and adds them to the sandbox's fixed (static) MCP set at create time; registrations are host-global and left in place bysbx env rm.ports:pins explicit host-port bindings for container ports the sandbox exposes — the equivalent ofsbx ports --publish— and is torn down automatically whensbx env rmdeletes the sandbox.sandboxOptions:(beyondwritableEnvFiles, below) maps onto the remainingsbx createflags:template,memory,cpus,pullPolicy,profile,skills.
See references/env-schema-fields.md for the exact field shapes, required
keys, and a YAML example for each of the five blocks above.
sandboxOptions.writableEnvFiles — a deliberate, explicit downgrade
By default, every environment file mounted inside the workspace is read-only at its own path, even though the rest of the mount is writable. This stops an agent editing the very file that decides what host lifecycle commands and secret-resolving commands run on your machine on the next invocation.
Set
sandboxOptions.writableEnvFiles: trueonly where an agent is deliberately meant to edit its own environment file. This is a real security downgrade — the plan then reports the file as writable — so treat it the same as any other explicit trust decision, not a default.The protection is complete only at a mount's own root. A file placed directly at the root of a read-write mount cannot be reached even by renaming, because the sandbox cannot rename the mount point itself. A file in a subdirectory of that mount is a different case: it is read-only at its current path, but the sandbox can rename the directory holding it (which it can write to) and recreate a file at the original path, ending up with a sandbox-controlled file there.
sbx env planflags this gap for a file that is not directly at a mount's root — read the plan's output rather than assuming renaming is always harmless.
Related skills
For the
sbx create/run/rmflag-based workflow this file wraps, usedocker-sandboxes-lifecycle.For what
secrets:/registries:/bindings:mean at runtime, and for configuring network policy independent of any environment file, usedocker-sandboxes-network-credentials.For the schema of the kit
spec.yamlakits:entry (oragent:pointing at an agent kit) references, usedocker-sandboxes-kits.
References
references/sources.md— provenance for every rule above (help captures, source paths, docs URLs).references/env-schema-fields.md— exact field shapes and YAML examples forkits:,additionalWorkspaces:,mcp:,ports:, andsandboxOptions:.
Assets
assets/sbxenv.yaml— a complete, minimal, safe example: ashellagent mounting the declaring file's own directory, one static env var, and no credentials at all — it validates and plans without any onboarding authentication.
Checks
checks/verification.md— Verification runbook for sbxenv.yaml commands (unexecuted runbook; run manually with an isolated, uniquely-named--app-name, never with real secret values or untrusted lifecycle commands auto-approved).
Files
- ATTRIBUTION.mdAdded by AutoGineer832 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md15.8 KiB
- agents/openai.yaml428 B
- assets/sbxenv.yaml286 B
- checks/verification.md4.6 KiB
- references/env-schema-fields.md3.6 KiB
- references/sources.md7.2 KiB
- skill.yaml1.3 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an MCP server
The author says: Requires standalone sbx with sbx env support and sbxenv.yaml schemaVersion "1", not the legacy docker sandbox wrapper. Verified against docker/sandboxes df5c96ba60484fa2c375469dbac912c205da6c37; installed-help version and provenance are in references/sources.md. docker_help does not cover standalone sbx.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Docker
- Publisher
- Docker (Official)
- Source
- docker/skills · skills/docker-sandboxes-env · commit 9f04a05
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Docker or Docker.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download docker-sandboxes-env.zip