# Sandbox images

> Start a sandbox from Kuiper's ready-made images for documents, coding, coding agents, video and data by name, without building, publishing or allowlisting an image.

Web page: https://kuiper.sh/docs/sandbox-images/

## Images you can start by name

Kuiper keeps a catalog of ready-made sandbox images. A unit that declares `capabilities.sandbox` starts one as `kuiper/<name>`, with no image to build or publish and no allowlist entry:

```sh
docker run -d --network none kuiper/coding
```

| Name | Builds on | What it adds |
| --- | --- | --- |
| `kuiper/base` | Debian 12 | git, curl, jq, ripgrep, unzip and zip, procps, less, openssh-client, tini, Python 3.11 with venv and uv, Node.js 22 with npm and corepack |
| `kuiper/documents` | `base` | LibreOffice (headless), pandoc, poppler-utils, qpdf, fonts with CJK and emoji, python-docx, python-pptx, openpyxl, pypdf, pdfplumber, reportlab, the `docx` and `pptxgenjs` Node libraries, and Playwright with headless Chromium for HTML to PDF |
| `kuiper/coding` | `base` | Build tools, cmake, sqlite3, Go, Rust with rustup, the GitHub CLI, and pnpm and Yarn |
| `kuiper/coding-agents` | `coding` | OpenCode, the OpenAI Codex CLI with codex-acp, the Gemini CLI, and an installer for Claude Code |
| `kuiper/video` | `base` | ffmpeg, ImageMagick, sox, fonts, Pillow, NumPy, OpenCV and MoviePy |
| `kuiper/data` | `base` | NumPy, pandas, SciPy, Matplotlib, DuckDB, PyArrow and Polars |
| `kuiper/full` | `coding-agents` | Everything above |

Every image runs as the user `sandbox` (uid 1000) in `/workspace`, and its default command is `sleep infinity`, so a sandbox started without a command stays up for `docker exec`. `pip install` and `npm install -g` work without root. Like every sandbox, it runs under gVisor within your unit's limits: the catalog only picks the image.

In the dashboard, the **Images** tab of the project's **Sandboxes** page lists them with their contents and a snippet to copy for each way of starting one. From the CLI:

```sh
kuiper sandbox images
kuiper sandbox images --json
```

## Declare the ones you use

The images are large, so a node only has the ones its units ask for. List them in `kuiper.json` and the unit's node pulls them ahead of time:

```json
"capabilities": {
  "sandbox": { "maxConcurrent": 4, "images": ["documents", "coding-agents"] }
}
```

An image you don't declare still works, but is pulled the first time a sandbox needs it. Station never pulls an image itself, so declare the ones a Station daemon uses. A name this Kuiper's catalog doesn't have doesn't stop a deploy; the project's **Activity** says which names are missing.

## Start one

From Station, set the sandbox adapter's image to the name:

```ts
new ContainerSandboxAdapter({ image: "kuiper/coding", rootDir: "/data/workspaces", network: "none" });
```

From your own code, use the unit's Docker socket as you would any Docker:

```sh
docker run -d --name work --network bridge kuiper/coding-agents
docker exec -i -e OPENAI_API_KEY work codex-acp
```

The runtime API takes the same name: `CreateChild` with `capability` `sandbox` and `image` `kuiper/data`. A name the catalog doesn't have is refused with the list of names it has.

## Versions

`kuiper/coding` is the current version, and `kuiper/coding:1.0.0` holds one version. When the operator publishes a new version, a sandbox that asks for the old one is refused with a message naming the current one, so nothing changes under you without you knowing. Each image is pinned by digest, so every node runs the same bytes.

## Claude Code and the other coding agents

`kuiper/coding-agents` and `kuiper/full` include OpenCode (MIT), the OpenAI Codex CLI and codex-acp (Apache-2.0) and the Gemini CLI (Apache-2.0), whose licences allow Kuiper to redistribute them.

Claude Code is proprietary software from Anthropic, so Kuiper doesn't put it in an image. The image has an installer that downloads it into the sandbox user's home the first time you need it, once you accept Anthropic's terms yourself:

```sh
kuiper-install-agent claude-code --accept-terms
```

The sandbox needs network access for that (`--network bridge`). The same command installs a newer release of the other agents for one sandbox, such as `kuiper-install-agent codex 0.160.0`. Pass each agent its API key for that one process with `docker exec -e`, not in the container's environment.

> **Document skills**
>
> `kuiper/documents` has the tools that Anthropic's document skills use, but not the skills themselves, which are source-available rather than open source. Add them to your own image if you accept their terms.

## Your own image

Images of your own work as before, once the operator allowlists them. To add a few tools, build on a catalog image, `FROM ghcr.io/porkytheblack/kuiper-sandbox-coding:1.0.0`, publish it and ask for it to be allowlisted. Names under `kuiper/` always mean the catalog, never Docker Hub's `kuiper` organisation.

[Station units](https://kuiper.sh/docs/station.md) covers the Docker socket and what it allows.
