On Runtime, a preview that nobody is using costs nothing but storage. With
idlePauseSeconds, the sandbox pauses when visits stop. It keeps its files,
memory and the running server. The next visit wakes it, behind a short "Waking up" page. While it runs,
a 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while it waits on requests, because
Runtime bills the CPU the app uses.
The short answer
Write the agent's files, start the server with spawn, and share the port:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.create({ idlePauseSeconds: 900, labels: { project: "p-123" } });await sbx.files.write( "/workspace/app/index.html", "<!doctype html><h1>Built by the agent</h1>", // what the agent wrote);await sbx.spawn("python3 -m http.server 3000", { cwd: "/workspace/app" });const preview = await sbx.previews.create(3000);console.log(preview.urlWithToken); // a link that carries its token, for the userPythonfrom withruntime import Sandboxsbx = Sandbox.create(idle_pause_seconds=900, labels={"project": "p-123"})sbx.files.write("/workspace/app/index.html", "<!doctype html><h1>Built by the agent</h1>")sbx.spawn("python3 -m http.server 3000", cwd="/workspace/app")preview = sbx.previews.create(3000)print(preview["urlWithToken"]) # a link that carries its token, for the userFor a real project, replace the server with the project's own dev server, such
as npm run dev -- --port 3000. A process started with spawn keeps running
after your call returns. A process started with exec ends when its command
ends.
Private or public
| Visibility | Who can open it | Use it for |
|---|---|---|
| Private (default) | A request with the x-runtime-preview-token header, or the urlWithToken link |
The user watching the agent build |
| Public | Anyone with the address (paid sandboxes) | A shareable demo link |
| Custom domain | Anyone, at your own hostname, proved by a DNS TXT record (paid accounts) | Publishing the finished app |
On a paid sandbox, make a preview public with
previews.create(3000, { visibility: "public" }). A sandbox without credit keeps
its previews private. previews.rotate(port) rejects every token issued so far,
and previews.delete(port) stops sharing. WebSockets work, and dev servers use
them for live reload. Preview addresses are under runtimehost.com, never under
Runtime's own site. So an agent's app never shares an origin with your account
(security).
Start every project with the template running
Installing a framework's dependencies takes the longest part of a new project. Do it once in a template sandbox. Keep it as a snapshot, and start each new project from the snapshot. A snapshot keeps running processes, so the dev server is already up when the copy starts:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();// Once: install the template and start its dev server.const template = await runtime.sandboxes.create({ diskMiB: 8192 });await template.files.upload("./template", "/workspace/app");await template.exec("cd app && npm ci", { check: true, timeoutMs: 600_000 });await template.spawn("cd app && npm run dev -- --port 3000");const snapshot = await template.snapshot({ name: "web-template", retentionDays: 30 });await template.stop();// Each new project: a copy, a preview, and the agent at work.const project = await runtime.sandboxes.create({ snapshot: snapshot.id });await project.update({ idlePauseSeconds: 900 });const preview = await project.previews.create(3000);console.log(preview.urlWithToken);Pythonfrom withruntime import Runtimeruntime = Runtime()template = runtime.sandboxes.create(disk_mib=8192)template.files.upload("./template", "/workspace/app")template.exec("cd app && npm ci", check=True, timeout_ms=600_000)template.spawn("cd app && npm run dev -- --port 3000")snapshot = template.snapshot(name="web-template", retention_days=30)template.stop()project = runtime.sandboxes.create(snapshot=snapshot["id"])project.update(idle_pause_seconds=900)preview = project.previews.create(3000)print(preview["urlWithToken"])To show the user two versions side by side, fork the project into copies. Let
the agent change each copy, and share a preview of each one.
Find the user's project again
Name each project's sandbox. getOrCreate returns the same sandbox tomorrow,
woken if it paused:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.getOrCreate("project-p-123", { idlePauseSeconds: 900 });console.log(sbx.info.reused, sbx.id);What an app-preview product needs
| Need | How Runtime covers it |
|---|---|
| An HTTPS address per app | previews.create(port), private with a token by default |
| Live reload | WebSockets pass through the preview |
| Apps nobody is looking at | idlePauseSeconds pauses; a visit wakes it with a "Waking up" page |
| Fast new projects | Create from a snapshot with the dev server already running |
| An agent's code kept away from yours | A Firecracker microVM with its own kernel per project |
| Packages the agent installs | Any public host on any port on paid accounts; ports 80 and 443 without credit |
| Publishing | Custom domains, up to 50, included on paid accounts (networking) |
| Many users at the same time | 100 sandboxes at the same time on a paid account |
What it costs
Take 200 projects a month. Each keeps a 2 vCPU, 4 GiB sandbox running for 3 hours in all, while its user works. It uses 0.1 of a vCPU on average. It is paused the other 717 hours of a 30-day month, with 1 GB of its own disk and memory stored:
- CPU
- 200 × 3 h × 0.1 vCPU × $0.025
- $1.50
- Memory
- 200 × 3 h × 4 GiB × $0.0075
- $18.00
- Paused
- 200 × 1 GB × $0.08 × 717 h / 720 h
- $15.93
- Total
- $35.43
That is about 18 cents a project a month. Runtime charges $0.025 per vCPU-hour of measured CPU, $0.0075 per GiB-hour of memory while running, and $0.08 per GB per 30-day month while paused (pricing). The snapshot is billed as storage at the same $0.08 rate. Every new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card.
Start
Terminalnpx withruntime sandboxes run --keep -- python3 --versionThe first run prints a link to approve in your browser. From the CLI,
runtime sandboxes preview <id> 3000 --public shares a port (CLI).
Related: coding agent sandbox, per-user dev environments, sandbox snapshots, pause and resume a sandbox.
Facts on this page were checked on 26 October 2026.