A secured agent workspace: herdr (terminal multiplexer) + pi (coding agent) + Kaimon (Julia MCP server), all running inside a bubblewrap sandbox with deny-by-default filesystem, runtime, and environment policies — plus enforced secure defaults for package installs and per-project containment for agents.
┌─────────────────────────────────────────────────┐
│ HOST │
│ ./sandbox.sh ──► bubblewrap (deny-by-default) │
│ ┌───────────────────────────────────────────┐ │
│ │ SANDBOX │ │
│ │ herdr (PID 1) ── TUI, panes, workspaces │ │
│ │ ├─ pane: pi agent │ │
│ │ │ └─ (optional) pi-bwrap: NESTED │ │
│ │ │ bwrap scoped to one project │ │
│ │ ├─ pane: kaimon MCP server (Julia, │ │
│ │ │ localhost:2828) ◄─ MCP ── pi │ │
│ │ └─ panes: shells (fish, own history) │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
| File | Contents |
|---|---|
sandbox.sh |
the bubblewrap policy: mounts, env allowlist, hardened defaults, --check probe |
sandbox-project.sh |
optional wrapper: scope the whole sandbox to one project |
README.md |
this overview |
HERDR.md |
herdr session layout + the kaimon auto-start hook |
SANDBOX.md |
the sandbox policy, deep dive: mounts, env, hardening, troubleshooting |
PI.md |
pi installation, MCP setup (Kaimon), plugins, extensions, skills |
Three independent layers — a leak on any one of them defeats the other two, so all three matter:
- Containment (SANDBOX.md). Deny-by-default on every axis: no read-only
bind of
/(the root filesystem is enumerated, only allowlisted paths are visible);$HOMEis masked with a private tmpfs and rebound one path at a time;/runis masked (no session bus, keyring, gpg, or docker sockets);--clearenvkeeps every credential out of the environment. No tokens, no SSH keys, no token stores ever enter the sandbox. - Supply-chain defaults (SANDBOX.md). npm runs with an enforced
read-only
~/.npmrc(ignore-scripts=true,min-release-age=7) and uv with a forcedUV_EXCLUDE_NEWER=7 days— a poisoned registry package can't run install scripts and fresh typosquats are gated out. The host's npm/uv config is never even visible inside. - Per-project agent containment (
pi-bwrap, SANDBOX.md). herdr sees all of~/Git, but an agent launched withpi-bwrapgets a nested bwrap that hides~/Gitexcept the project it was launched in — a rogue agent can only read/poison the one project it's working on, and never even sees sibling repos.
./sandbox.sh # attach to the sandboxed herdr session
./sandbox.sh --check # policy probe — run after every sandbox.sh edit
./sandbox-project.sh [dir] # optional: sandbox scoped to one project
cd ~/Git/my-project && pi-bwrap # agent scoped to that one projectHERDR.md explains the two workspaces (pi-sandbox for agents, kaimon for
the MCP server TUI) and why kaimon auto-starts.
Security posture in one paragraph: the sandbox contains secrets, not
code — code execution inside is routine and expected (agents, Julia builds,
pip installs), so containment is about making exfiltration worthless (nothing
credentialed is reachable) and blast radius small (one project per agent).
The remaining trust-based boundaries are documented honestly in SANDBOX.md:
the ssh-agent forwarding (a live signing oracle, deliberate for git push)
and the fact that a rogue agent could still modify the one project the host
IDE has open.