pleach
Build

@pleach/sandbox

Vendor-neutral SandboxProvider contract plus four endpoint-shape adapters that ship inside the package — the seam @pleach/coding-agent reads.

@pleach/sandbox is the contract layer between @pleach/core runtimes and whatever process isolation a host chooses to ship — a Docker container, a Firecracker microVM, an E2B or Modal sandbox, an in-process fixture. It ships the SandboxProvider interface plus an in-memory fixture, and four adapters that ship inside the package — keyed by the shape of the backing endpoint (HTTP-stream, HTTP-poll, child-process, AWS Fargate), not by vendor name. @pleach/coding-agent is the canonical consumer — its file-read, file-write, and shell tools all dispatch through the provider this package defines.

What it provides

  • The SandboxProvider contract a host implements once and reuses across every sandboxed tool — read, write, list, exec — per the four-tool sketch in coding-agent.mdx.
  • An in-memory fixture suitable for tests and replay runs where the host hasn't wired a real backing process.
  • The canonical name (SandboxProvider) plus the legacy SandboxAdapter retained as a @deprecated alias, per the status row in packages.mdx.
  • The peer-dep anchor @pleach/coding-agent declares at ^0.1.0 (see Coding agent for the locked decisions).

Where it fits

@pleach/sandbox is the seam between the runtime and the sandboxed tool surface — the low-level SandboxProvider contract (execute, readFile, writeFile, listFiles, plus acquire / release / capabilities). There is no ctx.sandbox: core's ToolContext is sandbox-agnostic and carries only toolCallId + signal?. Instead the host closes over a sandbox handle when it constructs the tools; @pleach/coding-agent ships a thin SandboxClient facade (exec, readFile, writeFile) built over the low-level provider, and the tool handlers call that — see Coding agent. The direction lock keeps @pleach/core itself sandbox-agnostic: consumers reach for @pleach/sandbox directly, and the coding-agent SKU composes on top of both.

The SandboxProvider contract

A host implements this interface once, against Docker, Firecracker, E2B, Modal, or its own runner, and every sandboxed tool reuses it. Each I/O method is capability-gated — capabilities() drives graceful degradation when a backing process doesn't support, say, network egress.

interface SandboxProvider {
  readonly type: SandboxProviderType;
  acquire(sessionId: string, options?: AcquireOptions): Promise<SandboxHandle>;
  execute(handle: SandboxHandle, command: SandboxCommand): Promise<SandboxExecResult>;
  readFile(handle: SandboxHandle, path: string): Promise<string>;
  writeFile(handle: SandboxHandle, path: string, content: string): Promise<void>;
  listFiles(handle: SandboxHandle, path: string): Promise<readonly FileEntry[]>;
  release(handle: SandboxHandle): Promise<void>;
  isAlive(handle: SandboxHandle): Promise<boolean>;   // runtime heartbeat
  capabilities(): SandboxCapabilities;
}

acquire is idempotent on (sessionId × chatId), so a re-entered session reuses its sandbox rather than spawning a second one. An optional streaming execute variant yields SandboxExecChunk events for long-running commands. The exact option shapes (AcquireOptions, SandboxCommand, SandboxCapabilities) are on the npm README — see below.

Install

npm install @pleach/sandbox

Endpoint-shape adapters

Four adapters ship inside @pleach/sandbox, each implementing SandboxProvider against a different endpoint shape. The three HTTP/child-process adapters carry their own subpaths (so you pull only the one you wire); all four are also re-exported from the package root.

AdapterImportBacking shape
createHttpStreamSandboxProvider@pleach/sandbox/adapters/httpStreamHTTP service with streaming responses (baseURL + auth)
createHttpPollSandboxProvider@pleach/sandbox/adapters/httpPollHTTP service you poll for completion (baseURL + auth)
createChildProcessSandboxProvider@pleach/sandbox/adapters/childProcesslocal child process (workspaceDir, shell)
createFargateSandboxProvider@pleach/sandbox (root)AWS ECS/Fargate task (region, cluster, taskDefinition, subnets)

Vercel Sandbox, Modal, or E2B slot into whichever shape they present — an HTTP-streaming service uses createHttpStreamSandboxProvider; you don't need a per-vendor package. For tests, createInMemorySandboxProvider ships at @pleach/sandbox/testing.

import { createChildProcessSandboxProvider } from "@pleach/sandbox/adapters/childProcess"

const provider = createChildProcessSandboxProvider({ workspaceDir: "/srv/agent-scratch" })

API surface

The full SandboxProvider method set, per-adapter option shapes, and the @deprecated alias surface live on the package's npm page: @pleach/sandbox. The npm README is the source of truth for the contract itself; if a claim here disagrees with the published README, the README wins.

Where to go next

On this page