On Runtime, a name is a handle you can use from any process, on any day,
with no id to store. The name stays yours while the sandbox can still run,
including while it is paused. So getOrCreate gives an agent or a user the
same machine, files and memory each time. Between uses, it costs
$0.08 per decimal GB of saved state each month
(pricing, checked 26 October 2026).
Get it, or make it
TypeScriptimport { Sandbox } from "withruntime";const dev = await Sandbox.getOrCreate("dev", { idlePauseSeconds: 900, diskMiB: 8192 });console.log(dev.id, dev.info.reused ? "found it" : "made a new one");await dev.exec("git -C /workspace/app pull || true");// The next process, or tomorrow, gets the same sandbox and its files.Pythonfrom withruntime import Sandboxdev = Sandbox.get_or_create("dev", idle_pause_seconds=900, disk_mib=8192)print(dev.id, "found it" if dev.info.get("reused") else "made a new one")dev.exec("git -C /workspace/app pull || true")Terminalid=$(runtime sandboxes create --name dev --get-or-create --idle-pause 900)runtime sandboxes exec dev -- git -C /workspace/app pull # the name works as the idThe options you pass apply only when the call creates a sandbox. A sandbox that already has the name returns as it is. It is woken if paused, and restarted if it was stopped and is persistent.
Look one up without creating
List with a name filter. The list returns nothing, rather than creating a sandbox, when no live sandbox holds the name:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const page = await runtime.sandboxes.list({ name: "dev" });const [dev] = page.data;console.log(dev ? `${dev.id} is ${dev.state}` : "no sandbox is called dev");Pythonfrom withruntime import Runtimeruntime = Runtime()found = runtime.sandboxes.list(name="dev").to_list()print(f"{found[0].id} is {found[0].state}" if found else "no sandbox is called dev")In the CLI, a name works wherever an id does, in every runtime sandboxes
command. After runtime sandboxes ssh config --install runs once,
ssh dev.runtime connects to the sandbox
(SSH and editors).
How names behave
| Rule | Detail |
|---|---|
| Unique while it can run | Starting, running, paused, or stopped and persistent |
| A second create | Fails with 409 name_taken. details.sandboxId names the holder when your key can reach it |
getOrCreate |
Returns the holder with reused: true instead of name_taken |
| Stopped for good | The sandbox gives up the name and keeps it in its own record |
| Rename | sbx.update({ name: "dev-2" }), or runtime sandboxes update <id> --name dev-2 |
| Over HTTP | POST /v1/sandboxes with name and getOrCreate: true. GET /v1/sandboxes?name= |
| Over MCP | runtime_sandboxes_create with name and getOrCreate: true |
| Cost | Nothing for the name. A paused holder is billed as paused storage |
Mistakes to avoid
- Catching
name_takenand retrying with a new name. That leaves the first sandbox running or paused, and it is still billed. UsegetOrCreate, or read the holder from the error:
TypeScriptimport { ConflictError, Sandbox } from "withruntime";try { await Sandbox.create({ name: "dev" });} catch (error) { if (error instanceof ConflictError && error.code === "name_taken") console.log("dev is", error.details?.sandboxId); else throw error;}- One name for many users. A name is unique in the account. Give each
user or task its own name, such as
dev-${userId}. Use labels to group sandboxes. - Expecting new options on a found sandbox.
getOrCreatedoes not resize or reconfigure the holder. Change whatupdate()can change (name, labels, idle pause, automatic wake, persistence), or stop it and create a new one. - Looking for a stopped sandbox by name. Once an ordinary sandbox stops,
its name is free. To keep the name, use
persistent: true(keep a sandbox running).
Related
- Label and list sandboxes to find many at once.
- Pause when idle, which pairs with a named sandbox.
- Per-user dev environments, one name per user.
- Sandboxes by name in the SDK reference.
Facts on this page were checked on 26 October 2026.