Skip to main content

AppleContainerSandbox

Executes commands inside local OCI Linux containers through Apple's container CLI. The provider starts a long-lived container and uses container exec for workspace commands.

info

For interface details, see WorkspaceSandbox interface.

Installation
Direct link to Installation

npm install @mastra/apple-container

Requires an Apple silicon Mac running macOS 26 or newer with Apple's container CLI installed. Start the container system before using the provider:

container system start

Usage
Direct link to Usage

Add an AppleContainerSandbox to a workspace and assign it to an agent:

import { Agent } from '@mastra/core/agent'
import { Workspace } from '@mastra/core/workspace'
import { AppleContainerSandbox } from '@mastra/apple-container'

const workspace = new Workspace({
sandbox: new AppleContainerSandbox({
image: 'node:22-slim',
volumes: {
'/Users/me/project': '/workspace',
},
workingDir: '/workspace',
}),
})

const agent = new Agent({
id: 'dev-agent',
name: 'Dev Agent',
instructions: 'You are a coding assistant working in this workspace.',
model: 'anthropic/claude-sonnet-4-6',
workspace,
})

const response = await agent.generate('Run `node --version`.')
console.log(response.text)

Constructor parameters
Direct link to Constructor parameters

id?:

string
= Auto-generated
Unique identifier for this sandbox instance.

name?:

string
= The sandbox `id`
Apple container name passed to `container run --name`. Characters outside `[a-zA-Z0-9_.-]` are replaced with `-` and the result is prefixed if it would not start with an alphanumeric character.

image?:

string
= 'node:22-slim'
OCI image to use for the container.

command?:

string[]
= ['sleep', 'infinity']
Container init command. Must keep the container alive for exec-based command execution.

env?:

Record<string, string>
Environment variables to set in the container and on command execs.

volumes?:

Record<string, string>
Host-to-container bind mounts. Keys are host paths, values are container paths.

mounts?:

string[]
Raw `container run --mount` specs.

network?:

string
Apple container network attachment spec.

publishedPorts?:

string[]
Port publish specs passed as `--publish`.

publishedSockets?:

string[]
Socket publish specs passed as `--publish-socket`.

cpus?:

number | string
Number of CPUs to allocate.

memory?:

string
Memory allocation, for example '1G'.

platform?:

string
OCI platform, for example 'linux/arm64'.

arch?:

string
Image architecture when selecting a multi-arch image.

os?:

string
Image operating system when selecting a multi-platform image.

rosetta?:

boolean
= false
Enable Rosetta in the container.

readonlyRootfs?:

boolean
= false
Mount the container root filesystem as read-only.

ssh?:

boolean
= false
Forward the host SSH agent socket.

init?:

boolean
= true
Enable Apple's init process in the container.

virtualization?:

boolean
= false
Expose virtualization capabilities to the container.

capAdd?:

string[]
Linux capabilities to add.

capDrop?:

string[]
Linux capabilities to drop.

tmpfs?:

string[]
tmpfs destination paths passed as `--tmpfs`, for example `/tmp`.

dns?:

string[]
DNS nameserver IPs.

dnsSearch?:

string[]
DNS search domains.

noDns?:

boolean
= false
Do not configure DNS in the container.

labels?:

Record<string, string>
Additional container labels. Mastra labels (mastra.sandbox, mastra.sandbox.id) are always included.

workingDir?:

string
= '/workspace'
Working directory inside the container.

timeout?:

number
= 300000 (5 minutes)
Default command timeout in milliseconds.

deleteOnDestroy?:

boolean
= true
Delete the Apple container when the sandbox is destroyed. When false, destroy stops the container instead.

containerBinary?:

string
= 'container'
Path or name for the Apple container CLI.

instructions?:

string | function
Custom instructions that override the default instructions returned by getInstructions(). Pass an empty string to suppress instructions.

Properties
Direct link to Properties

id:

string
Sandbox instance identifier.

name:

string
Provider name ('AppleContainerSandbox').

provider:

string
Provider identifier ('apple-container').

status:

ProviderStatus
'pending' | 'starting' | 'running' | 'stopping' | 'stopped' | 'destroying' | 'destroyed' | 'error'

containerId:

string
Apple container ID when known, otherwise the configured container name.

Environment variables
Direct link to Environment variables

Set environment variables at the container level with env. Per-command environment variables can also be passed through executeCommand options:

const sandbox = new AppleContainerSandbox({
image: 'node:22-slim',
env: {
NODE_ENV: 'development',
},
})

await sandbox.executeCommand('node', ['-e', 'console.log(process.env.TASK_ID)'], {
env: { TASK_ID: '42' },
})

Bind mounts
Direct link to Bind mounts

Mount host directories into the container using the volumes option:

const sandbox = new AppleContainerSandbox({
image: 'node:22-slim',
volumes: {
'/Users/me/project': '/workspace/project',
'/Users/me/.npm': '/root/.npm',
},
})

Bind mounts are applied at container creation time. The host paths must exist before the sandbox starts.

Resource and platform options
Direct link to Resource and platform options

Apple container CLI options can be passed through the constructor:

const sandbox = new AppleContainerSandbox({
image: 'node:22-slim',
volumes: {
'/Users/me/project': '/workspace',
},
cpus: 2,
memory: '2G',
platform: 'linux/arm64',
readonlyRootfs: true,
tmpfs: ['/tmp'],
})

These options are only applied when a new container is created. If the sandbox reconnects to an existing container with the same name, destroy and recreate the sandbox to apply changed runtime options. Apple --tmpfs accepts container paths only, such as /tmp; it does not accept Docker-style option specs like /tmp:rw,size=256m. When readonlyRootfs is enabled, make sure workingDir points to a path supplied by the image, a bind mount, or a writable tmpfs.

Security model
Direct link to Security model

AppleContainerSandbox runs local containers through the host Apple container service. Treat constructor options as trusted server-side configuration:

  • volumes, mounts, and publishedSockets can expose host paths to containerized code.
  • publishedPorts can expose in-container services on the host or network; bind to 127.0.0.1 when only local access is intended.
  • ssh forwards the host SSH agent socket.
  • capAdd and virtualization can expand what containerized code can do.
  • containerBinary is a constructor-only escape hatch for trusted code and is not part of the serializable editor provider schema.

Use the narrowest mounts and capabilities your workload needs. Existing containers are only reconnected when they carry Mastra ownership labels for the sandbox ID. Containers created by this provider also include a config-hash label; when that label is present, reconnect fails if immutable runtime options such as image, command, mounts, ports, capabilities, or working directory changed.

Limitations
Direct link to Limitations

AppleContainerSandbox implements foreground workspace command execution with executeCommand(). It does not yet expose a SandboxProcessManager for background processes or LSP sessions.

Command timeouts are enforced inside the container so timed-out commands are cleaned up by the container runtime. Abort signals cancel the host CLI wait path and should not be used as a substitute for command timeouts when in-container cleanup matters.

Reconnection
Direct link to Reconnection

AppleContainerSandbox reconnects by inspecting a container with the configured name. When start() is called:

  • A running container is reused.
  • A stopped container is restarted.
  • A missing container is created from the configured image.
  • A container with the configured name but without matching Mastra ownership labels fails instead of being managed.
  • A Mastra-owned container with a config-hash label that does not match immutable runtime options fails instead of being reused.
const sandbox = new AppleContainerSandbox({ id: 'persistent-sandbox' })
await sandbox.start()

const sandbox2 = new AppleContainerSandbox({ id: 'persistent-sandbox' })
await sandbox2.start()

Editor provider
Direct link to Editor provider

Register the provider with MastraEditor to hydrate stored sandbox configs:

import { MastraEditor } from '@mastra/editor'
import { appleContainerSandboxProvider } from '@mastra/apple-container'

const editor = new MastraEditor({
sandboxes: {
[appleContainerSandboxProvider.id]: appleContainerSandboxProvider,
},
})