Skip to main content
Every build session runs against an isolated cloud microVM sandbox. The sandbox is where files are written, dependencies are installed, the dev server runs, and the preview URL is served from. The agent never touches the host filesystem.
Sandbox

Lifecycle

Templates

Templates are baked via bun run bake:e2b (see scripts/bake-e2b-templates.ts). Verify a baked template with bun run verify:e2b. Source templates are pulled from GitHub via git clone --depth 1 — never bundled into the server image.

Dev server start

PreviewManager.startDevServer() runs in the orchestrator before the agent’s first turn:
  1. Patch vite.config.ts so HMR works through the Cloudflare proxy.
  2. Run npm install if node_modules is stale.
  3. Spawn the dev command in the background.
  4. Poll for the port (detectPort, preferred 8080).
  5. Construct the branded URL — https://<shortId>.vibelyagent.com.
  6. Emit preview_url over SSE/WS so the iframe mounts before the agent has done anything.
This early start is why the system prompt can claim “the dev server is already running” — by the time the model reads it, that’s true. The bash tool short-circuits any npm run dev the model tries, because issuing it again would steal the port and break HMR.

Preview proxy

The <shortId>.vibelyagent.com URL is served by cloudflare/worker.js, which:
  • Proxies the request to the sandbox over its private hostname.
  • Strips X-Frame-Options and Content-Security-Policy: frame-ancestors so the preview can be embedded in the Vibely app’s iframe.
  • Forwards WebSocket upgrades for HMR.
If the iframe loads blank, the worker is the first place to look.

File persistence

Files written through write or edit are mirrored to Supabase (vibe_files) per turn. loopResult.writtenFiles is the canonical source per-turn — only files the loop saw written are saved, which is fast. As a fallback for bash-only turns (e.g. npm install produced new files), getAllFiles(sandbox) does a full tree scan. Full scans are slow (2–10 s) so they only run when the incremental list is empty. This is the contract that lets a paused sandbox resume cleanly: every file that matters is in Postgres, not just on the sandbox disk.

404 auto-recovery

The sandbox provider occasionally returns 404 for a sandbox we know exists — usually during snapshot rotation or metadata replication. The tool registry handles this transparently:
After 3 recoveries on the same project the agent bails with a hard error so a real fix (sandbox rebuild, project bounce) can happen instead of an infinite retry storm. See Tools.

Sandbox pool

A small pool of pre-warmed sandboxes can be kept ready so new sessions don’t pay the cold-start cost. The switch is SANDBOX_POOL_TARGET, which defaults to 0 — pooling is off unless you ask for it, because an idle sandbox bills continuously. (SANDBOX_POOL_ENABLED is on by default and only gates the feature; the target is what decides whether anything is warmed.) With pooling off, the first request to a new project pays ~5–15 s for sandbox spawn + template hydration; subsequent requests for the same project resume the existing sandbox in <1 s.

Self-hosted sandboxes

Set E2B_DOMAIN=https://your-control-plane to point at your own sandbox control plane instead of the managed cloud. Leave it empty to use the managed one. Every other sandbox env var works the same way against a self-hosted control plane.