Self-hosted sandbox API for isolated code execution and file management
npm install @treesap/sandboxA self-hosted sandbox API for isolated code execution and file management. Similar to Cloudflare's Sandbox SDK, but designed for self-hosting on your own infrastructure.
Perfect for AI agents, code execution platforms, and automation tools that need secure, isolated environments.
> ā ļø Warning: This package is experimental and exposes your machine to the local network. It executes arbitrary code with folder-based isolation only (not containerized). Proceed with caution.
- š Folder-based isolation - Each sandbox gets its own working directory
- š File Operations API - Read, write, list, and delete files
- ā” Command Execution - Run commands with streaming output
- š Process Management - Start, monitor, and kill background processes
- š Real-time Streaming - Server-Sent Events for live output
- šÆ Simple REST API - Easy to integrate with any language
- š¦ TypeScript SDK - Full-featured client library included
- š Self-hosted - Run on your own servers, no cloud dependencies
``bash`
npm install @treesap/sandbox
`bashUsing CLI
npx treesap-sandbox --port 3000
await startServer({ port: 3000 });
`
`typescript
import { SandboxClient } from '@treesap/sandbox';
// Create a new sandbox
const sandbox = await SandboxClient.create('http://localhost:3000');
// Execute commands
const result = await sandbox.exec('npm install');
console.log(result.stdout);
// File operations
await sandbox.writeFile('hello.txt', 'Hello, World!');
const content = await sandbox.readFile('hello.txt');
const files = await sandbox.listFiles();
// Background processes
const server = await sandbox.startProcess('node server.js');
const logs = await sandbox.streamProcessLogs(server.id);
// Cleanup
await sandbox.destroy({ cleanup: true });
`
#### Create a Sandbox
`typescript`
POST /sandbox
`typescript`
const sandbox = await SandboxClient.create('http://localhost:3000', {
workDir: '/custom/path', // optional
timeout: 60000, // optional, default timeout for commands
});
#### Get Sandbox Info
`typescript`
GET /sandbox/:id
`typescript`
const status = await sandbox.getStatus();
console.log(status);
// {
// id: 'abc123',
// workDir: '/path/to/sandbox',
// createdAt: 1234567890,
// processCount: 2,
// ...
// }
#### List All Sandboxes
`typescript`
GET /sandbox
#### Destroy a Sandbox
`typescript`
DELETE /sandbox/:id?cleanup=true
`typescript`
await sandbox.destroy({ cleanup: true });
#### Execute Command
`typescript`
POST /sandbox/:id/exec
`typescript
const result = await sandbox.exec('ls -la', {
timeout: 5000,
cwd: '/custom/dir',
env: { NODE_ENV: 'production' }
});
console.log(result);
// {
// success: true,
// stdout: '...',
// stderr: '...',
// exitCode: 0
// }
`
#### Stream Command Output
`typescript`
GET /sandbox/:id/exec-stream?command=npm%20install
`typescript
import { parseSSEStream } from '@treesap/sandbox';
const stream = await sandbox.execStream('npm install');
for await (const event of parseSSEStream(stream)) {
switch (event.type) {
case 'stdout':
console.log('Output:', event.data);
break;
case 'stderr':
console.error('Error:', event.data);
break;
case 'complete':
console.log('Exit code:', event.exitCode);
break;
}
}
`
#### Start a Background Process
`typescript`
POST /sandbox/:id/process
`typescript`
const process = await sandbox.startProcess('python -m http.server 8000');
console.log('Started with PID:', process.pid);
#### List Processes
`typescript`
GET /sandbox/:id/process
`typescript`
const processes = await sandbox.listProcesses();
#### Get Process Info
`typescript`
GET /sandbox/:id/process/:processId
`typescript`
const info = await sandbox.getProcess(processId);
#### Kill a Process
`typescript`
DELETE /sandbox/:id/process/:processId?signal=SIGTERM
`typescript`
await sandbox.killProcess(processId, 'SIGTERM');
#### Stream Process Logs
`typescript`
GET /sandbox/:id/process/:processId/logs
`typescript
const stream = await sandbox.streamProcessLogs(processId);
for await (const event of parseSSEStream(stream)) {
console.log([${event.timestamp}] ${event.data});`
}
#### List Files
`typescript`
GET /sandbox/:id/files?path=.&recursive=true&pattern=*.js
`typescript
const files = await sandbox.listFiles('.', {
recursive: true,
pattern: '*.js',
includeHidden: false
});
files.forEach(file => {
console.log(file.name, file.type, file.size);
});
`
#### Read File
`typescript`
GET /sandbox/:id/files/path/to/file.txt
`typescript`
const content = await sandbox.readFile('package.json');
console.log(content);
#### Write File
`typescript`
POST /sandbox/:id/files/path/to/file.txt
`typescript`
await sandbox.writeFile('README.md', '# Hello World');
#### Delete File
`typescript`
DELETE /sandbox/:id/files/path/to/file.txt?recursive=true
`typescript`
await sandbox.deleteFile('node_modules', { recursive: true });
`typescript
const sandbox = await SandboxClient.create('http://localhost:3000');
// Agent writes code
await sandbox.writeFile('script.py',
import pandas as pd
print(pd.__version__));
// Agent installs dependencies
await sandbox.exec('pip install pandas');
// Agent runs code
const result = await sandbox.exec('python script.py');
console.log(result.stdout);
// Cleanup
await sandbox.destroy({ cleanup: true });
`
`typescript
const sandbox = await SandboxClient.create('http://localhost:3000');
// Clone repo
await sandbox.exec('git clone https://github.com/user/repo.git');
await sandbox.exec('cd repo && npm install');
// Run tests
const testResult = await sandbox.exec('cd repo && npm test');
console.log('Tests passed:', testResult.success);
`
`typescript
const sandbox = await SandboxClient.create('http://localhost:3000');
// Start a web server
const server = await sandbox.startProcess('node server.js');
// Monitor logs in real-time
const logStream = await sandbox.streamProcessLogs(server.id);
for await (const log of parseSSEStream(logStream)) {
console.log('[Server]', log.data);
if (log.data.includes('Server started')) {
console.log('Server is ready!');
break;
}
}
// Later: stop the server
await sandbox.killProcess(server.id);
`
`bash
treesap-sandbox [options]
Options:
-p, --port
-h, --host
-b, --base-path
-m, --max-sandboxes
--cors Enable CORS (default: false)
--help Show this help message
`
`typescript
import { startServer } from '@treesap/sandbox';
const { server, manager } = await startServer({
port: 3000,
host: '0.0.0.0',
basePath: './.sandboxes',
maxSandboxes: 100,
cors: true,
});
// Access sandbox manager directly
const stats = manager.getStats();
console.log('Active sandboxes:', stats.totalSandboxes);
`
TreeSap Sandbox uses a simple, lightweight architecture:
``
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Client SDK / API ā
ā (HTTP REST + Server-Sent Events) ā
āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā
ā
ā HTTP/REST
ā
āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā
ā API Server (Hono) ā
ā - Sandbox Management ā
ā - Command Execution ā
ā - Process Management ā
ā - File Operations ā
āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā
ā
ā
āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā
ā Sandbox Manager ā
ā - Creates isolated sandboxes ā
ā - Manages lifecycle ā
ā - Auto-cleanup ā
āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā
ā
ā
āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā
ā Individual Sandboxes ā
ā - Isolated working directory ā
ā - Process spawning (child_process) ā
ā - File operations (fs) ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
- Folder-based isolation: Each sandbox operates in its own directory
- Path traversal prevention: File operations are validated to prevent ../ attacks
- Process limits: Configurable max processes per sandbox
- Automatic cleanup: Idle sandboxes are cleaned up after 30 minutes
- Resource monitoring: Optional timeout limits for commands
> ā ļø Note: This is folder-based isolation, not container-based. For production use with untrusted code, consider running the server inside a Docker container or VM for an additional security layer.
| Feature | TreeSap Sandbox | Cloudflare Sandbox |
|---------|----------------|-------------------|
| Self-hosted | ā
Yes | ā Cloud only |
| Folder isolation | ā
Yes | Container-based |
| File operations | ā
Full API | ā
Full API |
| Command execution | ā
Yes | ā
Yes |
| Process management | ā
Yes | ā
Yes |
| Streaming output | ā
SSE | ā
SSE |
| Code interpreters | ā ļø Planned | ā
Python/JS |
| Public URLs | ā No | ā
Yes |
| Platform | Node.js | Cloudflare Workers |
`typescript
import { Sandbox, FileService } from '@treesap/sandbox';
// Create a sandbox directly (without server)
const sandbox = new Sandbox({
workDir: '/tmp/my-sandbox',
timeout: 30000,
});
await sandbox.initialize();
// Execute commands
const result = await sandbox.exec('ls -la');
// Use file service
const fileService = new FileService(sandbox.workDir);
await fileService.writeFile('test.txt', 'Hello!');
const files = await fileService.listFiles();
// Cleanup
await sandbox.destroy({ cleanup: true });
`
`typescript
import { createServer, SandboxManager } from '@treesap/sandbox';
import { serve } from '@hono/node-server';
const { app, manager } = createServer({
basePath: '/custom/sandboxes',
maxSandboxes: 50,
});
// Add custom routes
app.get('/custom-endpoint', (c) => {
const stats = manager.getStats();
return c.json({ stats });
});
// Start server
serve({ fetch: app.fetch, port: 3000 });
``
Contributions are welcome! Please check out the GitHub repository for more information.
MIT
- Cloudflare Sandbox SDK - Cloud-based sandbox execution
- TreeSap - AI agent framework
---
Built with ā¤ļø by the TreeSap Team