# How Claude Code Sandbox Execution Integrates with External Providers Like e2b

> Explore how Claude Code Sandbox Execution integrates external providers like e2b.dev for secure remote code execution leveraging a Python bridge and real-time progress streaming.

- Repository: [Daniel Avila/claude-code-templates](https://github.com/davila7/claude-code-templates)
- Tags: how-to-guide
- Published: 2026-04-26

---

**Claude Code's sandbox execution feature routes remote code execution to e2b.dev's isolated containers via a Python bridge, while keeping API credentials server-side and streaming real-time progress back to the client.**

The `davila7/claude-code-templates` repository implements a secure **sandbox execution** architecture that lets developers choose between running Claude Code locally or inside remote **external sandbox providers**. This hybrid approach isolates potentially unsafe code generation in ephemeral cloud containers while maintaining a seamless local development experience through a unified HTTP API.

## The Mode Dispatch Logic in sandbox-server.js

When the Express server starts at [`cli-tool/src/sandbox-server.js`](https://github.com/davila7/claude-code-templates/blob/main/cli-tool/src/sandbox-server.js), it first loads sensitive credentials via `loadEnvFile()` (lines 13‑33), which parses `E2B_API_KEY` and `ANTHROPIC_API_KEY` from a local `.env` file into `process.env`. These credentials remain in server memory and never travel to the browser.

The core dispatch logic occurs in the POST `/api/execute` handler (lines 12‑53). When a client sends a JSON payload containing `prompt`, `mode`, and `agent`, the server creates a task object and routes it based on the `mode` parameter:

- **`mode='cloud'`** → Invokes `executeE2BTask(task)` (lines 41‑43)
- **`mode='local'`** → Invokes `executeLocalTask(task)` (lines 45‑47)

This branching allows a single endpoint to serve both **external sandbox provider** runs and local executions without client-side configuration changes.

## How the Python Bridge Orchestrates External Sandboxes

When `executeE2BTask` triggers (lines 17‑55), it constructs a command to spawn the Python bridge at [`cli-tool/components/sandbox/e2b/e2b-launcher.py`](https://github.com/davila7/claude-code-templates/blob/main/cli-tool/components/sandbox/e2b/e2b-launcher.py). The Node.js server passes the user prompt, selected agent, and both API keys as command-line arguments and environment variables:

```javascript
const pythonProcess = spawn('python3', [
  launcherPath,
  '--prompt', task.prompt,
  '--agent', task.agent,
  '--api-key', process.env.E2B_API_KEY,
  '--anthropic-key', process.env.ANTHROPIC_API_KEY
], {
  env: { ...process.env }  // Secure credential injection
});

```

The Python script authenticates against `https://api.e2b.dev`, provisions an isolated sandbox container, uploads the requested agent markdown file, and executes the `claude` binary inside that container. Because the sandbox runs on external infrastructure, arbitrary code generated by Claude cannot access the developer's local file system.

### Real-time Progress Streaming from Remote Sandboxes

The Node.js server listens to `stdout` and `stderr` of the Python child process (lines 66‑88), parsing structured log markers to update the task state:

- `Sandbox created: <id>` → Sets `task.sandboxId`
- `Installing` → Increments `task.progress` to 25%
- `Executing Claude Code` → Advances `task.progress` to 50%
- `Execution completed successfully` → Finalizes output

Clients poll GET `/api/task/:taskId` to receive the current state, including the live `progress` percentage and accumulated `output` strings. This architecture allows the UI to display a real-time progress bar while the **external sandbox provider** handles the heavy lifting.

## Error Handling and Credential Security

If the Python bridge exits with a non-zero code, the `close` listener (lines 98‑108) inspects the stderr buffer for specific missing-key errors:

- `E2B API key is required`
- `Anthropic API key is required`

When detected, the server surfaces actionable error messages without exposing the full stack trace. This design ensures that **sandbox execution** fails gracefully when credentials are missing, while keeping the actual key values encrypted in server memory and environment variables.

## Local vs. Cloud Sandbox Execution

The repository supports two distinct execution strategies within the same API:

| Feature | Local (`mode='local'`) | Cloud (`mode='cloud'`) |
|---------|------------------------|------------------------|
| **Isolation** | Runs directly on the developer's machine with full file-system access | Executes inside an e2b container provided by the **external sandbox provider** |
| **Dependencies** | Requires the `claude` CLI binary installed locally | No local Claude binary needed; the remote sandbox includes it |
| **API Keys** | Optional (uses local CLI configuration) | Requires both `E2B_API_KEY` and `ANTHROPIC_API_KEY` |
| **Performance** | Faster startup, limited by local compute resources | Slight provisioning latency, but safe for untrusted code |
| **Use Case** | Trusted code prototypes and quick iterations | AI-generated code that may modify files or perform network calls |

The `executeLocalTask` function (lines 37‑58) handles the local path by spawning the `claude` CLI directly with the prompt and optional agent prefix, bypassing the external provider entirely.

## Configuring the External Sandbox Provider Integration

To enable remote **sandbox execution** with e2b:

1. **Create environment file** in the directory where you launch the server:

   ```dotenv
   E2B_API_KEY=your-e2b-key
   ANTHROPIC_API_KEY=sk-ant-api03-...
   ```

2. **Start the orchestration server**:

   ```bash
   node cli-tool/src/sandbox-server.js
   ```

3. **Execute code via HTTP**:

   ```http
   POST /api/execute HTTP/1.1
   Content-Type: application/json
   
   {
     "prompt": "Create a React component that fetches data from an API",
     "mode": "cloud",
     "agent": "development-team/frontend-developer"
   }
   ```

The server immediately returns a `taskId`. Poll the status endpoint to retrieve results:

```http
GET /api/task/task-1703829273456-abc123 HTTP/1.1

```

A successful response includes the sandbox identifier and execution output:

```json
{
  "success": true,
  "task": {
    "id": "task-1703829273456-abc123",
    "status": "completed",
    "progress": 100,
    "sandboxId": "sbox-7f4c1a2b",
    "output": "✓ Component created successfully..."
  }
}

```

## Summary

- **Dual-mode architecture**: The [`sandbox-server.js`](https://github.com/davila7/claude-code-templates/blob/main/sandbox-server.js) dispatches to either local CLI execution or remote **external sandbox providers** based on the `mode` parameter.
- **Secure credential isolation**: API keys for e2b and Anthropic load from `.env` via `loadEnvFile()` and reside only in server memory, passed securely to the Python child process environment.
- **Python bridge pattern**: [`e2b-launcher.py`](https://github.com/davila7/claude-code-templates/blob/main/e2b-launcher.py) acts as a thin wrapper that creates isolated containers, uploads agents, and streams structured logs back to Node.js.
- **Real-time monitoring**: Progress parsing of markers like `Sandbox created:` and `Executing Claude Code` enables live UI updates without WebSocket complexity.
- **Isolation guarantee**: Cloud mode runs inside e2b's infrastructure, preventing AI-generated code from accessing the host file system, while local mode offers speed for trusted workloads.

## Frequently Asked Questions

### What external sandbox providers does Claude Code support?

Currently, the implementation supports **e2b.dev** as the primary external sandbox provider. The integration is handled through the Python bridge at [`cli-tool/components/sandbox/e2b/e2b-launcher.py`](https://github.com/davila7/claude-code-templates/blob/main/cli-tool/components/sandbox/e2b/e2b-launcher.py), which uses the official e2b SDK to authenticate against `https://api.e2b.dev` and provision ephemeral containers. The architecture is modular, allowing for future providers by implementing similar launcher scripts following the same stdout marker protocol.

### How are API keys secured during sandbox execution?

API keys are never transmitted to the client browser. The Node.js server loads `E2B_API_KEY` and `ANTHROPIC_API_KEY` from a `.env` file into `process.env` at startup via `loadEnvFile()`. When spawning the Python bridge, these credentials pass through the `env` option of `child_process.spawn()`, ensuring they remain in server-side memory and environment variables only. If keys are missing, the server returns specific error messages without exposing stack traces or attempting network requests.

### What is the difference between local and cloud execution modes?

**Local mode** (`mode='local'`) spawns the `claude` CLI directly on the host machine using `executeLocalTask()`, offering faster startup but no isolation from the host file system. **Cloud mode** (`mode='cloud'`) invokes `executeE2BTask()`, which delegates to the external provider's infrastructure, creating an isolated container where even malicious generated code cannot harm the developer's machine. Cloud mode requires both API keys and incurs slight latency for container provisioning, while local mode requires only the local CLI installation.

### How does the server track progress of remote sandbox tasks?

The Node.js server parses structured log markers from the Python bridge's `stdout` stream. Specific strings like `Sandbox created:`, `Installing`, and `Executing Claude Code` trigger increments to the task's `progress` field (stored in the `activeTasks` map). Clients poll the REST endpoint `/api/task/:taskId` to fetch the current `progress` percentage, `status`, and accumulated `output`, allowing the frontend to render real-time progress bars without maintaining a persistent WebSocket connection.