Templates#

A template is a reusable starting point for new sandboxes. Every template is stored as a RAM snapshot of a booted VM, so a sandbox created from it starts from a ready system instead of booting (target p95 < 500 ms).

Official templates#

Template Contents
base Ubuntu 24.04, systemd, Docker, Python 3.12, common build tools; user user with passwordless sudo
python, node, browser, coding-agent, jupyter language runtimes, a headless browser, coding-agent tools or JupyterLab, ready in one call; see the Template gallery
desktop base + XFCE, KasmVNC, Chromium, Firefox, xdotool and fonts; desktop is already running. Needs size default or larger

template defaults to base when you create a sandbox without a source.

Your own templates#

Create a template from either an OCI/Docker image or a snapshot.

From an OCI image#

We pull the image (linux/amd64), turn it into a VM root filesystem and add our guest agent. If the image has systemd, the agent and start_command run as systemd services; if it doesn't, a small init (taskcloud-init) starts the agent and your start_command (or the image's ENTRYPOINT/CMD). We then boot it, wait for ready_check to exit 0, and take a RAM snapshot. The call returns 202 with state building.

const tpl = await client.templates.create({
  name: "agent-env",
  image: { ref: "ghcr.io/acme/agent-env:1.4", registry_auth: { username: "acme-bot", password: process.env.GHCR_TOKEN! } },
  start_command: "/usr/local/bin/warmup.sh",
  ready_check: { command: "curl -sf localhost:8080/health", timeout_seconds: 120 },
  size: "default",
});
tpl = client.templates.create(
    name="agent-env",
    image={"ref": "ghcr.io/acme/agent-env:1.4",
           "registry_auth": {"username": "acme-bot", "password": os.environ["GHCR_TOKEN"]}},
    start_command="/usr/local/bin/warmup.sh",
    ready_check={"command": "curl -sf localhost:8080/health", "timeout_seconds": 120},
    size="default",
)
curl -sS -X POST https://api.task.cloud/v1/templates \
  -H "Authorization: Bearer $TASKCLOUD_API_KEY" -H "Content-Type: application/json" \
  -d '{"name":"agent-env","image":{"ref":"ghcr.io/acme/agent-env:1.4"},"size":"default"}'

taskcloud template create --name agent-env --image ghcr.io/acme/agent-env:1.4
taskcloud template logs agent-env --follow

Follow the build with GET /templates/{template_id}/logs (plain text, or SSE with Accept: text/event-stream). The template becomes ready or failed (see error).

Image build options:

Field Notes
image.ref OCI reference, linux/amd64
image.registry_auth username, password (write-only) for private registries
start_command started before the snapshot
ready_check command that must exit 0; timeout_seconds default 300, max 1800
env baked into the template
desktop true adds the XFCE + KasmVNC desktop stack (coming soon for custom images; use the desktop base template today)
size size used for the build snapshot

From a snapshot#

Set up a sandbox by hand or with exec, take a named snapshot, then turn it into a template. It is ready immediately (201) and keeps that exact RAM and disk state.

const snap = await sandbox.snapshots.create({ name: "python-preinstalled" });
await client.templates.create({ name: "python-preinstalled", snapshot_id: snap.id });
taskcloud template create --name python-preinstalled --snapshot snap_3kd7wq2mzn5x

Versions#

Creating a template with an existing name adds a new version. template: "agent-env" uses the latest ready version; pin one with template: "agent-env:3". Deleting a template does not affect sandboxes already created from it.

const sbx = await client.sandboxes.create({ template: "agent-env:3" });

Templates vs. images vs. snapshots#

  • Use an image directly (POST /sandboxes with image) for one-offs. Each create converts and boots the image, so it is slower than a template.
  • Use a template for anything you start often.
  • Use a snapshot to continue from one specific sandbox's state. See Snapshots and fork.

Template storage is billed like snapshot storage. See Billing.