# TaskCloud documentation (full text) > All pages of https://task.cloud/docs/ concatenated in navigation order, for LLMs and agents. > Generated by website/tools/build_docs.py from website/docs/**/*.md. Short index: https://task.cloud/docs/llms.txt --- # TaskCloud documentation `TaskCloud` gives every AI agent its own persistent cloud computer. You pay only while it works. > **Status:** private beta (waitlist). APIs may still change before general availability. Latency figures on these pages are **targets**, not guarantees. ## What a sandbox is Each sandbox is a full **Firecracker microVM**, not a container: - Its own Linux kernel, **Ubuntu 24.04**, root access, **systemd** and **Docker** inside. - A **persistent disk** (50 GB included for the `default` size). - Isolation per VM: Firecracker jailer, cgroups, and a separate network namespace. - Runs in the **EU** on dedicated AMD Ryzen servers. ## What you can do with it | Capability | Summary | Page | | --- | --- | --- | | Pause and resume | RAM and disk are snapshotted together. Processes, open windows and sessions survive. Resume target: p95 < 800 ms. | [Lifecycle](https://task.cloud/docs/concepts/lifecycle.md) | | Auto-pause and wake on request | Pauses after N minutes idle (default 5). An HTTP request, SSH connection or API call wakes it. Paused = $0 compute. | [Lifecycle](https://task.cloud/docs/concepts/lifecycle.md) | | Fork | Copy a running VM **including memory**. Target: < 2 s. | [Snapshots and fork](https://task.cloud/docs/concepts/snapshots-and-fork.md) | | Exec | Sync, background, SSE streaming, interactive PTY over WebSocket. 10+ concurrent commands per VM. | [Exec and files](https://task.cloud/docs/guides/exec-and-files.md) | | Files | Read, write, list, upload, download, watch. | [Exec and files](https://task.cloud/docs/guides/exec-and-files.md) | | Networking | Public HTTPS URL per port (`https://-.taskhost.cloud`), SSH through a gateway. | [Networking](https://task.cloud/docs/guides/networking.md) | | Desktop | Browser desktop streaming (KasmVNC, 1920x1080), signed links with TTL and read-only mode, screenshot + input API for computer use. | [Desktop and computer use](https://task.cloud/docs/guides/desktop-and-computer-use.md) | | Templates | Start from a snapshot or your own OCI/Docker image. | [Templates](https://task.cloud/docs/concepts/templates.md) | | Account | Scoped API keys, spend limits, signed webhooks, usage API. | [Security](https://task.cloud/docs/security.md), [Webhooks](https://task.cloud/docs/guides/webhooks.md), [Billing](https://task.cloud/docs/billing.md) | | Tooling | TypeScript and Python SDKs (typed by hand from the OpenAPI spec), CLI, MCP server, `llms.txt`. | [SDKs](https://task.cloud/docs/sdk/typescript.md), [CLI](https://task.cloud/docs/cli.md), [MCP](https://task.cloud/docs/mcp.md) | ## Start here 1. [Quickstart](https://task.cloud/docs/quickstart.md): first sandbox and first command in TypeScript, Python, CLI or curl. 2. [Sandboxes](https://task.cloud/docs/concepts/sandboxes.md) and [Lifecycle](https://task.cloud/docs/concepts/lifecycle.md): the mental model. 3. [API reference](https://task.cloud/docs/api-reference.md): every endpoint, plus the [OpenAPI spec](https://api.task.cloud/v1/openapi.yaml). ## All pages **Concepts** - [Sandboxes](https://task.cloud/docs/concepts/sandboxes.md) - [Lifecycle and auto-pause](https://task.cloud/docs/concepts/lifecycle.md) - [Snapshots and fork](https://task.cloud/docs/concepts/snapshots-and-fork.md) - [Templates](https://task.cloud/docs/concepts/templates.md) **Guides** - [Exec and files](https://task.cloud/docs/guides/exec-and-files.md) - [Networking: ports and SSH](https://task.cloud/docs/guides/networking.md) - [Desktop and computer use](https://task.cloud/docs/guides/desktop-and-computer-use.md) - [Webhooks](https://task.cloud/docs/guides/webhooks.md) - [Migrate from E2B](https://task.cloud/docs/guides/migrate-from-e2b.md) - [Migrate from boat.dev](https://task.cloud/docs/guides/migrate-from-boat.md) **Reference** - [API reference](https://task.cloud/docs/api-reference.md) - [TypeScript SDK](https://task.cloud/docs/sdk/typescript.md) - [Python SDK](https://task.cloud/docs/sdk/python.md) - [CLI](https://task.cloud/docs/cli.md) - [MCP server](https://task.cloud/docs/mcp.md) - [Billing and pricing](https://task.cloud/docs/billing.md) - [Limits](https://task.cloud/docs/limits.md) - [Security](https://task.cloud/docs/security.md) - [llms.txt](https://task.cloud/docs/llms.txt) (index for LLM agents) ## Not in the MVP These are on the roadmap and are **not** available today: WebRTC desktop streaming at 60 fps, an AI-key proxy, a `full` VM class with nested KVM, GPUs, an open-source core with self-hosting, regions outside the EU, SSO and audit logs. We do not hold a SOC 2 report. --- # Quickstart Create a sandbox, run a command, expose a port, and pause it. Takes about five minutes. > **Private beta.** You need a beta account. [Join the waitlist](https://task.cloud/#waitlist). The Free plan includes 20 one-time hours of the `default` size, no card required. ## 1. Get an API key Create a key in the dashboard (**Settings → API keys**) or with the CLI after `taskcloud login`: ```bash taskcloud key create --name quickstart --preset full-sandbox ``` Keys look like `taskcloud_sk_...` and are shown once. Export it: ```bash export TASKCLOUD_API_KEY="taskcloud_sk_..." ``` The SDKs and the CLI read `TASKCLOUD_API_KEY` automatically. ## 2. Install ```bash npm install @taskcloud/sdk # TypeScript / JavaScript (Node.js 20+; PTY needs Node.js 22+ or the `ws` package) pip install taskcloud # Python 3.9+ ``` The CLI is built from source during the beta (`go build` in `cli/`, Go 1.27.3+); see [CLI](https://task.cloud/docs/cli.md). The install script (`curl -fsSL https://task.cloud/install.sh | sh`) and prebuilt binaries work once the first CLI release is tagged. ## 3. Create a sandbox and run a command ### TypeScript ```ts import { Client } from "@taskcloud/sdk"; const client = new Client(); // reads TASKCLOUD_API_KEY const sandbox = await client.sandboxes.create({ template: "base", size: "default", name: "quickstart", auto_pause: { enabled: true, idle_timeout_seconds: 300 }, }); console.log(sandbox.id, sandbox.state); // sbx_... running const result = await sandbox.exec({ command: "uname -a && python3 --version" }); console.log(result.exit_code, result.stdout); ``` ### Python ```python from taskcloud import Client client = Client() # reads TASKCLOUD_API_KEY sandbox = client.sandboxes.create( template="base", size="default", name="quickstart", auto_pause={"enabled": True, "idle_timeout_seconds": 300}, ) print(sandbox.id, sandbox.state) result = sandbox.exec(command="uname -a && python3 --version") print(result.exit_code, result.stdout) ``` ### CLI ```bash id=$(taskcloud create --template base --size default --name quickstart --json | jq -r .id) taskcloud exec "$id" -- uname -a ``` ### curl ```bash API=https://api.task.cloud/v1 id=$(curl -sS -X POST "$API/sandboxes" \ -H "Authorization: Bearer $TASKCLOUD_API_KEY" \ -H "Content-Type: application/json" \ -d '{"template":"base","size":"default","name":"quickstart"}' | jq -r .id) curl -sS -X POST "$API/sandboxes/$id/exec" \ -H "Authorization: Bearer $TASKCLOUD_API_KEY" \ -H "Content-Type: application/json" \ -d '{"command":"uname -a && python3 --version"}' # {"command_id":"cmd_...","exit_code":0,"stdout":"Linux ...","stderr":"","duration_ms":41} ``` `POST /sandboxes` waits until the sandbox is `running` (target p95 < 500 ms from a template) and returns `201`. Pass `"wait": false` to get `202` immediately. ## 4. Start a server and open it in the browser ```ts await sandbox.files.write("/home/user/www/index.html", "

Hello from TaskCloud

"); await sandbox.exec({ command: "python3 -m http.server 8080", cwd: "/home/user/www", background: true }); const port = await sandbox.ports.expose({ port: 8080, visibility: "public" }); console.log(port.url); // https://-8080.taskhost.cloud ``` ```python sandbox.files.write("/home/user/www/index.html", "

Hello from TaskCloud

") sandbox.exec(command="python3 -m http.server 8080", cwd="/home/user/www", background=True) port = sandbox.ports.expose(port=8080, visibility="public") print(port.url) ``` ```bash taskcloud exec "$id" --background --cwd /home/user/www -- python3 -m http.server 8080 taskcloud port expose "$id" 8080 --public ``` ## 5. Pause, then wake it with a request ```ts await sandbox.pause(); // RAM + disk snapshot; compute billing stops // ...later: any request wakes it. Opening port.url, an SSH login or an API call all work: const again = await sandbox.exec({ command: "echo still here" }); // resumes transparently ``` ```bash curl -sS -X POST "$API/sandboxes/$id/pause" -H "Authorization: Bearer $TASKCLOUD_API_KEY" short=${id#sbx_} # hostnames use the ID without sbx_ curl -sS "https://$short-8080.taskhost.cloud/" # wakes the sandbox, then serves the page ``` You do not have to pause manually: with the default `auto_pause`, a sandbox with no activity for 5 minutes pauses itself. See [Lifecycle](https://task.cloud/docs/concepts/lifecycle.md). ## 6. Clean up ```ts await sandbox.delete(); ``` ```bash taskcloud delete "$id" --yes ``` ## Next steps - [Exec and files](https://task.cloud/docs/guides/exec-and-files.md): streaming, background jobs, PTY, uploads, file watching. - [Snapshots and fork](https://task.cloud/docs/concepts/snapshots-and-fork.md): clone a running VM with its memory. - [Desktop and computer use](https://task.cloud/docs/guides/desktop-and-computer-use.md): give an agent a screen. - [Webhooks](https://task.cloud/docs/guides/webhooks.md): get notified when sandboxes pause, resume or fail. - [Billing](https://task.cloud/docs/billing.md): what you pay for, per state. --- # Template gallery Official templates give your agent a working environment in one call: the runtime, libraries and tools are already installed, and the sandbox starts from a RAM snapshot of the booted system (target p95 < 500 ms), not from a cold boot. ```python sandbox = client.sandboxes.create(template="python") print(sandbox.exec(command="python -c 'import pandas; print(pandas.__version__)'").stdout) ``` Every official template is built from a declarative recipe with pinned versions and digests, ships with an SBOM, stays within a size budget, and passes an in-sandbox smoke test (`taskcloud-smoke`) before release. > **Private beta.** The gallery is rolling out region by region. `GET /templates?owner=builtin` lists the templates available to your account; `base` and `desktop` are available everywhere. ## Gallery | Template | What's inside | Default size | Ports | Good for | | --- | --- | --- | --- | --- | | `base` | Ubuntu 24.04, systemd, Docker, Python 3.12, git, build-essential | `default` | – | anything; the default | | `python` | Python 3.12 (default venv) and 3.13 via uv; NumPy, pandas, Polars, SciPy, scikit-learn, DuckDB, PyArrow, Matplotlib | `default` | – | data analysis, code interpreters, ML without GPU | | `node` | Node.js 22 LTS, npm, pnpm, Bun, TypeScript | `default` | – | JS/TS agents, web app builders | | `browser` | headless Chromium, Playwright for Python and Node, Noto/CJK/emoji fonts, Xvfb | `default` | – | browser automation, scraping, computer use without a desktop | | `coding-agent` | git, gh, ripgrep, fd, build-essential, Docker in the VM, Node 22, Python 3.12; Codex CLI, Gemini CLI, OpenCode, Aider | `default` | – | coding agents, CI-like tasks, repo work | | `jupyter` | JupyterLab (already running), Python 3.12 data stack | `default` | 8888 | notebooks, data exploration | | `desktop` | `base` + XFCE, KasmVNC, Chromium, Firefox, xdotool | `default` | – | computer use with a visible desktop, see [Desktop and computer use](https://task.cloud/docs/guides/desktop-and-computer-use.md) | All templates run as user `user` (uid 1000) with passwordless `sudo`, have SSH, and keep the full disk persistent across pause and resume. Templates are not tied to a size: pass `size` to override the default (`desktop` needs `default` or `large`). ## Create a sandbox from a template Use the template name, or its ID (`tpl_python`). The same call works for every template. ### TypeScript ```ts import { Client } from "@taskcloud/sdk"; const client = new Client(); const sandbox = await client.sandboxes.create({ template: "python" }); const result = await sandbox.exec({ command: "taskcloud-smoke" }); console.log(result.exit_code, result.stdout); // 0 ... TASKCLOUD_SMOKE_OK python ``` ### Python ```python from taskcloud import Client client = Client() sandbox = client.sandboxes.create(template="python") result = sandbox.exec(command="taskcloud-smoke") print(result.exit_code, result.stdout) # 0 ... TASKCLOUD_SMOKE_OK python ``` ### CLI ```bash id=$(taskcloud create --template python --json | jq -r .id) taskcloud exec "$id" -- taskcloud-smoke taskcloud template ls # the gallery and your own templates ``` ### curl ```bash curl -sS -X POST https://api.task.cloud/v1/sandboxes \ -H "Authorization: Bearer $TASKCLOUD_API_KEY" -H "Content-Type: application/json" \ -d '{"template":"python","name":"analysis-1"}' curl -sS "https://api.task.cloud/v1/templates?owner=builtin" -H "Authorization: Bearer $TASKCLOUD_API_KEY" ``` ### MCP The `create_sandbox` tool of the [MCP server](https://task.cloud/docs/mcp.md) describes the official templates, so an agent can pick one by itself. Tool call: ```json { "name": "create_sandbox", "arguments": { "template": "browser" } } ``` ## Templates ### base Ubuntu 24.04 with systemd, Docker, Python 3.12 (system `python3`), git and build-essential. This is what you get without a `template`. Built with debootstrap rather than from an OCI image. ```ts const sandbox = await client.sandboxes.create({ template: "base" }); await sandbox.exec({ command: "docker run --rm alpine echo hello" }); ``` ### python The default virtualenv `/opt/taskcloud/venv` (Python 3.12.16) is on `PATH` and owned by `user`, so `pip install` and `uv pip install` work without `sudo`. Python 3.13 is installed for `uv`: `uv run --python 3.13 ...`. Matplotlib uses the `Agg` backend (no display). ```python sandbox = client.sandboxes.create(template="python") sandbox.files.write("/home/user/sales.csv", "region,amount\neu,10\nus,32\n") r = sandbox.exec(command="python -c \"import pandas as pd; print(pd.read_csv('sales.csv').amount.sum())\"") print(r.stdout) # 42 ``` ### node Node.js 22 LTS in `/opt/taskcloud/node` (owned by `user`: `npm install -g` works without `sudo`), pnpm, Bun and TypeScript. ```ts const sandbox = await client.sandboxes.create({ template: "node" }); await sandbox.exec({ command: "pnpm create vite@latest app -- --template react-ts && cd app && pnpm install" }); await sandbox.exec({ command: "cd app && pnpm dev --host 0.0.0.0 --port 5173", background: true }); const port = await sandbox.ports.expose({ port: 5173, visibility: "public" }); console.log(port.url); ``` ### browser Headless Chromium from Playwright, shared by the Python and Node bindings (same Playwright version, one browser build in `/ms-playwright`). Fonts cover Latin, CJK and emoji, so screenshots of real pages render correctly. For headed runs use `xvfb-run`; for a visible desktop use `desktop`. ```python sandbox = client.sandboxes.create(template="browser") script = """ from playwright.sync_api import sync_playwright with sync_playwright() as p: page = p.chromium.launch().new_page() page.goto("https://example.com") page.screenshot(path="/home/user/shot.png") print(page.title()) """ sandbox.files.write("/home/user/shot.py", script) print(sandbox.exec(command="python shot.py").stdout) png = sandbox.files.read("/home/user/shot.png") # bytes ``` From Node, `require("playwright")` works out of the box (`NODE_PATH` points at the global modules). In your own project, install the same version (`npm i playwright@1.64.1`) and it reuses the installed browser. ### coding-agent Everything a coding agent needs in a repository: git, the GitHub CLI, ripgrep, fd, build-essential, Docker (the daemon runs inside the VM; `user` is in the `docker` group), Node 22 and Python 3.12. Agent CLIs: open-source ones are preinstalled (Codex CLI, Gemini CLI, OpenCode, Aider). Proprietary CLIs are not redistributed in the image; install them inside the sandbox from the vendor, under the vendor's terms, with `taskcloud-agents install`: ```bash taskcloud-agents list # what is installed, licenses, which env var each CLI reads taskcloud-agents install claude-code # npm install -g @anthropic-ai/claude-code (vendor's official method) ``` No credentials are in the image. Pass API keys as sandbox env when you create the sandbox: ```ts const sandbox = await client.sandboxes.create({ template: "coding-agent", env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY!, GH_TOKEN: process.env.GH_TOKEN! }, }); await sandbox.exec({ command: "gh repo clone acme/app && cd app && codex exec 'fix the failing test'", timeout_seconds: 1800 }); ``` ### jupyter JupyterLab is already running on port 8888 when the sandbox starts. Every sandbox has its own token: pass `JUPYTER_TOKEN` in `env` at create, or read the generated one with `taskcloud-jupyter-token`. A token or login cookie from another sandbox (including a fork) does not work. ```python import secrets token = secrets.token_urlsafe(32) sandbox = client.sandboxes.create( template="jupyter", env={"JUPYTER_TOKEN": token}, ports=[{"port": 8888, "visibility": "public"}], ) print(f"{sandbox.ports.url(8888)}/lab?token={token}") ``` ```ts const sandbox = await client.sandboxes.create({ template: "jupyter", ports: [{ port: 8888, visibility: "public" }] }); const token = (await sandbox.exec({ command: "taskcloud-jupyter-token" })).stdout.trim(); console.log(`${sandbox.ports.url(8888)}/lab?token=${token}`); ``` With `visibility: "private"` (the default) the edge also requires a sandbox access token; see [Networking](https://task.cloud/docs/guides/networking.md). Health check without a token: `curl -fsS http://127.0.0.1:8888/api`. ### desktop `base` plus an XFCE desktop streamed with KasmVNC, Chromium and Firefox. The desktop is already running. See [Desktop and computer use](https://task.cloud/docs/guides/desktop-and-computer-use.md) for screenshots, input and the stream URL. ## Smoke tests Every official template contains `taskcloud-smoke`, the same test we run before each release. It needs no network and no credentials, prints one line per check and ends with `TASKCLOUD_SMOKE_OK