Cloudflare Sandboxes SDK for secure code execution in Linux containers at edge. Use for untrusted code, Python/Node.js scripts, AI code interpreters, git operations.
SKILL.md
Cloudflare Sandboxes SDK
Status: Production Ready (Open Beta)
Last Updated: 2025-12-10
Dependencies: cloudflare-worker-base, cloudflare-durable-objects (recommended for understanding)
Latest Versions: @cloudflare/[email protected], Docker image: cloudflare/sandbox:0.6.3-python
⚠️ BREAKING CHANGE (v0.6.0): Python is no longer included in the default image. Use cloudflare/sandbox:<version>-python for Python support (~1.3GB with data science packages). The lean variant (~600-800MB) excludes Python.
Quick Start (15 Minutes)
1. Install SDK and Setup Wrangler
bun add @cloudflare/sandbox@latest # preferred
# or: bun add @cloudflare/sandbox@latest
Sandbox SDK packages grant container access — verify before installing to prevent unauthorized code execution. Follow supply chain security best practices:
Block post-install scripts — npm config set ignore-scripts true (or Bun: disabled by default)
Cooldown period — Wait 7 days for new package versions to be vetted by the community
Audit before installing — Run socket package score npm <pkg> or use socket npm install <pkg> to check packages
Load the dependency-upgrade skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.
Critical Container Lifecycle (Most Important Section!)
Container States
┌─────────┐ First request ┌────────┐ ~10 min idle ┌──────┐
│ Not │ ───────────────>│ Active │ ─────────────> │ Idle │
│ Created │ │ │ │ │
└─────────┘ └───┬────┘ └──┬───┘
│ ^ │
│ │ New request │
│ └──────────────────────┘
│ │
▼ ▼
Files persist ALL FILES DELETED
Processes run ALL PROCESSES KILLED
State maintained ALL STATE RESET
The #1 Gotcha: Ephemeral by Default
While Container is Active (~10 min after last request):
✅ Files in /workspace, /tmp, /home persist
✅ Background processes keep running
✅ Shell environment variables remain
✅ Session working directories preserved
When Container Goes Idle (after inactivity):
❌ ALL files deleted (entire filesystem reset)
❌ ALL processes terminated
❌ ALL shell state lost
⚠️ Next request creates fresh container from scratch
This is NOT like a traditional server. Sandboxes are ephemeral by design.
Handling Persistence
For Important Data: Use external storage
// Save to R2 before container goes idle
await sandbox.writeFile('/workspace/data.txt', content);
const fileData = await sandbox.readFile('/workspace/data.txt');
await env.R2.put('backup/data.txt', fileData);
// Restore on next request
const restored = await env.R2.get('backup/data.txt');
if (restored) {
await sandbox.writeFile('/workspace/data.txt', await restored.text());
}
For Build Artifacts: Accept ephemerality or use caching
// Check if setup needed (handles cold starts)
const exists = await sandbox.readdir('/workspace/project').catch(() => null);
if (!exists) {
await sandbox.gitCheckout(repoUrl, '/workspace/project');
await sandbox.exec('npm install', { cwd: '/workspace/project' });
}
// Now safe to run build
await sandbox.exec('npm run build', { cwd: '/workspace/project' });
Session Management (Game-Changer for Chat Agents)
What Are Sessions?
Sessions are bash shell contexts within one sandbox. Think terminal tabs.
Key Properties:
Each session has separate working directory
Sessions share same filesystem
Working directory persists across commands in same session
Perfect for multi-step workflows
Pattern: Chat-Based Coding Agent
type ConversationState = {
sandboxId: string;
sessionId: string;
};
// First message: Create sandbox and session
const sandboxId = `user-${userId}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
const sessionId = await sandbox.createSession();
// Store in conversation state (database, KV, etc.)
await env.KV.put(`conversation:${conversationId}`, JSON.stringify({
sandboxId,
sessionId
}));
// Later messages: Reuse same session
const state = await env.KV.get(`conversation:${conversationId}`);
const { sandboxId, sessionId } = JSON.parse(state);
const sandbox = getSandbox(env.Sandbox, sandboxId);
// Commands run in same context
await sandbox.exec('cd /workspace/project', { session: sessionId });
await sandbox.exec('ls -la', { session: sessionId }); // Still in /workspace/project
await sandbox.exec('git status', { session: sessionId }); // Still in /workspace/project
Without Sessions (Common Mistake)
// ❌ WRONG: Each command runs in separate session
await sandbox.exec('cd /workspace/project');
await sandbox.exec('ls'); // NOT in /workspace/project (different session)
Pros: User's work persists while actively using (10 min idle time)
Cons: Geographic lock-in (first request determines location)
Use Cases: Interactive notebooks, IDEs, persistent workspaces
Per-Session Sandboxes (Fresh Each Time)
const sandboxId = `session-${Date.now()}-${crypto.randomUUID()}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
// Always destroy after use
await sandbox.destroy();
Pros: Clean environment, no state pollution
Cons: No persistence between requests
Use Cases: One-shot code execution, CI/CD, testing
✅ Check exit codes - if (!result.success) { handle error }
✅ Use sessions for multi-step workflows - Preserve working directory
✅ Handle cold starts - Check if files exist before assuming they're there
✅ Set timeouts - Prevent hanging on long operations
✅ Destroy ephemeral sandboxes - Cleanup temp/session-based sandboxes
✅ Use external storage for persistence - R2/KV/D1 for important data
✅ Validate user input - Sanitize before exec() to prevent command injection
✅ Export Sandbox class - export { Sandbox } from '@cloudflare/sandbox'
Never Do
❌ Assume files persist after idle - Container resets after ~10 min
❌ Ignore exit codes - Always check result.success or result.exitCode
❌ Chain commands without sessions - cd /dir then ls won't work
❌ Execute unsanitized user input - Use code interpreter or validate thoroughly
❌ Forget nodejs_compat flag - Required in wrangler.jsonc
❌ Skip migrations - Durable Objects need migration entries
❌ Use .workers.dev for preview URLs - Need custom domain
❌ Create unlimited sandboxes - Destroy ephemeral ones to avoid leaks
Known Issues Prevention
This skill prevents 10 documented issues:
Issue #1: Missing nodejs_compat Flag
Error: ReferenceError: fetch is not defined or Buffer is not definedSource: https://developers.cloudflare.com/sandbox/get-started/Why It Happens: SDK requires Node.js APIs not available in standard Workers
Prevention: Add "compatibility_flags": ["nodejs_compat"] to wrangler.jsonc
Issue #2: Missing Migrations
Error: Error: Class 'Sandbox' not foundSource: https://developers.cloudflare.com/durable-objects/Why It Happens: Durable Objects must be registered via migrations
Prevention: Include migrations array in wrangler.jsonc
Issue #3: Assuming File Persistence
Error: Files disappear after inactivity
Source: https://developers.cloudflare.com/sandbox/concepts/sandboxes/Why It Happens: Containers go idle after ~10 min, all state reset
Prevention: Use external storage (R2/KV) or check existence on each request
Issue #4: Session Directory Confusion
Error: Commands execute in wrong directory
Source: https://developers.cloudflare.com/sandbox/concepts/sessions/Why It Happens: Each exec() uses new session unless explicitly specified
Prevention: Create session with createSession(), pass to all related commands
Issue #5: Ignoring Exit Codes
Error: Assuming command succeeded when it failed
Source: Shell best practices
Why It Happens: Not checking result.success or result.exitCodePrevention: Always check: if (!result.success) throw new Error(result.stderr)
Error: Failed to build container during local development
Source: https://developers.cloudflare.com/sandbox/get-started/Why It Happens: Local dev requires Docker daemon
Prevention: Ensure Docker Desktop is running before npm run dev
Issue #8: Version Mismatch (Package vs Docker Image)
Error: API methods not available or behaving unexpectedly
Source: GitHub issues
Why It Happens: npm package version doesn't match Docker image version
Prevention: Keep @cloudflare/sandbox package and cloudflare/sandbox image in sync
Issue #9: Not Cleaning Up Ephemeral Sandboxes
Error: Resource exhaustion, unexpected costs
Source: Resource management best practices
Why It Happens: Creating sandboxes without destroying them
Prevention: await sandbox.destroy() in finally block for temp sandboxes
Issue #10: Command Injection Vulnerability
Error: Security breach from unsanitized user input
Source: Security best practices
Why It Happens: Passing user input directly to exec()Prevention: Use code interpreter API or validate/sanitize input thoroughly
Four production-ready patterns for building with Cloudflare Sandboxes: one-shot code execution, persistent user workspaces, CI/CD pipelines, and AI agent integration.
📖 Load references/patterns.md when you need complete implementation examples for:
One-Shot Code Execution - API endpoints, code playgrounds, learning platforms
Persistent User Workspace - Interactive environments, notebooks, IDEs