Skip to content

Commit b2bd1d6

Browse files
dvdksnclaude
andcommitted
docs: add shell environment customization to kit examples
Show how to source a tool's init script as part of a kit so its command lands on PATH in every shell, using nvm as a worked example. nvm installs cleanly in a default sandbox (reachable egress, no extra packages), so the snippet works as copy-pasted. Append to /etc/sandbox-persistent.sh — the sandbox's established persistent environment file, sourced for both interactive and non-interactive shells — to match the convention documented in the FAQ for custom environment variables, and cross-link it. Also document install-command gotchas that apply to any download-based kit: deny-by-default egress can silently block downloads, curl | bash masks those failures (exits 0), install steps run under sh not bash, and some tools need base packages such as zip/unzip. Add nvm to the Vale vocabulary. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6e99480 commit b2bd1d6

2 files changed

Lines changed: 86 additions & 1 deletion

File tree

_vale/config/vocabularies/Docker/accept.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ Netplan
173173
NFSv\d
174174
Nginx
175175
npm
176+
nvm
176177
Nutanix
177178
Nuxeo
178179
NVIDIA

content/manuals/ai/sandboxes/customize/kit-examples.md

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Kit examples
33
linkTitle: Examples
4-
description: Copy-and-adapt spec.yaml snippets for common mixin and agent kit patterns — static files, install commands, background services, initFiles, Claude Code skills, and agent forks.
4+
description: Copy-and-adapt spec.yaml snippets for common mixin and agent kit patterns — static files, install commands, shell customization, background services, initFiles, Claude Code skills, and agent forks.
55
keywords: sandboxes, sbx, kits, mixins, examples, patterns, skills
66
weight: 25
77
---
@@ -72,6 +72,90 @@ step should run as the agent user — for example, `npm install -g`
7272
against a user-scoped prefix, or anything that writes to
7373
`/home/agent/`.
7474

75+
Install steps run under `sh`, not bash, so bash-only builtins such as
76+
`source` fail with `sh: source: not found`. Pipe explicitly to `bash`
77+
(`curl … | bash`) or wrap the step in `bash -c '…'` when you need them.
78+
79+
Downloads are subject to the sandbox's
80+
[deny-by-default network policy](../governance/local.md). A domain that
81+
resolves from your host can still be blocked inside the sandbox — for
82+
example, `get.sdkman.io` returns a 403 until you allow it with
83+
`sbx policy allow network get.sdkman.io`. A tool may also need base
84+
packages that aren't in the image: [SDKMAN!](https://sdkman.io/), for
85+
instance, needs `zip` and `unzip`, so add an
86+
`apt-get install -y zip unzip` step (as root) before installing it.
87+
88+
> [!WARNING]
89+
> `curl … | bash` masks download failures. The pipe's exit status is
90+
> bash's, and bash exits `0` on empty input, so a blocked or failed
91+
> download still reports success — the sandbox is created with no error
92+
> even though nothing was installed. Download first, then run, so a
93+
> failed fetch fails the step:
94+
>
95+
> ```yaml
96+
> commands:
97+
> install:
98+
> - command: "curl -fsSL https://example.com/install.sh -o /tmp/install.sh && bash /tmp/install.sh"
99+
> user: "1000"
100+
> ```
101+
102+
## Customize the shell environment
103+
104+
Some tools install into a versioned directory and expect you to source
105+
an init script from your shell profile so their commands land on `PATH`.
106+
Version managers like [nvm](https://github.com/nvm-sh/nvm) and
107+
[SDKMAN!](https://sdkman.io/) follow this pattern. To make the tool
108+
available in every shell, append the source line to
109+
`/etc/sandbox-persistent.sh` in an install command.
110+
111+
`/etc/sandbox-persistent.sh` is the sandbox's persistent environment
112+
file. It's sourced before every bash invocation — interactive shells and
113+
non-interactive ones, including agents started with `sbx run` and
114+
commands run with `sbx exec`. Appending here makes the tool available to
115+
the agent regardless of how its shell is launched. The same file is where
116+
you'd set a custom environment variable; see the
117+
[FAQ](../faq.md#how-do-i-set-custom-environment-variables-inside-a-sandbox).
118+
119+
```yaml {title="nvm/spec.yaml"}
120+
schemaVersion: "1"
121+
kind: mixin
122+
name: nvm
123+
displayName: nvm
124+
description: Node version manager available in every shell
125+
126+
commands:
127+
install:
128+
- command: "curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash"
129+
user: "1000"
130+
description: Install nvm
131+
- command: |
132+
cat >> /etc/sandbox-persistent.sh <<'EOF'
133+
export NVM_DIR="$HOME/.nvm"
134+
unset NPM_CONFIG_PREFIX
135+
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
136+
EOF
137+
description: Source nvm for every shell
138+
```
139+
140+
The install step runs as `user: "1000"` so the tool lands under
141+
`/home/agent/`. The append step runs as root (the default), since
142+
`/etc/sandbox-persistent.sh` is a system file. The `$HOME` in the
143+
appended lines resolves per user at source time, so the agent user finds
144+
its own install. Append to the file rather than overwriting it — the
145+
sandbox relies on its existing contents.
146+
147+
The base image ships its own Node and sets `NPM_CONFIG_PREFIX`, which
148+
nvm won't activate alongside. `unset NPM_CONFIG_PREFIX` before sourcing
149+
`nvm.sh` clears that conflict. Sourcing makes the `nvm` command
150+
available; it doesn't put a Node version on `PATH`. Run
151+
`nvm install --lts` to add one — wrap it in `bash -c '…'` if you script
152+
it as an install step, since install steps run under `sh`.
153+
154+
Append only the init script, not the tool's tab-completion script.
155+
Because `/etc/sandbox-persistent.sh` is sourced before every command,
156+
completion scripts — which rely on variables that exist only during
157+
completion — can break non-interactive shells that agents rely on.
158+
75159
## Install an internal CA certificate
76160

77161
If your organization uses a proxy that inspects HTTPS traffic, install

0 commit comments

Comments
 (0)