withruntime 0.9.0 → 0.11.0

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 (124) hide show
  1. package/BLAXEL.md +4 -4
  2. package/DAYTONA.md +52 -40
  3. package/E2B.md +65 -62
  4. package/README.md +15 -7
  5. package/README.src.md +15 -7
  6. package/VERCEL.md +34 -22
  7. package/compatibility-lock.json +16 -16
  8. package/dist/blaxel/errors.js +1 -1
  9. package/dist/blaxel/lookup.d.ts +3 -2
  10. package/dist/blaxel/lookup.js +3 -2
  11. package/dist/blaxel/pagination.d.ts +2 -2
  12. package/dist/blaxel/pagination.js +45 -17
  13. package/dist/blaxel/preview.d.ts +2 -1
  14. package/dist/blaxel/preview.js +15 -13
  15. package/dist/blaxel/process.js +56 -10
  16. package/dist/blaxel/sandbox.d.ts +2 -0
  17. package/dist/blaxel/sandbox.js +2 -0
  18. package/dist/blaxel/snapshot.js +3 -5
  19. package/dist/cli.d.ts +2 -0
  20. package/dist/cli.js +262 -56
  21. package/dist/client.d.ts +41 -3
  22. package/dist/client.js +67 -11
  23. package/dist/cloudflare/identity.d.ts +7 -0
  24. package/dist/cloudflare/identity.js +13 -0
  25. package/dist/cloudflare/index.d.ts +9 -0
  26. package/dist/cloudflare/index.js +47 -9
  27. package/dist/cloudflare/worker.d.ts +4 -0
  28. package/dist/cloudflare/worker.js +166 -16
  29. package/dist/codesandbox/guest-service.js +57 -20
  30. package/dist/codesandbox/index.js +42 -8
  31. package/dist/compat/core.d.ts +9 -8
  32. package/dist/compat/core.js +60 -21
  33. package/dist/compat/files.js +22 -4
  34. package/dist/compat/lease.d.ts +36 -0
  35. package/dist/compat/lease.js +87 -0
  36. package/dist/credentials.d.ts +6 -1
  37. package/dist/credentials.js +107 -38
  38. package/dist/daytona/computer-use.d.ts +162 -0
  39. package/dist/daytona/computer-use.js +324 -0
  40. package/dist/daytona/context.d.ts +10 -0
  41. package/dist/daytona/context.js +24 -0
  42. package/dist/daytona/daytona.d.ts +20 -0
  43. package/dist/daytona/daytona.js +134 -20
  44. package/dist/daytona/filesystem.d.ts +17 -4
  45. package/dist/daytona/filesystem.js +129 -38
  46. package/dist/daytona/index.d.ts +3 -27
  47. package/dist/daytona/index.js +2 -7
  48. package/dist/daytona/process.d.ts +63 -6
  49. package/dist/daytona/process.js +224 -23
  50. package/dist/daytona/sandbox.d.ts +20 -6
  51. package/dist/daytona/sandbox.js +55 -32
  52. package/dist/e2b/client.d.ts +5 -0
  53. package/dist/e2b/client.js +6 -2
  54. package/dist/e2b/commands.d.ts +43 -12
  55. package/dist/e2b/commands.js +217 -64
  56. package/dist/e2b/errors.d.ts +7 -0
  57. package/dist/e2b/errors.js +20 -0
  58. package/dist/e2b/filesystem.d.ts +2 -1
  59. package/dist/e2b/filesystem.js +43 -6
  60. package/dist/e2b/index.d.ts +3 -2
  61. package/dist/e2b/index.js +2 -1
  62. package/dist/e2b/pty.d.ts +24 -0
  63. package/dist/e2b/pty.js +83 -0
  64. package/dist/e2b/sandbox.d.ts +17 -6
  65. package/dist/e2b/sandbox.js +239 -43
  66. package/dist/e2b/users.d.ts +30 -0
  67. package/dist/e2b/users.js +185 -0
  68. package/dist/file-source.d.ts +16 -0
  69. package/dist/file-source.js +162 -0
  70. package/dist/freestyle/index.d.ts +9 -1
  71. package/dist/freestyle/index.js +38 -5
  72. package/dist/index.d.ts +3 -1
  73. package/dist/login.js +16 -10
  74. package/dist/mcp.d.ts +2 -1
  75. package/dist/mcp.js +6 -1
  76. package/dist/modal/index.js +2 -1
  77. package/dist/network-cli.js +139 -43
  78. package/dist/openai-agents/index.js +9 -45
  79. package/dist/page.d.ts +1 -1
  80. package/dist/page.js +2 -2
  81. package/dist/products/browser.d.ts +60 -0
  82. package/dist/products/browser.js +37 -0
  83. package/dist/products/desktop.d.ts +2 -2
  84. package/dist/products/desktop.js +2 -2
  85. package/dist/products/images.d.ts +3 -1
  86. package/dist/products/images.js +14 -2
  87. package/dist/products/index.d.ts +14 -0
  88. package/dist/products/index.js +12 -0
  89. package/dist/products/network-products.d.ts +7 -0
  90. package/dist/products/network-products.js +3 -0
  91. package/dist/products/observability.d.ts +44 -0
  92. package/dist/products/observability.js +6 -0
  93. package/dist/products/previews.d.ts +8 -2
  94. package/dist/products/previews.js +11 -3
  95. package/dist/products/private-network.d.ts +22 -0
  96. package/dist/products/private-network.js +10 -0
  97. package/dist/products/volumes.d.ts +42 -0
  98. package/dist/products/volumes.js +36 -0
  99. package/dist/products/watch.js +61 -8
  100. package/dist/proxy.js +3 -1
  101. package/dist/runloop/index.d.ts +13 -27
  102. package/dist/runloop/index.js +149 -52
  103. package/dist/sandbox.d.ts +59 -8
  104. package/dist/sandbox.js +479 -68
  105. package/dist/snapshots.d.ts +9 -4
  106. package/dist/sprites/index.js +69 -33
  107. package/dist/tar.d.ts +3 -1
  108. package/dist/tar.js +140 -14
  109. package/dist/transport.d.ts +4 -7
  110. package/dist/transport.js +205 -122
  111. package/dist/types.d.ts +5 -2
  112. package/dist/vercel/command.d.ts +1 -1
  113. package/dist/vercel/command.js +3 -2
  114. package/dist/vercel/errors.d.ts +1 -1
  115. package/dist/vercel/errors.js +7 -1
  116. package/dist/vercel/index.d.ts +1 -7
  117. package/dist/vercel/index.js +1 -3
  118. package/dist/vercel/sandbox-user.d.ts +70 -0
  119. package/dist/vercel/sandbox-user.js +206 -0
  120. package/dist/vercel/sandbox.d.ts +55 -20
  121. package/dist/vercel/sandbox.js +353 -99
  122. package/dist/vercel/snapshot.d.ts +3 -2
  123. package/dist/vercel/snapshot.js +9 -5
  124. package/package.json +2 -1
package/BLAXEL.md CHANGED
@@ -10,8 +10,8 @@ load it.
10
10
  import { SandboxInstance } from "withruntime/blaxel"; // was: from "@blaxel/core"
11
11
  ```
12
12
 
13
- The mapping was written against `@blaxel/core` 0.3.23 and Blaxel's sandbox API
14
- source, checked 27 September 2026. Every name `@blaxel/core` exports can be
13
+ The mapping was written against `@blaxel/core` 0.3.24 and Blaxel's sandbox API
14
+ source, checked 30 September 2026. Every name `@blaxel/core` exports can be
15
15
  imported: code that only mentions an agent, model or MCP helper still loads.
16
16
 
17
17
  ## Keys
@@ -100,7 +100,7 @@ name, or through `getByExternalId`, use the same Runtime key.
100
100
  | `process.exec` without `waitForCompletion` | One Runtime process, answered running. Its Blaxel name is kept in its command line, so `get("name")` finds it from any client. |
101
101
  | `process.exec({ waitForCompletion: true })` | One streamed call, answered with `status`, `exitCode`, `stdout`, `stderr` and `logs`. Past `timeout` the wait ends with a 422 and the process runs on. |
102
102
  | `onLog`, `onStdout`, `onStderr`, `streamLogs` | The process's output as it comes; `streamLogs` gives whole lines, as Blaxel's does. |
103
- | `process.get`, `wait`, `list`, `logs`, `stop`, `kill`, `writeStdin`, `closeStdin` | Runtime processes by id or name. `wait` follows the output instead of polling. `stop` is SIGTERM, `kill` SIGKILL. |
103
+ | `process.get`, `wait`, `list`, `logs`, `stop`, `kill`, `writeStdin`, `closeStdin` | Runtime processes by id or name. `wait` follows output with one deadline covering lookup and output. Cancellation leaves the process running. `stop` is SIGTERM, `kill` SIGKILL. |
104
104
  | `keepAlive`, `timeout` | The sandbox does not pause for idleness while the process may run (its `timeout`, 600 s by default, 0 for as long as a lease allows); once no `keepAlive` process runs, it gets its idle pause back. |
105
105
  | `restartOnFailure`, `maxRestarts`, `waitForPorts`, `workingDir`, `env`, `stdin` | A restart loop in the same process, with Blaxel's note in the output (`restartCount` counts the notes); a wait in the sandbox for the ports; as in Blaxel. |
106
106
  | `fs.read`, `write`, `readBinary`, `writeBinary`, `writeTree`, `mkdir`, `rm`, `cp` | Runtime's files API, or one command. A path only root may read or write (outside `/workspace`, or made by a root process) goes through sudo, as Blaxel's root-owned API could. |
@@ -208,7 +208,7 @@ leaves those names alone.
208
208
 
209
209
  `bun run test` in `packages/cloud-sdk` runs the unit tests against a fake of
210
210
  Runtime's SDK: `tests/blaxel`, including a check that every name
211
- `@blaxel/core` 0.3.23 exports is exported here.
211
+ `@blaxel/core` 0.3.24 exports is exported here.
212
212
 
213
213
  The end-to-end test runs Blaxel's guides, unmodified but for the import,
214
214
  against the real API: `tests/fixtures/blaxel-quickstart.mjs` (create, processes,
package/DAYTONA.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Code written for Daytona, on Runtime
2
2
 
3
- Run code written for [Daytona](https://www.daytona.io)'s SDK on Runtime Cloud
4
- by changing one import. It is part of Runtime's SDK (`withruntime`), built on
3
+ Supported sandbox calls from [Daytona](https://www.daytona.io)'s SDK keep
4
+ their call shapes on Runtime Cloud after changing the import. It is part of Runtime's SDK (`withruntime`), built on
5
5
  the same client, so it gets that SDK's retries, idempotency keys and errors.
6
6
  Importing `withruntime` alone does not load it.
7
7
 
@@ -16,8 +16,9 @@ from withruntime.daytona import Daytona # was: from daytona import Daytona
16
16
  from withruntime.daytona import AsyncDaytona # was: from daytona import AsyncDaytona
17
17
  ```
18
18
 
19
- The mapping was written against `@daytona/sdk` 0.216.1 and `daytona` 0.216.1
20
- on PyPI, checked 23 September 2026.
19
+ The mapping was written against `@daytona/sdk` 0.220.0 and `daytona` 0.220.0
20
+ on PyPI, checked 29 September 2026. The exact releases and artifact hashes
21
+ are kept in `compatibility-lock.json`.
21
22
 
22
23
  ## Keys
23
24
 
@@ -38,10 +39,13 @@ package talks only to Runtime.
38
39
  `autoDeleteInterval` minutes rounded up to whole days. `delete()` ends it.
39
40
  An `ephemeral` sandbox (or `autoDeleteInterval: 0`) ends on `stop()`.
40
41
  - **Auto-stop:** Runtime runs a sandbox on a lease of up to an hour. The lease
41
- is `autoStopInterval` minutes (default 15; `0` is an hour), and every call
42
- through the adapter moves it on once less than half is left, so a sandbox
43
- pauses after that long without calls, as Daytona's does. `ttlMinutes` caps
44
- the renewals and ends the sandbox at the deadline.
42
+ is `autoStopInterval` minutes (default 15), and every call through the
43
+ adapter moves it on once less than half is left, so a sandbox pauses after
44
+ that long without calls, as Daytona's does. Past an hour, or `0` (never),
45
+ the sandbox object also renews the lease each minute while it lives, toward
46
+ `autoStopInterval` after the last call; once the program ends, the sandbox
47
+ pauses within an hour. `ttlMinutes` caps the renewals and ends the sandbox at
48
+ the deadline.
45
49
  - **Funding:** left to Runtime, as `withruntime`'s own `create()` does: the free
46
50
  trial while the account has trial time, then prepaid credit. Pass
47
51
  `withruntime: { create: { funding: "trial" } }` to `new Daytona(...)` or to
@@ -54,31 +58,35 @@ package talks only to Runtime.
54
58
 
55
59
  ## Mapping
56
60
 
57
- | Daytona | On Runtime |
58
- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59
- | `daytona.create()`, `create({ snapshot })` | `sandboxes.create`. Daytona's own snapshots (`daytona-*`) are Runtime's stock image. Any other name is a ready Runtime image of that name, then a Runtime snapshot of that name. |
60
- | `create({ image: "python:3.12" })` | Built once as a Runtime image from the registry reference (named after it), then reused. `onSnapshotCreateLogs` receives the build log. |
61
- | `create({ image: Image.debianSlim(...).pipInstall(...)... })` | The Dockerfile Daytona's `Image` stands for, with its local files, built as a Runtime image named after its content and reused. |
62
- | `resources`, `envVars`, `labels`, `name`, `volumes` | `vcpu`, `memoryMiB`, `diskMiB`; environment given to every command; labels; name; Runtime volumes by id or by name. |
63
- | `networkBlockAll`, `networkAllowList`, `domainAllowList`, `outboundProxyUrl` | Runtime network rules (`internet: false`, or an `allow` list); the proxy as `HTTP_PROXY` and `HTTPS_PROXY` for commands. |
64
- | `public: true` | `getPreviewLink(port)` shares the port publicly; without it, privately with a token. |
65
- | `language` | The language of `codeRun`, kept in Daytona's `code-toolbox-language` label so a sandbox found later keeps it. |
66
- | `daytona.get(idOrName)`, `daytona.list({ labels, states, name })` | `sandboxes.get`, or the newest live sandbox with that name; `sandboxes.list`. Awaiting `list()` gives the older `{ items, total }` shape. |
67
- | `process.executeCommand(cmd, cwd, env, timeout)` | `exec` under bash with stderr joined to stdout, as Daytona's `result`, streamed so the whole output comes back. A non-zero exit is a result. Past `timeout` (seconds): `DaytonaProcessExecutionTimeoutError`. |
68
- | `process.codeRun(code, { argv, env })` | `python3 -c`, `node -e` or `bun -e` by the sandbox's language. `artifacts.charts` is always empty. |
69
- | `createSession`, `executeSessionCommand`, `getSessionCommandLogs` | One bash per session, kept running: directory, variables and functions carry from one command to the next. `runAsync` returns at once; logs stream to callbacks. |
70
- | `sendSessionCommandInput`, `getSession`, `getSessionCommand`, `deleteSession` | Input to the session's shell, which the running command reads; the commands sent through this object; killing the shell. |
71
- | `fs.uploadFile(s)`, `downloadFile(s)`, `listFiles`, `getFileDetails` | Runtime's files API. Relative paths resolve from `/workspace`. `owner` and `group` are always `""`. |
72
- | `fs.createFolder`, `deleteFile`, `moveFiles`, `setFilePermissions` | `mkdir -m`, `files.remove`, `files.rename`, `chmod` and `sudo chown`. |
73
- | `fs.findFiles`, `searchFiles`, `replaceInFiles` | `grep -rn`, a files glob, and a read and write of each file. |
74
- | `git.clone`, `status`, `add`, `commit`, `push`, `pull`, branches | The sandbox's git. Credentials reach git through the environment, never the command line. |
75
- | `codeInterpreter.runCode`, contexts | Runtime's Python interpreter. The sandbox's `envVars` reach code through a context made once for them. |
76
- | `start`, `stop`, `pause`, `archive`, `delete`, `fork`, `createSnapshot` | `wake`, `pause` (or `stop` when ephemeral), `pause`, `pause`, `stop`, Runtime's fork with memory, a Runtime snapshot with that name. |
77
- | `getPreviewLink(port)` | A Runtime preview. Send its token as `x-runtime-preview-token`; Daytona's header is `x-daytona-preview-token`. |
78
- | `getUserHomeDir`, `getWorkDir`, `user` | `/workspace`, and `daytona`, so `/home/daytona` (linked to `/workspace` the first time something names it) works. |
79
- | `daytona.snapshot.create`, `get`, `list`, `delete` | Runtime images built, found, listed and deleted by name. |
80
- | `daytona.volume.get`, `list`, `delete` | Runtime volumes by name. |
81
- | Error classes | Daytona's names and parents, by HTTP status. Each also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
61
+ | Daytona | On Runtime |
62
+ | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | `daytona.create()`, `create({ snapshot })` | `sandboxes.create`. Daytona's own snapshots (`daytona-*`) are Runtime's stock image. Any other name is a ready Runtime image of that name, then a Runtime snapshot of that name. |
64
+ | `create({ image: "python:3.12" })` | Built once as a Runtime image from the registry reference (named after it), then reused. `onSnapshotCreateLogs` receives the build log. |
65
+ | `create({ image: Image.debianSlim(...).pipInstall(...)... })` | The Dockerfile Daytona's `Image` stands for, with its local files, built as a Runtime image named after its content and reused. |
66
+ | `resources`, `envVars`, `labels`, `name`, `volumes` | `vcpu`, `memoryMiB`, `diskMiB`; environment given to every command; labels; name; Runtime volumes by id or by name. |
67
+ | `setLabels` (Python `set_labels`) | Replaces customer labels while preserving the language and Runtime compatibility labels; reconnects retain the language. |
68
+ | `networkBlockAll`, `networkAllowList`, `domainAllowList`, `outboundProxyUrl` | Runtime network rules (`internet: false`, or an `allow` list); the proxy as `HTTP_PROXY` and `HTTPS_PROXY` for commands. |
69
+ | `public: true` | `getPreviewLink(port)` shares the port publicly; without it, privately with a token. |
70
+ | `language` | The language of `codeRun`, kept in Daytona's `code-toolbox-language` label so a sandbox found later keeps it. |
71
+ | `daytona.get(idOrName)`, `daytona.list(query)` | `sandboxes.get`, or the newest live sandbox with that name; `sandboxes.list` by labels and states, then Daytona's other filters (`id` and `name` prefixes, CPU, memory, disk, dates), `sort` and `order` here. Awaiting `list()` gives the older `{ items, total }` shape. |
72
+ | `process.executeCommand(cmd, cwd, env, timeout)` | `exec` under bash with stderr joined to stdout, as Daytona's `result`, streamed so the whole output comes back. A non-zero exit is a result. Past `timeout` (seconds): `DaytonaProcessExecutionTimeoutError`. |
73
+ | `process.codeRun(code, { argv, env })` | `python3 -c`, `node -e` or `bun -e` by the sandbox's language. `artifacts.charts` is always empty. |
74
+ | `createSession`, `executeSessionCommand`, `getSessionCommandLogs` | One bash per session, kept running: directory, variables and functions carry from one command to the next. `runAsync` returns at once; logs stream to callbacks. |
75
+ | `sendSessionCommandInput`, `getSession`, `getSessionCommand`, `deleteSession` | Input to the session's shell, which the running command reads; the commands sent through this object; killing the shell. |
76
+ | `fs.uploadFile(s)`, `downloadFile(s)`, `listFiles`, `getFileDetails` | Runtime's files API. Relative paths resolve from `/workspace`. `owner` and `group` are always `""`. |
77
+ | `fs.createFolder`, `deleteFile`, `moveFiles`, `setFilePermissions` | `mkdir -m`, `files.remove`, `files.rename`, `chmod` and `sudo chown`. |
78
+ | `fs.findFiles`, `searchFiles`, `replaceInFiles` | `grep -rn`, a files glob, and a read and write of each file. |
79
+ | `git.clone`, `status`, `add`, `commit`, `push`, `pull`, branches | The sandbox's git. Credentials reach git through the environment, never the command line. |
80
+ | `codeInterpreter.runCode`, contexts | Runtime's Python interpreter. The sandbox's `envVars` reach code through a context made once for them. |
81
+ | `start`, `stop`, `pause`, `archive`, `delete`, `fork`, `createSnapshot` | `wake`, `pause` (or `stop` when ephemeral), `pause`, `pause`, `stop`, Runtime's fork with memory, a Runtime snapshot with that name. |
82
+ | `getPreviewLink(port)` | A Runtime preview. Send its token as `x-runtime-preview-token`; Daytona's header is `x-daytona-preview-token`. |
83
+ | `getUserHomeDir`, `getWorkDir`, `user` | `/workspace`, and `daytona`, so `/home/daytona` (linked to `/workspace` the first time something names it) works. |
84
+ | `create({ user })` (Python `os_user`) | The user must exist in the image, as on Daytona. Commands, sessions and terminals run as it through `sudo`; files written through `fs` are given to it. It joins the owner's group, so both can share `/workspace`. |
85
+ | `process.createPty`, `connectPty`, `listPtySessions`, `resizePtySession` | A shell started with a terminal, which outlives the connection: `disconnect()` leaves it running, `connectPty` attaches again with what it printed so far, `killPtySession` ends it. |
86
+ | `computerUse.mouse`, `keyboard`, `screenshot`, `display`, `recording` | Runtime's desktop. `start()` installs it the first time, which takes a minute or two. Key names are Daytona's or xdotool's. |
87
+ | `daytona.snapshot.create`, `get`, `list`, `delete` | Runtime images built, found, listed and deleted by name. |
88
+ | `daytona.volume.get`, `list`, `delete` | Runtime volumes by name. |
89
+ | Error classes | Daytona's names and parents, by HTTP status. Each also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
82
90
 
83
91
  ## Gaps
84
92
 
@@ -90,22 +98,26 @@ Each of these throws `NotSupportedError` before anything happens. Its
90
98
  | A snapshot name with no Runtime image or snapshot | `daytona.snapshot.create({ name, image })` here, or `npx withruntime image build`. This throws `DaytonaNotFoundError`. |
91
99
  | GPUs, `spot`, `linkedSandbox`, `secrets`, `otelEndpointOverride` | Runtime runs Linux on CPUs. For `secrets`, a Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder. For telemetry, `runtime.otel.create()`. |
92
100
  | A `target` other than `us`, `jwtToken` | Runtime runs in one US region and signs in with keys. |
93
- | `user` other than `daytona` | Commands run as the sandbox owner with passwordless `sudo`. |
94
- | PTY sessions, the entrypoint session, language servers | `sandbox.withruntime.terminal(...)`, and sessions with `runAsync`. |
95
- | `computerUse` | Runtime's desktop, `sandbox.withruntime.desktop`. |
96
- | `setLabels`, `resize`, `recover` | Set labels and resources at create; create a new sandbox. |
101
+ | The entrypoint session, language servers | Sessions with `runAsync`. |
102
+ | Screenshots of a region, with the cursor, scaled, or as WebP | The whole screen as PNG or JPEG; crop and scale it yourself. |
103
+ | `computerUse.accessibility`, the desktop's processes one by one | Screenshots with the mouse and keyboard; `computerUse.getStatus()`, `stop()` and `start()`. |
104
+ | `resize`, `recover` | Set labels and resources at create; create a new sandbox. |
97
105
  | Signed preview URLs, signed upload and download URLs, SSH access | `getPreviewLink`, `fs.uploadFile` and `downloadFile`, `npx withruntime sandbox ssh <id>`. |
98
106
  | `getMetrics` | `sandbox.withruntime.metrics()`: its CPU and memory over time. |
99
107
  | `Image.pipInstallFromPyproject`, snapshot `resources` or `entrypoint` | `pipInstallFromRequirements`; resources at create; a session after create. |
100
108
  | `volume.create(name)` | Runtime volumes have a size: `runtime.volumes.create({ name, sizeMiB })`. |
101
109
  | `secret`, `warmPool` | A Runtime secret for credentials; Runtime starts from warm templates already. |
102
110
  | `runCode(code, { envs })` | `envVars` at create, or `os.environ` in the code. |
103
- | Listing by anything but name, labels and states | Filter the result yourself. |
111
+ | Listing by `isPublic`, `snapshots` or `autoDestroyAt` | Filter by a label you set at create. |
112
+
113
+ File download timeouts are seconds, including buffer and local-path overloads
114
+ and batches. A batch shares one deadline and stops starting later files once
115
+ it expires. JavaScript `downloadFileStream(path, { timeout, signal })` also
116
+ bounds and cancels the stream. An incomplete local download is never published
117
+ as the completed file.
104
118
 
105
119
  Some differences are not refusals:
106
120
 
107
- - Sandbox `envVars` live in the object that created the sandbox;
108
- `daytona.get(id)` from another process does not know them.
109
121
  - A session runs one command at a time. A command sent while another runs
110
122
  waits for it, as it would typed into a shell. Sessions made by another
111
123
  client are found by name, but only their output from then on is known.
package/E2B.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Code written for E2B, on Runtime
2
2
 
3
- Run code written for [E2B](https://e2b.dev)'s SDK on Runtime Cloud by changing
4
- one import. It is part of Runtime's SDK (`withruntime`), built on the same
3
+ Supported sandbox calls from [E2B](https://e2b.dev)'s SDK keep their call
4
+ shapes on Runtime Cloud after changing the import. It is part of Runtime's SDK (`withruntime`), built on the same
5
5
  client, so it gets that SDK's retries, idempotency keys and errors. Importing
6
6
  `withruntime` alone does not load it.
7
7
 
@@ -20,9 +20,9 @@ from withruntime.e2b import Sandbox # was: from e2b import Sandbox
20
20
  from withruntime.e2b.code_interpreter import Sandbox # was: from e2b_code_interpreter import Sandbox
21
21
  ```
22
22
 
23
- The mapping was written against `e2b` 2.51.0 and `@e2b/code-interpreter`
24
- 2.8.0 (Python: `e2b` 2.51.0, `e2b-code-interpreter` 2.10.0), checked
25
- 29 September 2026. The exact package releases and artifact hashes are kept in
23
+ The mapping was written against `e2b` 2.51.0 and checked against `e2b` 2.52.0
24
+ and `@e2b/code-interpreter` 2.8.0 (Python: `e2b` 2.52.0, `e2b-code-interpreter`
25
+ 2.10.1) on 2 October 2026. The exact package releases and artifact hashes are kept in
26
26
  `compatibility-lock.json`.
27
27
 
28
28
  ## Keys
@@ -51,38 +51,40 @@ machine. An E2B key (`e2b_...`) is never sent anywhere. If one is passed as
51
51
 
52
52
  ## Mapping
53
53
 
54
- | E2B | On Runtime |
55
- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
56
- | `Sandbox.create()`, `Sandbox.create(template, opts)` | `sandboxes.create`. `base` and `code-interpreter-v1` are Runtime's stock image. Any other name must be a ready Runtime image with that name. A UUID is an image or a snapshot. |
57
- | `timeoutMs` (Python `timeout`, seconds) | `timeoutSeconds`, rounded up. Under 60 s becomes 60 s, with a warning. Over an hour is refused. |
58
- | `metadata` | labels (at most 32). |
59
- | `envs` | Given to every command and code run through this object. |
60
- | `allowInternetAccess: false` | `network: { internet: false }`. |
61
- | `lifecycle.onTimeout` | `onLeaseEnd`: `kill` is `stop`, `pause` is `pause`. |
62
- | `commands.run(cmd, { cwd, envs, timeoutMs, onStdout, onStderr })` | A native process with streamed output; output lost before it was read sets `truncated` and warns. The default command connection deadline is 60 s; `0` disables it. The sandbox lease still bounds the process. |
63
- | Non-zero exit | Throws `CommandExitError` with `exitCode`, `stdout`, `stderr` and `error` (`exit status N`). A command killed by a signal has `exitCode` -1. |
64
- | Command past its timeout | Disconnects with `TimeoutError` (Python: `TimeoutException`) without killing the command; reconnect by pid to keep reading. |
65
- | `commands.run(cmd, { background: true })` | `spawn`. Returns a `CommandHandle` with `pid`, `wait()`, `kill()` (SIGKILL), `sendStdin`, `closeStdin`, `disconnect`, `stdout`, `stderr`, `exitCode`. |
66
- | `commands.list`, `kill(pid)`, `sendStdin(pid)`, `closeStdin(pid)`, `connect(pid)` | Runtime's processes. A pid is a number derived from Runtime's process id, not the Linux pid. |
67
- | `files.read(path, { format })` | `files.read`. `text`, `bytes`, `blob` and `stream` (Python: `text`, `bytes`, `stream`). |
68
- | `files.write(path, data)`, `write([...])`, `writeFiles` | `files.write`. Parent directories are made, and a file that exists is replaced. |
69
- | `files.list(path, { depth })` | `files.list`, hidden files included. `owner` and `group` come from native metadata, with `""` for older guests that omit them. |
70
- | `files.makeDir`, `exists`, `getInfo`, `rename`, `remove` | `files.stat`, `mkdir`, `rename` (replacing a file that exists) and `remove` (recursive). A missing file throws `FileNotFoundError`. |
71
- | Relative paths | Resolved against the home directory, `/workspace` on Runtime. |
72
- | `/home/user` (E2B's home) | The first time a path, `cwd` or command names it, it becomes a link to `/workspace`, unless something is already there. |
73
- | `sandbox.kill()`, `Sandbox.kill(id)` | `stop`, without waiting. `false` when the sandbox was not found or had already ended. |
74
- | `sandbox.setTimeout(ms)`, `Sandbox.setTimeout(id, ms)` | `extend`: the end moves to now + ms. Moving it earlier is refused. |
75
- | `Sandbox.connect(id, { timeoutMs })`, `sandbox.connect()` | `get`. A paused sandbox is woken. A running one's end moves later, never earlier. An ended one throws `SandboxNotFoundError`. |
76
- | `sandbox.pause()`, `betaPause`, `Sandbox.pause(id)` | `pause`, keeping memory and files. `false` when it was already paused. |
77
- | `getInfo`, `isRunning` | `get`. `templateId` is `base` or the image or snapshot id. `envdVersion` is `runtime`. |
78
- | `Sandbox.list({ query: { metadata, state }, limit })` | `sandboxes.list` by labels and state, oldest first, with E2B's paginator (`hasNext`, `nextItems()`). |
79
- | `fork`, `createSnapshot`, `deleteSnapshot` | Runtime's forks and snapshots. While Runtime has them switched off, they throw `NotSupportedError` with Runtime's own message. |
80
- | `getHost(port)` | `<port>-<id>.runtimehost.com` at once, as E2B answers it, and the port is shared as a public Runtime preview beside the caller (the sync Python sandbox shares it before returning). `await sandbox.getPublicHost(port)` returns once the share has landed. |
81
- | `runCode(code, { language, context, onStdout, onStderr, onResult, onError, timeoutMs })` | Runtime's interpreter: Python, JavaScript, TypeScript, R, Java and Bash, plus Go. The sandbox's `envs` reach code through a context made once for them. `onResult` streams each result and waits for asynchronous callbacks. |
82
- | `Execution`, `Result`, `Logs`, `ExecutionError`, `OutputMessage` | The same shapes. Results that are too large to send inline are fetched and inlined. `logs.stdout` has one entry per line. |
83
- | `createCodeContext`, `listCodeContexts`, `restartCodeContext`, `removeCodeContext` | Runtime's interpreter contexts. |
84
- | `getMetrics({ start, end })`, `Sandbox.getMetrics(id)` | Runtime's measured CPU and memory, one entry per host reading (every minute by default). `diskUsed` is null: Runtime does not read disk use inside the sandbox. |
85
- | Error classes | E2B's names and parents. Each also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
54
+ | E2B | On Runtime |
55
+ | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
56
+ | `Sandbox.create()`, `Sandbox.create(template, opts)` | `sandboxes.create`. `base` and `code-interpreter-v1` are Runtime's stock image. Any other name must be a ready Runtime image with that name. A UUID is an image or a snapshot. |
57
+ | `timeoutMs` (Python `timeout`, seconds) | `timeoutSeconds`, rounded up. Under 60 s becomes 60 s, with a warning. Up to 24 hours, as on E2B: a Runtime lease reaches at most an hour ahead, so while this process runs the adapter extends it every five minutes, never past the end asked for. If the process ends first, the sandbox ends with its last lease, at most an hour later. Over 24 hours throws `InvalidArgumentError`. |
58
+ | `metadata` | labels (at most 32). |
59
+ | `envs` | Given to every command and code run through this object. |
60
+ | `allowInternetAccess: false` | `network: { internet: false }`. |
61
+ | `lifecycle.onTimeout` | `onLeaseEnd`: `kill` is `stop`, `pause` is `pause`. |
62
+ | `commands.run(cmd, { cwd, envs, timeoutMs, onStdout, onStderr })` | A native process started by a streamed exec that reads it from the first byte, so Runtime holds a fast writer back rather than drop output: the result is whole, however long. The default command connection deadline is 60 s; `0` disables it. The process lives up to 24 hours, within the sandbox lease. |
63
+ | Non-zero exit | Throws `CommandExitError` with `exitCode`, `stdout`, `stderr` and `error` (`exit status N`). A command killed by a signal has `exitCode` -1. |
64
+ | Command past its timeout | Disconnects with `TimeoutError` (Python: `TimeoutException`) without killing the command; reconnect by pid to keep reading. |
65
+ | `commands.run(cmd, { background: true })` | `spawn`. Returns a `CommandHandle` with `pid`, `wait()`, `kill()` (SIGKILL), `sendStdin`, `closeStdin`, `disconnect`, `stdout`, `stderr`, `exitCode`. Runtime keeps the last 1 MiB a process printed; anything older that was not read in time is lost, which sets `truncated` and warns. A command with `stdin: true` starts the same way. |
66
+ | `user` (commands, PTY and files) | Runs as that Linux user through `sudo -u`; `root` needs nothing more. A user the sandbox lacks throws `InvalidArgumentError` saying how to add one; none is ever created. `user: "user"` is the sandbox's own user. Watching a directory as another user is refused. |
67
+ | `commands.list`, `kill(pid)`, `sendStdin(pid)`, `closeStdin(pid)`, `connect(pid)` | Runtime's processes. A pid is a number derived from Runtime's process id, not the Linux pid. |
68
+ | `pty.create`, `connect`, `sendInput`, `resize`, `kill` (Python snake_case) | Native PTY processes with lossless byte callbacks. A reader timeout or disconnect detaches without killing the process; reconnect resumes reading. |
69
+ | `files.read(path, { format })` | `files.read`. `text`, `bytes`, `blob` and `stream` (Python: `text`, `bytes`, `stream`). |
70
+ | `files.write(path, data)`, `write([...])`, `writeFiles` | `files.write`. Parent directories are made, and a file that exists is replaced. |
71
+ | `files.list(path, { depth })` | `files.list`, hidden files included. `owner` and `group` come from native metadata, with `""` for older guests that omit them. |
72
+ | `files.makeDir`, `exists`, `getInfo`, `rename`, `remove` | `files.stat`, `mkdir`, `rename` (replacing a file that exists) and `remove` (recursive). A missing file throws `FileNotFoundError`. |
73
+ | Relative paths | Resolved against the home directory, `/workspace` on Runtime. |
74
+ | `/home/user` (E2B's home) | The first time a path, `cwd` or command names it, it becomes a link to `/workspace`, unless something is already there. |
75
+ | `sandbox.kill()`, `Sandbox.kill(id)` | `stop`, without waiting. `false` when the sandbox was not found or had already ended. |
76
+ | `sandbox.setTimeout(ms)`, `Sandbox.setTimeout(id, ms)` | `extend`: the end moves to now + ms, up to 24 hours (past an hour it is carried on as for `timeoutMs`). An earlier end is refused: Runtime cannot end a lease early. |
77
+ | `Sandbox.connect(id, { timeoutMs })`, `sandbox.connect()` | `get`. A paused sandbox is woken. A running one's end moves later, never earlier, up to 24 hours. An ended one throws `SandboxNotFoundError`. |
78
+ | `sandbox.pause()`, `betaPause`, `Sandbox.pause(id)` | `pause`, keeping memory and files. `false` when it was already paused. |
79
+ | `getInfo`, `isRunning` | `get`. `templateId` is `base` or the image or snapshot id. `envdVersion` is `runtime`. |
80
+ | `Sandbox.list({ query: { metadata, state }, limit })` | `sandboxes.list` by labels and state, oldest first, with E2B's paginator (`hasNext`, `nextItems()`, `nextToken`). A `template` or `startedAfter` filter, `order: "desc"` and a saved `nextToken` are applied by the adapter, which reads every match once and pages through them. |
81
+ | `fork`, `createSnapshot`, `deleteSnapshot` | Runtime's memory-preserving forks and snapshots; deleting a snapshot removes that saved capture. A fork's `count` is 1 to 20, as E2B checks it. |
82
+ | `getHost(port)` | `<port>-<id>.runtimehost.com` at once, as E2B answers it, and the port is shared as a public Runtime preview beside the caller (the sync Python sandbox shares it before returning). `await sandbox.getPublicHost(port)` returns once the share has landed. On the free trial a shared port is private and a host alone cannot reach it, so both throw `PublicPreviewNotAllowedError` (Python: `PublicPreviewNotAllowedException`, a kind of `NotSupportedError`) at once. Use `(await sandbox.runtime.previews.create(port)).urlWithToken`, or send its token as the `x-runtime-preview-token` header. |
83
+ | `runCode(code, { language, context, onStdout, onStderr, onResult, onError, timeoutMs })` | Runtime's interpreter: Python, JavaScript, TypeScript, R, Java and Bash, plus Go. The sandbox's `envs` reach code through a context made once for them. `onResult` streams each result and waits for asynchronous callbacks. |
84
+ | `Execution`, `Result`, `Logs`, `ExecutionError`, `OutputMessage` | The same shapes. Results that are too large to send inline are fetched and inlined. `logs.stdout` has one entry per line. |
85
+ | `createCodeContext`, `listCodeContexts`, `restartCodeContext`, `removeCodeContext` | Runtime's interpreter contexts. |
86
+ | `getMetrics({ start, end })`, `Sandbox.getMetrics(id)` | Runtime's measured CPU and memory, one entry per host reading. `diskUsed` is null: Runtime does not read disk use inside the sandbox. |
87
+ | Error classes | E2B's names and parents. Each also carries Runtime's `code`, `hint` and `requestId`, with the original error as `cause`. |
86
88
 
87
89
  ## Gaps
88
90
 
@@ -90,27 +92,23 @@ Each of these throws `NotSupportedError` (Python: `NotSupportedException`)
90
92
  before anything happens. The error's `feature` names the gap and its
91
93
  `alternative` says what to use.
92
94
 
93
- | E2B | Use instead |
94
- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
95
- | An E2B template name with no Runtime image of that name | Build it: `npx withruntime image build --dockerfile e2b.Dockerfile --name <template>`. This throws `TemplateError`. |
96
- | `Template`, `waitForPort` and the other ready checks | `runtime.images.build(...)` |
97
- | `timeoutMs` over one hour | Create with up to an hour, then call `setTimeout` before it ends, as often as needed. |
98
- | `setTimeout` to an earlier time | `kill()` when the work is done. |
99
- | `keepMemory: false` | Runtime's pause keeps memory. |
100
- | `onResume: "reboot"` | Stop the sandbox and create a new one. |
101
- | `fork({ timeoutMs })` | Fork without it, then call `setTimeout` on each fork. |
102
- | `user: "root"` (commands and files) | Prefix the command with `sudo`, which needs no password. |
103
- | `network`, `updateNetwork` | `runtime: { create: { network } }` and `sandbox.runtime.network.set(...)`. |
104
- | `mcp`, `getMcpUrl`, `getMcpToken` | Runtime's own MCP server, `npx withruntime mcp`. |
105
- | `iam`, `Secret` | A Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder. |
106
- | `volumeMounts`, `Volume` | Runtime volumes: `runtime: { create: { volumes: [{ volumeId, path }] } }`. |
107
- | `pty` | `sandbox.runtime.terminal(...)`. |
108
- | `git` | `commands.run("git ...")`. E2B has deprecated its git module too. |
109
- | File `metadata` | Keep it in a file beside the data. |
110
- | `uploadUrl`, `downloadUrl` | `files.write` and `files.read`. |
111
- | `Sandbox.list` by `template` or `startedAfter`, `order: "desc"`, or from a saved `nextToken` | Filter by metadata, and keep the paginator. |
112
- | `runCode(code, { envs })` | A context made with them: `sandbox.runtime.interpreter.contexts.create({ env })`. |
113
- | `domain`, `apiUrl`, `sandboxUrl`, `headers`, `proxy`, `debug` | Remove them. `RUNTIME_API_URL` sets Runtime's origin, and `HTTPS_PROXY` sets a proxy. |
95
+ | E2B | Use instead |
96
+ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
97
+ | An E2B template name with no Runtime image of that name | Build it: `npx withruntime image build --dockerfile e2b.Dockerfile --name <template>`. This throws `TemplateError`. |
98
+ | `Template`, `waitForPort` and the other ready checks | `runtime.images.build(...)` |
99
+ | `setTimeout` to an earlier time | `kill()` when the work is done. |
100
+ | `keepMemory: false` | Runtime's pause keeps memory. |
101
+ | `onResume: "reboot"` | Stop the sandbox and create a new one. |
102
+ | `fork({ timeoutMs })` | Fork without it, then call `setTimeout` on each fork. |
103
+ | `network`, `updateNetwork` | `runtime: { create: { network } }` and `sandbox.runtime.network.set(...)`. |
104
+ | `mcp`, `getMcpUrl`, `getMcpToken` | Runtime's own MCP server, `npx withruntime mcp`. |
105
+ | `iam`, `Secret` | A Runtime secret (`npx withruntime secrets set NAME --host <host>`): the sandbox sees a placeholder. |
106
+ | `volumeMounts`, `Volume` | Runtime volumes: `runtime: { create: { volumes: [{ volumeId, path }] } }`. |
107
+ | `git` | `commands.run("git ...")`. E2B has deprecated its git module too. |
108
+ | File `metadata` | Keep it in a file beside the data. |
109
+ | `uploadUrl`, `downloadUrl` | `files.write` and `files.read`. |
110
+ | `runCode(code, { envs })` | A context made with them: `sandbox.runtime.interpreter.contexts.create({ env })`. |
111
+ | `domain`, `apiUrl`, `sandboxUrl`, `headers`, `proxy`, `debug` | Remove them. `RUNTIME_API_URL` sets Runtime's origin, and `HTTPS_PROXY` sets a proxy. |
114
112
 
115
113
  Directory watches use Runtime's native watch stream. JavaScript uses
116
114
  `files.watchDir(path, onEvent, options)`. Python's synchronous `watch_dir(path)`
@@ -120,16 +118,21 @@ a callback. Stream failures and lost events are reported, never treated as a
120
118
  successful empty watch. A positive watch timeout bounds the client subscription and stops its owned watch;
121
119
  zero leaves the subscription unlimited. The sandbox lease still applies. Both languages refuse watching network mounts.
122
120
 
121
+ PTY `timeoutMs` (Python `timeout`, seconds) defaults to sixty seconds, including
122
+ the opening handshake; zero leaves the reader unlimited. Callbacks receive raw
123
+ bytes while the handle's `stdout` and `stderr` stay empty. PTYs made before
124
+ lossless output support cannot reconnect through this adapter; create a new one.
125
+ The sandbox lease still applies.
126
+
123
127
  Some differences are not refusals, so code that depends on them should check:
124
128
 
125
- - Sandbox-level `envs` live in the object that created the sandbox.
126
- `Sandbox.connect(id)` from another process does not know them.
127
129
  - Runtime's stock image is Ubuntu 24.04 with Python 3.12, Node.js 24 and Bun.
128
130
  The current stock image includes NumPy, pandas and matplotlib; build an image
129
131
  for additional dependencies. Results never carry `chart`. A DataFrame arrives in
130
132
  `extra` under `application/vnd.runtime.table+json`, not in E2B's `data`.
131
- - JavaScript file operations and command creation honor `requestTimeoutMs`.
132
- Python file `request_timeout` bounds the request, including streamed reads. `retries`, `logger`, `secure` and `validateApiKey` are
133
+ - JavaScript file operations, command creation and reads, stdin/EOF, lookup, kill and reconnect honor `requestTimeoutMs` and `signal`.
134
+ Python file `request_timeout` bounds the request, including streamed reads. `retries`, `logger`, `secure`, `validateApiKey` and
135
+ `httpVersion` (Python `http_version`; `'1.1'` or `'2'`, as E2B checks it) are
133
136
  accepted without changing the native transport settings.
134
137
  - Interpreter deadlines follow the pinned packages: JavaScript defaults to
135
138
  sixty seconds and Python to five minutes; zero disables the read deadline.
package/README.md CHANGED
@@ -12,7 +12,7 @@ The client uses `RUNTIME_API_KEY` when it is set, and otherwise the connection
12
12
  this machine saved when the CLI connected it (one browser approval, no key to
13
13
  copy). On a server or a CI runner, set `RUNTIME_API_KEY` from your secret
14
14
  manager: `npx withruntime keys create` prints a new key once after an account
15
- owner approves it in the browser, or create one at
15
+ owner, admin or developer approves it in the browser, or create one at
16
16
  https://withruntime.com/account/keys. Never put a key in browser code, a URL or
17
17
  a command-line argument.
18
18
 
@@ -20,7 +20,8 @@ a command-line argument.
20
20
  import { Sandbox } from "withruntime";
21
21
 
22
22
  await using sbx = await Sandbox.create();
23
- const result = await sbx.exec("python3 -c 'print(6 * 7)'");
23
+ await sbx.files.write("/workspace/invoice.py", "print(sum([125, 250, 375]))\n");
24
+ const result = await sbx.exec("python3 /workspace/invoice.py");
24
25
  console.log(result.exitCode, result.stdout);
25
26
  ```
26
27
 
@@ -30,6 +31,8 @@ Node 22 call `await sbx.stop()`). With no arguments you get the free
30
31
  trial while it lasts (100 free hours, up to eight sandboxes running at once), 2 vCPU, 4 GiB of
31
32
  memory and a 4 GiB disk. The current default image includes NumPy, pandas and
32
33
  matplotlib; see the [sandbox environment](https://withruntime.com/docs/sandbox-environment).
34
+ Omitting `funding` can use prepaid credit after the trial is exhausted. Use
35
+ `Sandbox.create({ funding: "trial" })` for free use only; it never falls back to paid.
33
36
 
34
37
  The sandbox object does the rest:
35
38
 
@@ -57,7 +60,9 @@ no compute; `idlePauseSeconds` sets 10 to 86,400, or 0 for never.
57
60
  `Sandbox.getOrCreate(name)` returns the sandbox with that name, woken if it is
58
61
  paused, or creates it.
59
62
 
60
- The client has `sandboxes`, `images`, `volumes`, `snapshots`, `jobs`, `secrets`,
63
+ `runtime.sandbox`, `snapshot`, `image`, `volume`, `job`, `domain`, `port` and
64
+ `address` name the products as the CLI does. Their existing plural names
65
+ remain aliases of the same product clients. The client has `sandboxes`, `images`, `volumes`, `snapshots`, `jobs`, `secrets`,
61
66
  `limits`, `feedback` and `support`; `webhooks`, `events`, `otel` and `audit`
62
67
  to watch the account; `domains`, `ports`, `addresses`, `tunnel` and `network`
63
68
  to connect sandboxes to your own world (paid accounts); and `mcp`, `sso`,
@@ -65,6 +70,8 @@ to connect sandboxes to your own world (paid accounts); and `mcp`, `sso`,
65
70
  the key is read-only and what its agent may still spend today. Every write carries an idempotency key, made for you, so the SDK's
66
71
  own retries (timeouts, 429, 503) never do anything twice. Errors are typed and
67
72
  carry a `code`, a `hint` and a `requestId`.
73
+ `runtime.usageRequests("7d")` reads the account's API call counts and error rates;
74
+ counts are exact decimal strings, and an empty window has a null `errorPercent`.
68
75
 
69
76
  ## Behind a proxy
70
77
 
@@ -87,7 +94,7 @@ Runtime improves fast because agents tell us what they run into: reports go stra
87
94
 
88
95
  ## Code written for E2B
89
96
 
90
- `withruntime/e2b` runs code written for E2B's SDK on Runtime. Change the
97
+ `withruntime/e2b` translates supported E2B sandbox calls to Runtime. Change the
91
98
  import and set `RUNTIME_API_KEY`. The
92
99
  [switch guide](https://withruntime.com/docs/migrate) covers the other providers
93
100
  and how to work out what you save:
@@ -121,7 +128,7 @@ package list every mapping and gap.
121
128
 
122
129
  ## Code written for Blaxel
123
130
 
124
- `withruntime/blaxel` runs code written for Blaxel's sandbox SDK. Change the
131
+ `withruntime/blaxel` translates supported Blaxel sandbox calls. Change the
125
132
  import:
126
133
 
127
134
  ```ts no-run
@@ -132,7 +139,7 @@ Sandboxes get Blaxel's default of 4096 MB, with one vCPU for every 2048 MB.
132
139
  Standby becomes Runtime's pause: after 60 seconds without a call a sandbox
133
140
  pauses with its memory and processes, and the next call wakes it. Envs,
134
141
  processes by name, files, previews, snapshots, forks and the code interpreter
135
- work as they do on Blaxel, and so do sessions: `sandbox.sessions` makes a
142
+ are supported by the adapter, along with sessions: `sandbox.sessions` makes a
136
143
  Runtime sandbox session and `SandboxInstance.fromSession` drives the sandbox
137
144
  with its token. A Blaxel key is never sent anywhere. Drives, codegen, schedules and Blaxel's agent, model and MCP hosting throw
138
145
  `NotSupportedError` before anything happens, naming what to use instead.
@@ -152,7 +159,8 @@ https://withruntime.com/docs/frameworks.
152
159
  ## CLI
153
160
 
154
161
  ```bash no-run
155
- npx withruntime sandbox run -- python3 -c 'print(6 * 7)' # connects on first use
162
+ printf '%s\n' 'print(sum([125, 250, 375]))' > invoice.py
163
+ npx withruntime sandbox run -- python3 - < invoice.py # connects on first use
156
164
  npx withruntime sandbox create
157
165
  npx withruntime help
158
166
  ```