# Switch to Runtime from another sandbox provider Move your sandbox code to Runtime in one pass, test it on the free usage, and see what you save each month. Your model, prompts and application stay as they are; only the sandbox calls change. For a project with no sandbox yet, start with [Get started](./start). ## Give your agent one instruction > Move this project to Runtime Cloud: read https://withruntime.com/llms.txt and > follow it. The agent follows the steps below and keeps going until your real job runs on Runtime. It ends with your monthly saving in dollars, and what is left for you to do before going live. It tests without credit. It asks before going on once the free usage is used. It never touches your old provider's account. **Why teams switch:** - **You pay for the CPU you use.** $0.025 per active vCPU-hour, measured, and $0.0075 per reserved GiB-hour of memory. No plan fee, and no one-minute minimum. - **The calls map one to one.** Create, exec, files and stop have direct equivalents (table below). Code written for E2B, Daytona, Vercel Sandbox or Blaxel, Morph and others runs after changing one import. - **Pause keeps memory.** A paused sandbox wakes where it left off, kept while a paid account has credit. A fork copies a running sandbox with its memory and processes. - **More is built in.** A desktop, a code interpreter, custom images, volumes, and preview URLs that are private by default. - **No API key to copy.** One browser approval connects the CLI, SDKs and MCP. - **Test it free.** 100 free hours of a 1 GB machine, no card, up to four running at the same time. A sandbox without credit reaches ports 80 and 443 and shares previews privately, with a token; other outbound ports and public previews need paid credit. The [comparison pages](./e2b-alternative) work through the cost of the same job on each provider. ## 1. Find the old provider's calls Read the project before changing it: - dependency manifests and lockfiles; - provider imports and sandbox configuration; - creation calls, command execution, file access, background processes and cleanup; - the names of environment variables, never their values; - the framework and its version. A framework's tool integration is not its sandbox backend. Adding an MCP tool does not redirect a framework's local shell or filesystem operations. ## 2. Check what the project needs **Most projects map straight across.** Check whether the application needs Docker, root access, WebSockets, browser sessions, custom images, GPU support, snapshots or region guarantees. On Runtime: | The project needs | Runtime | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Root | Passwordless `sudo` inside the sandbox | | Docker | Docker Engine and Compose with `sudo enable-docker` ([environment](./sandbox-environment#docker)) | | SSH or an editor | `runtime sandboxes ssh`, and `.runtime` in VS Code or JetBrains ([SSH and editors](./editors)) | | A port on your machine | `runtime sandboxes port-forward 5432`, any TCP port, over the API | | WebSockets | Supported, including through a preview | | A browser | Playwright's Chromium installs in two commands, or use the [desktop](./products) | | Custom images | Build from a package list, any public or private image, or a Dockerfile | | Snapshots and forks | Keep files, memory and running processes | | A public URL | A preview: an HTTPS address for one port | | Other ports outbound | Paid accounts reach every port, raw sockets included ([environment](./sandbox-environment#the-network)) | | API keys in the sandbox | Secrets: a placeholder in the sandbox, the value added by the proxy ([security](./security#secrets-sandboxes-never-see)) | Do not represent a missing feature as supported. If the project needs something Runtime does not offer, tell the owner which call before you remove it, and send it as feedback. We build next from these reports: ```bash no-run npx withruntime feedback --kind migration_blocker --competitor E2B \ "Our evaluation jobs need X" ``` ## 3. Connect and prove it ```bash no-run npx withruntime login --no-browser npx withruntime sandboxes run -- echo hello ``` The first command prints a link and a code: show them to the owner and wait for their approval of **Connect agent**. The second must print `hello` and exit 0. [Get started](./start) has the details. ## 4. Replace the calls **Replace every call and leave no fallback.** Work on a branch, so git keeps the old code. Then: - Map create, readiness, exec, read and write, and stop to Runtime (table below). - Remove the old provider's SDK, its client setup and its settings from the code. - Test within the free usage. Once it is used up, sandboxes run on the account's credit by themselves. Check what is left with `npx withruntime usage`, and ask the owner before going on. - Use one sandbox per isolated task or tenant, not a shared global sandbox. - Choose an idempotency key before a write that accepts one, and reuse it with identical input after a lost response; a new key can run the work twice. The SDKs keep the same key for retries within a call. Across calls or restarts, choose and keep your own. - Pass argument arrays rather than shell commands built from untrusted strings. **From Daytona or Vercel Sandbox:** change the import to `withruntime/daytona` or `withruntime/vercel` (Python `withruntime.daytona`, `withruntime.vercel`). Their `stop()` keeps the disk to start again, as it does there, so it pauses the sandbox; `delete()` ends it. See [JavaScript](./javascript) and [Python](./python). **From Blaxel:** change `from "@blaxel/core"` to `from "withruntime/blaxel"` (Python `from blaxel.core import SandboxInstance` to `from withruntime.blaxel import SandboxInstance`). Standby becomes a pause that keeps memory and processes after 300 seconds idle, and the next call wakes the sandbox. Sessions carry over as Runtime's [sandbox sessions](./javascript#a-sandbox-from-a-browser). A call Runtime handles differently, such as drives or schedules, throws `NotSupportedError` naming what to use instead. - A Blaxel workspace key sees every sandbox; a Runtime key sees the ones it made unless an owner or admin makes it account-wide (the API keys page, or `runtime keys create --account-wide`). Give services that share sandboxes account-wide keys ([keys in a team](./teams#keys-in-a-team)). - Without credit, a sandbox is at most 2 vCPU and 4096 MB; `memory: 8192` needs paid credit. - An image other than Blaxel's own templates must be a ready Runtime image of the same name: `npx withruntime images build --dockerfile Dockerfile --name `. - Blaxel's preview token header (`X-Blaxel-Preview-Token`) and parameter (`?bl_preview_token=`) are accepted. **From Morph:** change `from "morphcloud"` to `from "withruntime/morph"` (Python: `morphcloud` to `withruntime.morph` in the imports, so `from withruntime.morph import MorphCloudClient`). `MorphCloudClient`'s snapshots, instances, `setup`, `branch`, `pause`, `resume`, `exec` and `exposeHttpService` work as they are; metadata become labels. `stop` deletes the sandbox, as on Morph. Give `ttlSeconds` at `instances.start` (60 to 86400): Runtime cannot add a time limit later. An HTTP service with `auth_mode: "api_key"` is a private preview: send its token (`instance.native.previews.get(port)`) as `x-runtime-preview-token`. Morph's SSH calls refuse; use `npx withruntime sandboxes ssh `. In Python, `set_ttl` moves a time limit later but never adds or shortens one, and a snapshot's `ttl_seconds` is whole days. Commands run as the user `runtime` (with `sudo`), not root, so write to `/workspace` or `/tmp`. **From Modal Sandboxes:** change `from "modal"` to `from "withruntime/modal"` (Python `import modal` to `from withruntime import modal`), SDK 0.25.0 and later (Python 0.23.0). Modal's own sandbox examples run unchanged where they use none of what is refused below, and no Modal token is needed or sent. Commands run as root, as in a Modal container. A `timeout` ends the sandbox, and an `idle_timeout` pauses it with its memory kept until the next call wakes it. A Function with a `schedule` deploys as a [job](./jobs#modal) (SDK 0.36.0, Python 0.34.0). GPUs, other Modal Functions, named secrets, volumes made on first use, sidecars, connect tokens and directory snapshots throw `CompatibilityError` before anything is created, naming what to use instead ([Modal](./modal-sandbox-alternative#what-the-drop-in-refuses)). **From E2B:** change `from "e2b"` to `from "withruntime/e2b"` (Python `from withruntime.e2b import ...`, SDK 0.4.0 and later). Errors stay E2B's: `commands.run` throws `CommandExitError` (Python `CommandExitException`) on a non-zero exit and `TimeoutError` (Python `TimeoutException`) past its timeout, so keep your `try`/`catch`. A call Runtime handles differently throws `NotSupportedError` naming what to use instead. Without credit a shared port is private, so `getHost(port)` throws `PublicPreviewNotAllowedError` (Python `PublicPreviewNotAllowedException`) instead of returning a host nobody can reach: while you test, open `(await sandbox.runtime.previews.create(port)).urlWithToken` instead, or send its token in the `x-runtime-preview-token` header. An E2B template becomes a Runtime image of the same name, built once from the same Dockerfile: 1. Build it: `npx withruntime images build --dockerfile e2b.Dockerfile --name