Skip to content

Latest commit

 

History

History
97 lines (72 loc) · 5.36 KB

File metadata and controls

97 lines (72 loc) · 5.36 KB

Agent Safehouse: LLM Quick Reference

What This Project Is

Agent Safehouse is a macOS sandbox wrapper for coding agents (Claude, Cursor, Aider, Gemini, etc.) built on sandbox-exec. Policy model is strict by default: start from (deny default), then add explicit allow rules via layered .sb profiles. Core sandbox wrapper is pure Bash + Sandbox Profile Language (.sb) and has no build step. Repo also includes a VitePress docs site and Cloudflare deploy tooling (pnpm + Wrangler).

Fast Working Rules

  • Use rg for text search.
  • Use fd for file listing/find.
  • Make least-privilege policy edits; avoid broad subpath grants unless required.
  • Do not hand-edit dist/*; edit bin/ and profiles/, then regenerate dist artifacts.
  • If you change any .sb file or policy assembly/runtime logic (bin/safehouse.sh, bin/lib/*.sh), run ./scripts/generate-dist.sh.
  • Run tests with ./tests/run.sh on macOS with sandbox-exec, outside any existing sandbox. Use ./tests/run.sh e2e for the tmux-driven startup/prompt-roundtrip suite for agent TUIs.
  • If tests cannot run because the current session is already sandboxed, state that explicitly and continue with static validation.

Core Commands

# Generate policy only (prints temp policy path)
./bin/safehouse.sh [--add-dirs-ro=...] [--add-dirs=...] [--enable=...] [--append-profile=...]

# Run command in sandbox
./bin/safehouse.sh [policy opts] -- <command> [args...]
./bin/safehouse.sh --stdout

# Explain effective workdir/grants/profile selection (debugging)
./bin/safehouse.sh --explain --stdout

# Trust and load <workdir>/.safehouse config (disabled by default)
./bin/safehouse.sh --trust-workdir-config --stdout

# Validate behavior
./tests/run.sh
./tests/run.sh e2e

# Regenerate committed dist artifacts
./scripts/generate-dist.sh

./scripts/generate-dist.sh updates these deterministic outputs:

  • dist/safehouse.sh

Dist Purpose

dist/ is for consumers: it provides ready-to-run packaged artifacts, especially dist/safehouse.sh, a single executable containing the assembled policy + runtime shell logic. Authoring source of truth is bin/ and profiles/; make functional changes there, then regenerate dist/. Agents should usually avoid loading dist/ files into context unless validating generated distribution output or debugging packaging/compression regressions.

Policy Assembly Order (Critical)

Policy concatenation order in bin/safehouse.sh/bin/lib/*.sh:

  1. profiles/00-base.sb
  2. profiles/10-system-runtime.sb
  3. profiles/20-network.sb
  4. profiles/30-toolchains/*.sb
  5. profiles/40-shared/*.sb
  6. profiles/50-integrations-core/*.sb (container-runtime-default-deny, git, scm-clis, ssh-agent-default-deny, worktrees always on)
  7. profiles/55-integrations-optional/*.sb (--enable, with electron implying macos-gui; keychain injected selectively)
  8. profiles/60-agents/*.sb
  9. profiles/65-apps/*.sb
  10. CLI path grants: --add-dirs-ro then --add-dirs
  11. Workdir grant (omitted if --workdir explicitly empty)
  12. --append-profile overlays last

Later rules win. Check ordering first when behavior is unexpected.

.sb Authoring Rules

  • Profiles are authored as modular sections by stage prefix (00, 10, 20, 30, 40, 50, 55, 60, 65).
  • Assembly is deterministic: stage order is fixed, and files within each stage directory are concatenated in lexicographic order (find ... | sort).
  • Declare dependency metadata with $$require=path/to/profile.sb[,path/to/other.sb]$$ only when you need implicit optional integration injection.
  • $$require=...$$ is machine-read by policy assembly; ;; Requires: ... comments are human-facing documentation only.
  • Keep each .sb file standalone for its concern: include complete rules for that capability in the file, avoid splitting one feature across many files without an explicit dependency.
  • New profile checklist: add standard header (Category/description/Source), add tests in tests/policy/integrations/ or the relevant topic folder, and run ./scripts/generate-dist.sh.

Important Internals

  • 00-base.sb includes HOME_DIR placeholder __SAFEHOUSE_REPLACE_ME_WITH_ABSOLUTE_HOME_DIR__; replaced at assembly time in bin/lib/policy/render.sh.
  • Ancestor directory literal read grants (up to /) are intentionally generated by emit_path_ancestor_literals() for directory traversal compatibility.
  • .sb matcher semantics: literal (exact), subpath (recursive), prefix (starts-with), regex.

Test/CI Signals

  • Tests live under tests/policy/, tests/surface/, and tests/e2e/, with shared helpers in tests/test_helper.bash.
  • ./tests/run.sh runs policy + surface by default, ./tests/run.sh e2e runs the tmux-driven startup/prompt-roundtrip suite for agent TUIs, and ./tests/run.sh all runs every suite.
  • If adding policy behavior, add/update Bats coverage for the public contract or security boundary that changed.
  • Keep .sb header comments and any #safehouse-test-id:*# markers used by ordering/structure assertions.
  • CI runs macOS tests and auto-regenerates/commits dist artifacts on relevant changes.

Mindful Of

  • --append-profile is the final override layer; deny rules there take precedence.
  • Keep /System/Volumes/Data/... aliases only when a concrete integration requires them.
  • Verify behavior with tests (when runnable) and regenerated dist artifacts before finalizing changes.