diff --git a/README.md b/README.md
index 66c5f11..87a2413 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Mintlify Starter Kit
+# Mintlify Starter Kit .
Use the starter kit to get your docs deployed and ready to customize.
diff --git a/docs.json b/docs.json
index 732b55e..0eae860 100644
--- a/docs.json
+++ b/docs.json
@@ -16,26 +16,7 @@
"groups": [
{
"group": "Custom sandbox",
- "pages": [
- "template/quickstart",
- "template/how-it-works",
- "template/caching",
- {
- "group": "Customization",
- "icon": "wand-magic-sparkles",
- "pages": [
- "template/customization/authentication",
- "template/customization/base-image",
- "template/customization/defining-template",
- "template/customization/start-ready-command",
- "template/customization/build",
- "template/customization/logging",
- "template/customization/error-handling"
- ]
- },
- "template/examples",
- "template/migration"
- ]
+ "pages": ["template/quickstart"]
}
]
}
diff --git a/template/caching.mdx b/template/caching.mdx
deleted file mode 100644
index 6db4e8a..0000000
--- a/template/caching.mdx
+++ /dev/null
@@ -1,98 +0,0 @@
----
-title: "Caching"
-description: "How the caching process works"
-icon: "layer-group"
----
-
-The caching concept is similar to [Docker's layer caching](https://docs.docker.com/build/cache/). For each layer command (`.copy()`, `.runCmd()`, `.setEnvs()`, etc.), we create a new layer on top of the existing.
-Each layer is cached based on the command and its inputs (e.g., files copied, command executed, environment variables set).
-If a layer command is unchanged and its inputs are the same as in any previous build, we reuse the cached layer instead of rebuilding it.
-
-This significantly speeds up the build process, especially for large templates with many layers.
-The cache is scoped to the team, so even if you have multiple templates, they can share the same cache if they have identical layers.
-
-## Invalidation
-You can invalidate the caches only partially, or for the whole template.
-
-### Partial
-Force rebuild from the next instruction, use the method:
-
-
-
-```typescript highlight={3}
-const template = Template()
- .fromBaseImage()
- .skipCache()
- .runCmd("echo 'Hello, World!'")
-```
-
-```python highlight={4}
-template = (
- Template()
- .from_base_image()
- .skip_cache()
- .run_cmd("echo 'Hello, World!'")
-)
-```
-
-
-
-This will force rebuild from the next instruction, invalidating the cache for all subsequent instructions in the template.
-
-### Whole Template
-To force rebuild the whole template, you can use also `skipCache`/`skip_cache` parameter in the `Template.build` method:
-
-
-
-```typescript wrap highlight={3}
-Template.build(template, {
- alias: 'my-template',
- skipCache: true, // Configure cache skip (except for files)
-})
-```
-
-```python wrap highlight={4}
-Template.build(
- template,
- alias="my-template",
- skip_cache=True, # Configure cache skip (except for files)
-)
-```
-
-
-
-This will skip the cache usage for the whole template build.
-
-## Files Caching
-When using the `.copy()` command, we cache the files based on their content. If the files haven't changed since the last build, we reuse them from the files cache.
-
-We differ from Docker here. Because we build the template on our infrastructure, we use improved caching on files level.
-Even if you invalidate the layer before `.copy()` (e.g., by changing ENV variables), we'll reuse the already uploaded files.
-The `copy()` command will still be re-executed, but the files for the layer will be reused from the files cache, no need to upload them from your computer again.
-
-To invalidate the cache for all subsequent instructions in the template **AND** the layer files cache, use the `forceUpload`/`force_upload` parameter.
-
-
-
-```typescript highlight={3}
-const template = Template()
- .fromBaseImage()
- .copy("config.json", "/app/config.json", { forceUpload: true })
-```
-
-```python highlight={4}
-template = (
- Template()
- .from_base_image()
- .copy("config.json", "/app/config.json", force_upload=True)
-)
-```
-
-
-
-## Use Case for Caching
-You can leverage caching to create templates with multiple variants (e.g., different RAM or CPU) while reusing the common layers.
-When building the template, just change the template alias to a specific RAM/CPU configuration (e.g., `my-template-2cpu-2gb`, `my-template-1cpu-4gb`), keep the rest of the template definition the same, and the build process will reuse the cached layers.
-
-## Optimize Build Times
-To optimize build times, place frequently changing commands (e.g., copying source code) towards the end of your template definition. This way, earlier layers can be cached and reused more often.
diff --git a/template/customization/authentication.mdx b/template/customization/authentication.mdx
deleted file mode 100644
index 893c80f..0000000
--- a/template/customization/authentication.mdx
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "Authentication"
-description: "How to login to the E2B Cloud"
-icon: "key"
----
-
-The SDK uses environment variables for authentication:
-
-- `E2B_API_KEY`: Your E2B API key
-- `E2B_DOMAIN`: (Optional) E2B domain, defaults to 'e2b.dev'
diff --git a/template/customization/base-image.mdx b/template/customization/base-image.mdx
deleted file mode 100644
index 85b54b0..0000000
--- a/template/customization/base-image.mdx
+++ /dev/null
@@ -1,237 +0,0 @@
----
-title: "Base Image"
-description: "How to define a base image for your template"
-icon: "1"
----
-
-## Creating template
-
-When creating a template, you can specify options:
-
-
-
-```typescript
-const template = Template({
- fileContextPath: ".", // Custom file context path
- fileIgnorePatterns: [".git", "node_modules"], // File patterns to ignore
-});
-```
-
-```python
-template = Template(
- file_context_path=".", # Custom file context path
- file_ignore_patterns=[".git", "node_modules"], # File patterns to ignore
-)
-```
-
-
-
-**File ignoring**: The SDK automatically reads `.dockerignore` files and combines them with your `fileIgnorePatterns` (TypeScript) or `file_ignore_patterns` (Python). Files matching these patterns are excluded from uploads and hash calculations.
-
-## Defining base image
-Choose from predefined base images or use custom ones:
-
-
-
-```typescript
-// Predefined base images
-template.fromUbuntuImage("lts"); // ubuntu:lts
-template.fromUbuntuImage("22.04"); // ubuntu:22.04
-template.fromDebianImage("slim"); // debian:slim
-template.fromDebianImage("bullseye"); // debian:bullseye
-template.fromPythonImage("3.13"); // python:3.13
-template.fromPythonImage("3.11"); // python:3.11
-template.fromNodeImage("lts"); // node:lts
-template.fromNodeImage("20"); // node:20
-
-// Custom base image
-template.fromImage("custom-image:latest");
-
-// Use default E2B base image
-template.fromBaseImage(); // e2bdev/base
-
-// Parse existing Dockerfile
-const dockerfileContent = `
-FROM node:18-alpine
-WORKDIR /app
-COPY package*.json ./
-RUN npm ci --only=production
-COPY . .
-ENV NODE_ENV=production`;
-
-template.fromDockerfile(dockerfileContent);
-```
-
-```python
-# Predefined base images
-template.from_ubuntu_image("lts") # ubuntu:lts
-template.from_ubuntu_image("22.04") # ubuntu:22.04
-template.from_debian_image("slim") # debian:slim
-template.from_debian_image("bullseye") # debian:bullseye
-template.from_python_image("3.13") # python:3.13
-template.from_python_image("3.11") # python:3.11
-template.from_node_image("lts") # node:lts
-template.from_node_image("20") # node:20
-
-# Custom base image
-template.from_image("custom-image:latest")
-
-# Use default E2B base image
-template.from_base_image() # e2bdev/base
-
-# Build from existing template
-template.from_template("existing-template-alias")
-
-# Parse and build from Dockerfile
-template.from_dockerfile("Dockerfile")
-template.from_dockerfile("FROM ubuntu:22.04\nRUN apt-get update")
-```
-
-
-
-
-You can only call base image methods once per template. Subsequent calls will throw an error.
-
-
-## Parsing existing Dockerfiles
-
-Convert existing Dockerfiles to template format using `fromDockerfile()`:
-
-
-
-```typescript
-const dockerfileContent = `
-FROM ubuntu:22.04
-RUN apt-get update && apt-get install -y curl
-WORKDIR /app
-COPY . .
-ENV NODE_ENV=production
-ENV PORT=3000
-USER appuser`;
-
-const template = Template()
- .fromDockerfile(dockerfileContent)
- .setStartCmd("npm start", waitForTimeout(5_000));
-```
-
-```python
-dockerfile_content = """
-FROM ubuntu:22.04
-RUN apt-get update && apt-get install -y curl
-WORKDIR /app
-COPY . .
-ENV NODE_ENV=production
-ENV PORT=3000
-USER appuser
-"""
-
-template = (
- Template()
- .from_dockerfile(dockerfile_content)
- .set_start_cmd("npm start", wait_for_timeout(5_000))
-)
-```
-
-
-
-### Dockerfile instructions support
-
-| Instruction | Supported | Behavior |
-| :--- | :----: | :--- |
-| `FROM` | | Sets base image |
-| `RUN` | | Converts to `runCmd()` / `run_cmd()` |
-| `COPY` / `ADD` | | Converts to `copy()` |
-| `WORKDIR` | | Converts to `setWorkdir()` / `set_workdir()` |
-| `USER` | | Converts to `setUser()` / `set_user()` |
-| `ENV` | | Converts to `setEnvs()` / `set_envs()`; supports both `ENV key=value` and `ENV key value` formats |
-| `CMD` / `ENTRYPOINT` | | Converts to `setStartCmd()` / `set_start_cmd()` with 20 seconds timeout as ready command |
-| `EXPOSE` | | Skipped (not supported) |
-| `VOLUME` | | Skipped (not supported) |
-
-
-Multi-stage Dockerfiles are not supported.
-
-
-## Login to private registries
-If your base image is hosted in a private registry, you can provide credentials using the following helpers:
-- General registry
-- GCP Artifact Registry
-- AWS ECR
-
-### General Registry
-
-
-
-```typescript
-Template().fromImage('ubuntu:22.04', {
- username: 'user',
- password: 'pass',
-})
-```
-
-```python
-Template().from_image(
- image="ubuntu:22.04",
- username="user",
- password="pass",
-)
-```
-
-
-
-
-### GCP Artifact Registry
-
-
-
-```typescript
-// From file path
-Template().fromGCPRegistry('ubuntu:22.04', {
- serviceAccountJSON: './service_account.json',
-})
-
-// From object
-Template().fromGCPRegistry('ubuntu:22.04', {
- serviceAccountJSON: { project_id: '123', private_key_id: '456' },
-})
-```
-
-```python
-# From file path
-Template().from_gcp_registry(
- image="ubuntu:22.04",
- service_account_json="./service_account.json",
-)
-
-# From object
-Template().from_gcp_registry(
- image="ubuntu:22.04",
- service_account_json={"project_id": "123", "private_key_id": "456"},
-)
-```
-
-
-
-
-### AWS ECR
-
-
-
-```typescript
-Template().fromAWSRegistry('ubuntu:22.04', {
- accessKeyId: '123',
- secretAccessKey: '456',
- region: 'us-west-1',
-})
-```
-
-```python
-Template().from_aws_registry(
- image="ubuntu:22.04",
- access_key_id="123",
- secret_access_key="456",
- region="us-west-1",
-)
-```
-
-
diff --git a/template/customization/build.mdx b/template/customization/build.mdx
deleted file mode 100644
index add4383..0000000
--- a/template/customization/build.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Build"
-description: "How to build the template"
-icon: "hammer"
----
-
-Configure the build process:
-
-
-
-```typescript wrap
-Template.build(template, {
- alias: 'my-template', // Template alias (required)
- cpuCount: 2, // CPU cores
- memoryMB: 2048, // Memory in MB
- skipCache: false, // Configure cache skip (except for files)
- onBuildLogs: (logEntry) => console.log(logEntry.toString()), // Log callback receives LogEntry objects
- apiKey: 'your-api-key', // Override API key
- domain: 'your-domain', // Override domain
-})
-```
-
-```python wrap
-Template.build(
- template,
- alias="my-template", # Template alias (required)
- cpu_count=2, # CPU cores
- memory_mb=2048, # Memory in MB
- skip_cache=False, # Configure cache skip (except for files)
- on_build_logs=lambda log_entry: print(log_entry), # Log callback receives LogEntry objects
- api_key="your-api-key", # Override API key
- domain="your-domain", # Override domain
-)
-```
-
-
diff --git a/template/customization/defining-template.mdx b/template/customization/defining-template.mdx
deleted file mode 100644
index 9d46645..0000000
--- a/template/customization/defining-template.mdx
+++ /dev/null
@@ -1,279 +0,0 @@
----
-title: "Defining Template"
-description: "How to create your own template"
-icon: "2"
----
-
-### Method chaining
-
-All template methods return the template instance, allowing for fluent API usage:
-
-
-
-```typescript
-const template = Template()
- .fromUbuntuImage("22.04")
- .aptInstall(["curl"]) // necessary for waitForPort
- .setWorkdir('/app')
- .copy("package.json", "/app/package.json")
- .runCmd("npm install")
- .setStartCmd("npm start", waitForPort(3000));
-```
-
-```python
-template = (
- Template()
- .from_ubuntu_image("22.04")
- .set_workdir("/app")
- .copy("package.json", "/app/package.json")
- .run_cmd("npm install")
- .set_start_cmd("npm start", wait_for_timeout(10_000)))
-```
-
-
-
-### User and workdir
-
-Set the working directory and user for the template:
-
-
-
-```typescript
-// Set working directory
-template.setWorkdir("/app");
-
-// Set user (runs subsequent commands as this user)
-template.setUser('node')
-template.setUser("1000:1000"); // User ID and group ID
-```
-
-```python
-# Set working directory
-template.set_workdir("/app")
-
-# Set user (runs subsequent commands as this user)
-template.set_user("node")
-template.set_user("1000:1000") # User ID and group ID
-```
-
-
-
-### Copying files
-
-Copy files from your local filesystem to the template:
-
-
-
-```typescript
-// Copy a single file
-template.copy("package.json", "/app/package.json");
-
-// Copy multiple files to same destination
-template.copy(["file1", "file2"], "/app/file")
-
-// Multiple copy operations using copyItems
-template.copyItems([
- { src: "src/", dest: "/app/src/" },
- { src: "package.json", dest: "/app/package.json" },
-]);
-
-// Copy with user and mode options
-template.copy("config.json", "/app/config.json", {
- user: "appuser",
- mode: 0o644,
-});
-```
-
-```python
-# Copy a single file
-template.copy("package.json", "/app/package.json")
-
-# Copy multiple files to the same destination
-template.copy(["file1", "file2"], "/app/file")
-
-# Multiple copy operations using copy_items
-template.copy_items([
- {"src": "src/", "dest": "/app/src/"},
- {"src": "package.json", "dest": "/app/package.json"},
-])
-
-# Copy with user and mode options
-template.copy("config.json", "/app/config.json", user="appuser", mode=0o644)
-```
-
-
-
-### File operations
-
-Perform various file operations during template build:
-
-
-
-```typescript
-// Remove files or directories
-template.remove("/tmp/temp-file.txt");
-template.remove("/old-directory", { recursive: true });
-template.remove("/file.txt", { force: true });
-
-// Rename files or directories
-template.rename("/old-name.txt", "/new-name.txt");
-template.rename("/old-dir", "/new-dir", { force: true });
-
-// Create directories
-template.makeDir("/app/logs");
-template.makeDir("/app/data", { mode: 0o755 });
-
-// Create symbolic links
-template.makeSymlink("/app/data", "/app/logs/data");
-```
-
-```python
-# Remove files or directories
-template.remove("/tmp/old-file")
-template.remove("/tmp/old-dir", recursive=True)
-template.remove("/tmp/file", force=True) # Force removal
-
-# Rename files or directories
-template.rename("/old/path", "/new/path")
-template.rename("/old/path", "/new/path", force=True) # Force rename
-
-# Create directories
-template.make_dir("/app/data")
-template.make_dir("/app/data", mode=0o755) # Set permissions
-
-# Create symbolic links
-template.make_symlink("/path/to/target", "/path/to/link")
-```
-
-
-
-### Installing packages
-
-Install packages using package managers:
-
-
-
-```typescript
-// Install Python packages
-template.pipInstall('requests pandas numpy')
-template.pipInstall(['requests', 'pandas', 'numpy'])
-
-// Install Node.js packages
-template.npmInstall('express lodash')
-template.npmInstall(['express', 'lodash'])
-
-// Install system packages (automatically runs apt update)
-template.aptInstall('curl wget git')
-template.aptInstall(['curl', 'wget', 'git'])
-```
-
-```python
-# Install Python packages
-template.pip_install("requests pandas numpy")
-template.pip_install(["requests", "pandas", "numpy"])
-
-# Install Node.js packages
-template.npm_install("express lodash")
-template.npm_install(["express", "lodash"])
-
-# Install system packages (Ubuntu/Debian)
-template.apt_install("curl wget git")
-template.apt_install(["curl", "wget", "git"])
-```
-
-
-
-### Git operations
-
-Clone Git repositories during template build (requires `git` to be installed):
-
-
-
-```typescript
-// Clone a repository
-template.gitClone('https://github.com/user/repo.git')
-
-// Clone a repository to a specific path
-template.gitClone('https://github.com/user/repo.git', '/app/repo')
-
-// Clone a specific branch
-template.gitClone('https://github.com/user/repo.git', '/app/repo', {
- branch: 'main',
-})
-
-// Shallow clone with depth limit
-template.gitClone('https://github.com/user/repo.git', '/app/repo', {
- depth: 1,
-})
-```
-
-```python
-# Clone a repository
-template.git_clone("https://github.com/user/repo.git")
-
-# Clone a repository to a specific path
-template.git_clone("https://github.com/user/repo.git", "/app/repo")
-
-# Clone a specific branch
-template.git_clone("https://github.com/user/repo.git", "/app/repo", branch="main")
-
-# Shallow clone with depth limit
-template.git_clone("https://github.com/user/repo.git", "/app/repo", depth=1)
-
-```
-
-
-
-### Environment variables
-
-Set environment variables in the template:
-
-
-
-```typescript
-template.setEnvs({
- NODE_ENV: 'production',
- API_KEY: 'your-api-key',
- DEBUG: 'true',
-})
-```
-
-```python
-template.set_envs({
- "NODE_ENV": "production",
- "API_KEY": "your-api-key",
- "DEBUG": "true",
-})
-```
-
-
-
-### Running commands
-
-Execute shell commands during template build:
-
-
-
-```typescript
-// Run a single command
-template.runCmd('apt-get update && apt-get install -y curl')
-
-// Run multiple commands
-template.runCmd(['apt-get update', 'apt-get install -y curl', 'curl --version'])
-
-// Run commands as a specific user
-template.runCmd('npm install', { user: 'node' })
-```
-
-```python
-# Run a single command
-template.run_cmd("apt-get update && apt-get install -y curl")
-
-# Run multiple commands
-template.run_cmd(["apt-get update", "apt-get install -y curl", "curl --version"])
-
-# Run command as specific user
-template.run_cmd("npm install", user="node")
-```
-
-
diff --git a/template/customization/error-handling.mdx b/template/customization/error-handling.mdx
deleted file mode 100644
index a730936..0000000
--- a/template/customization/error-handling.mdx
+++ /dev/null
@@ -1,42 +0,0 @@
----
-title: "Error Handling"
-description: "Handle errors in your template"
-icon: "bug"
----
-
-The SDK provides specific error types:
-
-
-
-```typescript
-import { AuthError, BuildError, FileUploadError } from "e2b";
-
-try {
- await Template.build(template, {
- alias: "my-template",
- });
-} catch (error) {
- if (error instanceof AuthError) {
- console.error("Authentication failed:", error.message);
- } else if (error instanceof FileUploadError) {
- console.error("File upload failed:", error.message);
- } else if (error instanceof BuildError) {
- console.error("Build failed:", error.message);
- }
-}
-```
-
-```python
-from e2b import AuthError, BuildError, FileUploadError
-
-try:
- Template.build(template, alias="my-template")
-except AuthError as error:
- print(f"Authentication failed: {error}")
-except FileUploadError as error:
- print(f"File upload failed: {error}")
-except BuildError as error:
- print(f"Build failed: {error}")
-```
-
-
diff --git a/template/customization/logging.mdx b/template/customization/logging.mdx
deleted file mode 100644
index c78ca65..0000000
--- a/template/customization/logging.mdx
+++ /dev/null
@@ -1,78 +0,0 @@
----
-title: "Logging"
-description: "How to view logs from the template build"
-icon: "eye"
----
-
-You can retrieve the build logs using the SDK.
-
-## SDK
-
-The `onBuildLogs`/`on_build_logs` callback receives structured `LogEntry` objects with the following properties:
-
-
-
-```typescript
-type LogEntry = {
- timestamp: Date
- level: 'debug' | 'info' | 'warn' | 'error'
- message: string
- toString(): string // Returns formatted log string
-}
-```
-
-```python
-@dataclass
-class LogEntry:
- timestamp: datetime
- level: Literal["debug", "info", "warn", "error"]
- message: str
-
- def __str__(self) -> str: # Returns formatted log string
-```
-
-
-
-
-You can customize how logs are handled:
-
-
-
-```typescript
-// Simple logging
-onBuildLogs: (logEntry) => console.log(logEntry.toString());
-
-// Custom formatting
-onBuildLogs: (logEntry) => {
- const time = logEntry.timestamp.toISOString();
- console.log(`[${time}] ${logEntry.level.toUpperCase()}: ${logEntry.message}`);
-};
-
-// Filter by log level
-onBuildLogs: (logEntry) => {
- if (logEntry.level === "error" || logEntry.level === "warn") {
- console.error(logEntry.toString());
- }
-};
-```
-
-```python
-# Simple logging
-on_build_logs=lambda log_entry: print(log_entry)
-
-# Custom formatting
-def custom_logger(log_entry):
- time = log_entry.timestamp.isoformat()
- print(f"[{time}] {log_entry.level.upper()}: {log_entry.message}")
-
-Template.build(template, alias="my-template", on_build_logs=custom_logger)
-
-# Filter by log level
-def error_logger(log_entry):
- if log_entry.level in ["error", "warn"]:
- print(f"ERROR/WARNING: {log_entry}", file=sys.stderr)
-
-Template.build(template, alias="my-template", on_build_logs=error_logger)
-```
-
-
diff --git a/template/customization/start-ready-command.mdx b/template/customization/start-ready-command.mdx
deleted file mode 100644
index 2d459a3..0000000
--- a/template/customization/start-ready-command.mdx
+++ /dev/null
@@ -1,93 +0,0 @@
----
-title: "Start & Ready Commands"
-description: "Define running processes for the sandbox"
-icon: "3"
----
-
-## Start command
-The start command allows you to specify a command that will be **already running** when you spawn your custom sandbox.
-This way, you can for example have running servers or seeded databases inside the sandbox that are already fully ready when you spawn the sandbox using the SDK and with zero waiting time for your users during the runtime.
-
-The idea behind the start command feature is to lower the wait times for your users and have everything ready for your users when you spawn your sandbox.
-
-You can see how it works [here](/template/how-it-works).
-
-## Ready command
-The ready command allows you to specify a command that will determine **template sandbox** readiness before a [snapshot](/template/how-it-works) is created.
-It is executed in an infinite loop until it returns a successful **exit code 0**.
-This way you can control how long should we wait for the [start command](/template/customization/start-ready-command#start-command) or any system state.
-
-## Usage
-
-Set the command that runs when the sandbox starts and the command that determines when the sandbox is ready:
-
-
-
-```typescript
-// Set both start command and ready command
-template.setStartCmd('npm start', waitForPort(3000))
-
-// Set only ready command
-template.setReadyCmd('curl -f http://localhost:3000/health')
-```
-
-```python
-# Set both start command and ready command
-template.set_start_cmd("npm start", wait_for_timeout(10_000))
-
-# Set only ready command
-template.set_ready_cmd(wait_for_port(3000))
-```
-
-
-
-The ready command is used to determine when the sandbox is ready to accept connections.
-
-
- You can only call these commands once per template. Subsequent calls will throw an error.
-
-
-## Ready command helpers
-
-The SDK provides helper functions for common ready command patterns:
-
-
-
-```typescript
-import {
- waitForPort,
- waitForProcess,
- waitForFile,
- waitForTimeout,
-} from 'e2b'
-
-// Wait for a port to be available
-waitForPort(3000)
-
-// Wait for a process to be running
-waitForProcess('node')
-
-// Wait for a file to exist
-waitForFile('/app/ready.txt')
-
-// Wait for a timeout
-waitForTimeout(10_000) // 10 seconds
-```
-
-```python
-from e2b import wait_for_port, wait_for_process, wait_for_file, wait_for_timeout
-
-# Wait for a port to be available
-wait_for_port(3000)
-
-# Wait for a process to be running
-wait_for_process("nginx")
-
-# Wait for a file to exist
-wait_for_file("/tmp/ready")
-
-# Wait for a specified duration
-wait_for_timeout(10_000) # 10 seconds
-```
-
-
diff --git a/template/examples.mdx b/template/examples.mdx
deleted file mode 100644
index 5042cce..0000000
--- a/template/examples.mdx
+++ /dev/null
@@ -1,380 +0,0 @@
----
-title: "Examples"
-description: "Examples of using the template"
-icon: "book"
----
-
-## Next.js
-
-Basic Next.js app with Tailwind and shadcn UI
-
-
-
-```typescript template.ts
-import { Template, waitForPort } from 'e2b'
-
-export const template = Template()
- .fromNodeImage('21-slim')
- .setWorkdir('/home/user/nextjs-app')
- .runCmd(
- 'npx create-next-app@14.2.30 . --ts --tailwind --no-eslint --import-alias "@/*" --use-npm --no-app --no-src-dir'
- )
- .runCmd('npx shadcn@2.1.7 init -d')
- .runCmd('npx shadcn@2.1.7 add --all')
- .runCmd(
- 'mv /home/user/nextjs-app/* /home/user/ && rm -rf /home/user/nextjs-app'
- )
- .setWorkdir('/home/user')
- .setStartCmd('npx next --turbo', waitForPort(3000))
-
-```
-
-
-```python template.py
-from e2b import Template, wait_for_port
-
-template = (
- Template()
- .from_node_image("21-slim")
- .set_workdir("/home/user/nextjs-app")
- .run_cmd(
- 'npx create-next-app@14.2.30 . --ts --tailwind --no-eslint --import-alias "@/*" --use-npm --no-app --no-src-dir'
- )
- .run_cmd("npx shadcn@2.1.7 init -d")
- .run_cmd("npx shadcn@2.1.7 add --all")
- .run_cmd("mv /home/user/nextjs-app/* /home/user/ && rm -rf /home/user/nextjs-app")
- .set_workdir("/home/user")
- .set_start_cmd("npx next --turbo", wait_for_port(3000))
-)
-```
-
-
-
-
-
-```typescript build.ts
-import { Template } from 'e2b'
-import { template as nextJSTemplate } from './template'
-
-Template.build(nextJSTemplate, {
- alias: 'nextjs-app',
- cpuCount: 1,
- memoryMB: 1024,
- onBuildLogs: (logEntry) => console.log(logEntry.toString()),
-})
-```
-
-
-```python build.py
-from e2b import Template
-from .template import template as nextjsTemplate
-
-Template.build(nextjsTemplate,
- alias="nextjs-app",
- cpu_count=4,
- memory_mb=4096,
- on_build_logs=lambda log_entry: print(log_entry),
-)
-```
-
-
-
-## Desktop
-
-Basic Ubuntu Desktop with GUI and VNC access
-
-
-
-
-```typescript template.ts expandable
-import { Template, waitForPort } from 'e2b'
-
-export const template = Template()
- .fromUbuntuImage('22.04')
- // Desktop environment and system utilities
- .runCmd([
- 'yes | unminimize',
- 'apt-get update',
- 'apt-get install -y \
- xserver-xorg \
- xorg \
- x11-xserver-utils \
- xvfb \
- x11-utils \
- xauth \
- xfce4 \
- xfce4-goodies \
- util-linux \
- sudo \
- curl \
- git \
- wget \
- python3-pip \
- xdotool \
- scrot \
- ffmpeg \
- x11vnc \
- net-tools \
- netcat \
- x11-apps \
- libreoffice \
- xpdf \
- gedit \
- xpaint \
- tint2 \
- galculator \
- pcmanfm',
- 'apt-get clean',
- 'rm -rf /var/lib/apt/lists/*',
- ])
- // Streaming server setup
- .runCmd([
- 'git clone --branch e2b-desktop https://github.com/e2b-dev/noVNC.git /opt/noVNC',
- 'ln -s /opt/noVNC/vnc.html /opt/noVNC/index.html',
- 'git clone --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify',
- ])
- // Set default terminal
- .runCmd(
- 'ln -sf /usr/bin/xfce4-terminal.wrapper /etc/alternatives/x-terminal-emulator'
- )
- .copy('start_command.sh', '/start_command.sh')
- .runCmd('chmod +x /start_command.sh')
- .setStartCmd('/start_command.sh', waitForPort(6080))
-
-```
-
-```python template.py expandable
-from e2b import Template, wait_for_port
-
-template = (
- Template()
- .from_image("ubuntu:22.04")
- # Initial system setup and packages
- # We are not using .apt_install() here because some packages have interactive prompts (keyboard layout setup, etc.)
- .run_cmd(
- [
- "yes | unminimize",
- "apt-get update",
- "apt-get install -y \
- xserver-xorg \
- x11-xserver-utils \
- xvfb \
- x11-utils \
- xauth \
- xfce4 \
- xfce4-goodies \
- util-linux \
- sudo \
- curl \
- git \
- wget \
- python3-pip \
- xdotool \
- scrot \
- ffmpeg \
- x11vnc \
- net-tools \
- netcat \
- x11-apps \
- libreoffice \
- xpdf \
- gedit \
- xpaint \
- tint2 \
- galculator \
- pcmanfm",
- "apt-get clean",
- "rm -rf /var/lib/apt/lists/*",
- ]
- )
- # Setup NoVNC and websockify
- .run_cmd(
- [
- "git clone --branch e2b-desktop https://github.com/e2b-dev/noVNC.git /opt/noVNC",
- "ln -s /opt/noVNC/vnc.html /opt/noVNC/index.html",
- "git clone --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify",
- ]
- )
- # Set default terminal
- .run_cmd(
- "ln -sf /usr/bin/xfce4-terminal.wrapper /etc/alternatives/x-terminal-emulator"
- )
- # Copy the start command
- .copy("start_command.sh", "/start_command.sh")
- .run_cmd("chmod +x /start_command.sh")
- # Set start command to launch the desktop environment
- .set_start_cmd("/start_command.sh", wait_for_port(6080))
-)
-```
-
-
-
-
-```bash start_command.sh
-#!/bin/bash
-
-# Set display
-export DISPLAY=${DISPLAY:-:0}
-
-# Start Xvfb
-Xvfb $DISPLAY -ac -screen 0 1024x768x24 -nolisten tcp &
-sleep 2
-
-# Start XFCE session
-startxfce4 &
-sleep 5
-
-# Start VNC server
-x11vnc -bg -display $DISPLAY -forever -wait 50 -shared -rfbport 5900 -nopw \
- -noxdamage -noxfixes -nowf -noscr -ping 1 -repeat -speeds lan &
-sleep 2
-
-# Start noVNC server
-cd /opt/noVNC/utils && ./novnc_proxy --vnc localhost:5900 --listen 6080 --web /opt/noVNC --heartbeat 30 &
-sleep 2
-```
-
-
-
-
-```typescript build.ts
-import { Template } from 'e2b'
-import { template as desktopTemplate } from './template'
-
-await Template.build(desktopTemplate, {
- alias: 'desktop',
- cpuCount: 8,
- memoryMB: 8192,
- onBuildLogs: (logEntry) => console.log(logEntry.toString()),
-})
-```
-
-```python build.py
-from e2b import Template
-from .template import template as desktopTemplate
-
-Template.build(desktopTemplate,
- alias="desktop",
- cpu_count=8,
- memory_mb=8192,
- on_build_logs=lambda log_entry: print(log_entry),
-)
-```
-
-
-
-## Claude Code
-
-Claude Code Agent in a Sandbox
-
-
-
-```typescript template.ts
-import { Template } from 'e2b'
-
-export const template = Template()
- .fromNodeImage('24')
- .aptInstall(['curl', 'git', 'ripgrep'])
- // Claude Code will be available globally as "claude"
- .npmInstall('-g @anthropic-ai/claude-code@latest')
-
-```
-
-```python template.py
-from e2b import Template
-
-template = (
- Template()
- .from_node_image("24")
- .apt_install(["curl", "git", "ripgrep"])
- # Claude Code will be available globally as "claude"
- .npm_install("-g @anthropic-ai/claude-code@latest")
-)
-```
-
-
-
-
-
-
-```typescript build.ts
-import { Template } from 'e2b'
-import { template as claudeCodeTemplate } from './template'
-
-Template.build(claudeCodeTemplate, {
- alias: 'claude-code',
- cpuCount: 1,
- memoryMB: 1024,
- onBuildLogs: (logEntry) => console.log(logEntry.toString()),
-})
-```
-
-```python build.py
-from e2b import Template
-from .template import template as claudeCodeTemplate
-
-Template.build(claudeCodeTemplate,
- alias="claude-code",
- cpu_count=1,
- memory_mb=1024,
- on_build_logs=lambda log_entry: print(log_entry),
-)
-```
-
-
-
-
-
-```typescript sandbox.ts
-
-import { Sandbox } from 'e2b'
-
-const sbx = await Sandbox.create('claude-code', {
- envs: {
- ANTHROPIC_API_KEY: '',
- },
-})
-
-console.log('Sandbox created', sbx.sandboxId)
-
-// Print help for Claude Code
-// const result = await sbx.commands.run('claude --help')
-// console.log(result.stdout)
-
-// Run a prompt with Claude Code
-const result = await sbx.commands.run(
- `echo 'Create a hello world index.html' | claude -p --dangerously-skip-permissions`,
- { timeoutMs: 0 }
-)
-
-console.log(result.stdout)
-
-sbx.kill()
-```
-
-```python sandbox.py
-from e2b import Sandbox
-
-sbx = Sandbox(
- 'claude-code',
- envs={
- 'ANTHROPIC_API_KEY': '',
- },
-)
-print("Sandbox created", sbx.sandbox_id)
-
-# Print help for Claude Code
-# result = sbx.commands.run('claude --help')
-# print(result.stdout)
-
-# Run a prompt with Claude Code
-result = sbx.commands.run(
- "echo 'Create a hello world index.html' | claude -p --dangerously-skip-permissions",
- timeout=0,
-)
-print(result.stdout)
-
-sbx.kill()
-```
-
-
diff --git a/template/how-it-works.mdx b/template/how-it-works.mdx
deleted file mode 100644
index 0f0d941..0000000
--- a/template/how-it-works.mdx
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "How It Works"
-description: "How the template building process works"
-icon: "file-lines"
----
-
-## General overview
-Every time you are building a sandbox template, we create a container based on the definition.
-We extract the container's filesystem, do provisioning and configuration (e.g. installing required dependencies), run layers commands and start a sandbox.
-
-Then, these steps happen:
- 1. We take the running sandbox.
- 2. (Only if you specified the [start command](/template/customization/start-ready-command#start-command), otherwise this step is skipped) Execute the start command.
- 3. Wait for readiness (by default 20 seconds if start command is specified, otherwise immediately ready). Readiness check can be configured using [ready command](/template/customization/start-ready-command#ready-command).
- 4. Snapshot the sandbox and make it ready for you to spawn it with the SDK.
-
-We call this sandbox snapshot a _sandbox template_.
-
-
- Snapshots are saved running sandboxes. We serialize and save the whole sandbox's filesystem together with all the
- running processes in a way that can be loaded later.
-
- This allows us to load the sandbox in a few hundred milliseconds any time later with all the processes already running
- and the filesystem exactly as it was.
-
-
-## Caching
-To learn more about caching, please refer to the [Caching](/template/caching) section.
diff --git a/template/migration.mdx b/template/migration.mdx
deleted file mode 100644
index f4cb607..0000000
--- a/template/migration.mdx
+++ /dev/null
@@ -1,117 +0,0 @@
----
-title: "Migration"
-description: "How to migrate from the legacy template definition"
-icon: "forward-fast"
----
-
-We've made ready for you three ways how to migrate existing template to the new definition format.
-
-- Using the migration command (recommended)
-- Using the `fromDockerfile()` method to parse existing Dockerfile
-- Building the Docker image manually and using `fromImage()` method
-
-## Migration Command (Recommended)
-
-To migrate the existing template definition to the new format, follow these steps:
-
-
-
- Install the latest version of the [E2B CLI](https://e2b.dev/docs/cli)
-
-
- Navigate to the folder of your existing template definition (where you have `e2b.toml` and `e2b.Dockerfile` files).
-
-
- ```bash
- e2b template migrate
- ```
-
-
- Follow the prompts to complete the migration process.
-
-
-
-
-
-### Generated Output
-The migration command generates three files (based on the selected language).
-
-
-
-
-```typescript
-template.ts - Template definition using the SDK
-build.dev.ts - Development build script
-build.prod.ts - Production build script
-```
-
-```python
-template.py - Template definition using the SDK
-build_dev.py - Development build script
-build_prod.py - Production build script
-```
-
-
-
-
-## Using `fromDockerfile()` Method
-
-If you want to keep using Dockerfile for your template, you can use the `fromDockerfile()` method.
-We'll automatically parse the Dockerfile for you and build the template based on it.
-You can find more at [Base Image](/template/customization/base-image#parsing-existing-dockerfiles).
-
-
-
-```typescript template.ts
-import { Template } from "e2b";
-
-const template = Template()
- .fromDockerfile(dockerfileContent);
-```
-```python template.py
-from e2b import Template
-
-template = (
- Template()
- .from_dockerfile(dockerfile_content)
-)
-```
-
-
-
-
- Only a limited set of instructions are supported and converted to equivalent template.
-
- Compatible instructions:
-
- `FROM`, `RUN`, `COPY`, `ADD`, `WORKDIR`, `USER`, `ENV`, `ARG`, `CMD`, `ENTRYPOINT`
-
-
-After the template definition, you can create the build scripts as described in the [Quickstart](/template/quickstart#create-a-development-build-script) section.
-
-
-## Using `fromImage()` Method
-
-If you already have a Docker image built, or you want to keep building the Docker image yourself you can use the `fromImage()` method.
-Simply build the Docker image for the `linux/amd64` platform, push it to a registry of your choice and reference the image tag in the `fromImage()` method.
-You can also specify credentials for private registries as described in the [Base Image](/template/customization/base-image#custom-base-image) section.
-
-
-
-
-```typescript template.ts
-import { Template } from "e2b";
-
-const template = Template()
- .fromImage("image-tag");
-```
-```python template.py
-from e2b import Template
-
-template = (
- Template()
- .from_image("image-tag")
-)
-```
-
-
diff --git a/template/quickstart.mdx b/template/quickstart.mdx
index 9607a8a..4886803 100644
--- a/template/quickstart.mdx
+++ b/template/quickstart.mdx
@@ -4,232 +4,36 @@ description: "Start with custom sandbox templates"
icon: "rocket"
---
-E2B templates allow you to define custom sandboxes.
-You can define the base image, environment variables, files to copy, commands to run, and
-a start command that will be already running when you spawn the sandbox.
-This way, you can have fully configured sandboxes with running processes ready to use with zero wait time for your users.
+**Build System 2.0** is now public and available for all users! Please check out the [documentation here](https://e2b.dev/docs/template) for more details.
-There are two ways how you can start creating a new template:
-- using the CLI
-- manually using the SDK
+## Migrating from the pre-release SDK version (pre 2.3.0)
+If you have been using the pre-release version of the SDK, please note that there are some breaking changes in the new version.
-## CLI
+The most notable change is that the default user in the template is now `user` and the set user and working directory are persisted to the Sandbox runtime.
-You can use the E2B CLI to create a new template.
+If you want to keep your existing template code, simply add the following lines to your template (`fromDockerfile`/`from_dockerfile` handles this automatically):
-
-
- Install the latest version of the [E2B CLI](https://e2b.dev/docs/cli)
-
-
- ```bash
- e2b template init-v2
- ```
-
-
- Follow the prompts to create a new template.
-
-
- Check the generated `README.md` file to see how to build and use your new template.
-
-
-
-## Manual
-
-### Install the packages
-
-Requires the E2B version at least 2.1.0
-
-
-
-
-```typescript Terminal
-npm install e2b dotenv
-```
-
-```python Terminal
-pip install e2b dotenv
-```
-
-
-
-Create the `.env` file
-
-```bash
-E2B_API_KEY=e2b_***
+
+```ts JavaScript & TypeScript
+const template = Template()
+ .fromImage("your-image")
+ // Switch to root to perform setup steps
+ .setUser("root")
+ //... steps
+ // Switch back to user for the Sandbox runtime
+ .setUser("user")
```
-### Create a new template file
-Create a template file with the following name and content
-
-
-
-```typescript template.ts
-import { Template, waitForTimeout } from "e2b";
-
-export const template = Template()
- .fromBaseImage()
- .setEnvs({
- HELLO: "Hello, World!",
- })
- .setStartCmd("echo $HELLO", waitForTimeout(5_000));
-```
-
-```python template.py
-from e2b import Template, wait_for_timeout
-
+```python Python
template = (
Template()
- .from_base_image()
- .set_envs(
- {
- "HELLO": "Hello, World!",
- }
- )
- .set_start_cmd("echo $HELLO", wait_for_timeout(5_000)))
-```
-
-
-
-
-### Create a development build script
-
-
-
-```typescript build.dev.ts
-import "dotenv/config";
-import { template } from "./template";
-import { Template } from "e2b";
-
-async function main() {
- await Template.build(template, {
- alias: "template-tag-dev",
- cpuCount: 1,
- memoryMB: 1024,
- onBuildLogs: (logEntry) => console.log(logEntry.toString()),
- });
-}
-
-main().catch(console.error);
-```
-
-```python build_dev.py
-from dotenv import load_dotenv
-from e2b import Template
-from template import template
-
-load_dotenv()
-
-if __name__ == '__main__':
- Template.build(
- template,
- alias="template-tag-dev",
- cpu_count=1,
- memory_mb=1024,
- on_build_logs=lambda log_entry: print(log_entry),
- )
-```
-
-
-
-Build the development template
-
-
-
-```typescript Terminal
-npx tsx build.dev.ts
-```
-
-```python Terminal
-python build_dev.py
-```
-
-
-
-### Create a production build script
-
-
-
-```typescript build.prod.ts
-import "dotenv/config";
-import { template } from "./template";
-import { Template } from "e2b";
-
-async function main() {
- await Template.build(template, {
- alias: "template-tag",
- cpuCount: 1,
- memoryMB: 1024,
- onBuildLogs: (logEntry) => console.log(logEntry.toString()),
- });
-}
-
-main().catch(console.error);
-```
-
-```python build_prod.py
-from dotenv import load_dotenv
-from e2b import Template
-from template import template
-
-load_dotenv()
-
-if __name__ == '__main__':
- Template.build(
- template,
- alias="template-tag",
- cpu_count=1,
- memory_mb=1024,
- on_build_logs=lambda log_entry: print(log_entry),
- )
-```
-
-
-
-Build the production template
-
-
-
-```typescript Terminal
-npx tsx build.prod.ts
-```
-
-```python Terminal
-python build_prod.py
-```
-
-
-
-## Create a new Sandbox from the Template
-
-
-
-```typescript
-import "dotenv/config";
-import { Sandbox } from "e2b";
-
-// Create a Sandbox from development template
-const sandbox = await Sandbox.create("template-tag-dev");
-
-// Create a Sandbox from production template
-const sandbox = await Sandbox.create("template-tag");
-```
-
-```python
-from dotenv import load_dotenv
-from e2b import Sandbox
-
-load_dotenv()
-
-# Create a new Sandbox from the development template
-sbx = Sandbox(template="template-tag-dev")
-
-# Create a new Sandbox from the production template
-sbx = Sandbox(template="template-tag")
+ .from_image("your-image")
+ # Switch to root to perform setup steps
+ .set_user("root")
+ #... steps
+ # Switch back to user for the Sandbox runtime
+ .set_user("user")
+)
```
-
-
-The template alias is the identifier that can be used to create a new Sandbox.
-