## Summary
- Skip the unnecessary `isRunning()` API call and `wait(400)` when
`--follow` is not set in `sandbox logs`, preventing flaky timeouts in
the backend integration test
- Fix `waitForSandboxEnd` to return the `running` variable instead of
the `isRunning` function reference, so the follow-mode loop actually
terminates when the sandbox stops
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small control-flow fixes in the CLI logs loop and sandbox status
monitor; low blast radius with minimal behavioral change beyond making
termination conditions correct.
>
> **Overview**
> `sandbox logs` now breaks out immediately after printing the first
batch when `--follow` isn’t set, avoiding extra status polling/sleeps
that could cause flaky timeouts.
>
> Fixes `waitForSandboxEnd` to return the mutable `running` boolean
(instead of the `isRunning` function reference), so follow-mode loops
can actually stop when the sandbox exits.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
87cd7af5b1bdf9a7a4fe16e7a2100256b3d55d7b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Example:
```
e2b sbx create base -d
```
Output:
```
Use the following link to inspect this Sandbox live inside the E2B Dashboard️:
↪ https://e2b.dev/dashboard/inspect/sandbox/i4dct03zur3guplje3eia
Sandbox created with ID i4dct03zur3guplje3eia using template base
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small CLI behavior change isolated to sandbox creation/connection
flow; primary risk is unintended behavior differences in terminal-attach
path due to the refactor.
>
> **Overview**
> Adds `-d, --detach` to `e2b sandbox create` so users can create a
sandbox and get its dashboard/ID output without connecting a terminal.
>
> Refactors sandbox creation to happen in the command handler and passes
the created `sandbox` into `connectSandbox`, which now only manages the
keep-alive loop and terminal attachment when not detached.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cb8be14bb71073b8299010cd45509ca2a58ca32e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR updates the sandbox spawn process to print the inspect URL to
the console when a new sandbox is created using `e2b sbx spawn` or `e2b
sbx create`. This makes it easier for users to access and debug new
sandboxes directly after creation.
<img width="556" height="87" alt="Screenshot 2025-09-15 at 2 54 22 PM"
src="https://github.com/user-attachments/assets/783129e3-443d-4a7c-a86e-a4265d90831f"
/>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: primarily adds extra CLI output and URL construction with
env-configurable base; no changes to sandbox lifecycle or auth logic.
>
> **Overview**
> **Prints a Dashboard inspection link when connecting to or creating a
sandbox.** Both `sandbox connect` and `sandbox create` now output a
terminal-clickable E2B Dashboard *Inspect Sandbox* URL immediately after
obtaining the `sandboxId`.
>
> Adds `DASHBOARD_BASE`/`SANDBOX_INSPECT_URL` (env-overridable via
`E2B_DASHBOARD_BASE`/`E2B_DOMAIN`) and a new
`printDashboardSandboxInspectUrl` helper to format and print the link,
plus a changeset bump for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f132029f7540408e47e4c37ee58716c95c63a000. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- 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
- When E2B_API_KEY is set via environment variable, the CLI no longer
falls back to the teamId from
~/.e2b/config.json, avoiding "Team ID param mismatch with the API key"
errors
- Adds E2B_TEAM_ID environment variable support
- Introduces resolveTeamId() helper with clear precedence: --team CLI
flag > E2B_TEAM_ID env var > config
file (only when E2B_API_KEY env var is not set)
Problem
When using E2B_API_KEY env var (e.g. for local development or CI with a
different team), the CLI still
reads teamId from ~/.e2b/config.json and sends it as a query parameter.
If the config file belongs to a
different team than the API key, the API rejects the request with 400:
Team ID param mismatch with the
API key.
Changes
- api.ts: Export E2B_TEAM_ID env var, add resolveTeamId() helper
- list.ts, build.ts, delete.ts, publish.ts: Use resolveTeamId() instead
of inline userConfig?.teamId
fallback
Test plan
- Set E2B_API_KEY to a key from team A, have ~/.e2b/config.json with
team B's ID → e2b template list
should work (no mismatch error)
- Set both E2B_API_KEY and E2B_TEAM_ID → CLI uses the env var team ID
- Without any env vars, normal e2b auth login flow still works as before
- --team flag still takes highest priority
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small, localized change to CLI argument/env/config precedence for team
selection; main risk is behavior changes for users relying on implicit
`~/.e2b/config.json` teamId when also setting `E2B_API_KEY`.
>
> **Overview**
> Fixes sandbox template commands failing with "Team ID param mismatch"
when `E2B_API_KEY` is set via environment by changing team resolution
precedence and avoiding `~/.e2b/config.json` team fallback in that case.
>
> Introduces `E2B_TEAM_ID` and a centralized `resolveTeamId()` helper
(CLI flag > env var > local `e2b.toml` > user config *only when no env
API key*), and updates template `build`, `list`, `delete`, and `publish`
flows to use it consistently. Adds a changeset bump for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
905172fc8e59f8325a8d36af913326f7eb47a15f. 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>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds the ability to execute commands inside a running sandbox from the
CLI.
>
> - New `sandbox exec` command (`exec.ts`): runs a command in a
specified sandbox, supports `--background`, `--cwd`, `--user`, and
repeatable `--env` options; streams stdout/stderr; returns remote exit
code; explicitly disallows stdin piping due to protocol limitations
> - Signal handling utility (`utils/signal.ts`): installs/removes
handlers to kill the remote process on termination signals
> - Registers `exec` in `sandbox/index.ts`
> - Updates `configOption` help in `options.ts` to recommend the new
build system
> - Adds changeset for `@e2b/cli` minor release
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dcbc64211934c1f92ff033ff77ff6ad50497e8a7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Current instructions would fail unless e2b was already installed
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Add `e2b` install instructions to template init/migrate outputs and
README, with minor wording tweaks and a patch changeset.
>
> - **CLI (templates)**:
> - Update `template init` and `template migrate` post-run output to
include installing `e2b` (`npm install e2b` or `pip install e2b`).
> - Reword headings to “To get started with your template” and clarify
build command labels (run dev/prod build).
> - **Docs/Templates**:
> - Add “Installing Dependencies” section to
`packages/cli/src/templates/readme.hbs` with language-specific `e2b`
install instructions.
> - **Release**:
> - Add patch changeset for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
68d3093b910ef711923ecfc300ab9fc2ece69456. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Here's what it will look like. This highlights that the files are no
longer used.
```
🔄 Migrating template configuration to SDK format...
Using language: TypeScript
✅ Generated TypeScript template files:
./template.ts
./build.dev.ts
./build.prod.ts
📁 Old template files no longer needed:
./e2b.Dockerfile → ./e2b.Dockerfile.old
./e2b.toml → ./e2b.toml.old
🎉 Migration completed successfully!
🔨 You can now build your template using:
npx tsx build.dev.ts (for development)
npx tsx build.prod.ts (for production)
Learn more about Template SDK: https://e2b.dev/docs
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Post-migration, the CLI renames `e2b.Dockerfile` and `e2b.toml` to
`.old` and refactors migration to use Dockerfile content directly.
>
> - **CLI Template Migration
(`packages/cli/src/commands/template/migrate.ts`)**
> - **Refactor**: `migrateToLanguage` now accepts `dockerfileContent`
(string) instead of a path; Dockerfile retrieval moved to the command
action via `getDockerfile`.
> - **Post-migration cleanup**: Renames `e2b.Dockerfile` and `e2b.toml`
to `*.old` if present and logs old→new paths.
> - Minor output tweaks (status messages/icons).
> - **Tests (`packages/cli/tests/commands/template/migrate.test.ts`)**
> - Add checks ensuring `e2b.Dockerfile.old` and `e2b.toml.old` exist
and originals are removed across fixtures/languages.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5fc1add2ac8e688b7509c299211b53ac6b09188e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Set default user for Dockerfiles. Includes also small migrate fixes.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Defaults Dockerfile-based templates to user 'user' and workdir
'/home/user', updates CLI templates (sudo start/ready, relative Python
import), and allows template migration without a config file.
>
> - **SDKs (Dockerfile parsing)**:
> - JS (`packages/js-sdk/src/template/dockerfileParser.ts`) and Python
(`packages/python-sdk/e2b/template/dockerfile_parser.py`): after
parsing, set defaults `setUser('user')` and `setWorkdir('/home/user')`.
> - **CLI Templates**:
> - Python build scripts: switch to relative import `from .template
import template`.
> - Generated template hbs: start/ready commands now prefixed with
`sudo`; removed explicit root/workdir before start/ready.
> - **CLI Migrate**:
> - Supports migration without `e2b.toml`; uses default config values
and prints a warning instead of exiting.
> - Initializes default config when missing; success messaging adjusted.
> - **Tests**:
> - Update fixtures to reflect new defaults (`set_user('user')`,
`set_workdir('/home/user')`, `sudo` start/ready, relative imports).
> - Relax error case to succeed with warning when config is missing.
> - Comment out stacktrace tests for `fromDockerfile` in JS/Python until
fixed.
> - **Changesets**: Patch bumps for `@e2b/cli`, `@e2b/python-sdk`, and
`e2b`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
934dc3b23b5607f70d4a4f5b7a9413a9d04df28a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Adds beta MCP support to JS/Python SDKs with template auto-selection,
config POST, MCP URL helpers, and codegen for MCP types/schemas.
>
> - **SDKs (Beta MCP support)**:
> - **JS SDK**:
> - Add `McpServer` types and export; extend `Sandbox.betaCreate` with
`mcp` option that auto-selects `mcp-gateway-v0`, configures MCP via POST
`/config` on port `50005` with retries, and expose `betaGetMcpUrl()`.
> - Add `wait(ms)` util; generate MCP types from `spec/mcp-server.json`;
new `generate:mcp` script and dev dep `json-schema-to-typescript`.
> - **Python SDK**:
> - Generate and export `McpServer` (TypedDict); extend sync/async
`beta_create` with `mcp` option, auto-select default MCP template, POST
MCP config with retries, and add `beta_get_mcp_url()`; define `mcp_port`
and `default_mcp_template`.
> - Makefile: add `generate-mcp` target; include
`datamodel-code-generator` in tooling; update lockfile/pyproject deps.
> - **Tooling**:
> - Add `spec/mcp-server.json` schema; update codegen Dockerfile to
install `datamodel-code-generator`.
> -
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cf3f175d310d4c242cd2e867efd801f5c04f2099. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Jonas Scholz <Jonas.Scholz@bbscholz.de>
Add template `build-v2` command that uses template SDK
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Introduce `template build-v2` command that builds templates directly
from a Dockerfile via the Template SDK and wire it into the CLI.
>
> - **CLI - Template**:
> - **New Command**: `template build-v2`
(`packages/cli/src/commands/template/build-v2.ts`)
> - Builds from Dockerfile using SDK:
`Template(...).fromDockerfile(...)` and `Template.build(...)`.
> - Options: `--dockerfile`, `--cmd`, `--ready-cmd`, `--cpu-count`,
`--memory-mb`, `--no-cache`, path via `--path`; alias `bd-v2`.
> - Validations: template name format, even `memory-mb`.
> - Auth/config: uses access token, API key, domain; streams build logs;
prints success examples.
> - **Wiring**: Add `buildV2Command` to
`packages/cli/src/commands/template/index.ts`.
> - **Release**: Changeset adds patch for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
33578b56dfbcd76c3bb2ecf7fdf6f2cb80c3d0dd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR fixes 2 bugs that made the follow option in `e2b sbx logs` not
work:
1. `e2b sbx logs -f <id>` failed to follow because the `isRunning`
function was always returning false due to the API call being
unauthenticated if you dont have the `E2B_API_KEY` environment variable
set.
This follows the existing pattern from other API calls:
https://github.com/e2b-dev/E2B/blob/c4ce97e9b9a1809e3419d64499c1e56f9138e3d0/packages/cli/src/commands/sandbox/list.ts#L138-L152
Eventually it would make sense to handle the error here, for now just a
hotfix to fix the --follow usage
2. Once it actually followed, it never stopped following because
`isRunning` was not inside the loop and always true. Now when you kill
the sandbox follow actually stops following
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Fixes `e2b sbx logs -f` by authenticating `isRunning` and re-checking
sandbox state each loop so following works and stops when closed.
>
> - **CLI — `packages/cli/src/commands/sandbox`**:
> - **Logs follow behavior (`logs.ts`)**:
> - Re-check `isRunning(sandboxID)` inside the loop (`isSandboxRunning`)
instead of using a cached promise, ensuring follow stops when sandbox is
closed or not found.
> - **Sandbox state check auth (`utils.ts`)**:
> - Use `ensureAPIKey()` and pass `apiKey` to
`Sandbox.getInfo(getShortID(sandboxID), { apiKey })` so `isRunning` is
authenticated.
> - **Release**:
> - Changeset adds patch for `@e2b/cli` with note: fix sbx logs follow
option.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5fbd87166b70aca7229ccc1ff8fa2c27f12b1641. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Follow up my last PR, improves DX consistency and added docs.
Changelog
- format "table" > "pretty" to match other commands (metrics, logs)
- added doc section
**Changelog**
- Added ability to pass multiple sandbox ids to "sbx kill id1 id2 id3"
- Added ability to filter sandboxes to be killed by metadata and by
state using --state, --metadata (requires --all)
- Fixed metadata parser and moved to utils
Adds a deprecated `spawn` command to the CLI, ensuring backward
compatibility and guiding users toward the preferred `create` command.
```
$ e2b sandbox
Usage: index sandbox|sbx [options] [command]
work with sandboxes
Options:
-h, --help display help for command
Commands:
connect|cn <sandboxID> connect terminal to already running sandbox
list|ls [options] list all sandboxes, by default it list only running ones
kill|kl [options] [sandboxID] kill sandbox
create|cr [options] [template] create sandbox and connect terminal to it
logs|lg [options] <sandboxID> show logs for sandbox
metrics|mt [options] <sandboxID> show metrics for sandbox
help [command] display help for command
```
```
$ sbx sp base
Warning: The 'spawn' command is deprecated and will be removed in future releases. Please use 'e2b sandbox create' instead.
Terminal connecting to template base with sandbox ID in897x2dqs7aws8h1x0in
```
Introduce beta submodule with beta features - pause and resume
Update Sandbox list to also return paused sandboxes
---------
Co-authored-by: Tomas Valenta <valenta.and.thomas@gmail.com>
- CLI spawn, connect, and logs work with and without the client part
provided
- JavaScript and Python SDKs are no longer returning IDs with client
part
## Description
Add option for a template ready check. You can specify `ready_cmd` which
will be run until it exits with code 0. Max timeout is 5 minutes. After
exit code 0, the template will be marked as ready.
If no ready command is defined, `sleep 20` is assumed when the start
command is present, and `sleep 0` when none is defined. It is also
possible to define ready command without any start command. This might
be helpful if the filesystem contains self-booted services (e.g. using
systemd).
```
ready_cmd = "echo 'Starting ready check'; sleep 40; echo 'Template is ready'"
```
This adds possibility to configure the default 20 seconds wait time for
a start command.
New documentation can be found at `/docs/sandbox-template/ready-cmd`.
## Checklist
- [x] Make sure the https://github.com/e2b-dev/infra/pull/719 is
deployed
---------
Co-authored-by: Vasek Mlejnsky <vasek@e2b.dev>
Co-authored-by: Jakub Novák <jakub@e2b.dev>