This repository provides a comprehensive Docker image that runs the pi coding-agent (pi).
container/Containerfile- builds the image fromnode:25-trixie, installs required tools, clones thepisource at the pinned version, builds it, and copies thepiCLI entry point.container/pi-run.sh- container entrypoint that delegates to a generated shell script containing all CLI argumentscontainer/pi- helper script copied into the image as thepiCLI entry point.pnpm-rc,.npmrc,.bunfig.toml,.config-uv-uv.toml- configuration files for pnpm, npm, bun, and uv package managers used during image buildMakefile– convenient targetmake build-dockerthat extracts the version fromcontainer/Containerfileand runs:docker build --no-cache -t localhost/pi:<version> .ppi– helper script on the host that runs the container in CLI mode or HTTP-RPC server mode
make build-docker # builds the image with the tag localhost/pi:<version>The <version> is taken from the ARG PI_MONO_VERSION line in container/Containerfile.
Extensions can be installed during the Docker build by passing PI_MONO_EXTENSIONS:
# With make (comma-separated list)
make build-docker PI_MONO_EXTENSIONS="git:https://github.com/combust-labs/read-website,subagent"
# With docker directly
version=$(grep -E '^ARG PI_MONO_VERSION=' container/Containerfile | cut -d'=' -f2)
docker build -f container/Containerfile \
--build-arg PI_MONO_EXTENSIONS="read-website,subagent" \
-t "localhost/pi:${version}" container/Extensions are installed into ~/.pi/agent/extensions/ inside the image and are available at runtime without additional setup.
The following build args are supported:
| Build Arg | Default | Description |
|---|---|---|
PI_MONO_VERSION |
from Containerfile |
Version of pi to clone and build |
PI_MONO_GIT_REPO |
https://github.com/badlogic/pi.git |
Git repository to clone pi from |
PI_MONO_EXTENSIONS |
(empty) | Comma-separated list of extensions to install at build time (e.g., read-website,subagent) |
PI_RPC_HTTP_SERVER_VERSION |
(empty) | Version of pi-rpc-http-server to install (uses pi version if empty) |
NPM_VERSION |
(empty) | Specific npm version to install (optional) |
NODE_VERSION |
25 |
Node.js version to use (reflected in node:<VERSION>-trixie base) |
version=$(grep -E '^ARG PI_MONO_VERSION=' container/Containerfile | cut -d'=' -f2)
docker run \
-v $(pwd):/code \
-e HTTP_PROXY=... \
-e HTTPS_PROXY=... \
"localhost/pi:${version}" \
<args>Replace <args> with any command supported by the coding-agent CLI.
The helper script ppi provides two distinct ways to run the agent:
-
Interactive CLI mode (default) - When
--mode rpcis not specified,ppigenerates a temporary shell script containing all CLI arguments and mounts it into the container. The container's entrypoint (pi-run.sh) executes this script, which calls thepiCLI directly. Use this for quick, one-off queries.ppi # runs the CLI inside the container ppi --model gpt-4 # specify a different model
Consequences: the process runs synchronously, outputs to STDOUT/STDERR, and exits when the query is complete.
-
HTTP-RPC server mode - Supplying
--mode rpccausesppito start the container with thepi-rpc-http-serverentry-point (/opt/agent/pi/node_modules/pi-rpc-http-server/bin/run.sh). The agent listens on the configured port (default3000inside the container) and serves a JSON-over-HTTP API.ppi --mode rpc # start the RPC server (default port 3000) ppi --mode rpc --ppi-container-port 8080 # custom container port ppi --mode rpc --ppi-host-port 9000 # custom host port
Consequences: the container stays running, accepting HTTP requests; suitable for integration with other tools or remote clients. No direct CLI output is produced; interactions must be performed via HTTP calls.
Both modes mount the current project directory at /code and bind-mount user configuration (~/.gitconfig, ~/.pi/agent/*, etc.) into the container.
The ppi script supports the following flags, segregated into flags inherited from pi and ppi-specific flags.
| Flag | Default | Description |
|---|---|---|
--append-system-prompt <text> |
nickname injection | Append text to system prompt (default: sets agent nickname to model name; allows multiple) |
--export <file> |
(empty) | Export session to HTML |
--extension <path>, -e |
(empty) | Load extension file (allows multiple) |
--list-models [search] |
enabled | List available models (optional search term; enabled when flag is present) |
--mode <text|json|rpc> |
text |
Output mode (rpc triggers HTTP-RPC server mode) |
--model <pattern> |
(required) | Model pattern or ID (supports provider/id and optional :thinking) |
--prompt <text> |
Summarize current the project |
Initial prompt to send to the agent |
--prompt-template <path> |
(empty) | Load prompt template (allows multiple) |
--provider <name> |
(empty) | Provider name |
--session <path|id> |
(empty) | Use specific session |
--session-dir <dir> |
/sessions |
Session storage directory (container path) |
--skill <path> |
(empty) | Load skill file/directory (allows multiple) |
--system-prompt <text> |
(empty) | System prompt (default: coding assistant prompt) |
--theme <path> |
(empty) | Load theme file/directory (allows multiple) |
--thinking <level> |
(empty) | Thinking level: off, minimal, low, medium, high, xhigh |
--tools <tools> |
(empty) | Tool allowlist (allows multiple) |
| Flag | Description |
|---|---|
--continue, -c |
Continue previous session |
--no-context-files, -nc |
Disable AGENTS.md/CLAUDE.md context files |
--no-extensions, -ne |
Disable extension discovery |
--no-prompt-templates, -np |
Disable prompt templates |
--no-session |
Don't save session (ephemeral mode) |
--no-skills, -ns |
Disable skills |
--no-themes |
Disable themes |
--no-tools |
Disable all tools |
--offline |
Disable startup network operations |
--print, -p |
Non-interactive mode (process prompt and exit) |
--resume, -r |
Select and resume a session |
--verbose |
Force verbose startup |
| Flag | Default | Description |
|---|---|---|
--host-sessions-dir <dir> |
$(pwd)/.pi/sessions |
Host directory to mount as /sessions volume |
--ppi-container-network <name> |
(empty) | Docker network to connect the container to (e.g., host, bridge, or a custom network) |
--ppi-container-port <n> |
3000 |
Internal container port (used in -e PORT env var) |
--ppi-extra-host <host:ip> |
(empty) | Add host-to-IP mapping to the container (repeatable; e.g., myhost:host-gateway) |
--ppi-host-add-path <path> |
(empty) | Add custom volume mount (format: host-path:container-path:rw or host-path:container-path:ro; allows multiple) |
--ppi-host-port <n> |
(container port) | Host port exposed to localhost; defaults to container port if not set |
--ppi-pass-env <name>=<value> |
(empty) | Pass environment variable to container as -e name=value (allows multiple) |
--version <v> |
from Containerfile | Override pi container version |
| Flag | Description |
|---|---|
--ppi-host-attach-agents |
Attach agents directory to container |
--ppi-host-attach-models-json |
Attach models.json file to container |
--ppi-host-attach-prompts |
Attach prompts directory to container |
--ppi-no-ppi-prompts |
Skip prepending the default nickname prompt |
By default, ppi automatically prepends a system prompt that sets the agent's nickname to the selected model name:
Your nickname is unconditionally `<model>`, do not reinterpret. Use this value whenever you need to introduce yourself.
This ensures the agent consistently uses the model name as its identity. User-provided --append-system-prompt values are appended after this default.
Use --ppi-no-ppi-prompts to disable this behavior and start with a clean system prompt.
# Basic usage with default prompt
# Note: This call requires --model to be specified explicitly. It also
# needs the models.json path via --ppi-host-attach-models-json or a
# custom mount via --ppi-host-add-path
ppi --model gpt-4o
# Custom prompt
ppi --prompt "List all TypeScript files in src/"
# Different model with thinking level
ppi --model gpt-4o --thinking high "Analyze this code"
# Continue previous session
ppi --continue "What did we discuss last time?"
# With custom system prompt
ppi --system-prompt "You are a code reviewer" --prompt "Review PR #123"
# Start RPC server on default port 3000
ppi --mode rpc
# Start RPC server with custom ports
ppi --mode rpc --ppi-container-port 8080
ppi --mode rpc --ppi-host-port 9000 --ppi-container-port 8080
# With custom container network
ppi --ppi-container-network host "Check network connectivity"
ppi --mode rpc --ppi-container-network my-custom-network
# With extra host entries (e.g., to resolve a service name to host gateway)
ppi --ppi-extra-host "myhost:host-gateway" "Access myhost service"
ppi --ppi-extra-host "db.local:host-gateway" --ppi-extra-host "api.local:host-gateway" "Access multiple services"
# Resolve host's services via host.docker.internal (common pattern on macOS/Windows)
ppi --ppi-extra-host "host.docker.internal:host-gateway" "Access services on host machine"
# With prompts, agents and models.json directories attached
ppi --ppi-host-attach-prompts --ppi-host-attach-agents --ppi-host-attach-models-json "Analyze this code"
# With custom volume mounts
ppi --ppi-host-add-path /path/to/config:/root/.config:ro --ppi-host-add-path /path/to/data:/data:rw "Process data"
# With custom environment variables passed to container
ppi --ppi-pass-env OPENAI_API_KEY=sk-xxx --ppi-pass-env CUSTOM_VAR=hello "Use the env vars"By default, ppi doesn't mount any pi configuration from the host. If your ppi invocations involve a wider number of flags, you may want to create a bash function to apply them automatically. For example:
function ppi {
"${HOME}/.local/bin/ppi" \
--ppi-host-attach-models-json \
--ppi-host-attach-agents \
--ppi-host-attach-prompts \
--ppi-pass-env "READ_WEBSITE_CONFIG=/.pi/dot/read_website_config.js" \
--ppi-host-add-path "${HOME}/.gitconfig:/root/.gitconfig:ro" \
--ppi-host-add-path "${HOME}/.gitconfig-github-private.inc:/root/.gitconfig-github-private.inc:ro" \
--ppi-host-add-path "${HOME}/.pi/local-configs/read_website_config.js:/.pi/dot/read_website_config.js:ro" \
"$@"
}The following pi flags are not yet exposed through ppi:
--api-key- API key (use environment variables instead)--fork <path|id>- Fork a session--help,-h- Show help--version,-v- Show version
Session data is uploaded to the Hugging Face dataset rgruchalski/combust-labs_pi-mono-docker. You can view the datasets at https://huggingface.co/datasets/rgruchalski/combust-labs_pi-mono-docker
Generated by gpt-4