Sandbox for pi.
Sandboxes pi like this:
- read/write/edit: direct control using allow/deny lists
- bash: uses Anthropic Sandbox Runtime to control network and file system access
When a blocked action is attempted, the user is prompted to allow it temporarily or permanently rather than silently failing.
pi install npm:pi-sandboxAdd a config like this either to ~/.pi/agent (global) or to .pi/sandbox.json (local).
Local config takes precedence over global.
Note below that the order of precedence for filesystem read and write are opposite.
{
"enabled": true,
"network": {
"allowedDomains": ["github.com", "*.github.com"],
"deniedDomains": []
},
"filesystem": {
// For READS:
// - ANY read is prompted unless the path is already in allowRead
// - Granting a prompt adds to allowRead, which overrides denyRead
// - denyRead is not a hard-block; it just marks regions as denied by default
"denyRead": ["/Users", "/home"],
"allowRead": [".", "~/.config", "~/.local", "Library"],
// For WRITES:
// - empty ALLOW means no write access at all
// - DENY takes precedence and is never prompted
"allowWrite": [".", "/tmp"],
"denyWrite": [".env", ".env.*", "*.pem", "*.key"]
}
}pi --no-sandbox disable sandboxing for the session
/sandbox show current configuration and session allowances
Bash commands are wrapped with sandbox-exec (macOS) or bubblewrap
(Linux) to enforce network and filesystem restrictions at the OS level.
Read, write, and edit tool calls are intercepted before execution and checked against the same filesystem policy. The OS-level sandbox cannot cover these tools because they run directly in the Node.js process rather than in a subprocess.
When a block is triggered, a prompt appears with four options:
- Abort (keep blocked)
- Allow for this session only
- Allow for this project — written to
.pi/sandbox.json - Allow for all projects — written to
~/.pi/agent/sandbox.json
Session allowances are held in memory only. They are never written to disk and the agent has no way to read or modify them. They are reset when the extension reloads or pi restarts.
| Rule | Behaviour |
|---|---|
Domain not in allowedDomains |
Prompted (bash and !cmd) |
Path not in allowRead |
Prompted (read tool); granting adds to allowRead |
Path not in allowWrite |
Prompted (write/edit tools and bash write failures) |
Path in denyWrite |
Hard-blocked, no prompt |
Domain in deniedDomains |
Hard-blocked at OS level, no prompt |
If a path is added to allowWrite via a prompt but is also present in
denyWrite, it remains blocked. A warning is shown explaining which config
files to check.
allowedDomains supports *.example.com wildcards. allowWrite uses prefix
matching, so . covers the entire current working directory.
⚠️ Read and write have different precedence rules:
- Read: Every read is prompted unless the path is already in
allowRead.denyReadis not a hard-block — it marks regions as denied by default, but granting a prompt adds the path toallowRead, overridingdenyRead.- Write:
denyWritetakes precedence overallowWriteand is never prompted. A path indenyWriteis always blocked, even if it matchesallowWrite.
If neither file exists, built-in defaults apply (see above for the defaults).
The footer shows a lock indicator while the sandbox is active.
Based on code from badlogic/pi-mono by Mario Zechner, used under the MIT License.
