Skip to content

feat(sdk): filesystem-only snapshots (pause memory:false)#1465

Draft
bchalios wants to merge 2 commits into
mainfrom
feat/pause-filesystem-only
Draft

feat(sdk): filesystem-only snapshots (pause memory:false)#1465
bchalios wants to merge 2 commits into
mainfrom
feat/pause-filesystem-only

Conversation

@bchalios

Copy link
Copy Markdown

Summary

Adds an optional memory flag to pause in both the JS and Python SDKs. When memory is false, the pause captures only the filesystem (no memory snapshot); resuming such a snapshot cold-boots (reboots) the sandbox from disk — losing in-memory state, running processes, and open connections. Defaults to true (full memory snapshot), so existing callers are unaffected.

This is the SDK surface for the filesystem-only snapshot feature on the infra side.

Usage

// JS / TS
const sbx = await Sandbox.create()
await sbx.pause({ memory: false })   // filesystem-only snapshot
const resumed = await sbx.connect()  // resumes by cold-booting from disk
# Python (sync)
sbx = Sandbox()
sbx.pause(memory=False)              # filesystem-only snapshot
resumed = sbx.connect()              # resumes by cold-booting from disk

# Python (async)
sbx = await AsyncSandbox.create()
await sbx.pause(memory=False)
resumed = await sbx.connect()

memory defaults to truepause() / pause({}) behave exactly as before.

What changed

  • spec: optional memory: boolean (default true) on POST /sandboxes/{sandboxID}/pause (SandboxPauseRequest); both API clients regenerated via make codegen.
  • JS: Sandbox.pause / betaPause accept { memory }SandboxApi.pause sends the request body.
  • Python: pause(memory=...) / beta_pause_cls_pause (sync + async) sends SandboxPauseRequest(memory=...).
  • Tests: filesystem-only pause+resume reboots the guest while the filesystem survives — JS (tests/sandbox/snapshot.test.ts) and Python sync + async. All pass against a local stack; format / lint / typecheck clean.
  • Changeset: minor for e2b and @e2b/python-sdk.

Note (related infra observation, not addressed here)

While testing, a filesystem-only resume cold-boots into a different default exec context (root / /root) than a memory resume (user / /home/user). The filesystem itself is fully intact; tests use absolute paths to be robust to this. Worth confirming on the infra reboot path whether the template's default user should be restored after a cold boot.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9e798d5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
e2b Minor
@e2b/python-sdk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cursor

cursor Bot commented Jun 19, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Pause now always sends a request body and filesystem-only resume cold-boots the guest (processes and connections lost), which changes sandbox lifecycle semantics for callers opting out of memory snapshots.

Overview
PR description and title refer to a JS memory pause option; the JS SDK in this diff only accepts keepMemory (mapped to API memory). Python keep_memory matches the changeset.

SandboxApi.pause always sends a JSON body (memory: true by default). That is a behavior change from a bodyless POST and may matter for older API gateways or strict clients, though the OpenAPI marks the body optional.

Reviewed by Cursor Bugbot for commit 9e798d5. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 3bfdd0c. Download artifacts from this workflow run.

JS SDK (e2b@2.30.4-feat-pause-filesystem-only.0):

npm install ./e2b-2.30.4-feat-pause-filesystem-only.0.tgz

CLI (@e2b/cli@2.12.2-feat-pause-filesystem-only.0):

npm install ./e2b-cli-2.12.2-feat-pause-filesystem-only.0.tgz

Python SDK (e2b==2.29.3+feat-pause-filesystem-only):

pip install ./e2b-2.29.3+feat.pause.filesystem.only-py3-none-any.whl

@bchalios bchalios force-pushed the feat/pause-filesystem-only branch from 4b7cf94 to d434332 Compare June 19, 2026 14:30

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b7cf94857

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/js-sdk/src/sandbox/index.ts Outdated
Comment on lines 557 to 558
async pause(opts?: ConnectionOpts & { memory?: boolean }): Promise<boolean> {
return await SandboxApi.pause(this.sandboxId, this.resolveApiOpts(opts))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rebuild the sandbox handle after filesystem-only resumes

When memory:false is used on an existing sandbox, callers resume a cold-booted envd through the same object, but the instance connect() path in this file only awaits SandboxApi.connectSandbox(...) and returns this without applying the resume response's envdAccessToken/traffic token or rebuilding the envd/RPC clients. For secure sandboxes where a filesystem-only cold boot reinitializes envd and returns fresh credentials, subsequent commands/files calls on this object still send the pre-pause headers, so the resume appears to succeed but guest operations fail; refresh the instance state or direct this flow through static Sandbox.connect(sandboxId).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the backend should probably keep the current envdAccessToken when resuming from fs-only snapshot

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mishushakov @chatgpt-codex-connector confirmed — the backend keeps the same envdAccessToken across a filesystem-only resume. RebootSandbox re-establishes envd /init auth on the cold boot with the same access token (via the MMDS path), and the resume/connect response returns that same token. The infra PR has an integration test for exactly this — TestSecureSandboxFilesystemOnlyResumeAuth: it pauses a secure sandbox with memory:false, cold-boot resumes it, then authorizes an envd request with the original token captured before the pause and reads back a file written pre-pause.

So the existing handle's credentials stay valid after a filesystem-only resume — no rebuild needed. This isn't a new code path on the SDK side: memory:false only changes how the backend persists/restores the snapshot; the SDK resume flow (connect) is unchanged and identical to a memory resume. The instance connect() returning this is pre-existing behavior shared with memory resume, and it remains correct because the token and sandbox domain are stable across the resume.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bchalios bchalios force-pushed the feat/pause-filesystem-only branch from d434332 to d54797f Compare June 19, 2026 14:35

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d54797f. Configure here.

Comment thread packages/js-sdk/src/sandbox/index.ts Outdated
@bchalios bchalios marked this pull request as draft June 19, 2026 14:43
@bchalios bchalios force-pushed the feat/pause-filesystem-only branch from d54797f to 57674a0 Compare June 19, 2026 14:52

@mishushakov mishushakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything looks good - only thing is that i believe the envd token should be persistent across pause/resume cycle.
please use SandboxPauseOpts consistently.

Comment thread packages/js-sdk/src/sandbox/index.ts Outdated
* ```
*/
async pause(opts?: ConnectionOpts): Promise<boolean> {
async pause(opts?: ConnectionOpts & { memory?: boolean }): Promise<boolean> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're not using the SandboxPauseOpts here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was anchored to the pre-amend commit — it's addressed in the latest commit (57674a071): both pause and betaPause now take the exported SandboxPauseOpts (and the static SandboxApi.pause/betaPause too), matching how createSnapshot uses CreateSnapshotOpts. resolveApiOpts spreads the opts through, so memory reaches SandboxApi.pause.

/**
* @deprecated Use {@link Sandbox.pause} instead.
*/
async betaPause(opts?: ConnectionOpts): Promise<boolean> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're not using SandboxPauseOpts here

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bchalios bchalios force-pushed the feat/pause-filesystem-only branch from 57674a0 to 59a8378 Compare June 19, 2026 16:34
@bchalios

Copy link
Copy Markdown
Author

Per offline feedback from @mishushakov, renamed the SDK-facing parameter to make the drop-on-false semantics explicit:

  • JS/TS: pause({ keepMemory: false })
  • Python: pause(keep_memory=False)

The wire/spec field stays memory (the contract with the API in the infra PR is unchanged) — the SDK simply maps keepMemory/keep_memory onto the memory body field with identical semantics (true = keep the full memory snapshot). No generated files changed. Typecheck/lint/format pass for both SDKs; changeset and docstrings updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants