diff --git a/sandboxes/pi-agent/Dockerfile b/sandboxes/pi-agent/Dockerfile new file mode 100644 index 0000000..95f6a7d --- /dev/null +++ b/sandboxes/pi-agent/Dockerfile @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1.4 + +# Pi Agent sandbox image for OpenShell +# +# Builds on the community base sandbox and adds the pi coding agent. +# Build: docker build -t openshell-pi-agent --build-arg BASE_IMAGE=openshell-base . +# Run: openshell sandbox create --from pi-agent + +ARG BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest +FROM ${BASE_IMAGE} + +USER root + +# Install pi coding agent +RUN npm install -g @mariozechner/pi-coding-agent + +# Copy sandbox policy +COPY policy.yaml /etc/openshell/policy.yaml + +# Create pi config and session directories +RUN mkdir -p /sandbox/.pi/agent && \ + chown -R sandbox:sandbox /sandbox/.pi + +USER sandbox + +ENTRYPOINT ["/bin/bash"] diff --git a/sandboxes/pi-agent/README.md b/sandboxes/pi-agent/README.md new file mode 100644 index 0000000..afe0b9e --- /dev/null +++ b/sandboxes/pi-agent/README.md @@ -0,0 +1,79 @@ +# Pi Agent Sandbox + +OpenShell sandbox image pre-configured with [pi](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent), a minimal terminal coding agent harness. + +## What's Included + +- **Pi coding agent** — Terminal-based coding agent with read, write, edit, and bash tools +- **Node.js 22** — Runtime required by pi +## Build + +```bash +docker build -t openshell-pi-agent . +``` + +To build against a specific base image: + +```bash +docker build -t openshell-pi-agent --build-arg BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest . +``` + +## Usage + +### Create a sandbox + +```bash +openshell sandbox create --from pi-agent +``` + +### With an API key + +```bash +openshell sandbox create --from pi-agent -- env ANTHROPIC_API_KEY=sk-ant-... pi +``` + +### Interactive startup + +If you prefer to start pi manually inside the sandbox: + +```bash +openshell sandbox connect +export ANTHROPIC_API_KEY=sk-ant-... +pi +``` + +## Supported Providers + +Pi supports many providers out of the box. Pass the appropriate API key: + +| Variable | Provider | +|----------|----------| +| `ANTHROPIC_API_KEY` | Anthropic (Claude) | +| `OPENAI_API_KEY` | OpenAI | +| `GOOGLE_API_KEY` | Google Gemini | + +Or use `/login` inside pi for OAuth-based authentication (Anthropic, OpenAI, Google, GitHub Copilot). + +## Network Policy + +The sandbox policy allows pi to reach: + +- **Anthropic** (`api.anthropic.com`) +- **OpenAI** (`api.openai.com`) +- **Google** (`generativelanguage.googleapis.com`) +- **NVIDIA** (`integrate.api.nvidia.com`) +- **GitHub** (read-only git and REST API) +- **npm** (`registry.npmjs.org` for `pi install`) + +All other outbound connections are blocked by the policy engine. + +## Configuration + +Pi stores its configuration in `~/.pi/agent/` inside the sandbox. Customize with: + +- `~/.pi/agent/settings.json` — Global settings +- `~/.pi/agent/AGENTS.md` — Global context/instructions +- `.pi/settings.json` — Project-level settings +- `AGENTS.md` — Project-level context + +See the [pi documentation](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) for full details. diff --git a/sandboxes/pi-agent/policy.yaml b/sandboxes/pi-agent/policy.yaml new file mode 100644 index 0000000..162b782 --- /dev/null +++ b/sandboxes/pi-agent/policy.yaml @@ -0,0 +1,118 @@ +version: 1 + +# --- Sandbox setup configuration (queried once at startup) --- + +filesystem_policy: + include_workdir: true + read_only: + - /usr + - /lib + - /proc + - /dev/urandom + - /app + - /etc + - /var/log + read_write: + - /sandbox + - /tmp + - /dev/null + +landlock: + compatibility: best_effort + +process: + run_as_user: sandbox + run_as_group: sandbox + +# --- Network policies (queried per-CONNECT request) --- + +network_policies: + # Pi coding agent — Anthropic + pi_anthropic: + name: pi_anthropic + endpoints: + - { host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full, tls: terminate } + - { host: statsig.anthropic.com, port: 443 } + - { host: sentry.io, port: 443 } + binaries: + - { path: /usr/local/bin/pi } + - { path: /usr/bin/node } + + # Pi coding agent — OpenAI + pi_openai: + name: pi_openai + endpoints: + - { host: api.openai.com, port: 443, protocol: rest, enforcement: enforce, access: full, tls: terminate } + binaries: + - { path: /usr/local/bin/pi } + - { path: /usr/bin/node } + + # Pi coding agent — Google + pi_google: + name: pi_google + endpoints: + - { host: generativelanguage.googleapis.com, port: 443, protocol: rest, enforcement: enforce, access: full, tls: terminate } + binaries: + - { path: /usr/local/bin/pi } + - { path: /usr/bin/node } + + # Pi coding agent — NVIDIA + pi_nvidia: + name: pi_nvidia + endpoints: + - { host: integrate.api.nvidia.com, port: 443 } + binaries: + - { path: /usr/local/bin/pi } + - { path: /usr/bin/node } + + # GitHub (read-only git clone/fetch/pull) + github: + name: github + endpoints: + - host: github.com + port: 443 + protocol: rest + tls: terminate + enforcement: enforce + rules: + - allow: + method: GET + path: "/**/info/refs*" + - allow: + method: POST + path: "/**/git-upload-pack" + binaries: + - { path: /usr/bin/git } + + # GitHub REST API (read-only) + github_rest_api: + name: github-rest-api + endpoints: + - host: api.github.com + port: 443 + protocol: rest + tls: terminate + enforcement: enforce + rules: + - allow: + method: GET + path: "/**" + - allow: + method: HEAD + path: "/**" + - allow: + method: OPTIONS + path: "/**" + binaries: + - { path: /usr/local/bin/pi } + - { path: /usr/bin/node } + - { path: /usr/bin/gh } + + # npm registry (for pi install/update) + npm_registry: + name: npm_registry + endpoints: + - { host: registry.npmjs.org, port: 443 } + binaries: + - { path: /usr/bin/node } + - { path: /usr/local/bin/pi } diff --git a/sandboxes/pi-agent/skills/.gitkeep b/sandboxes/pi-agent/skills/.gitkeep new file mode 100644 index 0000000..e69de29