Generates Pi Coding Agent TypeScript extensions and Claude Code hook bundles (shell shim + TypeScript stdin handler + hooks/hooks.json) from a single YAML policy file.
Policy is active only when gate.env is set in the process environment and its value equals gate.value (string comparison).
- Pi: the generated extension returns immediately without registering listeners when the gate is inactive.
- Claude Code: the generated
portal-sandbox-shim.shexits0with no stdout when the gate is inactive, so the tool call or prompt proceeds unchanged (hook exit behavior).
cargo build -p gen-agent-sandbox
./target/debug/gen-agent-sandbox \
--config templates/agent-sandbox/portal-sandbox.example.yaml \
--out-dir ./out/sandbox-plugin
# Optional: also write plugin.json for a Claude Code plugin directory layout
./target/debug/gen-agent-sandbox \
--config path/to/portal-sandbox.yaml \
--out-dir ./out/sandbox-plugin \
--emit-plugin-jsonFlags:
--pi-only— emit onlyportal-pi-sandbox.ts.--claude-only— emit Claude hook bundle (no Pi file).--emit-plugin-json— writeplugin.json(requires Claude outputs; incompatible with--pi-only).
Copy portal-pi-sandbox.ts to ~/.pi/agent/extensions/ or .pi/extensions/ in a project. Peer dependency: @mariozechner/pi-coding-agent (see Pi extensions). Set the gate environment variable before starting Pi when you want enforcement.
- Copy
portal-claude-sandbox-hook.ts,portal-sandbox-shim.sh, and mergehooks/hooks.jsoninto your pluginhooks/hooks.jsonor project.claudehooks. - Ensure
npx/tsxare available, or setclaude_ts_runnerin YAML to another argv prefix (for examplepnpm,exec,tsx). - Set the same gate env var when you want the shim to invoke the TypeScript handler.
See templates/agent-sandbox/schema.md and templates/agent-sandbox/portal-sandbox.example.yaml.
When required: true, generated hooks deny bash commands whose text does not start with one of the accepted_invocations prefixes (after trimStart). This avoids claiming full shell safety: compound commands, bash -c, env, etc. will not match a simple ./wrap.sh prefix unless you add explicit prefixes for those forms. Pair with prompts so the model knows to call only the wrapper.
- docs/design/agent-sandbox-todo.md — harder targets (Cursor, CI agents, etc.).