@agimon-ai/po-sandbox

Per-workspace sandbox containers for Po: the container provider, the shared image, the container lifecycle, and a host credential broker

Packages

Package details

extension

Install @agimon-ai/po-sandbox from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@agimon-ai/po-sandbox
Package
@agimon-ai/po-sandbox
Version
0.0.0-alpha.40
Published
Oct 21, 2026
Downloads
3,531/mo · 3,531/wk
Author
agiflow-ai
License
BUSL-1.1
Types
extension
Size
365.4 KB
Dependencies
3 dependencies · 1 peer

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@agimon-ai/po-sandbox

Sandbox layer for Po: registers the container sandbox provider on the host, runs one container per sandboxed workspace, reports whether a session runs inside a container, and routes brokered providers when a launch grants a credential broker.

Part of the Po distribution.

Status

The host side of per-workspace containers is in place: the container provider, the shared image, and the container lifecycle. Sessions are not routed into a container yet, so a sandboxed workspace stays unavailable for sessions. See The container plan and current wiring for what the current server runtime connects.

The container provider

When the layer loads on a host server's global scope, it registers the container provider in po/workspace-sandboxes and publishes the po/workspace-containers service. A contained server registers nothing, so containers never nest.

At hub start, in the background:

  1. docker info checks the engine. A missing or stopped engine leaves the provider unavailable, with the reason.
  2. The provider needs the Linux Po runtime bundle at ~/.po/container-runtime/<version>/, with its container-runtime.json. Without it the provider reports "The container runtime is not installed." and starts nothing. The json is validated first: only its known keys, and every path inside /opt/po. Otherwise the provider reports why and starts nothing. The server runs from its entry with all of its environment.
  3. The image po-sandbox:<digest> is built once if missing: node:24-bookworm-slim, git, procps, ripgrep, Chromium libraries and fonts, corepack, and the headless cloak browser at /opt/cloak.
  4. For each workspace whose sandbox is container, a running container labelled with this hub's po.owner and the workspace's po.workspace is adopted. Otherwise stale *.po-v4.lock files under the workspace's sandbox folder are deleted and a new container starts.

Each container mounts the workspace at its own path, the runtime bundle read-only at /opt/po, and P = ~/.po/sandboxes/<workspace> at its own path with PO_HOME=P, so conversations and artifacts stay on host disk. Package caches, worktrees and the container home live in named volumes. The container publishes one port on host loopback only, runs with --cap-drop=ALL, no-new-privileges and a pid limit, and gets no credentials, no hub token, no engine socket, and no part of the host ~/.po beyond P, the bundle, the three seed files (modes.yaml, domains.yaml, config.yaml, read-only) and its own token file (read-only).

Every container runs with --user: the host user on Linux, 1000:1000 elsewhere (Docker Desktop maps it to the host user on shared folders). A new runtime or git volume is first mounted on a world-writable image folder, so it stays writable for that user, as the /po-home volume is.

Containers outlive the hub process: a reload, an idle restart (exit 75) or a crash leaves them running, and the next start adopts them. A clean user stop stops them: the provider's onCleanStop hook in po/workspace-sandboxes calls stopAll. po/workspace-containers also exposes stop for switching the sandbox off.

Requirements

  • Node.js 24 or newer
  • @earendil-works/pi-coding-agent 1.3.0

Install

npm install @agimon-ai/po-sandbox

Enable the sandbox

po init writes a sandbox layer and adds it to the copilot mode. To use it in another mode, list the layer on that mode in .po/modes.yaml:

layers:
  sandbox:
    packages:
      - '@agimon-ai/po-sandbox'

majorMode:
  copilot:
    description: General-purpose coding mode.
    layers: [team, ask-user, task, sandbox]

In-session command

/po-sandbox

Reports whether the current session runs inside a sandbox container (the server's po/sandbox-identity says it is contained) or directly on the host.

Brokered providers

When a session's admitted environment names brokered providers (PO_BROKER_PROVIDERS) and a broker route (PO_BROKER_SOCKET or PO_BROKER_ADDRESS), the server plugin overrides those providers' base URLs so requests go through the broker. The session's credential variables are expected to hold the broker's session token, not the real key. With no broker route the layer changes nothing.

How a container reaches the broker depends on the engine:

Host Transport Why
Linux Unix socket, bind-mounted, owner-only Container and host share a kernel, so no port is needed
macOS, Windows, any VM engine Loopback TCP through host.docker.internal A container in a virtual machine cannot connect to a mounted host socket (ENOTSUP)

A socket route goes through a loopback bridge inside the container, because no SDK can dial a socket path. A TCP route is addressed directly.

Current limits

  • Sessions do not run in a container yet, and nothing starts a broker for a session.
  • The broker carries a curated provider list. OAuth subscription logins are not brokered.
  • A host *_BASE_URL override is dropped rather than used as the broker's upstream.

Public API

import { DefaultSandboxExtensionService } from '@agimon-ai/po-sandbox';

DefaultSandboxExtensionService reports sandbox state from the environment it is given. /extensions/server registers the in-session command, its Help resources, and the brokered provider overrides.

Development

Run from this package directory in the workspace:

pnpm build
pnpm typecheck
pnpm test
pnpm lint
pnpm exec vibe-lint check .
npm pack --dry-run

Maintained by Agimon.

License

Business Source License 1.1: free for personal use, organisations under USD 1M revenue, non-profits and education. See LICENSE and https://agimon.ai/licensing.