Custom sandboxes
Give the agents the toolchain your repository needs, at the size it needs, before a mission starts.
Overview
Every agent runs in a sandbox: an isolated container with Node, pnpm, git and the agent CLIs already installed. A repository that also needs Python, a JDK, Go, a system library or a private package registry gets a custom sandbox: steps that run on top of that platform base, built once and reused by every mission.
A build runs your steps, checks them, and keeps a snapshot of the result. Missions start from that snapshot, so the tools are there from the first second and no mission pays for installing them.
You can do everything on this page from the console (Sandboxes), the ship CLI, the API and the MCP server.
Define a sandbox
A sandbox is a short Dockerfile without a FROM line: the platform base is always the starting point.
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update \
&& apt-get install -y --no-install-recommends python3 python3-venv python3-pip \
&& rm -rf /var/lib/apt/lists/*
RUN python3 -m venv /opt/uv && /opt/uv/bin/pip install uv==0.8.22 \
&& ln -sf /opt/uv/bin/uv /usr/local/bin/uv
ENV UV_LINK_MODE=copyRUN, ENV, ARG and WORKDIR are supported; LABEL and EXPOSE are accepted and ignored. A sandbox has no build context, so COPY and ADD are refused: fetch files in a RUN step instead. Agents run as root, so USER is refused too. Every refusal names the line and the reason.
The platform manages Node, pnpm, git and the agent CLIs. A build that installs, upgrades or shadows one of them fails and names it, because the agents depend on the exact versions the platform ships.
Start from a starter (Python, Java, Go, Rust, Ruby) and edit it, or bring your own definition:
ship sandbox starters
ship sandbox create --name python-uv --starter python --wait
ship sandbox create --name ml --file ml.Dockerfile --size 2x8192x16000 --waitIn the console, the same is Sandboxes → New sandbox.
Builds
Saving a change builds it straight away. A build goes through four phases, and its log streams while it runs:
| Phase | What happens |
|---|---|
| Validate | The definition and size are checked |
| Run steps | Your steps run on the platform base |
| Snapshot | The result is snapshotted |
| Warm start | A sandbox starts from the snapshot once, so the first mission does not wait for it |
ship sandbox build python-uv --wait # build the active version and stream its log
ship sandbox logs python-uv --follow # follow the latest build--wait and --follow exit with code 7 and the build's own reason when the build fails, so a script can stop on it.
SHIP also rebuilds on its own when the platform base changes, and before a snapshot that has gone unused for 25 days reaches its 30-day retention. A build that failed on your steps is not retried until you change the definition. One that failed on the platform's side is retried after 10 minutes, up to five times.
Versions and rollback
Every saved change to the definition or the size is a new version, which becomes active and is built. A rename is not a new version. A mission that starts while the new version builds waits for the build, and stops with the build's reason if it fails.
ship sandbox update python-uv --file sandbox.Dockerfile --wait
ship sandbox versions python-uv
ship sandbox rollback python-uv --to 2A rollback is instant when that version's snapshot still exists; otherwise the version is rebuilt first. In the console, the sandbox's page lists the versions with their build status, and Use this version switches back to one.
Choose where agents run
The first of these that applies wins:
- a per-mission override:
ship delegate … --sandbox <name>, oragents.<role>.sandboxin the API'sagents-override; agents.<role>.sandboxinship.yml, naming a sandbox by name or id;- a
.ship/sandbox.Dockerfilein your repository; - the project's default sandbox;
- the platform base.
version: 1
agents:
builder:
sandbox: python-uv
qa:
sandbox: python-uv
size: standard-3
deployments:
# ...Set or clear the project default from the CLI, or in the console under the project's settings:
ship sandbox default python-uv --project prj_123
ship sandbox default none --project prj_123ship.yml and .ship/sandbox.Dockerfile are read from your default branch, never from the pull request under review, so a pull request cannot change the sandbox that reviews or tests it.
A .ship/sandbox.Dockerfile is built the first time a mission sees its content. That mission waits for the build, and says so on its timeline. The sandbox it creates is listed with the others but is edited in the repository.
A ship.yml entry that names a sandbox that no longer exists fails that role's dispatch with the name, rather than running somewhere you did not choose. A sandbox cannot be deleted while it is a project's default.
Sizes
A sandbox has a default size, and agents.<role>.size (or --size on ship delegate) changes it per role. Use a tier:
| Tier | vCPU | Memory | Disk |
|---|---|---|---|
standard-1 | 1/2 | 4 GiB | 8 GB |
standard-2 | 1 | 6 GiB | 12 GB |
standard-3 | 2 | 8 GiB | 16 GB |
standard-4 | 4 | 12 GiB | 20 GB |
or a custom shape: { vcpu, memoryMib, diskMb } in ship.yml and the API, <vcpu>x<memoryMib>x<diskMb> on the CLI, with 1 to 4 vCPU, at least 3072 MiB per vCPU, at most 12288 MiB, and 8000 to 20000 MB of disk. Without either, agents get standard-4.
Private registries
Store a token, or a username and password, for each package registry host your builds and agents install from, such as npm.pkg.github.com or a company PyPI mirror. The CLI reads the secret from a file, so it never lands in your shell history:
ship sandbox registry set --host npm.pkg.github.com --token-file gh-packages.txt
ship sandbox registry set --host pypi.acme.io --username ci --password-file pypi.txt
ship sandbox registry list
ship sandbox registry remove npm.pkg.github.comIn the console, the same is Sandboxes → Private registries.
The credential is attached to requests for that host only, as they leave the sandbox, when a sandbox builds and when agents run. It never enters the sandbox, its build log or its snapshot, and it is never shown again after you save it. Git hosts and the model providers' hosts are reserved and cannot be registered.
API and agents
Everything above is available through the API (/v1/sandbox-templates, /v1/sandbox-registries, and defaultSandboxTemplateId on PATCH /v1/projects/{projectId}) and the MCP server (save_sandbox_template, build_sandbox_template, get_sandbox_build_log, activate_sandbox_template_version, save_sandbox_registry and others), so an agent can set up a sandbox and follow its build without the console. The command reference lists every ship sandbox flag.
How is this page?