# pi-agent-sandbox

Sandbox awareness for [pi](https://github.com/earendil-works/pi). When pi runs
inside [agent-sandbox](https://github.com/anonx3247/agent-sandbox) (`asb`), this
package:

- shows a colored **`[sandboxed:<profile>]` footer** so it is always obvious that
  the current pi session is confined to a sandbox profile;
- injects **sandbox-access context** (parsed from the `ASB_PROFILE_JSON` env var)
  so the agent knows what the active profile is allowed to read, write, and reach;
- installs an **`asb-pi` shell wrapper** that launches pi sandboxed inside tmux.

> **Status:** this is the initial scaffold. The footer, context injection, and
> `asb-pi` wrapper are implemented in subsequent PRs; the extension currently
> loads as a no-op stub.

## Install

This is a pi *package* (it declares a pi extension + skill under the `pi` key in
`package.json`). Install it with `pi install` in any of these forms:

```sh
# from npm
pi install pi-agent-sandbox

# from git
pi install github:anonx3247/pi-agent-sandbox

# from a local checkout
pi install /path/to/pi-agent-sandbox
```

## How sandbox detection works

Detection relies entirely on the `ASB_*` environment variables that `asb` emits
inside the sandbox:

| Variable           | Meaning                                                        |
| ------------------ | ------------------------------------------------------------- |
| `ASB_SANDBOX=1`    | Marks that pi is running inside an `asb` sandbox.             |
| `ASB_PROFILE`      | The active sandbox profile name (shown in the footer).        |
| `ASB_PROFILE_JSON` | The resolved profile as JSON (parsed into access context).    |
| `ASB_SECRETS_FILE` | Optional: path to the secrets file the profile may read.      |
| `ASB_AWS_PROFILE`  | Optional: the named AWS profile the sandbox may use.          |

See [`docs/agent-sandbox-handoff.md`](docs/agent-sandbox-handoff.md) for the full
contract of what `asb` injects.

## Running pi sandboxed in tmux — the safe launch pattern

> **Security footgun — read this.** To run pi sandboxed inside tmux you must give
> the inner tmux server a **dedicated socket** so it starts fresh *inside* the
> sandbox. The `asb-pi` wrapper uses:
>
> ```sh
> asb -p <profile> -- tmux -L asb-pi new-session -A -s "pi-$RANDOM" pi
> ```
>
> The `-L asb-pi` flag is the critical part: it names a dedicated tmux socket.
> Without it, a bare `tmux new-session` collides with the host's default tmux
> socket and **attaches to the host tmux server**, which runs *outside* the
> sandbox — silently escaping confinement. Always launch the inner tmux on its
> own socket so the server is spawned inside `asb`.
>
> Each run gets a **unique tmux session** (the session name carries a per-run
> `$RANDOM` suffix) so concurrent `asb-pi` launches in the same repo don't
> collide on or reattach to each other's session. Set `ASB_PI_SESSION` to a
> fixed name to opt into a shared/reattachable session instead.
>
> The wrapper also runs the sandboxed pi with **`PI_OFFLINE=1`** by default. This
> gates pi's npm self-update, which would otherwise try to write to the
> read-only `~/.npm` inside the sandbox, hit `EPERM`, and crash the process
> (taking the tmux pane down with it). Export your own `PI_OFFLINE` before
> running `asb-pi` to override this default.

## Secrets

The `sx` secrets skill (for running commands that need credentials without
exposing their values) is installed separately:

```sh
sx skill install
```

## License

MIT © anonx3247
