| name | e2b-sandbox |
| description | Create, manage, and use E2B sandboxes — run commands, manage files, use git, persist state, and configure networking. Use when building agent workflows that need isolated execution environments.
|
E2B Sandbox — Lifecycle & Operations
Quick Start
Install the SDK and set your API key:
npm install @e2b/code-interpreter
pip install e2b-code-interpreter
Set E2B_API_KEY in your environment (get one at https://e2b.dev/dashboard).
Create a sandbox and run a command
import { Sandbox } from '@e2b/code-interpreter'
const sandbox = await Sandbox.create()
const result = await sandbox.commands.run('echo "Hello from E2B"')
console.log(result.stdout)
await sandbox.kill()
from e2b_code_interpreter import Sandbox
sandbox = Sandbox.create()
result = sandbox.commands.run('echo "Hello from E2B"')
print(result.stdout)
sandbox.kill()
Package Choice
| Need | Package | JS import | Python import |
|---|
Code execution (runCode) | Code Interpreter | import { Sandbox } from '@e2b/code-interpreter' | from e2b_code_interpreter import Sandbox |
| MCP gateway | Base SDK | import Sandbox from 'e2b' | from e2b import Sandbox |
| Templates only | Base SDK | import { Template } from 'e2b' | from e2b import Template |
Recommendation: Use Code Interpreter by default — it includes all base features plus runCode()/run_code().
Sandbox Creation Options
const sandbox = await Sandbox.create({
template: 'my-template',
timeoutMs: 5 * 60_000,
metadata: { user: 'alice' },
envs: { API_KEY: 'secret' },
secure: true,
allowInternetAccess: false,
network: {
denyOut: [ALL_TRAFFIC],
allowOut: ['api.example.com'],
},
})
sandbox = Sandbox.create(
template='my-template',
timeout=300,
metadata={'user': 'alice'},
envs={'API_KEY': 'secret'},
secure=True,
allow_internet_access=False,
network={
'deny_out': [ALL_TRAFFIC],
'allow_out': ['api.example.com'],
},
)
Running Commands
const repoPath = '/home/user/repo'
const result = await sandbox.commands.run('ls -la')
console.log(result.stdout)
const result = await sandbox.commands.run('npm start', {
cwd: repoPath,
envs: { NODE_ENV: 'production' },
user: 'root',
timeoutMs: 30_000,
onStdout: (data) => console.log(data),
onStderr: (data) => console.error(data),
})
const proc = await sandbox.commands.run('npm start', { background: true })
await proc.kill()
const processes = await sandbox.commands.list()
await proc.sendStdin('yes\n')
repo_path = '/home/user/repo'
result = sandbox.commands.run('ls -la')
print(result.stdout)
result = sandbox.commands.run(
'npm start',
cwd=repo_path,
envs={'NODE_ENV': 'production'},
user='root',
timeout=30,
on_stdout=lambda data: print(data),
on_stderr=lambda data: print(data, file=sys.stderr),
)
proc = sandbox.commands.run('npm start', background=True)
proc.kill()
processes = sandbox.commands.list()
proc.send_stdin('yes\n')
File Operations
const content = await sandbox.files.read('/home/user/config.json')
await sandbox.files.write('/home/user/hello.txt', 'Hello, World!')
await sandbox.files.write([
{ path: '/home/user/file1.txt', data: 'Content 1' },
{ path: '/home/user/file2.txt', data: 'Content 2' },
])
const entries = await sandbox.files.list('/home/user')
await sandbox.files.makeDir('/home/user/new-dir')
await sandbox.files.remove('/home/user/old-file.txt')
await sandbox.files.rename('/home/user/old.txt', '/home/user/new.txt')
const watcher = await sandbox.files.watch('/home/user', (event) => {
console.log(event)
})
content = sandbox.files.read('/home/user/config.json')
sandbox.files.write('/home/user/hello.txt', 'Hello, World!')
sandbox.files.write_files([
{"path": "/home/user/file1.txt", "data": "Content 1"},
{"path": "/home/user/file2.txt", "data": "Content 2"},
])
entries = sandbox.files.list('/home/user')
sandbox.files.make_dir('/home/user/new-dir')
sandbox.files.remove('/home/user/old-file.txt')
sandbox.files.rename('/home/user/old.txt', '/home/user/new.txt')
watcher = sandbox.files.watch('/home/user', lambda event: print(event))
Git Operations
Authentication
Three options for private repositories:
1. Inline credentials — pass with each command:
await sandbox.git.push(repoPath, {
username: process.env.GIT_USERNAME,
password: process.env.GIT_TOKEN,
})
sandbox.git.push(
repo_path,
username=os.environ.get("GIT_USERNAME"),
password=os.environ.get("GIT_TOKEN"),
)
2. Credential helper — authenticate once, reuse across commands:
await sandbox.git.dangerouslyAuthenticate({
username: process.env.GIT_USERNAME,
password: process.env.GIT_TOKEN,
})
sandbox.git.dangerously_authenticate(
username=os.environ.get("GIT_USERNAME"),
password=os.environ.get("GIT_TOKEN"),
)
3. Keep credentials in remote URL — pass dangerouslyStoreCredentials: true / dangerously_store_credentials=True to clone().
Common git workflows
const repoPath = '/home/user/repo'
await sandbox.git.clone('https://github.com/org/repo.git', {
path: repoPath, branch: 'main', depth: 1,
})
await sandbox.git.configureUser('Bot', 'bot@example.com')
await sandbox.git.createBranch(repoPath, 'feature/my-change')
await sandbox.git.add(repoPath, { files: ['README.md', 'src/index.ts'] })
await sandbox.git.commit(repoPath, 'Add feature')
await sandbox.git.push(repoPath, { remote: 'origin', branch: 'feature/my-change', setUpstream: true })
const status = await sandbox.git.status(repoPath)
console.log(status.currentBranch, status.ahead, status.behind, status.fileStatus)
const branches = await sandbox.git.branches(repoPath)
repo_path = '/home/user/repo'
sandbox.git.clone(
'https://github.com/org/repo.git',
path=repo_path, branch='main', depth=1,
)
sandbox.git.configure_user('Bot', 'bot@example.com')
sandbox.git.create_branch(repo_path, 'feature/my-change')
sandbox.git.add(repo_path, files=['README.md', 'src/index.ts'])
sandbox.git.commit(repo_path, 'Add feature')
sandbox.git.push(repo_path, remote='origin', branch='feature/my-change', set_upstream=True)
status = sandbox.git.status(repo_path)
print(status.current_branch, status.ahead, status.behind, status.file_status)
branches = sandbox.git.branches(repo_path)
Persistence (Pause & Resume)
Sandboxes can be paused and resumed later, preserving full state (RAM, disk, running processes).
import { Sandbox } from '@e2b/code-interpreter'
const sandbox = await Sandbox.create()
await sandbox.commands.run('echo "state to preserve" > /tmp/data.txt')
const sandboxId = sandbox.sandboxId
await sandbox.betaPause()
const resumed = await Sandbox.connect(sandboxId)
const result = await resumed.commands.run('cat /tmp/data.txt')
console.log(result.stdout)
from e2b_code_interpreter import Sandbox
sandbox = Sandbox.create()
sandbox.commands.run('echo "state to preserve" > /tmp/data.txt')
sandbox_id = sandbox.sandbox_id
sandbox.beta_pause()
resumed = Sandbox.connect(sandbox_id)
result = resumed.commands.run('cat /tmp/data.txt')
print(result.stdout)
Auto-pause (pause when idle instead of killing)
const sandbox = await Sandbox.betaCreate({
autoPause: true,
timeoutMs: 5 * 60_000,
})
sandbox = Sandbox.beta_create(
auto_pause=True,
timeout=300,
)
List paused sandboxes
const paginator = await Sandbox.list({
query: { state: ['paused'] },
})
const sandboxes = await paginator.nextItems()
from e2b_code_interpreter import Sandbox, SandboxQuery, SandboxState
paginator = Sandbox.list(SandboxQuery(state=[SandboxState.PAUSED]))
sandboxes = paginator.next_items()
Reconnecting to a Running Sandbox
const sandboxId = sandbox.sandboxId
const sandbox = await Sandbox.connect(sandboxId)
const paginator = await Sandbox.list({
query: { state: ['running'] },
})
const sandboxes = await paginator.nextItems()
sandbox_id = sandbox.sandbox_id
sandbox = Sandbox.connect(sandbox_id)
paginator = Sandbox.list()
sandboxes = paginator.next_items()
Networking
See the networking reference for port exposure, public URLs, traffic access tokens, domain-based filtering, and host masking.
Quick: Get a public URL for a port
const host = sandbox.getHost(3000)
const url = `https://${host}`
host = sandbox.get_host(3000)
url = f'https://{host}'