- Refactor BuildCommand to support session continuation using --continue flag. - Introduce BuildCommandWithContinuation to handle both initial and continuation requests. - Add BuildLastUserMessageJSONL for generating JSONL from the last user message in continuation scenarios. - Enhance Executor to check for existing sessions and adjust command building accordingly. - Update environment setup to ensure session data is stored correctly for persistence. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|---|---|---|
| .. | ||
| bridge | ||
| docker | ||
| ipc | ||
| proxy | ||
| config.go | ||
| config_test.go | ||
| DESIGN.md | ||
| errors.go | ||
| helpers.go | ||
| helpers_test.go | ||
| manager.go | ||
| manager_test.go | ||
| PLAN.md | ||
| README.md | ||
| types.go | ||
Yao Sandbox
Sandbox provides persistent Docker containers as isolated execution environments for external CLI agents like Claude Code.
Overview
The sandbox module enables Yao to safely run external AI coding agents (like Claude CLI) in isolated Docker containers. Each user+chat session gets its own container with:
- Persistent workspace for code and dependencies
- IPC communication via Unix sockets
- Resource limits (CPU, memory)
- Security isolation
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Yao Server │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Sandbox Manager │ │
│ │ │ │
│ │ - GetOrCreate(userID, chatID) → container │ │
│ │ - Exec/Stream commands in container │ │
│ │ - Filesystem operations (read, write, copy) │ │
│ │ │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Container │ │ Container │ │ Container │ │
│ │ (user1) │ │ (user2) │ │ (user3) │ │
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
│ │ │ │ │
│ ──────┴───────────────┴───────────────┴──── │
│ Unix Socket IPC │
│ (one socket per container) │
└───────────────────────────────────────────────────────────────┘
Quick Start
Build Docker Images
cd sandbox/docker
./build.sh claude
Usage
import "github.com/yaoapp/yao/sandbox"
// Create manager
config := sandbox.DefaultConfig()
config.Init("/path/to/yao/data")
manager, err := sandbox.NewManager(config)
if err != nil {
log.Fatal(err)
}
defer manager.Close()
// Get or create container
container, err := manager.GetOrCreate(ctx, "user123", "chat456")
if err != nil {
log.Fatal(err)
}
// Execute command
result, err := manager.Exec(ctx, container.Name, []string{"echo", "hello"}, nil)
fmt.Println(result.Stdout) // "hello\n"
// Write file
err = manager.WriteFile(ctx, container.Name, "/workspace/test.txt", []byte("content"))
// Read file
data, err := manager.ReadFile(ctx, container.Name, "/workspace/test.txt")
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
YAO_SANDBOX_IMAGE |
yao/sandbox-claude:latest |
Docker image |
YAO_SANDBOX_WORKSPACE |
{YAO_DATA_ROOT}/sandbox/workspace |
Workspace directory |
YAO_SANDBOX_IPC |
{YAO_DATA_ROOT}/sandbox/ipc |
IPC socket directory |
YAO_SANDBOX_MAX |
100 |
Max concurrent containers |
YAO_SANDBOX_IDLE_TIMEOUT |
30m |
Idle timeout |
YAO_SANDBOX_MEMORY |
2g |
Memory limit |
YAO_SANDBOX_CPU |
1.0 |
CPU limit |
Docker Images
| Image | Description |
|---|---|
yao/sandbox-base:latest |
Base image with git, curl, yao-bridge |
yao/sandbox-claude:latest |
+ Claude CLI, Node.js 20, Python 3.11 |
yao/sandbox-claude:full |
+ Go 1.23 |
IPC Communication
Sandbox containers communicate with Yao via Unix sockets using the MCP (Model Context Protocol) JSON-RPC format. The yao-bridge binary inside containers bridges stdio ↔ socket.
Supported methods:
initialize- Handshaketools/list- List available toolstools/call- Execute a tool
Directory Structure
sandbox/
├── bridge/ # yao-bridge source
├── docker/ # Dockerfiles and build script
│ ├── base/
│ ├── claude/
│ └── build.sh
├── ipc/ # IPC system
│ ├── manager.go
│ ├── session.go
│ └── types.go
├── config.go # Configuration
├── errors.go # Error types
├── helpers.go # Helper functions
├── manager.go # Main manager
└── types.go # Type definitions
Testing
# Unit tests (no Docker required)
go test -v ./sandbox/... -run "^Test.*Validation|^Test.*Generation|^Test.*Parsing"
# All tests (requires Docker)
go test -v ./sandbox/...
Security
- Containers run as non-root user
--cap-drop ALLremoves all capabilitiesno-new-privilegesprevents privilege escalation- Only workspace directory is mounted
- Per-session IPC sockets with authorized tools only