# SandboxProcessManager **Added in:** `@mastra/core@1.7.0` Abstract base class for managing background processes in sandboxes. Provides methods to spawn processes, list them, get handles by PID, and kill them. [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox), [`E2BSandbox`](https://mastra.ai/reference/workspace/e2b-sandbox), and [`DaytonaSandbox`](https://mastra.ai/reference/workspace/daytona-sandbox) all include built-in process managers. You don't need to instantiate this class directly unless you're building a custom sandbox provider. ## Usage example Access the process manager through the sandbox's `processes` property: ```typescript import { LocalSandbox } from '@mastra/core/workspace' const sandbox = new LocalSandbox({ workingDirectory: './workspace' }) await sandbox.start() // Spawn a background process const handle = await sandbox.processes.spawn('node server.js', { env: { PORT: '3000' }, onStdout: data => console.log(data), }) // List all tracked processes const procs = await sandbox.processes.list() // Get a handle by PID const proc = await sandbox.processes.get(handle.pid) // Kill a process await sandbox.processes.kill(handle.pid) ``` ## Methods ### `spawn(command, options?)` Spawn a background process. Returns a `ProcessHandle` immediately without waiting for the process to finish. ```typescript const handle = await sandbox.processes.spawn('npm run dev', { cwd: '/app', env: { NODE_ENV: 'development' }, onStdout: data => console.log(data), }) ``` **Parameters:** **command** (`string`): The command to run. Interpreted by the shell. **options** (`SpawnProcessOptions`): Optional settings for the spawned process. **options.timeout** (`number`): Timeout in milliseconds. Kills the process if exceeded. **options.env** (`NodeJS.ProcessEnv`): Environment variables for the process. **options.cwd** (`string`): Working directory for the process. **options.onStdout** (`(data: string) => void`): Callback for stdout chunks. Called as data arrives. **options.onStderr** (`(data: string) => void`): Callback for stderr chunks. Called as data arrives. **options.abortSignal** (`AbortSignal`): Signal to abort the process. When aborted, the process is killed. **Returns:** `Promise` ### `list()` List all tracked processes. Returns info about each process including PID, running state, and exit code. ```typescript const procs = await sandbox.processes.list() for (const proc of procs) { console.log(proc.pid, proc.running, proc.exitCode) } ``` **Returns:** `Promise` ### `get(pid)` Get a handle to a process by PID. Returns `undefined` if the process is not found or has already been dismissed. ```typescript const handle = await sandbox.processes.get(1234) if (handle) { console.log(handle.stdout) await handle.kill() } ``` **Returns:** `Promise` ### `kill(pid)` Kill a process by PID. Waits for the process to terminate before returning. Returns `true` if the process was killed, `false` if it was not found. ```typescript const killed = await sandbox.processes.kill(handle.pid) ``` **Returns:** `Promise` ## ProcessInfo Information about a tracked process, returned by `list()`. **pid** (`number`): Process ID. **command** (`string`): The command that was executed. **running** (`boolean`): Whether the process is still running. **exitCode** (`number`): Exit code if the process has finished. *** ## ProcessHandle Handle to a spawned background process. Provides methods to read output, send stdin, wait for completion, and kill the process. You don't create `ProcessHandle` instances directly — they're returned by `spawn()` and `get()`. ### Usage example ```typescript const handle = await sandbox.processes.spawn('npm run dev', { onStdout: data => console.log(data), }) // Read accumulated output console.log(handle.pid) console.log(handle.stdout) console.log(handle.stderr) console.log(handle.exitCode) // undefined while running // Wait for completion const result = await handle.wait() // Send stdin await handle.sendStdin('input data\n') // Kill the process await handle.kill() ``` ### Properties **pid** (`number`): Process ID. **stdout** (`string`): Accumulated stdout output so far. **stderr** (`string`): Accumulated stderr output so far. **exitCode** (`number | undefined`): Exit code. undefined while the process is still running. **command** (`string | undefined`): The command that was spawned. Set automatically by the process manager. **reader** (`Readable`): Readable stream of stdout. Useful for protocols like LSP or JSON-RPC that communicate over stdio. **writer** (`Writable`): Writable stream to stdin. Useful for protocols like LSP or JSON-RPC that communicate over stdio. ### Methods #### `wait(options?)` Wait for the process to exit and return the result. Optionally pass `onStdout`/`onStderr` callbacks to stream output while waiting. Callbacks are automatically removed when `wait()` resolves. ```typescript // Simple wait const result = await handle.wait() console.log(result.success, result.exitCode, result.stdout) // Wait with streaming const result = await handle.wait({ onStdout: data => process.stdout.write(data), onStderr: data => process.stderr.write(data), }) ``` **Parameters:** **options** (`WaitOptions`): Optional settings for waiting. **options.onStdout** (`(data: string) => void`): Callback for stdout chunks while waiting. **options.onStderr** (`(data: string) => void`): Callback for stderr chunks while waiting. **Returns:** `Promise` The `CommandResult` object contains: **success** (`boolean`): true if exit code is 0. **exitCode** (`number`): Numeric exit code. **stdout** (`string`): Full stdout output. **stderr** (`string`): Full stderr output. **executionTimeMs** (`number`): Execution time in milliseconds. **timedOut** (`boolean`): true if the process was killed due to timeout. **killed** (`boolean`): true if the process was killed by a signal. #### `kill()` Kill the process. Returns `true` if the process was killed, `false` if it had already exited. ```typescript const killed = await handle.kill() ``` **Returns:** `Promise` #### `sendStdin(data)` Send data to the process's stdin. Throws if the process has already exited or stdin is not available. ```typescript await handle.sendStdin('console.log("hello")\n') ``` **Returns:** `Promise` ## Stream interop `ProcessHandle` exposes `reader` and `writer` properties for integration with Node.js stream-based protocols like LSP or JSON-RPC: ```typescript import { createMessageConnection, StreamMessageReader, StreamMessageWriter, } from 'vscode-jsonrpc/node' const handle = await sandbox.processes.spawn('typescript-language-server --stdio') const connection = createMessageConnection( new StreamMessageReader(handle.reader), new StreamMessageWriter(handle.writer), ) connection.listen() ``` ## Building a custom process manager To build a process manager for a custom sandbox provider, extend `SandboxProcessManager` and implement `spawn()` and `list()`. The base class automatically wraps your methods with `ensureRunning()` so the sandbox starts before any process operation. ```typescript import { SandboxProcessManager, ProcessHandle } from '@mastra/core/workspace' import type { ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace' class MyProcessManager extends SandboxProcessManager { async spawn(command: string, options: SpawnProcessOptions = {}): Promise { // Your spawn implementation const handle = new MyProcessHandle(/* ... */) this._tracked.set(handle.pid, handle) return handle } async list(): Promise { return Array.from(this._tracked.values()).map(handle => ({ pid: handle.pid, running: handle.exitCode === undefined, exitCode: handle.exitCode, })) } } ``` Pass the process manager to your sandbox via the `processes` option in `MastraSandbox`: ```typescript class MySandbox extends MastraSandbox { constructor() { super({ name: 'MySandbox', processes: new MyProcessManager(), }) } } ``` When a process manager is provided, `MastraSandbox` automatically creates a default `executeCommand` implementation that uses `spawn()` + `wait()`, so you don't need to implement both. ## Related - [Sandbox](https://mastra.ai/docs/workspace/sandbox) - [WorkspaceSandbox interface](https://mastra.ai/reference/workspace/sandbox) - [LocalSandbox reference](https://mastra.ai/reference/workspace/local-sandbox) - [E2BSandbox reference](https://mastra.ai/reference/workspace/e2b-sandbox) - [DaytonaSandbox reference](https://mastra.ai/reference/workspace/daytona-sandbox)