Skip to main content
This guide helps you diagnose and fix common Agent Safehouse issues.

Common Issues

Symptoms: Agent reports permission errors or can’t see project files.Solution: Verify workdir detection:
# Check effective workdir and grants
safehouse --explain --stdout
If workdir is incorrect:
# Override workdir explicitly
safehouse --workdir=/path/to/project -- claude --dangerously-skip-permissions
If you need additional directories:
# Grant extra read-only access
safehouse --add-dirs-ro=/path/to/other/repo -- claude --dangerously-skip-permissions

# Grant writable access
safehouse --add-dirs=/tmp/scratch -- claude --dangerously-skip-permissions
Symptoms: forbidden-sandbox-reinit or sandbox initialization failed: Operation not permitted.Cause: Electron apps have their own sandbox that conflicts with sandbox-exec.Solution: Launch with --no-sandbox flag:
safehouse --enable=electron -- /Applications/Claude.app/Contents/MacOS/Claude --no-sandbox
safehouse --enable=electron -- "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" --no-sandbox
Symptoms: git commands fail with permission errors.Solution: Git support is enabled by default. Check if you need SSH access:
# For git-over-ssh workflows
safehouse --enable=ssh -- claude --dangerously-skip-permissions
SSH metadata (~/.ssh/config, ~/.ssh/known_hosts) is readable by default. Private keys require --enable=ssh.
Symptoms: Agent can’t find API keys or environment configuration.Solution: Safehouse uses a sanitized environment by default.Pass specific variables:
safehouse --env-pass=OPENAI_API_KEY,ANTHROPIC_API_KEY -- codex --dangerously-bypass-approvals-and-sandbox
Or inherit full environment:
safehouse --env -- codex --dangerously-bypass-approvals-and-sandbox
Or load from file:
safehouse --env=./agent.env -- codex --dangerously-bypass-approvals-and-sandbox
Symptoms: docker commands return permission errors.Solution: Docker socket access is opt-in:
safehouse --enable=docker -- claude --dangerously-skip-permissions
Symptoms: Agent can’t read from or write to clipboard.Solution: Clipboard access is opt-in:
safehouse --enable=clipboard -- claude --dangerously-skip-permissions

Debugging Sandbox Denials

Use /usr/bin/log (full path) for denial analysis, not shell-aliased log commands.

Live Stream Denials

Watch sandbox denials in real-time:
/usr/bin/log stream --style compact --predicate 'eventMessage CONTAINS "Sandbox:" AND eventMessage CONTAINS "deny("'

Filter by Agent or Process

Filter denials for a specific process:
/usr/bin/log stream --style compact --predicate 'eventMessage CONTAINS "Sandbox: 2.1.34(" AND eventMessage CONTAINS "deny("'

Kernel-Level Denials

Capture additional low-level events:
/usr/bin/log stream --style compact --info --debug --predicate '(processID == 0) AND (senderImagePath CONTAINS "/Sandbox")'

Recent History

View recent sandbox events:
/usr/bin/log show --last 2m --style compact --predicate 'process == "sandboxd"'

Filter Common Noise

Suppress frequent harmless denials:
/usr/bin/log stream --style compact \
  --predicate 'eventMessage CONTAINS "Sandbox:" AND eventMessage CONTAINS "deny(" AND NOT eventMessage CONTAINS "duplicate report" AND NOT eventMessage CONTAINS "/dev/dtracehelper" AND NOT eventMessage CONTAINS "apple.shm.notification_center" AND NOT eventMessage CONTAINS "com.apple.diagnosticd" AND NOT eventMessage CONTAINS "com.apple.analyticsd"'
Suppress dtrace noise:
DYLD_USE_DTRACE=0 sandbox-exec -f policy.sb command

Correlate with Filesystem Activity

Track filesystem operations:
sudo fs_usage -w -f filesystem <pid> | grep -iE "open|create|write|rename"

Converting Denials to Allow Rules

Denial log format: deny(<pid>) <operation> <path-or-name>

File Operations

Denial: deny(1234) file-read* /path/to/fileAllow rule:
(allow file-read*
  (literal "/path/to/file")
)

Sysctl Read

Denial: deny(1234) sysctl-read kern.versionAllow rule:
(allow sysctl-read
  (sysctl-name "kern.version")
)

Mach Lookup

Denial: deny(1234) mach-lookup com.apple.serviceAllow rule:
(allow mach-lookup
  (global-name "com.apple.service")
)

Network

Denial: deny(1234) network-outbound 127.0.0.1:8080Allow rule:
(allow network-outbound
  (remote ip "localhost:*")
)

Building a Profile from Scratch

If you need to create a custom profile:
1

Start with base policy

Create a minimal deny-all profile:
(version 1)
(deny default)
2

Run with log stream active

In one terminal, start the log stream:
/usr/bin/log stream --style compact --predicate 'eventMessage CONTAINS "Sandbox:" AND eventMessage CONTAINS "deny("'
In another, run your command:
sandbox-exec -f policy.sb your-command
3

Map denials to allow rules

For each deny(...) event, add the minimum required allow rule to your profile.
4

Test full workflows

Exercise complete toolchain workflows (git, npm, cargo, etc.) since child processes inherit the sandbox policy.
See the Prior Art page for profile examples and language reference.

Policy Inspection

Verify effective policy and grants:
# Print assembled policy
safehouse --stdout

# Explain workdir selection and grants
safehouse --explain --stdout

Test Validation

Run Agent Safehouse’s test suite (macOS only, outside existing sandbox):
# Core tests
./tests/run.sh

# TUI simulation tests
./tests/e2e/run.sh

# Live agent tests (requires API keys)
./tests/e2e/live/run.sh
Tests must run outside any existing sandboxed session. If you’re already sandboxed, tests will fail.

Getting Help

FAQ

Check frequently asked questions.

GitHub Issues

Report bugs or ask questions.

Build docs developers (and LLMs) love