Yolocode E2B Sandboxes API Documentation
š The Magic Hack to Win Any Hackathon
Add Claude Code - the world's most powerful coding agent - to your React app with ONE API call.
# 1. Create a sandbox (takes ~10 seconds)
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"name": "my-agent"}'
// 2. Plug the URL into Vercel AI SDK (literally one line)
const { messages, input, handleSubmit } = useChat({
api: 'https://9999-{sandboxId}.e2b.app/chat',
});
That's it. You now have a full coding agent in your app that can:
- šØ Image generation pipelines - Execute 20-30 complex steps automatically
- šļø Self-updating admin panels - Agent modifies your UI in real-time
- š Document processing - Upload 50+ random files, ask agent to convert them
- š¬ Video editing - Crop, edit, convert with ffmpeg using natural language
- š Data analysis - Upload massive CSVs and get instant insights
Quick Start
Step 1: Get Your Agent URL
# Create sandbox and get the chat URL
RESPONSE=$(curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"name": "hackathon-agent"}')
CHAT_URL=$(echo $RESPONSE | jq -r '"https://" + .claudeHost + "/chat"')
echo $CHAT_URL
# Output: https://9999-abc123xyz.e2b.app/chat
Step 2: Integrate with React
import { useChat } from '@ai-sdk/react';
export default function MyApp() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: 'https://9999-abc123xyz.e2b.app/chat', // Your agent URL
});
return (
<div>
{messages.map(m => (
<div key={m.id}>
{m.role}: {m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
</div>
);
}
Step 3: Test via cURL
# Send a message to your agent
curl -X POST "https://9999-abc123xyz.e2b.app/chat" \
-H "Content-Type: application/json" \
-d '{
"messages": [{
"role": "user",
"content": "Create a data visualization from sales.csv"
}]
}' \
--no-buffer
Real-World Examples
Image Processing Pipeline
// User uploads images, agent processes them automatically
const { sendMessage } = useChat({
api: 'https://9999-xyz.e2b.app/chat',
});
sendMessage({
content: 'Resize all images in /uploads to 800x600, convert to WebP, optimize for web',
});
// Agent executes: find, convert, imagemagick, optimization - all automatically
Self-Updating Dashboard
// Agent modifies your React components live
sendMessage({
content: 'Add a new chart showing revenue by region to Dashboard.tsx',
});
// Agent reads your code, adds the component, installs dependencies if needed
Document Converter
// Process dozens of files with natural language
sendMessage({
content: 'Convert all PDFs in /docs to markdown, extract tables to CSV',
});
// Agent uses pdftotext, pandoc, custom scripts - figures it out
Overview
The Yolocode API provides cloud-based development environments (sandboxes) powered by E2B infrastructure, with:
- Claude Code integration - Full coding agent with filesystem access
- GitHub repository support - Auto-clone and setup your repos (tested with private repos)
- WebSSH terminal - Direct shell access
- Real-time code execution - Run commands, edit files, install packages
Repository Cloning
When you provide githubRepo and githubToken, the sandbox automatically:
- Clones the repository to
/home/user/workspace - Configures git with your GitHub credentials
- Installs dependencies (detects bun, npm, yarn, pnpm)
- Runs any setup defined in
yolocode.yaml
Example startup log showing successful clone:
š Cloning repository: makedora/dora-telegram ā Repository setup complete! Repository: /home/user/workspace (cloned from makedora/dora-telegram)
Authentication
GitHub Authentication (Required)
All API endpoints require GitHub OAuth authentication. Include your GitHub token in the Authorization header:
Authorization: Bearer YOUR_GITHUB_TOKEN
To obtain a GitHub token:
gh auth token
Claude Authentication (Optional - Use Your Own Credits)
Claude AI is always enabled in your sandbox. You have two options for how it's authenticated:
Option 1: No Claude Credentials (Uses yolocode API credits - Default)
If you don't provide claudeCredentials, the sandbox will use yolocode's Claude API key. This means:
- ā Claude AI works immediately, no setup needed
- ā Perfect for testing and hackathons
- ā ļø Uses yolocode's API credits (limited free usage)
- ā ļø May be rate-limited during high usage
# Create sandbox using yolocode's Claude API credits
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"name": "my-sandbox"}'
Option 2: Bring Your Own Claude Credentials (Unlimited usage on your account)
For unlimited usage without rate limits, bring your own Claude OAuth credentials. Here's how:
Step 1: Get Claude Account
- Sign up at claude.ai
- Get a Pro or Max subscription (required for API access)
Step 2: Extract Credentials from Claude Desktop/Web
The easiest way is to inspect your browser's network requests:
- Open claude.ai in Chrome/Firefox
- Open Developer Tools (F12) ā Network tab
- Filter for "oauth" or "token"
- Make a request (start a chat)
- Look for requests to
api.anthropic.comorconsole.anthropic.com - Find the Authorization header - it contains your access token
Alternative: Use the yolocode mobile app
- Download yolocode mobile app
- Connect Claude account via OAuth
- Credentials are stored and automatically used
Step 3: Pass Credentials to API
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{
"name": "my-ai-sandbox",
"claudeCredentials": {
"accessToken": "your_access_token_here",
"refreshToken": "your_refresh_token_here",
"expiresAt": "2025-12-31T23:59:59Z"
}
}'
Note: Claude credentials format:
{
"accessToken": string, // OAuth access token
"refreshToken": string, // OAuth refresh token
"expiresAt": string, // ISO 8601 timestamp
"account": { // Optional
"id": string,
"name": string
},
"subscriptionInfo": { // Optional
"hasAvailableMaxSubscription": boolean,
"hasAvailableSubscription": boolean
}
}
Security Warning: Never commit credentials to git. Use environment variables or secure credential management.
Base URL
https://staging.yolocode.ai/api/e2b-sandboxes
API Endpoints
Create Sandbox (The Only Endpoint You Need)
POST /api/e2b-sandboxes
Creates a new E2B sandbox with optional GitHub repository setup and Claude credentials.
What happens during sandbox creation:
The API automatically sets up a fully configured development environment:
- Creates E2B sandbox with specified template and metadata
- Starts background startup script (
/home/user/start.sh) for repository cloning and setup - Configures Claude authentication:
- OAuth mode: Writes
.claude/.credentials.jsonand.claude.jsonfiles - JWT mode: Adds
ANTHROPIC_BASE_URLandANTHROPIC_AUTH_TOKENto environment - No auth mode: Creates minimal
.claude.jsonto skip onboarding
- OAuth mode: Writes
- Sets up workspace at
/home/user/workspaceand makes it the default directory - Starts WebSSH server via systemd on port 8888 (
/usr/local/bin/wssh) - Starts Claude SSE server via systemd on port 9999 (
/home/user/claude-sse-server.ts) - Configures environment variables in both systemd services and
.bashrcfor terminal sessions
The sandbox is immediately ready to use - no additional API calls needed to start services.
Minimal Request
# Simplest possible request - just a name
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"name": "my-sandbox"}'
Request Body
All fields except name are optional. The API will automatically:
- Generate an AI-based display name from
taskDescription(or usenameas fallback) - Add
userId,userLogin, anddisplayNameto metadata - Select appropriate template based on hosting (cloud or self-hosted)
- Convert
claudeCredentialsto internal authentication format
{
"name": "my-dev-sandbox",
"template": "yhviqh0tk1bo8z7uu1qf",
"taskDescription": "Build a React application with TypeScript",
"githubToken": "ghp_xxxxx",
"githubRepo": "username/repository",
"repositorySetup": {
"environmentVariables": {
"NODE_ENV": "development",
"API_KEY": "secret123"
}
},
"claudeCredentials": {
"accessToken": "claude_access_token",
"refreshToken": "claude_refresh_token",
"expiresAt": "2025-01-12T10:00:00Z",
"account": {
"id": "user_123",
"name": "John Doe"
},
"selectedModel": "claude-3-5-sonnet-20241022",
"subscriptionInfo": {
"hasAvailableMaxSubscription": true,
"hasAvailableSubscription": false
}
},
"envVars": {
"CUSTOM_VAR": "value"
},
"timeout": 3600,
"autoPause": true
}
Field Notes:
name(required): Unique identifier for the sandboxtemplate(optional): E2B template ID - defaults toyhviqh0tk1bo8z7uu1qf(cloud) orrki5dems9wqfm4r03t7g(self-hosted)taskDescription(optional): Used to generate human-readable display name via AIgithubToken(optional): GitHub personal access token for repository operationsgithubRepo(optional): Repository to clone in format "owner/repo"repositorySetup(optional): Configuration for repository environmentenvironmentVariables(optional): Environment variables to set in the sandbox- Note: Setup commands and dev server config are now handled via
yolocode.yamlin the repository
claudeCredentials(optional): Claude OAuth credentials for AI assistance- If not provided, a JWT token will be generated for gateway authentication
account,selectedModel,subscriptionInfoare optional but recommended for full Claude integration
envVars(optional): Additional environment variablestimeout(optional): Sandbox timeout in seconds - defaults to 3600 (1 hour) for cloud, 86400 (24 hours) for self-hostedautoPause(optional): Enable auto-pause when idle - defaults totrue
Response Example
{
"id": "sb_abc123xyz",
"name": "react-dev-env",
"template": "yhviqh0tk1bo8z7uu1qf",
"status": "running",
"createdAt": "2025-01-11T11:00:00Z",
"metadata": {
"userId": "12345",
"userLogin": "johndoe",
"displayName": "react typescript application builder",
"name": "react-dev-env",
"actualSandboxName": "react-dev-env",
"githubRepo": "myuser/my-react-app",
"autoPause": "true"
},
"githubRepo": "myuser/my-react-app",
"host": "https://8888-sb_abc123xyz.e2b.app",
"websshHost": "https://8888-sb_abc123xyz.e2b.app",
"claudeHost": "https://9999-sb_abc123xyz.e2b.app"
}
Response Field Notes:
id: E2B sandbox ID (format:sb_<random>)displayName: AI-generated human-readable name based ontaskDescriptionmetadata: Automatically includesuserId,userLogin,displayName, and request fieldshost,websshHost,claudeHost: Full URLs with ports embedded (format:https://<port>-<sandboxId>.e2b.app)- Use
claudeHost+/chatfor your Vercel AI SDK integration
List All Sandboxes
GET /api/e2b-sandboxes
Lists all E2B sandboxes for the authenticated user.
cURL Example
curl -X GET https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)"
Response Example
[
{
"id": "sandbox_abc123",
"name": "my-dev-sandbox",
"template": "4mc4d3ts8akgu5790i35",
"status": "running",
"createdAt": "2025-01-11T10:00:00Z",
"metadata": {
"userId": "12345",
"userLogin": "johndoe",
"displayName": "Build React App"
},
"githubRepo": "johndoe/my-project",
"region": "us-east-1",
"host": "sandbox-abc123.e2b.dev"
}
]
Get Sandbox Details
GET /api/e2b-sandboxes/{id}
Retrieves details of a specific sandbox.
cURL Example
curl -X GET https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789 \
-H "Authorization: Bearer $(gh auth token)"
Execute Command
POST /api/e2b-sandboxes/{id}/exec
Executes a command inside the sandbox and returns the output.
Request Body
{
"command": "ls -la"
}
cURL Example
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "npm run test"}'
Response Example
{
"output": "Test Results:\nā All tests passed (42 tests, 0 failures)"
}
Start Sandbox
POST /api/e2b-sandboxes/{id}/start
Starts a stopped sandbox.
cURL Example
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789/start \
-H "Authorization: Bearer $(gh auth token)"
Stop Sandbox
POST /api/e2b-sandboxes/{id}/stop
Stops a running sandbox (Note: E2B may only support killing, not graceful stop).
cURL Example
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789/stop \
-H "Authorization: Bearer $(gh auth token)"
Delete Sandbox
DELETE /api/e2b-sandboxes/{id}
Permanently deletes a sandbox.
cURL Example
curl -X DELETE https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789 \
-H "Authorization: Bearer $(gh auth token)"
Write File to Sandbox
POST /api/e2b/{sandboxId}/files/write
Writes a file to the sandbox filesystem. Supports both binary file uploads (via FormData) and text content (via JSON).
FormData Upload (for binary files)
curl -X POST https://staging.yolocode.ai/api/e2b/sandbox_xyz789/files/write \
-H "Authorization: Bearer $(gh auth token)" \
-F "file=@/path/to/local/image.png" \
-F "path=/home/user/workspace/uploads/image.png"
JSON Upload (for text content)
curl -X POST https://staging.yolocode.ai/api/e2b/sandbox_xyz789/files/write \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{
"path": "/home/user/workspace/config.json",
"content": "{\"key\": \"value\"}"
}'
Request Body (JSON)
{
"path": "/home/user/workspace/file.txt",
"content": "file content as string"
}
Request Body (FormData)
| Field | Type | Description |
|---|---|---|
file | File | The file to upload |
path | string | Destination path in the sandbox |
Response Example
{
"success": true
}
Use Cases
- Upload images, PDFs, or other binary files for processing
- Write configuration files
- Deploy static assets to the sandbox
- Upload data files for analysis
Configure Claude Credentials
POST /api/e2b-sandboxes/{id}/claude-credentials
Updates Claude AI credentials for a sandbox after creation.
Request Body
{
"claudeCredentials": {
"accessToken": "claude_access_token",
"refreshToken": "claude_refresh_token",
"expiresAt": "2025-01-12T10:00:00Z",
"subscriptionInfo": {
"hasAvailableMaxSubscription": true
}
}
}
cURL Example
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/sandbox_xyz789/claude-credentials \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{
"claudeCredentials": {
"accessToken": "xxx",
"refreshToken": "yyy",
"expiresAt": "2025-01-12T10:00:00Z"
}
}'
Integrating with Your App
React with Vercel AI SDK
After creating a sandbox, you can immediately interact with Claude AI using the claudeHost URL returned in the response. The Claude SSE server is automatically started during sandbox creation and provides an SSE (Server-Sent Events) endpoint compatible with Vercel AI SDK's useChat hook.
No additional setup required - the server is running and ready to accept requests as soon as the sandbox creation completes.
React Native Example
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from '@ai-sdk/ui-utils';
// After creating sandbox, you get claudeHost in response
// Example: "9999-sandbox-xyz789.e2b.app"
const sandboxResponse = await createSandbox(/* ... */);
const { claudeHost } = sandboxResponse;
// Build SSE URL for E2B Claude server
const sseUrl = claudeHost.startsWith('http') ? `${claudeHost}/chat` : `https://${claudeHost}/chat`;
// Use Vercel AI SDK's useChat hook with custom API endpoint
const { messages, sendMessage, error, status, stop } = useChat({
transport: new DefaultChatTransport({
fetch: expoFetch as unknown as typeof globalThis.fetch,
api: sseUrl,
}),
onFinish: ({ message }) => {
console.log('Chat finished, new message:', message);
},
onError: error => {
// Check if this is a cancellation error from the stop button
const errorMessage = error?.message || error?.toString() || '';
if (
errorMessage.includes('FetchRequestCanceledException') ||
errorMessage.includes('AbortError') ||
errorMessage.includes('canceled')
) {
console.log('Request cancelled by user');
return; // Don't show error for intentional cancellation
}
console.error('Chat error:', error);
showErrorToast('Connection Error', 'Failed to connect to Claude');
},
});
// Send a message programmatically
await sendMessage({
text: 'Help me build a React component',
});
Node.js/TypeScript Example
import { streamText } from 'ai';
// Build SSE URL from claudeHost
const claudeHost = '9999-sandbox-xyz789.e2b.app';
const sseUrl = `https://${claudeHost}/chat`;
// Send a message and stream the response
const response = await fetch(sseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [
{
role: 'user',
content: 'Explain the code in package.json',
},
],
}),
});
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
console.log('Received:', chunk);
}
cURL Example
# Get claudeHost from sandbox creation response
CLAUDE_HOST="9999-sandbox-xyz789.e2b.app"
# Send a message to Claude via SSE endpoint
curl -X POST "https://${CLAUDE_HOST}/chat" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "List all files in the workspace"
}
]
}' \
--no-buffer
Available Claude Commands
Claude in the E2B sandbox can execute various commands and file operations:
// Ask Claude to read files
await sendMessage({
role: 'user',
content: 'Read the package.json file and explain the dependencies',
});
// Ask Claude to write code
await sendMessage({
role: 'user',
content: 'Create a new React component called UserProfile',
});
// Ask Claude to run commands
await sendMessage({
role: 'user',
content: 'Run the test suite and explain any failures',
});
// Ask Claude to debug
await sendMessage({
role: 'user',
content: 'Debug why the server is not starting on port 3000',
});
Handling Streaming Responses
The Claude SSE endpoint streams responses in real-time:
// React Native component example
function ChatInterface({ claudeHost }) {
const sseUrl = `https://${claudeHost}/chat`;
const { messages, input, handleInputChange, handleSubmit, isLoading, stop } = useChat({
api: sseUrl,
});
return (
<View>
{/* Display messages */}
{messages.map((message, i) => (
<Text key={i}>
{message.role}: {message.content}
</Text>
))}
{/* Input form */}
<TextInput
value={input}
onChangeText={handleInputChange}
placeholder="Ask Claude..."
/>
{/* Submit/Stop button */}
<Button
title={isLoading ? "Stop" : "Send"}
onPress={isLoading ? stop : handleSubmit}
/>
</View>
);
}
Error Handling
Handle connection and authentication errors:
const { error, clearError } = useChat({
api: sseUrl,
onError: error => {
if (error.message.includes('401')) {
// Claude credentials may be invalid or expired
console.error('Authentication failed - update Claude credentials');
// Update credentials via API:
// POST /api/e2b-sandboxes/{id}/claude-credentials
} else if (error.message.includes('timeout')) {
console.error('Request timed out');
} else if (error.message.includes('canceled')) {
// User cancelled the request
return;
}
},
});
References
Complete Flow Example: Creating VM and Giving Tasks
Step 1: Create a Sandbox with Repository
# Create sandbox with GitHub repository
# Note: Setup commands are now defined in yolocode.yaml in the repository
SANDBOX_RESPONSE=$(curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{
"name": "task-runner",
"taskDescription": "Implement user authentication with JWT",
"githubRepo": "myuser/auth-project",
"repositorySetup": {
"environmentVariables": {
"DATABASE_URL": "postgresql://localhost:5432/mydb",
"JWT_SECRET": "your-secret-key"
}
}
}')
# Extract sandbox ID
SANDBOX_ID=$(echo $SANDBOX_RESPONSE | jq -r '.id')
echo "Created sandbox: $SANDBOX_ID"
Step 2: Execute Setup Commands
# Install dependencies
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "cd /home/user/workspace && npm install"}'
# Run tests
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "cd /home/user/workspace && npm test"}'
Step 3: Configure Claude for AI Assistance
# Add Claude credentials for AI pair programming
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/claude-credentials \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{
"claudeCredentials": {
"accessToken": "your_claude_token",
"refreshToken": "your_refresh_token",
"expiresAt": "2025-01-12T10:00:00Z"
}
}'
Step 4: Execute Development Tasks
# Create a new feature file
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "cat > /home/user/workspace/src/auth.js << EOF\nconst jwt = require(\"jsonwebtoken\");\n// Authentication logic here\nEOF"}'
# Start development server
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "cd /home/user/workspace && npm run dev &"}'
Step 5: Monitor and Interact
# Check running processes
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "ps aux | grep node"}'
# View logs
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "tail -n 50 /home/user/workspace/logs/dev.log"}'
Step 6: Clean Up
# Stop the sandbox when done
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/stop \
-H "Authorization: Bearer $(gh auth token)"
# Or delete it permanently
curl -X DELETE https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID \
-H "Authorization: Bearer $(gh auth token)"
Error Handling
All endpoints return appropriate HTTP status codes:
200- Success201- Created (for POST /api/e2b-sandboxes)400- Bad Request (invalid input)401- Unauthorized (missing or invalid GitHub token)403- Forbidden (accessing sandbox not owned by user)404- Not Found (sandbox doesn't exist)500- Internal Server Error
Error Response Format:
{
"error": "Error message description",
"details": {
"_tag": "ErrorType",
"message": "Detailed error message"
}
}
Template IDs
The API automatically selects the appropriate E2B template based on hosting configuration:
- Cloud Template:
yhviqh0tk1bo8z7uu1qf(default whenE2B_DOMAINis not set) - Self-hosted Template:
rki5dems9wqfm4r03t7g(whenE2B_DOMAINenvironment variable is configured)
You can override the template by providing a template field in your request.
Sandbox Lifecycle
- Creation: Sandbox starts automatically when created with all services running
- WebSSH server (port 8888) starts via systemd
- Claude SSE server (port 9999) starts via systemd
- Background startup script begins repository setup
- All environment variables configured in services and shell
- Running: Sandbox is active and executing commands
- Both services are accessible and auto-restart on failure
- Terminal sessions use configured environment variables
- Paused: Sandbox can be paused to save resources (auto-pause supported)
- Services stop but state is preserved
- Resume with
POST /api/e2b-sandboxes/{id}/resume
- Stopped: E2B doesn't support graceful stop - only kill (permanent deletion)
- Stop operation is equivalent to delete
- Cannot be restarted after stopping
- Deleted: Sandbox is permanently removed
Security Considerations
- Authentication: All requests require valid GitHub OAuth tokens
- Ownership: Users can only access their own sandboxes
- Isolation: Each sandbox runs in an isolated environment
- Credentials: Claude credentials are stored securely and never exposed in responses
- JWT Tokens: Sandbox-specific JWT tokens are generated for Claude gateway authentication
Rate Limits
- Maximum request duration: 300 seconds (5 minutes)
- Sandbox timeout: 1 hour (cloud) or 24 hours (self-hosted)
- Concurrent sandboxes: Depends on E2B plan
Service Endpoints
Each sandbox automatically starts two services via systemd:
WebSSH Terminal (Port 8888)
- URL format:
https://8888-{sandboxId}.e2b.app(cloud) orhttps://8888-{sandboxId}.{E2B_DOMAIN}(self-hosted) - Service:
webssh.servicerunning/usr/local/bin/wssh - Auto-started: Yes, during sandbox creation
- Environment: Includes
GITHUB_TOKEN,GITHUB_REPO, and custom env vars fromrepositorySetup - Working directory:
/home/user(shells start in/home/user/workspacevia.bashrc)
Claude SSE Server (Port 9999)
- URL format:
https://9999-{sandboxId}.e2b.app(cloud) orhttps://9999-{sandboxId}.{E2B_DOMAIN}(self-hosted) - Service:
claude-sse-server.servicerunning/usr/local/bin/bun /home/user/claude-sse-server.ts --continue - Auto-started: Yes, during sandbox creation
- Environment: Includes Claude auth tokens, GitHub credentials, and custom env vars
- Endpoints:
POST /chat- SSE endpoint for Claude AI conversations (Vercel AI SDK compatible)POST /stop- Optional endpoint to signal task cancellationGET /history- Retrieve chat history (optional, may not be implemented in all versions)
Both services are managed by systemd and will:
- Auto-restart on failure (
Restart=always,RestartSec=5) - Start automatically on sandbox boot
- Log to systemd journal (
journalctl -u websshorjournalctl -u claude-sse-server)
Debugging Sandbox Services
If you need to check the status of services or debug issues, use the /exec endpoint:
Check Service Status
# Check WebSSH service status
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo systemctl status webssh"}'
# Check Claude SSE server status
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo systemctl status claude-sse-server"}'
View Service Logs
# View WebSSH logs (last 50 lines)
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo journalctl -u webssh -n 50 --no-pager"}'
# View Claude SSE server logs
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo journalctl -u claude-sse-server -n 50 --no-pager"}'
Check Network Ports
# Verify services are listening on correct ports
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "ss -tlnp | grep -E \":(8888|9999)\""}'
Restart Services
# Restart WebSSH
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo systemctl restart webssh"}'
# Restart Claude SSE server
curl -X POST https://staging.yolocode.ai/api/e2b-sandboxes/$SANDBOX_ID/exec \
-H "Authorization: Bearer $(gh auth token)" \
-H "Content-Type: application/json" \
-d '{"command": "sudo systemctl restart claude-sse-server"}'
Best Practices
- Always clean up sandboxes when done to avoid unnecessary charges
- Use
autoPausefor sandboxes that may be idle - Store sensitive environment variables in
repositorySetup.environmentVariables - Use descriptive task descriptions for better AI-generated display names
- Monitor sandbox resource usage through the E2B dashboard