|
| 1 | +# pi-enclave |
| 2 | + |
| 3 | +> From [yapp](https://github.com/mgabor3141/yapp) · yet another pi pack |
| 4 | +
|
| 5 | +VM-isolated sandbox for [pi](https://pi.dev). Runs all tools inside a [Gondolin](https://github.com/earendil-works/gondolin) micro-VM so secrets never enter the agent's execution environment. |
| 6 | + |
| 7 | +```bash |
| 8 | +pi install npm:pi-enclave |
| 9 | +``` |
| 10 | + |
| 11 | +Requires QEMU: `brew install qemu` (macOS) or `sudo apt install qemu-system-aarch64` (Linux). |
| 12 | + |
| 13 | +## How it works |
| 14 | + |
| 15 | +pi-enclave starts an Alpine Linux micro-VM (QEMU/aarch64) and redirects all tool execution into it. Your workspace is mounted read-write at the same path inside the VM, so tools see identical paths on host and guest. File changes are bidirectional. |
| 16 | + |
| 17 | +The core security property: **secrets never enter the VM**. Credential tools on the host (like `gh auth token`) are auto-detected, and their values are replaced with random placeholders inside the VM. Gondolin's HTTP proxy substitutes real values on the wire, only for requests to configured hosts. |
| 18 | + |
| 19 | +``` |
| 20 | +┌──────────────────────────────────────────────────┐ |
| 21 | +│ Gondolin VM (Alpine Linux) │ |
| 22 | +│ │ |
| 23 | +│ /home/user/project ← bidirectional mount │ |
| 24 | +│ GH_TOKEN = "GONDOLIN_SECRET_a8f3..." (placeholder)│ |
| 25 | +│ All pi tools execute here │ |
| 26 | +└────────────────────┬─────────────────────────────┘ |
| 27 | + │ HTTP |
| 28 | + ▼ |
| 29 | +┌──────────────────────────────────────────────────┐ |
| 30 | +│ HTTP proxy (host-side) │ |
| 31 | +│ placeholder → real value (only for allowed hosts)│ |
| 32 | +└──────────────────────────────────────────────────┘ |
| 33 | +``` |
| 34 | + |
| 35 | +## Getting started |
| 36 | + |
| 37 | +After installing, run `/enclave init` in any project to enable it: |
| 38 | + |
| 39 | +``` |
| 40 | +/enclave init |
| 41 | +``` |
| 42 | + |
| 43 | +This creates two files: |
| 44 | +- `~/.pi/agent/extensions/pi-enclave.toml` — global defaults (commented out template) |
| 45 | +- `.pi/enclave.toml` — project config with `enabled = true` |
| 46 | + |
| 47 | +Once enabled, all tools (bash, read, write, edit) execute inside the VM automatically. |
| 48 | + |
| 49 | +## Zero-config behavior |
| 50 | + |
| 51 | +With `enabled = true` and no other configuration, pi-enclave: |
| 52 | + |
| 53 | +1. Starts a VM, mounts your project directory |
| 54 | +2. Installs `git`, `curl`, `jq` |
| 55 | +3. Auto-detects `gh auth token` and provisions `GH_TOKEN` scoped to GitHub hosts |
| 56 | +4. Allows all outbound HTTP traffic |
| 57 | +5. Redirects all tool execution to the VM |
| 58 | + |
| 59 | +## Configuration |
| 60 | + |
| 61 | +Place `.pi/enclave.toml` in your project (or any ancestor directory). |
| 62 | + |
| 63 | +```toml |
| 64 | +# Enable VM isolation for this project |
| 65 | +enabled = true |
| 66 | + |
| 67 | +# Stop walking up the directory tree |
| 68 | +# root = true |
| 69 | + |
| 70 | +# Alpine packages to install |
| 71 | +# packages = ["git", "curl", "jq", "ripgrep", "github-cli"] |
| 72 | + |
| 73 | +[secrets] |
| 74 | +# Source from a host command |
| 75 | +# GH_TOKEN = { command = "gh auth token", hosts = ["api.github.com", "github.com"] } |
| 76 | + |
| 77 | +# Source from a host environment variable |
| 78 | +# OPENAI_API_KEY = { env = "OPENAI_API_KEY", hosts = ["api.openai.com"] } |
| 79 | + |
| 80 | +# Disable an auto-detected provider |
| 81 | +# GH_TOKEN = false |
| 82 | + |
| 83 | +[network] |
| 84 | +# Restrict outbound access (unset = allow all) |
| 85 | +# allow-hosts = ["api.github.com", "github.com"] |
| 86 | + |
| 87 | +[policy.api-github-com] |
| 88 | +# Per-host HTTP method + path rules (section name = hostname, dots → dashes) |
| 89 | +# GET = ["*"] |
| 90 | +# POST = ["/graphql", "/repos/*/*/pulls"] |
| 91 | +# deny = ["/repos/*/*/pulls/*/merge"] |
| 92 | +# unmatched = "prompt" # "prompt" (default) | "deny" | "allow" |
| 93 | +``` |
| 94 | + |
| 95 | +Config files cascade: global (`~/.pi/agent/extensions/pi-enclave.toml`) is loaded first, then `.pi/enclave.toml` files from ancestor directories (closest wins). Config inside the workspace is protected from modification by the VM via Gondolin's `ShadowProvider`. |
| 96 | + |
| 97 | +## Commands |
| 98 | + |
| 99 | +| Command | Description | |
| 100 | +|---------|-------------| |
| 101 | +| `/enclave` or `/enclave status` | Show VM state, packages, secrets, network policy | |
| 102 | +| `/enclave init` | Create project and global config files, enable enclave | |
| 103 | +| `/enclave on` | Enable VM isolation for this session | |
| 104 | +| `/enclave off` | Disable VM isolation for this session (shuts down VM) | |
| 105 | +| `/enclave restart` | Restart VM on next tool use | |
| 106 | +| `/enclave add <package>` | Search for and install an Alpine package | |
0 commit comments