DocsTemplates

Templates

A template is what a sandbox boots from: the operating system, the installed tools, and the size. Impello ships a set of defaults, and you pick one by name when you create a sandbox. This page lists the defaults, what each one holds, and how to reach the CLIs and services inside them.

Choose a template

Pass the name to Sandbox.create. With no name you get base.

import { Sandbox } from '@impello/sdk'

const sandbox = await Sandbox.create('codex')
const result = await sandbox.commands.run('codex --version')

console.log(result.stdout)
await sandbox.kill()

Both SDKs read your key from IMPELLO_API_KEY; see API keys. In TypeScript the name can also go in the options object as template, and in Python as the template keyword argument.

The default templates

Every default ends as the user user with the working directory /home/user, so a command you run lands there. codex, opencode, pi, amp, droid, grok, openclaw, k3s and browser start from base. claude, code-interpreter, desktop and omarchy are built from their own image, so they do not carry base's toolchain. The table lists each default with its size.

NameWhat it holdsvCPUMemory
baseDebian 12 with Python 3.12, Node 22, git, GitHub CLI, jq, ripgrep, curl, unzip, yarn, pnpm and build tools. The default.21 GB
claudeClaude Code on Ubuntu 25.04, with Docker enabled at boot, Node 22, Python 3, pipx and uv. Binary at ~/.local/bin/claude.22 GB
codexbase plus the Codex CLI, installed globally with npm.22 GB
opencodebase plus the OpenCode CLI, installed globally with npm.22 GB
pibase plus the pi coding agent, installed globally with npm.22 GB
ampbase plus the Amp CLI at ~/.local/bin/amp.22 GB
droidbase plus the Droid CLI at ~/.local/bin/droid.22 GB
grokbase plus the Grok CLI at ~/.grok/bin/grok.22 GB
openclawbase plus the OpenClaw CLI at ~/.npm-global/bin/openclaw.24 GB
code-interpreterPython 3.13 with Jupyter kernels for Python, R, JavaScript, Bash and Java. Jupyter starts with the sandbox.22 GB
k3sbase plus single-node Kubernetes (k3s) and kubectl. The cluster starts at boot and KUBECONFIG is set.48 GB
desktopUbuntu 22.04 with XFCE, Firefox, Chrome, VS Code, LibreOffice, x11vnc and noVNC. The GUI stack is installed but no start command is declared, so a sandbox from this template boots to a shell only. There is no supported way to start the desktop; use omarchy for a browser-reachable desktop.48 GB
omarchyArch Linux with the Omarchy shell on a sway session, served over noVNC on port 6080.48 GB
browserbase plus a headful Chromium (fingerprint-chromium 150) with a fingerprint per profile, CDP on port 9222 and noVNC on port 6080. See Browser.24 GB

The CLIs installed with npm (codex, opencode, pi) are on the PATH. The vendor installers put their binary under the home directory at the path shown, and the template appends that directory to ~/.bashrc. commands.run runs your command with bash -l -c. A login shell reads ~/.profile, not the end of ~/.bashrc, so that appended line does not apply — call the binary by its full path.

Aliases

Two templates answer to a second name. claude is also claude-code, and code-interpreter is also code-interpreter-v1. Either name creates the same sandbox.

Run an agent CLI

The base-derived agent templates (codex, opencode, pi, amp, droid, grok, openclaw) are base plus one CLI; claude is its own Ubuntu image with Docker, uv and pipx. In every one, nothing is signed in — pass the vendor's key with envs when you create the sandbox. Those variables are set for every command you run, and envs on a single command overrides them. The example runs one prompt through Claude Code.

import { Sandbox } from '@impello/sdk'

const key = process.env.ANTHROPIC_API_KEY
if (!key) throw new Error('Set ANTHROPIC_API_KEY')

const sandbox = await Sandbox.create('claude', {
  envs: { ANTHROPIC_API_KEY: key },
  timeoutMs: 600_000,
})

const result = await sandbox.commands.run(
  '~/.local/bin/claude -p "List the files in this directory"',
  { timeoutMs: 300_000 }
)

console.log(result.stdout)
await sandbox.kill()

The pattern is the same for all of them: create by name, pass the vendor's key in envs, run the binary. -p is Claude Code's print mode, which runs one prompt and writes the answer to stdout; each vendor's CLI has its own flags, so check the vendor's documentation. A command gives up after 60 seconds unless you raise timeoutMs (timeout, in seconds, in Python); see Run commands.

Reach a service in a template

Three templates declare a start command and wait for it before the sandbox is ready: omarchy (noVNC on 6080), browser (CDP on 9222 and noVNC on 6080; see Browser) and code-interpreter (an HTTP server on 49999). k3s starts its cluster from a systemd unit instead, shortly after boot. getHost(port) returns the host for a port; you supply the scheme and the path.

The omarchy desktop is served at the path /vnc.html on port 6080. The example prints its URL and leaves the sandbox running for 30 minutes so you can open it.

import { Sandbox } from '@impello/sdk'

const sandbox = await Sandbox.create('omarchy', {
  timeoutMs: 1_800_000,
})

console.log(`https://${sandbox.getHost(6080)}/vnc.html`)

code-interpreter starts Jupyter with the sandbox and an HTTP server on port 49999 whose health check is /health. Neither SDK ships a client for that server, so run code in this template with commands.run, for example python3 -c "print(1 + 1)".

Sizes

Each template declares the vCPU count and memory it is built with, listed in the table above. Your plan sets the largest sandbox you can run: the free trial's ceiling is 4 vCPU and 8 GB per sandbox, and every paid plan's is 8 vCPU and 16 GB. Every default template fits inside all of them, the trial included: k3s, desktop and omarchy are the largest, at 4 vCPU and 8 GB. See Limits and pricing.

Updates

The defaults are rebuilt every week. The agent CLIs are installed unpinned, so each rebuild picks up the vendor's current release and the version inside a fresh sandbox moves with it. To freeze a version, build your own template from a default with fromTemplate('claude') and create sandboxes from that name instead.

Check that a name exists

Template.exists returns true when a name is taken, including a default template and a name another team owns. It lives in the @impello/sdk/template subpath and is TypeScript only; the Python SDK has no template module.

import { Template } from '@impello/sdk/template'

const exists = await Template.exists('my-app')

console.log(exists)

Build your own

When no default fits, start from one of them or from any Docker image and add what you need. The builder is TypeScript only, but the template it produces can be used from either SDK by name.

Next: Build a custom template.