diff --git a/content/manuals/ai/sandboxes/configuration/environment-files.md b/content/manuals/ai/sandboxes/configuration/environment-files.md index bdeedcbea8..6e22252866 100644 --- a/content/manuals/ai/sandboxes/configuration/environment-files.md +++ b/content/manuals/ai/sandboxes/configuration/environment-files.md @@ -88,22 +88,109 @@ for details. | [`sbx env exec`](/reference/cli/sbx/env/exec/) `[PATH...] -- COMMAND [ARG...]` | Runs a command in an existing environment without running lifecycle commands | | [`sbx env rm`](/reference/cli/sbx/env/rm/) `[PATH...]` | Shows a destroy plan, then removes the sandbox and resources named in the plan | -`PATH` can be a directory or a direct path to an environment file. A directory -always resolves to `sbxenv.yaml`. To use another filename, pass the file path -explicitly. With no path, `sbx` reads `sbxenv.yaml` from the working directory. +To use an environment file, pass its path to `sbx env`. If you pass a +directory, `sbx` looks for `sbxenv.yaml` inside it. If you don't pass a path, +`sbx` looks in the directory you run the command from and loads your +[user defaults](#set-user-defaults), if present. -Pass the same set of paths to each `sbx env` command so they resolve the same -sandbox. +Every `sbx env` subcommand accepts `--name`. This flag sets the sandbox name +for that command, overriding the `name` field in the file or the automatically +generated name: + +```console +$ sbx env create --name web-app-test +$ sbx env exec --name web-app-test -- npm test +$ sbx env rm --name web-app-test +``` + +Use the same file paths for each command. If you set `--name`, use that same +name for every command that manages the sandbox. ### Set user defaults -Create `~/.sbxenv.yaml` to define defaults shared across projects. When you run -an `sbx env` command without a path, `sbx` merges this file beneath the -project's `sbxenv.yaml`. Passing any path skips the user-level file. +Create `~/.sbxenv.yaml` to share settings across your projects. For example, +this file selects Claude as the agent and mounts the directory you run +`sbx env` from: -The user-level file must not set `name` or `workspace`, because those fields -identify a project. Lists such as `ports` and `mcp.servers` concatenate across -the user and project files. +```yaml +schemaVersion: "1" +agent: claude +workspace: ${{ env.projectDir }} +``` + +With this file saved in your home directory, run: + +```console +$ cd /projects/web-app +$ sbx env run +``` + +The sandbox mounts `/projects/web-app` as its workspace. Run the same command +from `/projects/api`, and it mounts `/projects/api` instead. You don't need a +separate `sbxenv.yaml` in either project. + +If the project has a `sbxenv.yaml`, `sbx` combines it with your user defaults. +Project settings override individual default values. Lists such as `ports` +and `mcp.servers` combine entries from both files. If you pass a file or +directory path to the command, `sbx` skips `~/.sbxenv.yaml`. + +In `~/.sbxenv.yaml`, you can set `workspace` to `${{ env.projectDir }}` or a +subdirectory such as `${{ env.projectDir }}/src`. Other workspace paths +aren't accepted in this file. + +The user defaults file cannot set `name`. Set the sandbox name in a project +environment file or with `--name`. + +### Reference directories + +You can use `${{ env.projectDir }}` and `${{ env.fileDir }}` in environment +files to insert absolute directory paths. They refer to directories on the +host. + +#### Project directory + +`${{ env.projectDir }}` is the absolute path to your project directory. +`sbx` chooses this directory from the command you run: + +- `sbx env run`: the directory you run the command from. +- `sbx env run /projects/web-app`: `/projects/web-app`. +- `sbx env run /projects/web-app/custom.yaml`: `/projects/web-app`, the + directory containing the file. + +If you pass several paths, the first one sets the project directory. Every +file loaded by that command uses the same value for `env.projectDir`. + +Use this reference in shared settings that need to point to each project's +files. For example, `workspace: ${{ env.projectDir }}/src` mounts the `src` +directory in whichever project you select. + +#### File directory + +`${{ env.fileDir }}` is the absolute path to the directory containing the +environment file where you write the reference. For example, inside +`/shared/environment.yaml`, its value is `/shared`. + +Use this reference when an environment file needs to locate files stored +alongside it. For example, suppose your setup script is +`/shared/scripts/setup.sh`. Add this [lifecycle command](#lifecycle) to +`/shared/environment.yaml` to run the script from `/shared`: + +```yaml +lifecycle: + initialize: + - command: ./scripts/setup.sh + workdir: ${{ env.fileDir }} +``` + +The command runs from `/shared`, even if you use this environment file with +a project in another directory. + +Relative workspace paths already use the directory containing the environment +file. For example, `workspace: ./src` in `/shared/environment.yaml` mounts +`/shared/src`. + +Both directory references can appear in YAML values, but not in field names +or inside the `args` block. ### Parameterize an environment @@ -170,11 +257,11 @@ command rejects undeclared arguments, missing required values, and values that don't satisfy an argument's `enum` or `pattern`. Values can contain `=`, and values in an argument file are read literally rather than expanded by a shell. -Argument references are the only variable expressions expanded in an -environment file. Shell-style expressions such as `${VAR}` aren't expanded -from the host environment. Other dollar signs remain literal, so a value such -as `$PATH:/opt/bin` is passed unchanged. Use `$${{ env.args.NAME }}` to produce -the literal text `${{ env.args.NAME }}`. Substituted values aren't expanded a +Argument references and the two directory references are the only variable +expressions expanded in an environment file. Shell-style expressions such as +`${VAR}` aren't expanded from the host environment. Other dollar signs remain +literal, so a value such as `$PATH:/opt/bin` is passed unchanged. +Use `$${{ env.args.NAME }}` to produce the literal text `${{ env.args.NAME }}`. Substituted values aren't expanded a second time. ## Common workflows @@ -221,8 +308,8 @@ $ sbx env run base.sbxenv.yaml local.sbxenv.yaml Nested mappings merge by key, lists concatenate, and values from later files replace earlier scalar values. In this example, the sandbox has four CPUs, -12 GB of memory, and both environment variables. The first file controls the -base directory for relative workspace paths and the default sandbox name. +12 GB of memory, and both environment variables. Each relative workspace path +resolves from the directory of the file that declares it. ### Work across multiple repositories @@ -245,9 +332,9 @@ additionalWorkspaces: The agent starts in `web-app`, can modify `shared-components`, and can read `architecture-docs` without changing it. The environment file stays outside all -three workspaces. Relative paths resolve from the directory of the first -environment file. Additional workspaces are mounted directly even when the -primary workspace uses clone mode. +three workspaces. Relative paths resolve from the directory of the +environment file that declares them. Additional workspaces are mounted directly +even when the primary workspace uses clone mode. ### Reuse an environment in automation @@ -342,7 +429,7 @@ The loader rejects unknown fields and unsupported schema versions. | Field | Type | Required | Default | Description | | ---------------------- | ---------------- | -------- | ------------------------------ | ------------------------------------------------------------------------------- | | `schemaVersion` | string | Yes | None | Schema version. The supported value is `"1"` | -| `name` | string | No | `-` | Sandbox name | +| `name` | string | No | `-` | Sandbox name, overridden by `--name` | | `agent` | string | Yes | None | Built-in agent or the name of an agent kit | | `args` | map | No | None | Environment arguments. See [`args`](#args) | | `kits` | list | No | None | Kits to install at creation. See [`kits`](#kits) | @@ -414,16 +501,16 @@ parameter and OCI kits with an immutable tag or digest. When specified as a string, `workspace` is the path. Use the object form for clone mode. Omit `workspace` to create a sandbox without a host bind mount. Set -`workspace: .` to mount the directory that contains the first environment -file. If `workspace` is present, its path can't be empty or contain only -whitespace. +`workspace: .` to mount the directory that contains the environment file +that declares it. If `workspace` is present, its path can't be empty or contain +only whitespace. `sbx` mounts the environment file read-only inside the sandbox. Keep the file outside direct-mounted workspaces or directly in a workspace root. | Field | Type | Required | Default | Description | | ------- | ------- | -------- | ------- | --------------------------------------------------------------- | -| `path` | string | Yes | None | Workspace directory. Relative paths resolve from the first file | +| `path` | string | Yes | None | Workspace directory. Relative paths resolve from the declaring file's directory | | `clone` | boolean | No | `false` | Use a private clone, equivalent to `sbx create --clone` | You can override `workspace.clone` for one `create` or `run` invocation with @@ -432,7 +519,7 @@ You can override `workspace.clone` for one `create` or `run` invocation with ### `additionalWorkspaces` Each additional workspace is mounted after the primary workspace. Relative -paths resolve from the directory of the first environment file. +paths resolve from the directory of the environment file that declares them. | Field | Type | Required | Default | Description | | ---------- | ------- | -------- | ------- | ----------------------------- |