05. Permissions, Plan Mode, and Safety

Sandbox

The sandbox is optional OS-level isolation around the Matcha CLI process and the commands it starts. Permissions decide what the model may request. The sandbox decides what the process can do after a request is approved.

Applied at startup

A non-off profile is applied to the entire process at startup (Landlock on Linux, Seatbelt on macOS). It is irreversible for that process. The assistant cannot relax it later. Child processes inherit the filesystem limits.

Off is the default. You opt in.

Built-in profiles

ProfileFS readFS writeChild networkTypical use
off (default)UnrestrictedUnrestrictedUnrestrictedTrusted machine, no isolation
workspaceEverywhereCWD + ~/.matcha/ + temp dirsAllowedEveryday development
devboxEverywhereTop-level dirs except /data (and /proc, /sys, /dev)AllowedDisposable VMs
read-onlyEverywhere~/.matcha/ + temp dirsBlocked on LinuxReview, exploration
strictCWD + system pathsCWD + ~/.matcha/ + temp dirsBlocked on LinuxUntrusted trees

Temp dirs include /tmp, /var/tmp, and on macOS the real TMPDIR under /private/var/folders. Child-network blocking uses seccomp on Linux only. On macOS restrict_network is a no-op.

workspace, read-only, and strict write-deny the user-global hook sources (~/.matcha/hooks/, ~/.matcha/hooks-paths, and absolute targets listed there) so a sandboxed session cannot rewrite those hooks. devbox does not apply that protection.

Custom profiles

Custom profiles live in ~/.matcha/sandbox.toml or .matcha/sandbox.toml. They extends a built-in, then add read_only, read_write, restrict_network, and a kernel-enforced deny list (globs such as **/.env). A custom name cannot reuse a built-in name: --sandbox devbox always runs the built-in. If user and project files define the same custom name differently, the user file wins and startup warns; /doctor shows both paths.

When a non-off profile is requested, the assistant stays in-process (no shared leader). matcha workspace start / restart / resume are unavailable; pause, stop, and status still work.

A built-in profile that cannot apply (old kernel, missing entitlements) warns and continues without enforcement, but still refuses the leader. A custom profile that cannot apply (unknown name, bad sandbox.toml, or Linux deny without bubblewrap) refuses to start.

The profile is stored with the session. Resume restores it. --sandbox on resume must match the saved profile or Matcha CLI errors; start a new session to change isolation.

When to use it

Use workspace when you want the assistant to read the system but only write in this project and Matcha CLI’s own home. Use read-only or strict on a tree you do not trust. Skip the sandbox when the assistant must install packages or write outside the working directory.

Permissions plus sandbox is stronger than either alone: a deny rule stops the model from asking; the kernel stops a process that tries anyway.

Start with a profile

matcha --sandbox workspace
matcha --sandbox read-only
matcha --sandbox strict

MATCHA_SANDBOX selects the same profile (GROK_SANDBOX is the registered alias). Resolution for a new session:

  1. A managed requirement that pins a profile
  2. --sandbox / MATCHA_SANDBOX
  3. [sandbox] profile in config
  4. off

Custom profile example

# ~/.matcha/sandbox.toml
[profiles.project]
extends = "workspace"
restrict_network = true
read_only = ["/data"]
read_write = ["/tmp/scratch"]
deny = ["/data/shared-secrets", "**/.env", "**/*.pem"]
matcha --sandbox project

deny entries with *, ?, or [ are globs. On macOS they apply at runtime (files created later still match). On Linux they expand at launch — later matches are not covered; name exact paths when Linux must be airtight. Unsupported glob syntax refuses to start on both platforms.

Resume

matcha --continue
matcha --resume <id>

Omit --sandbox to keep the saved profile. Passing a different profile is refused.

Shell environment

[shell_environment_policy] filters variables inherited by tool commands so a secret sitting in your shell does not leak into a subprocess. This is related, not the kernel sandbox. Default is leave-the-environment-alone (inherit = "all").

Events

Violations and profile-applied records go to ~/.matcha/sandbox-events.jsonl.