@cloudflare/sandbox 0.0.0-215ab49 → 0.0.0-2450ebd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/Dockerfile +112 -54
  3. package/README.md +91 -489
  4. package/dist/chunk-BFVUNTP4.js +104 -0
  5. package/dist/chunk-BFVUNTP4.js.map +1 -0
  6. package/dist/chunk-EKSWCBCA.js +86 -0
  7. package/dist/chunk-EKSWCBCA.js.map +1 -0
  8. package/dist/chunk-EXQOIRZI.js +2351 -0
  9. package/dist/chunk-EXQOIRZI.js.map +1 -0
  10. package/dist/chunk-JXZMAU2C.js +559 -0
  11. package/dist/chunk-JXZMAU2C.js.map +1 -0
  12. package/dist/chunk-Z532A7QC.js +78 -0
  13. package/dist/chunk-Z532A7QC.js.map +1 -0
  14. package/dist/file-stream.d.ts +43 -0
  15. package/dist/file-stream.js +9 -0
  16. package/dist/file-stream.js.map +1 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.js +66 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/interpreter.d.ts +33 -0
  21. package/dist/interpreter.js +8 -0
  22. package/dist/interpreter.js.map +1 -0
  23. package/dist/request-handler.d.ts +18 -0
  24. package/dist/request-handler.js +12 -0
  25. package/dist/request-handler.js.map +1 -0
  26. package/dist/sandbox-D9K2ypln.d.ts +583 -0
  27. package/dist/sandbox.d.ts +4 -0
  28. package/dist/sandbox.js +12 -0
  29. package/dist/sandbox.js.map +1 -0
  30. package/dist/security.d.ts +31 -0
  31. package/dist/security.js +13 -0
  32. package/dist/security.js.map +1 -0
  33. package/dist/sse-parser.d.ts +28 -0
  34. package/dist/sse-parser.js +11 -0
  35. package/dist/sse-parser.js.map +1 -0
  36. package/package.json +13 -5
  37. package/src/clients/base-client.ts +280 -0
  38. package/src/clients/command-client.ts +115 -0
  39. package/src/clients/file-client.ts +269 -0
  40. package/src/clients/git-client.ts +92 -0
  41. package/src/clients/index.ts +63 -0
  42. package/src/clients/interpreter-client.ts +329 -0
  43. package/src/clients/port-client.ts +105 -0
  44. package/src/clients/process-client.ts +177 -0
  45. package/src/clients/sandbox-client.ts +41 -0
  46. package/src/clients/types.ts +84 -0
  47. package/src/clients/utility-client.ts +94 -0
  48. package/src/errors/adapter.ts +180 -0
  49. package/src/errors/classes.ts +469 -0
  50. package/src/errors/index.ts +105 -0
  51. package/src/file-stream.ts +164 -0
  52. package/src/index.ts +85 -12
  53. package/src/interpreter.ts +159 -0
  54. package/src/request-handler.ts +69 -43
  55. package/src/sandbox.ts +558 -292
  56. package/src/security.ts +14 -23
  57. package/src/sse-parser.ts +4 -8
  58. package/startup.sh +3 -0
  59. package/tests/base-client.test.ts +328 -0
  60. package/tests/command-client.test.ts +407 -0
  61. package/tests/file-client.test.ts +643 -0
  62. package/tests/file-stream.test.ts +306 -0
  63. package/tests/git-client.test.ts +328 -0
  64. package/tests/port-client.test.ts +301 -0
  65. package/tests/process-client.test.ts +658 -0
  66. package/tests/sandbox.test.ts +465 -0
  67. package/tests/sse-parser.test.ts +290 -0
  68. package/tests/utility-client.test.ts +266 -0
  69. package/tests/wrangler.jsonc +35 -0
  70. package/tsconfig.json +9 -1
  71. package/vitest.config.ts +31 -0
  72. package/container_src/handler/exec.ts +0 -338
  73. package/container_src/handler/file.ts +0 -844
  74. package/container_src/handler/git.ts +0 -182
  75. package/container_src/handler/ports.ts +0 -314
  76. package/container_src/handler/process.ts +0 -640
  77. package/container_src/index.ts +0 -361
  78. package/container_src/package.json +0 -9
  79. package/container_src/types.ts +0 -108
  80. package/src/client.ts +0 -1038
  81. package/src/types.ts +0 -386
package/README.md CHANGED
@@ -1,532 +1,126 @@
1
- <div align="center">
2
- <h1>📦 Cloudflare Sandbox SDK</h1>
3
- <h3><strong>Run sandboxed code environments on Cloudflare's edge network</strong></h3>
4
- <p>
5
- <a href="https://www.npmjs.com/package/@cloudflare/sandbox"><img src="https://img.shields.io/npm/v/@cloudflare/sandbox.svg" alt="npm version"></a>
6
- <a href="https://github.com/cloudflare/sandbox-sdk"><img src="https://img.shields.io/badge/status-experimental-orange.svg" alt="status"></a>
7
- </p>
8
- </div>
9
-
10
- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
11
- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
12
-
13
- - [✨ Overview](#overview)
14
- - [🎯 Features](#features)
15
- - [🚀 Quick Start](#quick-start)
16
- - [Installation](#installation)
17
- - [Basic Setup](#basic-setup)
18
- - [📚 API Reference](#api-reference)
19
- - [Core Methods](#core-methods)
20
- - [🌐 Port Forwarding](#port-forwarding)
21
- - [Utility Methods](#utility-methods)
22
- - [💡 Examples](#examples)
23
- - [Run a Node.js App](#run-a-nodejs-app)
24
- - [Build and Test Code](#build-and-test-code)
25
- - [Interactive Development Environment](#interactive-development-environment)
26
- - [Expose Services with Preview URLs](#expose-services-with-preview-urls)
27
- - [🏗️ Architecture](#architecture)
28
- - [🛠️ Advanced Usage](#advanced-usage)
29
- - [AsyncIterable Streaming Support](#asynciterable-streaming-support)
30
- - [Session Management](#session-management)
31
- - [🔍 Debugging](#debugging)
32
- - [🚧 Known Limitations](#known-limitations)
33
- - [🤝 Contributing](#contributing)
34
- - [📄 License](#license)
35
- - [🙌 Acknowledgments](#acknowledgments)
36
-
37
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
38
-
39
- <h2 id="overview">✨ Overview</h2>
40
-
41
- The Cloudflare Sandbox SDK enables you to run isolated code environments directly on Cloudflare's edge network using Durable Objects and the Cloudflare Containers. Execute commands, manage files, run services, and expose them via public URLs - all within secure, sandboxed containers.
42
-
43
- <h2 id="features">🎯 Features</h2>
44
-
45
- - **🔒 Secure Isolation**: Each sandbox runs in its own container with full process isolation
46
- - **⚡ Edge-Native**: Runs on Cloudflare's global network for low latency worldwide
47
- - **📁 File System Access**: Read, write, and manage files within the sandbox
48
- - **🔧 Command Execution**: Run any command or process inside the container
49
- - **🌐 Preview URLs**: Expose services running in your sandbox via public URLs
50
- - **🔄 Git Integration**: Clone repositories directly into sandboxes
51
- - **🚀 Streaming Support**: Real-time output streaming for long-running commands
52
- - **🎮 Session Management**: Maintain state across multiple operations
53
-
54
- <h2 id="quick-start">🚀 Quick Start</h2>
55
-
56
- ### Installation
1
+ <img width="1362" height="450" alt="Image" src="https://github.com/user-attachments/assets/6f770ae3-0a14-4d2b-9aed-a304ee5446c5" />
57
2
 
58
- ```bash
59
- npm install @cloudflare/sandbox
60
- ```
61
-
62
- ### Basic Setup
63
-
64
- 1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
65
-
66
- ```dockerfile
67
- FROM docker.io/cloudflare/sandbox:0.1.3
68
-
69
- EXPOSE 3000
70
-
71
- # Run the same command as the original image
72
- CMD ["bun", "index.ts"]
73
- ```
3
+ # Cloudflare Sandbox SDK
74
4
 
75
- 2. **Configure wrangler.json**:
5
+ [![npm version](https://img.shields.io/npm/v/@cloudflare/sandbox.svg)](https://www.npmjs.com/package/@cloudflare/sandbox)
76
6
 
77
- > **NOTE**: In an upcoming release, this step will be removed entirely and you can reference a single Docker image published by us directly in your wrangler configuration below.
7
+ **Build secure, isolated code execution environments on Cloudflare.**
78
8
 
79
- ```jsonc
80
- {
81
- // ...
82
- "containers": [
83
- {
84
- "class_name": "Sandbox",
85
- "image": "./Dockerfile",
86
- "max_instances": 1
87
- }
88
- ],
89
- "durable_objects": {
90
- "bindings": [
91
- {
92
- "class_name": "Sandbox",
93
- "name": "Sandbox"
94
- }
95
- ]
96
- },
97
- "migrations": [
98
- {
99
- "new_sqlite_classes": ["Sandbox"],
100
- "tag": "v1"
101
- }
102
- ]
103
- }
104
- ```
105
-
106
- 3. **Create your Worker**:
9
+ The Sandbox SDK lets you run untrusted code safely in isolated containers. Execute commands, manage files, run background processes, and expose services — all from your Workers applications.
107
10
 
108
- ```typescript
109
- import { getSandbox } from "@cloudflare/sandbox";
11
+ Perfect for AI code execution, interactive development environments, data analysis platforms, CI/CD systems, and any application that needs secure code execution at the edge.
110
12
 
111
- // Export the Sandbox class in your Worker
112
- export { Sandbox } from "@cloudflare/sandbox";
13
+ > **Note:** The latest published version of the SDK is on the [v03 branch](https://github.com/cloudflare/sandbox-sdk/tree/v03). This main branch is currently the development version and is not yet published.
113
14
 
114
- export default {
115
- async fetch(request: Request, env: Env) {
116
- const sandbox = getSandbox(env.Sandbox, "my-sandbox");
15
+ ## Getting Started
117
16
 
118
- // Execute a command
119
- const result = await sandbox.exec("echo 'Hello from the edge!'");
120
- return new Response(result.stdout);
121
- },
122
- };
123
- ```
17
+ ### Prerequisites
124
18
 
125
- <h2 id="api-reference">📚 API Reference</h2>
19
+ 1. Install [Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) (version 16.17.0 or later)
20
+ 2. Ensure Docker is running locally
21
+ 3. For deploying to production, sign up for a [Cloudflare account](https://dash.cloudflare.com/sign-up/workers-and-pages)
126
22
 
127
- ### Core Methods
23
+ ### 1. Create a new project
128
24
 
129
- #### Command Execution
25
+ Create a new Sandbox SDK project using the minimal template:
130
26
 
131
- **`exec(command, options?)`** - Enhanced command execution that always returns results
132
-
133
- ```typescript
134
- // Simple execution
135
- const result = await sandbox.exec("npm install express");
136
- console.log(result.stdout, result.exitCode);
137
-
138
- // With streaming callbacks
139
- const result = await sandbox.exec("npm run build", {
140
- stream: true,
141
- onOutput: (stream, data) => console.log(`[${stream}] ${data}`)
142
- });
27
+ ```bash
28
+ npm create cloudflare@latest -- my-sandbox --template=cloudflare/sandbox-sdk/examples/minimal
29
+ cd my-sandbox
143
30
  ```
144
31
 
145
- **`execStream(command, options?)`** - Dedicated streaming method returning SSE stream
146
-
147
- ```typescript
148
- import { parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';
149
-
150
- const stream = await sandbox.execStream("npm run test");
151
- for await (const event of parseSSEStream<ExecEvent>(stream)) {
152
- switch (event.type) {
153
- case 'stdout':
154
- console.log(`Test output: ${event.data}`);
155
- break;
156
- case 'complete':
157
- console.log(`Tests ${event.exitCode === 0 ? 'passed' : 'failed'}`);
158
- break;
159
- }
160
- }
161
- ```
32
+ ### 2. Test locally
162
33
 
163
- **`startProcess(command, options?)`** - Start background processes with lifecycle management
34
+ Start the development server:
164
35
 
165
- ```typescript
166
- const process = await sandbox.startProcess("node server.js");
167
- console.log(`Started process ${process.id} with PID ${process.pid}`);
168
-
169
- // Monitor the process
170
- const logStream = await sandbox.streamProcessLogs(process.id);
171
- for await (const log of parseSSEStream<LogEvent>(logStream)) {
172
- console.log(`Server: ${log.data}`);
173
- }
36
+ ```bash
37
+ npm run dev
174
38
  ```
175
39
 
176
- #### `writeFile(path, content, options?)`
177
-
178
- Write content to a file.
40
+ > **Note:** First run builds the Docker container (2-3 minutes). Subsequent runs are much faster.
179
41
 
180
- ```typescript
181
- await sandbox.writeFile("/app.js", "console.log('Hello!');");
182
- ```
42
+ Test the endpoints:
183
43
 
184
- #### `readFile(path, options?)`
185
-
186
- Read a file from the sandbox.
44
+ ```bash
45
+ # Execute Python code
46
+ curl http://localhost:8787/run
187
47
 
188
- ```typescript
189
- const file = await sandbox.readFile("/package.json");
190
- console.log(file.content);
48
+ # File operations
49
+ curl http://localhost:8787/file
191
50
  ```
192
51
 
193
- #### `gitCheckout(repoUrl, options?)`
52
+ ### 3. Deploy to production
194
53
 
195
- Clone a git repository.
54
+ Deploy your Worker and container:
196
55
 
197
- ```typescript
198
- await sandbox.gitCheckout("https://github.com/user/repo", {
199
- branch: "main",
200
- targetDir: "my-project",
201
- });
56
+ ```bash
57
+ npx wrangler deploy
202
58
  ```
203
59
 
204
- #### `setEnvVars(envVars)`
60
+ > **Wait for provisioning:** After first deployment, wait 2-3 minutes before making requests.
205
61
 
206
- Set environment variables dynamically in the sandbox.
62
+ **📖 [View the complete getting started guide](https://developers.cloudflare.com/sandbox/get-started/)** for detailed instructions and explanations.
207
63
 
208
- > **Important**: This method must be called immediately after `getSandbox()` and before any other operations. Once a sandbox instance starts up, environment variables cannot be changed
209
- for that instance.
64
+ ## Quick API Example
210
65
 
211
66
  ```typescript
212
- const sandbox = getSandbox(env.Sandbox, "my-sandbox");
213
-
214
- // Set environment variables FIRST, before any other operations
215
- await sandbox.setEnvVars({
216
- NODE_ENV: "production",
217
- API_KEY: "your-api-key",
218
- DATABASE_URL: "postgresql://localhost:5432/mydb"
219
- });
220
-
221
- // Now you can run commands - environment variables are available
222
- const result = await sandbox.exec("echo $NODE_ENV");
223
- console.log(result.stdout); // "production"
224
- ```
225
-
226
- #### Process Management
227
-
228
- - `listProcesses()` - List all running processes
229
- - `getProcess(id)` - Get detailed process status
230
- - `killProcess(id, signal?)` - Terminate specific processes
231
- - `killAllProcesses()` - Kill all processes
232
- - `streamProcessLogs(id, options?)` - Stream logs from running processes
233
- - `getProcessLogs(id)` - Get accumulated process output
234
-
235
- #### File System Methods
236
-
237
- - `writeFile(path, content, options?)` - Write content to a file
238
- - `readFile(path, options?)` - Read a file from the sandbox
239
- - `mkdir(path, options?)` - Create a directory
240
- - `deleteFile(path)` - Delete a file
241
- - `renameFile(oldPath, newPath)` - Rename a file
242
- - `moveFile(sourcePath, destinationPath)` - Move a file
243
- - `gitCheckout(repoUrl, options?)` - Clone git repositories
244
-
245
- #### Network Methods
67
+ import { getSandbox, proxyToSandbox, type Sandbox } from '@cloudflare/sandbox';
246
68
 
247
- - `exposePort(port, options?)` - Expose a port and get a public URL
248
- - `unexposePort(port)` - Remove port exposure
249
- - `getExposedPorts()` - List all exposed ports with their URLs
69
+ export { Sandbox } from '@cloudflare/sandbox';
250
70
 
251
- <h2 id="port-forwarding">🌐 Port Forwarding</h2>
252
-
253
- The SDK automatically handles preview URL routing for exposed ports. Just add one line to your worker:
254
-
255
- ```typescript
256
- import { proxyToSandbox, getSandbox } from "@cloudflare/sandbox";
71
+ type Env = {
72
+ Sandbox: DurableObjectNamespace<Sandbox>;
73
+ };
257
74
 
258
75
  export default {
259
- async fetch(request, env) {
260
- // Route requests to exposed container ports via their preview URLs
76
+ async fetch(request: Request, env: Env): Promise<Response> {
77
+ // Required for preview URLs
261
78
  const proxyResponse = await proxyToSandbox(request, env);
262
79
  if (proxyResponse) return proxyResponse;
263
80
 
264
- // Your custom routes here
265
- // ...
266
- },
267
- };
268
- ```
269
-
270
- When you expose a port, the SDK returns a preview URL that automatically routes to your service:
271
-
272
- ```typescript
273
- const preview = await sandbox.exposePort(3000);
274
- console.log(preview.url); // https://3000-sandbox-id.your-worker.dev
275
- ```
276
-
277
- The SDK handles:
278
-
279
- - Subdomain routing (`3000-sandbox-id.domain.com`) for both production and local development
280
- - All localhost variants (127.0.0.1, ::1, etc.)
281
- - Request forwarding with proper headers
282
-
283
- > **Important for Local Development**: When developing locally with `wrangler dev`, you must explicitly expose ports in your Dockerfile using the `EXPOSE` instruction. This is **only required for local development** - in production, all container ports are automatically accessible.
284
-
285
- ```dockerfile
286
- # In your Dockerfile (only needed for local dev)
287
- FROM oven/bun:latest
288
-
289
- # Expose the ports you'll be using
290
- EXPOSE 3000 # For a web server
291
- EXPOSE 8080 # For an API server
292
- EXPOSE 3001 # For any additional services
293
-
294
- # Your container setup...
295
- ```
296
-
297
- Without the `EXPOSE` instruction in local development, you'll see this error:
298
-
299
- ```
300
- connect(): Connection refused: container port not found. Make sure you exposed the port in your container definition.
301
- ```
302
-
303
- For more details, see the [Cloudflare Containers local development guide](https://developers.cloudflare.com/containers/local-dev/#exposing-ports).
304
-
305
- ### Utility Methods
81
+ const url = new URL(request.url);
82
+ const sandbox = getSandbox(env.Sandbox, 'my-sandbox');
306
83
 
307
- - `ping()` - Health check for the sandbox
308
- - `containerFetch(request)` - Direct container communication
309
-
310
- <h2 id="examples">💡 Examples</h2>
311
-
312
- ### Run a Node.js App
313
-
314
- ```typescript
315
- const sandbox = getSandbox(env.Sandbox, "node-app");
316
-
317
- // Write a simple Express server
318
- await sandbox.writeFile(
319
- "/app.js",
320
- `
321
- const express = require('express');
322
- const app = express();
323
-
324
- app.get('/', (req, res) => {
325
- res.json({ message: 'Hello from Cloudflare!' });
326
- });
327
-
328
- app.listen(3000);
329
- `
330
- );
331
-
332
- // Install dependencies and start the server
333
- await sandbox.exec("npm init -y");
334
- await sandbox.exec("npm install express");
335
- const server = await sandbox.startProcess("node app.js");
336
-
337
- // Expose it to the internet
338
- const preview = await sandbox.exposePort(3000);
339
- console.log(`API available at: ${preview.url}`);
340
- ```
341
-
342
- ### Build and Test Code
343
-
344
- ```typescript
345
- const sandbox = getSandbox(env.Sandbox, "test-env");
346
-
347
- // Clone a repository
348
- await sandbox.gitCheckout("https://github.com/user/project");
349
-
350
- // Run tests
351
- const testResult = await sandbox.exec("npm test");
352
-
353
- // Build the project
354
- const buildResult = await sandbox.exec("npm run build");
355
-
356
- return new Response(
357
- JSON.stringify({
358
- tests: testResult.exitCode === 0 ? "passed" : "failed",
359
- build: buildResult.exitCode === 0 ? "success" : "failed",
360
- output: testResult.stdout,
361
- })
362
- );
363
- ```
364
-
365
- ### Interactive Development Environment
366
-
367
- ```typescript
368
- // Create a development sandbox with hot reload
369
- const sandbox = getSandbox(env.Sandbox, "dev-env");
370
-
371
- // Set up the project
372
- await sandbox.gitCheckout("https://github.com/user/my-app");
373
- await sandbox.exec("npm install");
374
-
375
- // Start dev server
376
- const devServer = await sandbox.startProcess("npm run dev");
377
-
378
- // Expose the dev server
379
- const preview = await sandbox.exposePort(3000, { name: "dev-server" });
380
-
381
- // Make changes and see them live!
382
- await sandbox.writeFile("/src/App.jsx", updatedCode);
383
- ```
384
-
385
- ### Expose Services with Preview URLs
386
-
387
- ```typescript
388
- // Create and start a web server
389
- await sandbox.writeFile(
390
- "/server.js",
391
- `Bun.serve({
392
- port: 8080,
393
- fetch(req) {
394
- return new Response("Hello from sandbox!");
84
+ // Execute Python code
85
+ if (url.pathname === '/run') {
86
+ const result = await sandbox.exec('python3 -c "print(2 + 2)"');
87
+ return Response.json({ output: result.stdout, success: result.success });
395
88
  }
396
- });`
397
- );
398
-
399
- const server = await sandbox.startProcess("bun run /server.js");
400
-
401
- // Expose the port - returns a public URL
402
- const preview = await sandbox.exposePort(8080);
403
- console.log(`Service available at: ${preview.url}`);
404
-
405
- // Note: Your Worker needs to handle preview URL routing.
406
- // See the example in examples/basic/src/index.ts for the routing implementation.
407
- ```
408
-
409
- <h2 id="architecture">🏗️ Architecture</h2>
410
-
411
- The SDK leverages Cloudflare's infrastructure:
412
-
413
- - **Durable Objects**: Manages sandbox lifecycle and state
414
- - **Containers**: Provides isolated execution environments
415
- - **Workers**: Handles HTTP routing and API interface
416
- - **Edge Network**: Enables global distribution and low latency
417
89
 
418
- <h2 id="advanced-usage">🛠️ Advanced Usage</h2>
419
-
420
- ### AsyncIterable Streaming Support
421
-
422
- The SDK provides powerful streaming capabilities with typed AsyncIterable support:
423
-
424
- ```typescript
425
- import { parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';
426
-
427
- // Stream command execution
428
- const stream = await sandbox.execStream('npm run build');
429
- for await (const event of parseSSEStream<ExecEvent>(stream)) {
430
- switch (event.type) {
431
- case 'start':
432
- console.log(`Build started: ${event.command}`);
433
- break;
434
- case 'stdout':
435
- console.log(`Build: ${event.data}`);
436
- break;
437
- case 'complete':
438
- console.log(`Exit code: ${event.exitCode}`);
439
- break;
440
- case 'error':
441
- console.error(`Error: ${event.error}`);
442
- break;
443
- }
444
- }
445
- ```
446
-
447
- #### Streaming Utilities
448
-
449
- The SDK exports utilities for working with Server-Sent Event streams:
450
-
451
- - **`parseSSEStream<T>(stream)`** - Convert ReadableStream to typed AsyncIterable
452
- - **`responseToAsyncIterable<T>(response)`** - Convert SSE Response to AsyncIterable
453
- - **`asyncIterableToSSEStream<T>(iterable)`** - Convert AsyncIterable back to SSE stream
454
-
455
- #### Advanced Streaming Examples
456
-
457
- **CI/CD Build System:**
458
- ```typescript
459
- export async function runBuild(env: Env, buildId: string) {
460
- const sandbox = getSandbox(env.SANDBOX, buildId);
461
- const stream = await sandbox.execStream('npm run build');
462
-
463
- for await (const event of parseSSEStream<ExecEvent>(stream)) {
464
- switch (event.type) {
465
- case 'start':
466
- await env.BUILDS.put(buildId, { status: 'running' });
467
- break;
468
- case 'complete':
469
- await env.BUILDS.put(buildId, {
470
- status: event.exitCode === 0 ? 'success' : 'failed',
471
- exitCode: event.exitCode
472
- });
473
- break;
90
+ // Work with files
91
+ if (url.pathname === '/file') {
92
+ await sandbox.writeFile('/workspace/hello.txt', 'Hello, Sandbox!');
93
+ const file = await sandbox.readFile('/workspace/hello.txt');
94
+ return Response.json({ content: file.content });
474
95
  }
475
- }
476
- }
477
- ```
478
96
 
479
- **System Monitoring:**
480
- ```typescript
481
- const monitor = await sandbox.startProcess('tail -f /var/log/system.log');
482
- const logStream = await sandbox.streamProcessLogs(monitor.id);
483
-
484
- for await (const log of parseSSEStream<LogEvent>(logStream)) {
485
- if (log.type === 'stdout' && log.data.includes('ERROR')) {
486
- await env.ALERTS.send({
487
- severity: 'high',
488
- message: log.data,
489
- timestamp: log.timestamp
490
- });
97
+ return new Response('Try /run or /file');
491
98
  }
492
- }
99
+ };
493
100
  ```
494
101
 
495
- ### Session Management
496
-
497
- Maintain context across commands:
498
-
499
- ```typescript
500
- const sessionId = crypto.randomUUID();
501
-
502
- // Commands in the same session share working directory
503
- await sandbox.exec("cd /app", { sessionId });
504
- await sandbox.exec("npm install", { sessionId });
505
- const app = await sandbox.startProcess("npm start", { sessionId });
506
- ```
102
+ ## Documentation
507
103
 
508
- <h2 id="debugging">🔍 Debugging</h2>
104
+ **📖 [Full Documentation](https://developers.cloudflare.com/sandbox/)**
509
105
 
510
- Enable verbose logging:
106
+ - [Get Started Guide](https://developers.cloudflare.com/sandbox/get-started/) - Step-by-step tutorial
107
+ - [API Reference](https://developers.cloudflare.com/sandbox/api/) - Complete API docs
108
+ - [Guides](https://developers.cloudflare.com/sandbox/guides/) - Execute commands, manage files, expose services
109
+ - [Examples](https://developers.cloudflare.com/sandbox/tutorials/) - AI agents, data analysis, CI/CD pipelines
511
110
 
512
- ```typescript
513
- const sandbox = getSandbox(env.Sandbox, "debug-sandbox");
514
- sandbox.client.onCommandStart = (cmd, args) =>
515
- console.log(`Starting: ${cmd} ${args.join(" ")}`);
516
- sandbox.client.onOutput = (stream, data) => console.log(`[${stream}] ${data}`);
517
- sandbox.client.onCommandComplete = (success, code) =>
518
- console.log(`Completed: ${success} (${code})`);
519
- ```
111
+ ## Key Features
520
112
 
521
- <h2 id="known-limitations">🚧 Known Limitations</h2>
113
+ - **Secure Isolation** - Each sandbox runs in its own container
114
+ - **Edge-Native** - Runs on Cloudflare's global network
115
+ - **Code Interpreter** - Execute Python and JavaScript with rich outputs
116
+ - **File System Access** - Read, write, and manage files
117
+ - **Command Execution** - Run any command with streaming support
118
+ - **Preview URLs** - Expose services with public URLs
119
+ - **Git Integration** - Clone repositories directly
522
120
 
523
- - Maximum container runtime is limited by Durable Object constraints
524
- - WebSocket support for preview URLs coming soon
525
- - Some system calls may be restricted in the container environment
121
+ ## Development
526
122
 
527
- <h2 id="contributing">🤝 Contributing</h2>
528
-
529
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
123
+ This repository contains the SDK source code. To contribute:
530
124
 
531
125
  ```bash
532
126
  # Clone the repo
@@ -541,22 +135,30 @@ npm test
541
135
 
542
136
  # Build the project
543
137
  npm run build
138
+
139
+ # Type checking and linting
140
+ npm run check
544
141
  ```
545
142
 
546
- <h2 id="license">📄 License</h2>
143
+ ## Examples
547
144
 
548
- [MIT License](LICENSE)
145
+ See the [examples directory](./examples) for complete working examples:
146
+
147
+ - [Minimal](./examples/minimal) - Basic sandbox setup
148
+ - [Code Interpreter](./examples/code-interpreter) - Use sandbox as an interpreter tool with gpt-oss
149
+ - [Complete](./examples/basic) - Huge example integrated with every sandbox feature
549
150
 
550
- <h2 id="acknowledgments">🙌 Acknowledgments</h2>
151
+ ## Status
551
152
 
552
- Built with ❤️ by the Cloudflare team. Special thanks to all early adopters and contributors.
153
+ **Beta** - The SDK is in active development. APIs may change before v1.0.
154
+
155
+ ## License
156
+
157
+ [MIT License](LICENSE)
553
158
 
554
- ---
159
+ ## Links
555
160
 
556
- <div align="center">
557
- <p>
558
- <a href="https://github.com/cloudflare/sandbox-sdk/issues">Issues</a> •
559
- <a href="https://discord.gg/cloudflaredev">Discord</a> •
560
- <a href="https://twitter.com/CloudflareDev">Twitter</a>
561
- </p>
562
- </div>
161
+ - [Documentation](https://developers.cloudflare.com/sandbox/)
162
+ - [GitHub Issues](https://github.com/cloudflare/sandbox-sdk/issues)
163
+ - [Developer Discord](https://discord.cloudflare.com)
164
+ - [Cloudflare Developers](https://twitter.com/CloudflareDev)