From 8c9d62e217e6cb1b2587e21478ae344cc483c332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20L=C3=BCbken?= Date: Tue, 17 Mar 2026 09:57:27 +0100 Subject: [PATCH 1/2] Add pi-agent sandbox configuration --- sandboxes/pi-agent/Dockerfile | 30 +++++++ sandboxes/pi-agent/README.md | 81 ++++++++++++++++++ sandboxes/pi-agent/pi-agent-start.sh | 31 +++++++ sandboxes/pi-agent/policy.yaml | 118 +++++++++++++++++++++++++++ sandboxes/pi-agent/skills/.gitkeep | 0 5 files changed, 260 insertions(+) create mode 100644 sandboxes/pi-agent/Dockerfile create mode 100644 sandboxes/pi-agent/README.md create mode 100644 sandboxes/pi-agent/pi-agent-start.sh create mode 100644 sandboxes/pi-agent/policy.yaml create mode 100644 sandboxes/pi-agent/skills/.gitkeep diff --git a/sandboxes/pi-agent/Dockerfile b/sandboxes/pi-agent/Dockerfile new file mode 100644 index 0000000..68d6ce4 --- /dev/null +++ b/sandboxes/pi-agent/Dockerfile @@ -0,0 +1,30 @@ +# 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 + +# Copy the pi-agent startup helper +COPY pi-agent-start.sh /usr/local/bin/pi-agent-start +RUN chmod +x /usr/local/bin/pi-agent-start + +# 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..82a7173 --- /dev/null +++ b/sandboxes/pi-agent/README.md @@ -0,0 +1,81 @@ +# 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 +- **pi-agent-start** — Helper script that detects API keys and launches 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-agent-start +``` + +### 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/pi-agent-start.sh b/sandboxes/pi-agent/pi-agent-start.sh new file mode 100644 index 0000000..9e7d3cb --- /dev/null +++ b/sandboxes/pi-agent/pi-agent-start.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# pi-agent-start — Launch pi coding agent inside an OpenShell sandbox. +# +# Usage: +# openshell sandbox create --from pi-agent -- pi-agent-start +# +# Pass API keys via environment variables: +# openshell sandbox create --from pi-agent -- env ANTHROPIC_API_KEY=sk-ant-... pi-agent-start +set -euo pipefail + +echo "" +echo "Pi coding agent is ready." +echo " Version: $(pi --version 2>/dev/null || echo 'unknown')" +echo "" + +if [ -n "${ANTHROPIC_API_KEY:-}" ]; then + echo " Provider: Anthropic (key from environment)" +elif [ -n "${OPENAI_API_KEY:-}" ]; then + echo " Provider: OpenAI (key from environment)" +elif [ -n "${GOOGLE_API_KEY:-}" ]; then + echo " Provider: Google (key from environment)" +else + echo " No API key detected. Use /login inside pi or set an API key env var." +fi + +echo "" +echo "Starting pi..." +echo "" + +exec pi "$@" 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 From af03f8c775fd8325583f7c9f1c40d2c6551e07a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20L=C3=BCbken?= Date: Tue, 17 Mar 2026 10:01:16 +0100 Subject: [PATCH 2/2] Remove pi-agent-start.sh wrapper, use pi directly --- sandboxes/pi-agent/Dockerfile | 4 ---- sandboxes/pi-agent/README.md | 4 +--- sandboxes/pi-agent/pi-agent-start.sh | 31 ---------------------------- 3 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 sandboxes/pi-agent/pi-agent-start.sh diff --git a/sandboxes/pi-agent/Dockerfile b/sandboxes/pi-agent/Dockerfile index 68d6ce4..95f6a7d 100644 --- a/sandboxes/pi-agent/Dockerfile +++ b/sandboxes/pi-agent/Dockerfile @@ -17,10 +17,6 @@ RUN npm install -g @mariozechner/pi-coding-agent # Copy sandbox policy COPY policy.yaml /etc/openshell/policy.yaml -# Copy the pi-agent startup helper -COPY pi-agent-start.sh /usr/local/bin/pi-agent-start -RUN chmod +x /usr/local/bin/pi-agent-start - # Create pi config and session directories RUN mkdir -p /sandbox/.pi/agent && \ chown -R sandbox:sandbox /sandbox/.pi diff --git a/sandboxes/pi-agent/README.md b/sandboxes/pi-agent/README.md index 82a7173..afe0b9e 100644 --- a/sandboxes/pi-agent/README.md +++ b/sandboxes/pi-agent/README.md @@ -6,8 +6,6 @@ OpenShell sandbox image pre-configured with [pi](https://github.com/badlogic/pi- - **Pi coding agent** — Terminal-based coding agent with read, write, edit, and bash tools - **Node.js 22** — Runtime required by pi -- **pi-agent-start** — Helper script that detects API keys and launches pi - ## Build ```bash @@ -31,7 +29,7 @@ openshell sandbox create --from pi-agent ### With an API key ```bash -openshell sandbox create --from pi-agent -- env ANTHROPIC_API_KEY=sk-ant-... pi-agent-start +openshell sandbox create --from pi-agent -- env ANTHROPIC_API_KEY=sk-ant-... pi ``` ### Interactive startup diff --git a/sandboxes/pi-agent/pi-agent-start.sh b/sandboxes/pi-agent/pi-agent-start.sh deleted file mode 100644 index 9e7d3cb..0000000 --- a/sandboxes/pi-agent/pi-agent-start.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# pi-agent-start — Launch pi coding agent inside an OpenShell sandbox. -# -# Usage: -# openshell sandbox create --from pi-agent -- pi-agent-start -# -# Pass API keys via environment variables: -# openshell sandbox create --from pi-agent -- env ANTHROPIC_API_KEY=sk-ant-... pi-agent-start -set -euo pipefail - -echo "" -echo "Pi coding agent is ready." -echo " Version: $(pi --version 2>/dev/null || echo 'unknown')" -echo "" - -if [ -n "${ANTHROPIC_API_KEY:-}" ]; then - echo " Provider: Anthropic (key from environment)" -elif [ -n "${OPENAI_API_KEY:-}" ]; then - echo " Provider: OpenAI (key from environment)" -elif [ -n "${GOOGLE_API_KEY:-}" ]; then - echo " Provider: Google (key from environment)" -else - echo " No API key detected. Use /login inside pi or set an API key env var." -fi - -echo "" -echo "Starting pi..." -echo "" - -exec pi "$@"