Thomas Piacentini
← Atelier

Chapitre

sbxenv.yaml and sbx env plan

Texte original · anglais

An environment file declares the agent, kits, workspace, secrets, ports, MCP servers, and host commands, and sbx env plan prints every change before create or run applies it.

A new contributor clones your repository and needs the sandbox you use. That means the shell workload, the hello-mixin, one published port, a greeting variable, and a host command that prepares the workspace. You could send a list of flags. An environment file sends the same thing as one checked-in file, and the contributor sees a plan before anything runs.

When you finish this section, you can write an sbxenv.yaml, read its plan symbol by symbol, and say which edits wait for the next create.

The file

Environment file: a sbxenv.yaml that declares one sandbox and the host resources around it, read by the five sbx env commands {{help-sbx sbx env}}. The capture kit wrote this one:

the environment file the capture kit wroteyamlFull source
schemaVersion: "1"
name: m101-env
agent: shell
workspace: .
args:
  greeting:
    default: hello
    description: Greeting word
kits:
  - source: ../kits/hello-mixin
env:
  GREETING: ${{ env.args.greeting }}
lifecycle:
  initialize:
    - command: echo init
ports:
  - sandbox: 8080
    host: 18083
Original source
title: the environment file the capture kit wrote
source: capture/fixtures/env/sbxenv.yaml
lang: yaml
---
schemaVersion: "1"
name: m101-env
agent: shell
workspace: .
args:
  greeting:
    default: hello
    description: Greeting word
kits:
  - source: ../kits/hello-mixin
env:
  GREETING: ${{ env.args.greeting }}
lifecycle:
  initialize:
    - command: echo init
ports:
  - sandbox: 8080
    host: 18083
Key What it declares
schemaVersion, name, agent the file version "1", the sandbox name, the built-in agent or kit
args inputs with default or required: true, read as ${{ env.args.NAME }}
kits mixins, as a reference or as source plus args
workspace, additionalWorkspaces the host directories to mount, with an object form for clone mode
env variables for the sandbox
secrets, bindings, registries credentials with value, ref, or command, and the domains they reach
mcp.servers MCP servers registered with the gateway
ports published ports, sandbox, host, protocol, hostIP
lifecycle host commands under initialize, postCreate, preRemove
sandboxOptions template, memory, cpus, skills, writableEnvFiles, and more

The keys come from the file reference {{docs-sbx Top-level fields}} and from the command's own help. Three placeholders expand, ${{ env.args.NAME }}, ${{ env.projectDir }}, and ${{ env.fileDir }}, and a $ anywhere else is literal text {{help-sbx sbx env create}}. A relative kit path or workspace resolves against the directory of the file that declares it, so workspace: . mounts the file's own directory {{help-sbx sbx env}}. A file with no workspace mounts nothing {{rel-sbx v0.42.0}}.

The plan

sbx env plan reads the file and prints what applying it would set up. It applies, approves, and records nothing {{help-sbx sbx env plan}}.

the first plan for m101-envtextFull source
── ENVIRONMENT PLAN
   m101-env

   kits:
+    - source: $CAPTURE/fixtures/kits/hello-mixin

   workspace:  (present, not recorded as applied, needs your approval)
     path: $CAPTURE/fixtures/env

   env:
+    GREETING: hello

+  sandbox:
+    name: m101-env
+    agent: shell

   ports:
+    - sandbox: 8080
+      protocol: tcp4
+      host: 18083

   lifecycle:
     initialize:
+      - command: echo init
+        workdir: $CAPTURE/fixtures/env
+        envFiles:
+          - $CAPTURE/fixtures/env/sbxenv.yaml

   Plan: + 5 to add, ~ 0 to change, - 0 to destroy.

   this plan runs commands on this machine, outside the sandbox, with your own privileges
   ✓ not approved yet; applying asks once
The LOAD ENVIRONMENT block is cut.
Original source
title: the first plan for m101-env
source: capture/out/14-env-plan.txt
lang: text
note: The LOAD ENVIRONMENT block is cut.
---
── ENVIRONMENT PLAN
   m101-env

   kits:
+    - source: $CAPTURE/fixtures/kits/hello-mixin

   workspace:  (present, not recorded as applied, needs your approval)
     path: $CAPTURE/fixtures/env

   env:
+    GREETING: hello

+  sandbox:
+    name: m101-env
+    agent: shell

   ports:
+    - sandbox: 8080
+      protocol: tcp4
+      host: 18083

   lifecycle:
     initialize:
+      - command: echo init
+        workdir: $CAPTURE/fixtures/env
+        envFiles:
+          - $CAPTURE/fixtures/env/sbxenv.yaml

   Plan: + 5 to add, ~ 0 to change, - 0 to destroy.

   this plan runs commands on this machine, outside the sandbox, with your own privileges
   ✓ not approved yet; applying asks once

The plan has the shape of your file, and the margin carries the verdict. Five symbols exist {{help-sbx sbx env}}. + adds, ~ changes, and - destroys. > marks a command that runs again, and ! marks a resource the environment applied and no longer declares.

A row that is unchanged and already approved is left out. A literal secret value appears as its SHA-256 digest {{docs-sbx Review an environment plan}}. The tcp4 protocol was not in the file: published ports default to it since v0.42.0 {{rel-sbx v0.42.0}}. Figure follows the file through the plan to the state record.

Fig. 4.4an environment file becomes a plan, an approval, and a state recordflow
sbx env plan turns the file into margin-marked rows, approval on create records them, and a later plan prints only the rows that moved.
sbx env plan turns the file into margin-marked rows, approval on create records them, and a later plan prints only the rows that moved. Read top down. The plan rows are the env plan capture, and the right branch is the second plan capture, with the greeting argument changed. The left branch after approval follows the help text of sbx env, because the kit never applied the plan.

Original SVG

Original source
id: fig-4-4
kind: flow
title: an environment file becomes a plan, an approval, and a state record
claim: sbx env plan turns the file into margin-marked rows, approval on create records them, and a later plan prints only the rows that moved.
caption: Read top down. The plan rows are the env plan capture, and the right branch is the second plan capture, with the greeting argument changed. The left branch after approval follows the help text of sbx env, because the kit never applied the plan.

Host commands and approval

The lifecycle block runs on the host, outside the sandbox, with your own privileges. initialize runs on every create and every run, postCreate once the sandbox exists, and preRemove after you confirm sbx env rm {{help-sbx sbx env}}. Commands run through your shell from the project directory, with workdir and timeout per command. An environment with any of them asks on every invocation, even one that does not run them {{help-sbx sbx env}}. The reason is that approving a command also trusts the script it calls. --skip-host-commands runs none of them, --auto-approve answers yes once, and sbx settings set env.rememberHostCommands true asks again only when a command changes.

The state record and the second plan

sbx records what you approved for each environment in its state directory, not next to the file {{help-sbx sbx env}}. A later invocation asks only about what changed {{help-sbx sbx env}}. The exact path was not captured, because the kit ran plan and never create. The second capture changed one input instead:

the same file with one argument changedtextFull source
$ sbx env plan --env-arg greeting=servus ./fixtures/env
…
+    GREETING: servus
…
   Plan: + 5 to add, ~ 0 to change, - 0 to destroy.
Only the changed row and the totals are shown.
Original source
title: the same file with one argument changed
source: capture/out/14-env-plan-arg.txt
lang: text
note: Only the changed row and the totals are shown.
---
$ sbx env plan --env-arg greeting=servus ./fixtures/env
…
+    GREETING: servus
…
   Plan: + 5 to add, ~ 0 to change, - 0 to destroy.

Every row is still +, because nothing was applied. After a create, the same edit prints ~ GREETING: hello -> servus and nothing else, in the form the help text shows for a changed kit argument {{help-sbx sbx env}}. Changes to workspaces, kits, ports, secrets, bindings, and sandboxOptions wait for the next create. New env values reach the next session {{docs-sbx Update an environment}}.

Several PATH arguments deep-merge in order, and a later file wins over an earlier one {{help-sbx sbx env create}}, and lists such as ports concatenate rather than override. With no PATH, a .sbxenv.yaml in your home directory merges underneath as a base layer {{help-sbx sbx env create}}. A hidden .sbxenv.yaml in the project is no longer read.

rm, the read-only file, and --cloud

sbx env rm removes the sandbox and the secrets provisioned at its scope. Bindings stay, because they belong to the user. To remove the bindings that this environment declares too, pass --prune-bindings {{help-sbx sbx env rm}}. The file itself is bound read-only inside the sandbox, because an agent that can edit it decides what the next plan asks about. sandboxOptions.writableEnvFiles: true lifts that {{help-sbx sbx env}}.

With --cloud, workspace, additionalWorkspaces, and clone are refused, because they name host directories that a cloud sandbox cannot mount {{help-sbx sbx env}}. Also, host port bindings, MCP definitions, and dynamic secret sources are rejected before any host command runs. The cloud section shows what remains.

Original source
- Expect `sbxenv.yaml` to be read-only inside the sandbox, and set `writableEnvFiles` only when an agent must edit it.
- Run `sbx env plan` before `create` or `run`, and read every `+`, `~`, `-`, `>`, and `!`.
- Expect a prompt on every invocation while the file declares host commands.
- Recreate the environment after a change to kits, ports, secrets, or `sandboxOptions`.

Sources: help-sbx sbx env, sbx env create, sbx env plan, sbx env rm (research/sources/help-sbx.md); docs-sbx Sandbox environment files (research/sources/docs-sandboxes.md); rel-sbx v0.42.0 (research/sources/sbx-releases.md); capture/fixtures/env/sbxenv.yaml; capture/out/14-env-plan.txt, 14-env-plan-arg.txt

Code et livrables 1
Ce que vous en retenez

Enregistré dans votre carnet sur cet appareil.

Sources et limites

Les repères de lecture sont déclaratifs. Les résultats de tests sont enregistrés séparément ; ils valent pour les cas exécutés.

AI Engineering from Scratch · 3f9715c · MIT

Télécharger ce fichier ↓