<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Changes how instance methods merge and forward connection options (api
key/domain/headers/timeouts) to API calls in both JS and Python SDKs,
which can affect request routing and auth headers. Regression tests
reduce risk but behavior changes could impact callers relying on
previous (incorrect) defaults.
>
> **Overview**
> Fixes **missing propagation of instance `connectionConfig`** when
calling sandbox instance methods (notably `pause`/`betaPause`/`connect`,
plus related methods) so default config is always forwarded and per-call
overrides still win.
>
> In the JS SDK this centralizes option merging via a new
`resolveApiOpts()` helper and updates multiple `SandboxApi.*` calls to
use it; in the Python SDK it updates `Sandbox.connect()` and
`Sandbox.pause()` (sync + async) to pass
`self.connection_config.get_api_params(**opts)`.
>
> Adds regression tests in both SDKs to assert defaults are forwarded
and overrides are applied correctly.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
60aa6ca1c386d99613976269106298267d5dbfbe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Changes public error/exception types in both JS and Python SDKs by
introducing new subclasses and remapping 404/NotFound conditions, which
may affect downstream error handling despite deprecation shims.
>
> **Overview**
> **Distinguishes “sandbox not found” from “file/directory not found”
across the SDKs.** Adds `FileNotFound*` and `SandboxNotFound*`
error/exception types (with `NotFound*` marked deprecated) and updates
sandbox lifecycle APIs to throw `SandboxNotFound*` for
missing/non-running sandboxes.
>
> Refactors envd HTTP/RPC error handling in both JS and Python to
support overridable status/code→error maps, and wires filesystem
operations to map 404/`NotFound` into `FileNotFound*`. Tests are updated
accordingly, and patch changesets are added for both packages.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
73da92694c02f71355b1f8625845c82865bf3b1d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Enable glob patterns to match files starting with dot (e.g., `.env`,
`.gitignore`)
- JS SDK: Add `dot: true` to glob calls in `getAllFilesInPath`
- Python SDK: Add `glob.DOTMATCH` flag to glob calls in
`get_all_files_in_path`
- Add comprehensive tests for dotfile handling in both SDKs
Previously, the glob library defaults prevented dotfiles from being
matched, preventing upload of configuration files like `.env`. This fix
enables proper handling of dotfiles in template file uploads.
## Test plan
- ✅ All 16 JS SDK tests pass (4 new dotfile tests)
- ✅ All 17 Python SDK tests pass (4 new dotfile tests)
- ✅ `pnpm run format` passes
- ✅ `pnpm run lint` passes
- ✅ `pnpm run typecheck` passes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small, well-scoped change to glob options that only broadens matched
file sets; main risk is unintentionally including hidden files unless
excluded via ignore patterns.
>
> **Overview**
> Template file collection now includes dot-prefixed files and
directories (e.g., `.env`, `.gitignore`, `.hidden/**`) when
building/uploading templates.
>
> This updates globbing in the JS SDK’s `getAllFilesInPath` to set `dot:
true` (including recursive directory expansion) and the Python SDK’s
`get_all_files_in_path` to add `glob.DOTMATCH`, and adds targeted tests
in both SDKs to verify dotfile inclusion and that ignore patterns still
exclude specified dotfiles. A changeset bumps both `e2b` and
`@e2b/python-sdk` as patch releases.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fc3cbcc232bc28559d38bb267162d3f55138b558. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Implements the `lifecycle` prop on `Sandbox.create`, taking over and
deprecating the `beta_pause` functionality.
Currently supports:
- `on_timeout`: `kill` (default) | `pause`. Controls what should happen
to the sandbox when it hits end of life. Pause allows for resuming
- `auto_resume`: False (default) | True. Whether the sandbox should
autoresume on traffic
Intended for additional functionality as we update the backend to
support additional props. Blocked from deploying until the API and
client-proxy are deployed but for pre-approval.
(Meant to be extended later as add more capabilities to the API)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes the API contract and request payload shape for sandbox
auto-resume and alters lifecycle/timeout behavior mapping, which could
break older integrations if backend/client versions are mismatched.
>
> **Overview**
> Adds a new `lifecycle` configuration on `Sandbox.create` (JS + Python)
to control what happens at timeout (`kill` vs `pause`) and whether
paused sandboxes auto-resume on traffic (`auto_resume`).
>
> Deprecates `betaPause`/`beta_pause` and the JS `autoPause` create
option in favor of the new lifecycle semantics, updates connect/pause
call paths accordingly, and expands tests to cover resume-on-connect and
auto-resume behaviors.
>
> Updates the OpenAPI contract and generated clients so `autoResume` is
now an object with an `enabled: boolean` flag (removing the previous
policy enum), and bumps SDK versions via a changeset.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
515f9b7fc13a5ec13db75450e8f6252e3c7bcf03. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Add `GET /templates/{templateID}/tags` endpoint to the OpenAPI spec
- Add `Template.getTags()` to JS/TS SDK
- Add `Template.get_tags()` (sync) and `AsyncTemplate.get_tags()`
(async) to Python SDK
- Returns a list of `TemplateTag` objects with `tag`, `buildId`, and
`createdAt` fields
## Test plan
- Added unit tests for JS SDK (`Template.getTags` happy path + 404
error)
- Added unit tests for Python SDK (sync + async, happy path + error)
The infra now validates sandbox ID format (^[a-z0-9]+$), allowing only
lowercase alphanumeric characters. The test was using
'non-existing-sandbox' which fails format validation due to hyphens,
returning a 400 error instead of reaching the expected 404 path.
This updates the test to use 'nonexistingsandbox' — a valid format that
doesn't exist, so it properly hits the 404 "not found" response and
returns false as expected.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: test-only change that updates hardcoded IDs to match new
validation rules, without modifying runtime logic.
>
> **Overview**
> Updates JS and Python SDK `kill non-existing sandbox` tests to use a
lowercase alphanumeric sandbox ID (`nonexistingsandbox`) instead of a
hyphenated one, so the tests exercise the intended *not-found* path
rather than failing format validation.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e43acb66ef4465ae60a368ac8c7377023b4a6da3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Jakub Novak <jakub@e2b.dev>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Mostly CI/test changes plus a small logging tweak; low production
impact, with main risk being altered test timing/flake behavior due to
new timeout defaults.
>
> **Overview**
> Improves release-candidate GitHub workflows by passing sanitized
`tag`/`preid` via step `env` vars and quoting them when running `npm
version`/`npm publish`, reducing the chance of input/expansion issues.
>
> Stabilizes sandbox internet-access tests in JS and Python by switching
the curl target to Google’s `generate_204` endpoint and updating
expected status codes. Python tests also tighten global `pytest` timeout
to 30s, remove per-sandbox default timeouts from fixtures, and add 180s
timeouts specifically for template test suites via new `conftest.py`
files.
>
> CLI sandbox status polling now logs the caught error when
`Sandbox.getInfo` fails (instead of silently returning `false`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
187849338dd46f9d0dd1adb0a070719ebad87309. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Resolved 43 type diagnostics reported by ty (Astral's Python type
checker)
- Fixed Self type issues on class singletons
- Added explicit type annotations for shadowed attributes
- Replaced None with UNSET for auto-generated API parameters
- Fixed method signature alignment for protocol matching
- Added targeted type: ignore suppressions for pattern-based limitations
All checks pass: ty check, ruff format, ruff check.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Mostly typing/CI changes, but some adjustments affect sandbox
connect/pause overload dispatch and API response/parameter handling
(`UNSET` vs `None`), which could alter edge-case runtime behavior.
>
> **Overview**
> Fixes Python SDK static typing issues for Astral’s `ty` checker and
wires typechecking into CI.
>
> Adds a new `Typecheck` GitHub Action plus workspace `typecheck`
scripts (TS packages via `tsc`, Python SDK via `make typecheck` running
`ty`), and publishes a patch changeset for `@e2b/python-sdk`.
>
> Across the Python SDK, adjusts type annotations and overloads (e.g.,
`Self`/singleton typing, `connect` overloads, optional
`user`/token/domain handling), tightens API model parsing with
`cast`/`Optional` checks and `UNSET` usage, and adds a few targeted `ty`
ignore comments in tests/protocols to silence checker limitations.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f66402847c40cee7e44e1aaa7caa97e271ba9978. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Add path validation to the copy method in both JS and Python SDKs to
ensure source paths are always relative and don't escape the context
directory.
This prevents:
- Absolute paths like /absolute/whatever (Unix) or C:\whatever (Windows)
- Path traversal attacks like ../whatever or ./foo/../../../bar
The validation works cross-platform using Node's
path.isAbsolute/normalize and Python's os.path.isabs/normpath plus
PureWindowsPath for detecting Windows paths on Unix.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes behavior of `copy`/`copy_items` to throw earlier for
previously-accepted absolute or escaping paths, which could break some
consumers; logic is localized and well-covered by tests.
>
> **Overview**
> Prevents path traversal in template `copy` operations by validating
`src` is *relative* and does not escape the context directory (rejects
absolute paths and `..`-based escapes) in both the JS and Python SDKs.
>
> Updates `copyItems`/`copy_items` error handling to preserve the
caller’s stack trace when validation fails, adds unit coverage for the
new path validator plus new stack-trace tests for absolute-path
failures, and ships as patch releases via a changeset.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c1a8eb978e3fd99fa829d571e811bb7ee18cd40b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fixes issue with missing `restore` and `reset` functionality on the
async git sandboxes.
Consolidate shared git helpers by moving remote URL argument
construction and
parsing into the git utilities package. Sync and async git modules now
reuse
the same builders where possible, with tests to ensure no drift.
---------
Co-authored-by: Filip Brebera <filip@bxxf.dev>
# Sandbox Git Commands
Adds Git support to the sandbox class. This allows the sandbox to manage
git via standard clone, checkout, branch, add, pull, and push commands
without needing to use commands.run. The API mirrors common Git
workflows while handling sandbox-specific concerns like auth injection
and safe remote handling.
**Python example**
```python
from e2b import Sandbox
sandbox = Sandbox.create()
repo_path = '/home/user/my-repo'
# Optional: set author for commits
sandbox.git.configure_user('Your Name', 'you@example.com')
# Clone or init
sandbox.git.clone('https://github.com/org/repo.git', path=repo_path)
# or
sandbox.git.init(repo_path, initial_branch='main')
# Make a change
sandbox.files.write(f'{repo_path}/README.md', '# Hello\n')
# Commit
sandbox.git.add(repo_path, files=['README.md'])
sandbox.git.commit(repo_path, message='Initial commit')
# Branching
sandbox.git.create_branch(repo_path, 'feature1')
# or
sandbox.git.checkout_branch(repo_path, 'main')
# Push
sandbox.git.remote_add(repo_path, 'origin', 'https://github.com/org/repo.git', overwrite=True)
sandbox.git.push(repo_path, remote='origin', branch='main', set_upstream=True)
```
**JavaScript / TypeScript example**
```ts
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create()
const repoPath = '/home/user/my-repo'
await sandbox.git.configureUser('Your Name', 'you@example.com')
await sandbox.git.clone('https://github.com/org/repo.git', { path: repoPath })
// or
await sandbox.git.init(repoPath, { initialBranch: 'main' })
await sandbox.files.write(`${repoPath}/README.md`, '# Hello\n')
await sandbox.git.add(repoPath, { files: ['README.md'] })
await sandbox.git.commit(repoPath, { message: 'Initial commit' })
await sandbox.git.createBranch(repoPath, 'feature1')
await sandbox.git.checkoutBranch(repoPath, 'main')
await sandbox.git.remoteAdd(repoPath, 'origin', 'https://github.com/org/repo.git', {
overwrite: true,
})
await sandbox.git.push(repoPath, { remote: 'origin', branch: 'main', setUpstream: true })
```
**Main commands**
- `clone`: Clone a repo into the sandbox. Supports `branch`, `depth`,
optional `username` + `password` for private repos, and
`dangerously_store_credentials` / `dangerouslyStoreCredentials` to keep
credentials in the remote URL.
- `init`: Initialize a new repo. Supports `initial_branch` /
`initialBranch` and `bare`.
- `status`: Get parsed `git status --porcelain -b` info.
- `branches`: List branches and current branch.
- `create_branch` / `createBranch`: Create and check out a new branch.
- `checkout_branch` / `checkoutBranch`: Switch to an existing branch.
- `delete_branch` / `deleteBranch`: Delete a branch. Supports `force`.
- `add`: Stage files. Supports explicit files or `all`.
- `commit`: Create a commit. Supports author override and `allow_empty`.
- `reset` / `reset`: Reset `HEAD` (supports modes like `soft`, `mixed`,
`hard`, etc.) and optional paths.
- `restore` / `restore`: Restore files or unstage changes (`worktree` /
`staged`) from a source ref.
- `pull`: Pull from a remote. Supports `remote`, `branch`, and optional
auth.
- `push`: Push to a remote. Supports `remote`, `branch`, `set_upstream`,
and optional auth.
- `remote_add` / `remoteAdd`: Add a remote. Supports `overwrite` and
`fetch`.
- `remote_get` / `remoteGet`: Read a remote URL.
- `set_config` / `setConfig`: Set a git config value. Supports `scope`
(`global`, `local`, `system`), and `path` for local scope.
- `get_config` / `getConfig`: Read a git config value. Supports the same
`scope` options and returns `None` / `undefined` if unset.
- `dangerously_authenticate` / `dangerouslyAuthenticate`: Persist
credentials via the git credential helper (global).
- `configure_user` / `configureUser`: Set default `user.name` and
`user.email` for commits.
- `create_github_repo` (Python only): Create a GitHub repo from inside
the sandbox and optionally add it as a remote.
**Status shape**
- `status` returns a `GitStatus` with `current_branch` /
`currentBranch`, `upstream`, `ahead`, `behind`, `detached`, and
`file_status` / `fileStatus`.
- `file_status` entries include `name`, `status`, `index_status` /
`indexStatus`, `working_tree_status` / `workingTreeStatus`, `staged`,
and optional `renamed_from` / `renamedFrom`.
- Convenience helpers include: `is_clean` / `isClean`, `has_changes` /
`hasChanges`, `has_staged` / `hasStaged`, `has_untracked` /
`hasUntracked`, `has_conflicts` / `hasConflicts`, plus counts
(`total_count` / `totalCount`, `staged_count` / `stagedCount`,
`unstaged_count` / `unstagedCount`, `untracked_count` /
`untrackedCount`, `conflict_count` / `conflictCount`). In Python these
are properties on the `GitStatus` object; in JS they are fields on the
returned object.
**Notes**
- For private HTTPS remotes, pass `username` + `password` (token) on
`clone`, `pull`, or `push`.
- Use `remote_add` / `remoteAdd` with `overwrite=True` to update an
existing remote URL and `fetch=True` to fetch after.
- Use `dangerously_authenticate` / `dangerouslyAuthenticate` only when
you want to persist credentials globally on the sandbox.
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Optimizes file uploads in both JS and Python SDKs to avoid unnecessary
reads and add broader input support.
>
> - JS SDK: `Filesystem.write`/`writeFiles` now build a single
`FormData` using `toBlob` (new util) to pass
`string`/`ArrayBuffer`/`Blob`/`ReadableStream` without pre-reading;
updated tests add `ReadableStream` coverage
> - Python SDK (sync/async): `write_files` accepts `str`/`bytes`
directly, reads `TextIOBase`, and passes `IOBase` (binary) streams
through without reading; new tests cover `BytesIO` and `StringIO`
> - Changeset: patch bumps for `@e2b/python-sdk` and `e2b`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
45516e31fa8ba8b678824a6c1adc217287a8effe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
To fix the inconsistency between the Python SDK and the JS SDK, add
writeFiles to the JS SDK. (no changes made to write function)
---------
Co-authored-by: Mish Ushakov <10400064+mishushakov@users.noreply.github.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Aligns metrics APIs to use Unix seconds (no milliseconds) for
`start`/`end` across SDKs.
>
> - **JS SDK**: `SandboxMetricsOpts` `start`/`end` now `Date` only;
convert to seconds before calling `GET /sandboxes/{sandboxID}/metrics`.
> - **Python SDK (async/sync)**: send `int(timestamp())` for
`start`/`end` instead of milliseconds.
> - **Tests**: JS and Python tests now pass `start`/`end` and validate
non-empty results.
> - **Changesets**: patch notes for `e2b` and `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7c59f8023fc0de9a5eda7ffd4c588057c7465f3e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Integration tests will fail until the feature is deployed in E2B Cloud
production.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Enables checking template alias availability from both SDKs.
>
> - JS: Implements `checkAliasExists` in `template/buildApi.ts`, exposes
`Template.aliasExists` in `template/index.ts`, adds `AliasExistsOptions`
type and tests
> - Python: Adds `Template.alias_exists` and
`AsyncTemplate.alias_exists` wired to generated
`get_templates_aliases_{alias}` client; includes sync/async tests
> - API: Regenerates schemas/clients to include `GET
/templates/aliases/{alias}`, template build logs endpoint and
parameters, and supporting models (e.g., `TemplateAliasResponse`)
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4e577fd77888478ac83b66db7537cd2355ea050b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds support for parsing ownership on file copy operations in
Dockerfile-based templates.
>
> - JS: Update `dockerfileParser.ts` to treat `COPY/ADD` as
`ModifiableInstruction`, parse `--chown` via `instruction.getFlags()`,
and pass `user` to `templateBuilder.copy(src, dest, { user })`
> - Python: Update `_handle_copy_instruction` in `dockerfile_parser.py`
to extract `--chown=<user[:group]>` and pass `user` to
`template_builder.copy(src, dest, user=user)`
> - Tests: Add JS and Python (sync/async) tests verifying `COPY --chown`
parsing and argument propagation
> - Changeset: Patch releases for `@e2b/python-sdk` and `e2b`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9f3b151be18288bdcc41eaf37157b5d4572f0abf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Introduce `connect` methods to attach to running PTY sessions across
JS and Python SDKs, with tests and default timeout handling.
>
> - **SDKs**:
> - **JS (`packages/js-sdk/src/sandbox/commands/pty.ts`)**:
> - Add `Pty.connect(pid, opts?)` to attach to running PTYs; accepts
`PtyConnectOpts` with `onData`, `timeoutMs`, and `requestTimeoutMs`.
> - Factor default PTY connection timeout via
`defaultPtyConnectionTimeout` and apply to `create`/`connect` calls.
> - **Python**:
> - Async: Add `AsyncSandbox.pty.connect(pid, on_data, timeout?,
request_timeout?)` in `e2b/sandbox_async/commands/pty.py`.
> - Sync: Add `sandbox.pty.connect(pid, timeout?, request_timeout?)` in
`e2b/sandbox_sync/commands/pty.py`.
> - **Tests**:
> - JS: `packages/js-sdk/tests/sandbox/pty/ptyConnect.test.ts` validates
connect/reconnect and output handling.
> - Python: async and sync tests under
`packages/python-sdk/tests/.../pty/test_pty_connect.py` verify
reconnection and exit codes.
> - **Release**:
> - Changeset: minor version bumps for `@e2b/python-sdk` and `e2b`; note
“added option to connect to a running pty session”.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
539c4f518606544dfcef253df5bde49354fe7903. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adjusts the watch directory test to modify the file content and scan
returned events for a WRITE on the target file instead of asserting the
first event.
>
> - **Tests (python-sdk)**:
> - Updates `tests/sync/sandbox_sync/files/test_watch.py`
`test_watch_directory_changes` to:
> - Write updated content after `watch_dir` is started.
> - Iterate over `handle.get_new_events()` to find a
`FilesystemEventType.WRITE` for the target filename, asserting its
presence.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f32678e4ed4b141ff9dc498fd9c655f374a66c76. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
What was happening is that the following snippet:
```dockerfile
CMD ["sleep", "20"]
```
Was incorrectly converted to:
```
sleep, 20
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Fixes parsing of Dockerfile CMD/ENTRYPOINT array syntax to a proper
start command and updates tests accordingly.
>
> - **Python SDK**:
> - `e2b/template/dockerfile_parser.py`: Parse CMD/ENTRYPOINT JSON array
(e.g., `["sleep", "20"]`) into a space-joined command (`sleep 20`) and
set as `start_cmd`.
> - **Tests**:
> - JS SDK and Python (sync/async): Add ENTRYPOINT case and assert
`startCmd`/`_start_cmd` equals `sleep 20`.
> - **Release**:
> - Changeset: patch bump for `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ed257ab11e618ece3e5fe70f232a3265fd857ad4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Caches Playwright binaries in JS CI and refactors JS/Python template
tests to use API mocks and aliases, add Dockerfile tests, and update
install APIs to single-package calls.
>
> - **CI**:
> - Cache Playwright binaries on `ubuntu-22.04` and `windows-latest` in
`.github/workflows/js_sdk_tests.yml` to speed JS SDK tests.
> - **JS SDK Tests**:
> - Extend `buildTemplate` options to accept `alias` in
`tests/setup.ts`.
> - Add `fromDockerfile` tests and switch some builds to
`fromBaseImage`; add build-from-base-template test.
> - Update install method tests to single-package calls for
`aptInstall`, `npmInstall`, `bunInstall`, `pipInstall`.
> - Tweak `makeSymlink` test order to ensure overwrite behavior.
> - Overhaul stacktrace tests to use `msw` server mocks and alias-based
failure mapping.
> - **Python SDK Tests**:
> - `build`/`async_build` fixtures accept optional `alias`.
> - Add `from_dockerfile` tests (sync/async); use base image/base
template where applicable.
> - Update install method tests to single-package calls.
> - Rewrite stacktrace tests to monkeypatch API calls with alias-based
failure mapping.
> - **Dependencies**:
> - Add dev dependency `msw` to `packages/js-sdk/package.json`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1b7f84f4ce692f664c3ce4cdb345f4c3a028b17a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Add Windows to CI matrices and make JS/Python utils and tests
cross-platform via path handling updates.
>
> - **CI**:
> - Add Windows to test matrices in `cli_tests.yml`, `js_sdk_tests.yml`,
`python_sdk_tests.yml`; set bash shell/workdirs; disable fail-fast for
some jobs.
> - Python CI runs `pytest -n 4` via Poetry.
> - **JS SDK**:
> - Path normalization for globbing (`normalizePath`) and use of
`Path.relativePosix()` in hashing and tar creation in
`src/template/utils.ts`.
> - **Python SDK**:
> - Add `normalize_path` and use forward-slash glob patterns in
`e2b/template/utils.py`.
> - **Tests**:
> - Make stack trace parsing robust to Windows paths; use `basename` in
file assertions; adjust Python tar tests tempdir fixture handling.
> - **Changeset**: add patch note for windows-related fixes.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1b8dbe4a1af642dbcb86500837e93f7998b223f6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Joseph Lombrozo <joe.lombrozo@e2b.dev>
Fixes issue https://github.com/e2b-dev/E2B/issues/1032
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Preserve Dockerfile USER/WORKDIR when provided and only apply E2B
defaults if absent, with tests and CLI fixtures updated accordingly.
>
> - **Dockerfile parsing (SDKs)**:
> - **JS (`packages/js-sdk/src/template/dockerfileParser.ts`)**: Track
`USER`/`WORKDIR` usage and only set E2B defaults (`user`, `/home/user`)
if not specified; keep Docker defaults (`root`, `/`) initially.
> - **Python
(`packages/python-sdk/e2b/template/dockerfile_parser.py`)**: Same
behavior—preserve explicit `USER`/`WORKDIR`, fallback to defaults only
when absent.
> - **Tests**:
> - **JS**: Add tests for default vs. custom `USER`/`WORKDIR` in
`fromMethods.test.ts`.
> - **Python (async/sync)**: Add analogous tests in
`test_from_methods.py`.
> - **CLI template fixtures**:
> - Update expected outputs to remove redundant
`.set_user('user')`/`.set_workdir('/home/user')` when already specified;
minor ordering tweak for `.setStartCmd` in TS fixture.
> - **Changeset**:
> - Minor version bumps for `@e2b/python-sdk` and `e2b`; note: keep
Docker `WORKDIR` and `USER` if specified.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1ce66362501932308292cef87b5d8a73012ee5f2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This takes some shortcuts in order to keep backwards compatibility.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Reuses a singleton httpx transport/client across the SDK, introduces a
generic retry decorator for connect calls, and refactors code/tests to
use the shared clients and fixtures.
>
> - **SDK (transport/client reuse)**
> - Add global `limits` (configurable via `E2B_*` env vars) and switch
`ApiClient` to accept `transport` instead of `limits`.
> - Introduce `e2b.api.client_async/client_sync` with `get_transport()`
(singleton) and `get_api_client()`; update `Sandbox`/`AsyncSandbox`,
paginators, and sandbox APIs to use them.
> - Remove per-class `_limits` from `SandboxBase`/`TemplateBase`; merge
extra headers correctly; pass `E2b-Sandbox-Port` as string.
> - Template build flows (sync/async) now reuse the API client's
underlying httpx client for file uploads.
> - **Connect client** (`e2b_connect/client.py`)
> - Add `_retry` decorator and apply to unary/server-stream methods;
simplify reconnection logic; minor typing/headers cleanups.
> - **Tests**
> - Add retry unit tests; introduce
`sandbox_factory`/`async_sandbox_factory` and a session `event_loop`;
refactor tests to use factories and shared transports; adjust tar
archive expectations.
> - **Misc**
> - Add `.editorconfig`, CLI `.envrc`, and changeset entries.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1d359231b63dc21b6c8d797886f7d6a77c9ed6b7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Tomas Valenta <valenta.and.thomas@gmail.com>
Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com>
- Individual tests must complete in less than 5 minutes
- Add a `make test` option that runs tests
- Upgrade poetry to 2.1.1 (the lock file was generated by this version,
so this just matches what we already expect)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Ensure file uploads honor ignore patterns (incl. .dockerignore),
refactor file discovery/tar streaming in JS/Python SDKs, and add
comprehensive tests.
>
> - **File upload behavior**:
> - JS/TS and Python uploads now pass `ignorePatterns` (merged from
`fileIgnorePatterns` and `.dockerignore`) to tar creation, ensuring
ignored files aren’t uploaded.
> - **Refactor/Utilities**:
> - Rename `getAllFilesForFilesHash` -> `getAllFilesInPath` with
optional directory inclusion in both SDKs.
> - Implement `tar_file_stream` (JS and Python) to build archives from
`getAllFilesInPath`, with `noDirRecurse` and symlink control.
> - Hashing functions updated to use `getAllFilesInPath`.
> - Type tweak: allow `None` in Python `stack_traces` during build wait.
> - **Integration**:
> - JS `uploadFile` and Python async/sync `upload_file` now use tar
streaming with ignore patterns; JS `Template` wires ignore patterns into
uploads.
> - **Tests**:
> - Add extensive tests for `getAllFilesInPath` and `tar_file_stream` in
JS and Python, covering ignore patterns, directories, sorting, and
symlinks.
> - Remove obsolete tests relying on old function names.
> - **Meta**:
> - Changeset entries for `@e2b/python-sdk` and `e2b` (patch).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2f83444f9006393f33e8c346bec1998b3a06044d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Currently, when you provide a simple folder pattern like `folder/` to
copy() it will not check folders contents for changes (only the folder
metadata itself) which leads to stale caches.
This fix appends ** pattern when no pattern is specified for recursive
hash computation.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Ensure folder COPY patterns hash contents recursively to fix cache
invalidation, adding a shared file-gathering helper, tests, and a Python
glob dependency.
>
> - **Template hashing (JS + Python SDKs)**:
> - Add `getAllFilesForFilesHash`
(`packages/js-sdk/src/template/utils.ts`) and
`get_all_files_for_files_hash`
(`packages/python-sdk/e2b/template/utils.py`) to collect directories and
nested files using glob patterns and ignores.
> - Update `calculateFilesHash`/`calculate_files_hash` to use the new
helpers, hashing recursive paths, metadata, and file contents; handle
symlinks consistently.
> - **Tests**:
> - Add comprehensive tests for recursive matching, ignore patterns,
sorting, empty dirs, symlinks in
`packages/js-sdk/tests/.../getAllFilesForFilesHash.test.ts` and Python
async/sync tests under
`packages/python-sdk/tests/.../test_get_all_files_for_files_hash.py`.
> - **Dependencies**:
> - Add `wcmatch` in `packages/python-sdk/pyproject.toml` for advanced
globbing.
> - **Release**:
> - Patch bump via `.changeset/green-mice-watch.md`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d495427d86ad4e4d5a280567baa63df40a3271fb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Jakub Dobry <jakub.dobry8@gmail.com>
Current env var syntax won't be anymore supported by Docker and is
currently blocking local development.
```
3 warnings found (use docker --debug to expand):
- LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 2)
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Use "ENV key=value" in generated Dockerfiles and add tests; minor
devcontainer path string cast.
>
> - **Template/Dockerfile generation**:
> - **JS SDK (`packages/js-sdk/src/template/index.ts`)**: Handle `ENV`
instructions and output as `ENV key=value ...`.
> - **Python SDK (`packages/python-sdk/e2b/template/main.py`)**: Same
`ENV` formatting; also cast `devcontainer_directory` to `str` in
devcontainer start command.
> - **Tests**:
> - **JS**: Add `toDockerfile` test covering `ENV` output.
> - **Python (sync/async)**: Add tests for `ENV` output in generated
Dockerfiles.
> - **Changeset**: Patch releases for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4a9c504167dd8069551724d83bfa66f0859c1bd4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Use new connect API for JS/Python SDKs to connect and only extend
(never shorten) running sandbox timeouts, with updated types/docs and
tests.
>
> - **SDKs**:
> - **JS**:
> - Replace `resume`/`setTimeout` flow with `SandboxApi.connectSandbox`
calling `POST /sandboxes/{sandboxID}/connect`.
> - Update `Sandbox.connect` (static/instance) to use returned
`sandboxDomain`, `envdAccessToken`, `envdVersion`.
> - Redefine `SandboxConnectOpts` to include `timeoutMs` that only
extends existing timeout.
> - **Python (async/sync)**:
> - Introduce `_cls_connect` using `post_sandboxes_sandbox_id_connect`
with `ConnectSandbox`; return `Sandbox` model.
> - Update `connect` methods to use API response for
domain/token/version; remove extra info fetch.
> - Docstrings clarify timeout only extends for running sandboxes.
> - **Tests**:
> - Add cases ensuring connect does not shorten timeout and does extend
when longer (JS, async Python, sync Python).
> - Preserve error on connecting to non-running sandbox.
> - **Meta**:
> - Changeset: minor releases for `@e2b/python-sdk`, `e2b`, and
`@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e76b07990cb4c05e51ba1c51fb5cc7bbd44b991b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds `fromBunImage` and `bunInstall` to JS/Python SDKs, and extends
`npmInstall` with a `dev` flag, with tests across sync/async suites.
>
> - **Template APIs**:
> - Add `fromBunImage` to start from `oven/bun:<variant>` in
`packages/js-sdk/src/template/index.ts` and
`packages/python-sdk/e2b/template/main.py`.
> - Add `bunInstall(packages, { g, dev })` in both SDKs.
> - Extend `npmInstall` to accept `{ dev: boolean }` in both SDKs.
> - **Types/Docs**:
> - Update `packages/js-sdk/src/template/types.ts` to declare
`fromBunImage`, `bunInstall`, and `npmInstall` `dev` option.
> - **Tests**:
> - Add tests for `fromBunImage` and `bunInstall` and update
`npmInstall` (global/dev) in JS (`packages/js-sdk/tests/...`) and Python
sync/async (`packages/python-sdk/tests/...`).
> - **Changeset**:
> - Minor releases for `@e2b/python-sdk` and `e2b`
(`.changeset/silly-lions-buy.md`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b6461d015743d38ba014d724167d2ca256cf7951. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds a force option to makeSymlink that passes -f to ln, with
typings/docs and tests across JS and Python SDKs.
>
> - **Template symlink enhancement**
> - **JS SDK (`packages/js-sdk`)**:
> - `makeSymlink(src, dest, options)` now accepts `{ user?: string;
force?: boolean }` and appends `-f` when `force` is true in
`src/template/index.ts`.
> - Types updated in `src/template/types.ts`, including example usage
with `{ force: true }`.
> - Tests added in `tests/template/methods/makeSymlink.test.ts` (regular
and forced).
> - **Python SDK (`packages/python-sdk`)**:
> - `make_symlink(src, dest, user=None, force=False)` now supports
`force` and appends `-f` when true in `e2b/template/main.py`.
> - Docstring examples updated to include `force=True`.
> - Tests added for async and sync in
`tests/async/template_async/methods/test_make_symlink.py` and
`tests/sync/template_sync/methods/test_make_symlink.py`.
> - **Release**:
> - Changeset added for patch releases of `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6c5bbf9edfc7234b703046f387d11b8f10a002ab. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This was causing some unexpected issues if users were trying to
apt-install some packages that needed recommended dependencies.
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds an option to `aptInstall`/`apt_install` to toggle
`--no-install-recommends`, updates typings/docs, and adds tests for both
modes.
>
> - **Template APIs**:
> - **JS SDK (`packages/js-sdk`)**:
> - `aptInstall` now accepts `options?: { noInstallRecommends?: boolean
}` and conditionally includes `--no-install-recommends`.
> - Types updated in `src/template/types.ts` with example usage.
> - **Python SDK (`packages/python-sdk`)**:
> - `apt_install` now accepts `no_install_recommends: bool = False` and
conditionally includes `--no-install-recommends`.
> - **Tests**:
> - JS: Add `aptInstall` tests (with and without `noInstallRecommends`);
refactor `npmInstall` tests to use `buildTemplateTest` helper.
> - Python: Add async and sync tests for `apt_install` with and without
`no_install_recommends`.
> - **Changeset**:
> - Patch bumps for `@e2b/python-sdk` and `e2b` with note on making
`--no-install-recommends` optional.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3963b7daca73f1cfb99f405b09fbfb86c40c4b4f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
The "lts" tag was unavailable on Docker Hub
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Switch default Ubuntu image tag from 'lts' to 'latest' across
JS/Python SDKs and expand/refactor template tests and test config.
>
> - **SDKs**:
> - **Ubuntu default**: Change `fromUbuntuImage`/`from_ubuntu_image`
default variant from `'lts'` to `'latest'` in
`packages/js-sdk/src/template/index.ts` and
`packages/python-sdk/e2b/template/main.py`; update TS docs in
`packages/js-sdk/src/template/types.ts`.
> - **Tests**:
> - **JS**: Refactor template tests to use `buildTemplateTest`, add
`tests/template/methods/fromMethods.test.ts`, adjust npm/pip/runCmd
tests (include user install with `g: false`), and remove per-test
timeouts where not needed.
> - **Python (async/sync)**: Add comprehensive tests for from* methods,
npm/pip installs (including user installs), and runCmd behaviors; switch
to shared build fixtures.
> - **Vitest config**: Exclude `tests/template/**` from the main suite
and include all template tests in a dedicated project in
`vitest.workspace.mts`.
> - **Changeset**:
> - Patch bumps for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0bf3a7c15122d28cbc99b8faa44e7e217f634377. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
(no tests as nothin was breaking)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Adds an optional `user` parameter to fs-related template methods and
`gitClone`, with tests for running commands as specific users.
>
> - **SDKs**:
> - **JS (`packages/js-sdk`)**:
> - Add `user` option to `TemplateBuilder` methods: `remove`, `rename`,
`makeDir`, `makeSymlink`, and `gitClone`; pass through to `runCmd`.
> - Update type defs and examples in `src/template/types.ts`.
> - **Python (`packages/python-sdk`)**:
> - Add `user` arg to `TemplateBuilder` methods: `remove`, `rename`,
`make_dir`, `make_symlink`, and `git_clone`; forward to `run_cmd`.
> - Update docstrings/examples.
> - **Tests**:
> - JS: add `runCmd` tests for default, specific `user`, and invalid
user in `packages/js-sdk/tests/template/methods/runCmd.test.ts`.
> - Python: add async and sync `run_cmd` tests (default, specific
`user`, invalid user) in
`packages/python-sdk/tests/async/.../test_run_cmd.py` and
`packages/python-sdk/tests/sync/.../test_run_cmd.py`.
> - **Release**:
> - Add changeset (`.changeset/warm-seals-design.md`) marking patch
bumps for `@e2b/python-sdk` and `e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b0cbedc1d5c136367155c5646859842bd666b0d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This will help for local development
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Add support to override the API base URL via `api_url` parameter or
`E2B_API_URL` env var with clear precedence.
>
> - **Python SDK**:
> - **ConnectionConfig**:
> - Add `api_url` parameter and `_api_url()` env lookup (`E2B_API_URL`).
> - Resolve `api_url` in order: constructor arg > `E2B_API_URL` >
`debug` localhost or `https://api.<domain>`.
> - **API Params**:
> - Include `api_url` in `ApiParams` and propagate via `get_api_params`.
> - **Tests** (`packages/python-sdk/tests/test_connection_config.py`):
> - Verify default, arg override, env override, and precedence.
> - **Changeset**: Patch release for `@e2b/python-sdk`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9be6d4e85bb0ad8ea52ad61c77530ac72f231c54. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->