5 Commits

Author SHA1 Message Date
joakimp b6cc2c748b Cut v0.75.4 — pi 0.75.3 -> 0.75.4
Publish Docker Image / smoke (push) Successful in 2m25s
Publish Docker Image / publish (push) Successful in 11m30s
Publish Docker Image / update-description (push) Successful in 14s
One upstream patch release. PI_VERSION=latest in Dockerfile resolves
to 0.75.4 at build time, so no Dockerfile change is needed; just a
CHANGELOG promote.

Tagged speculatively before opencode-devbox v1.15.6's omos-with-pi
smoke completes — pi 0.75.4 is a single patch on top of 0.75.3, low
risk on its own. If opencode-devbox v1.15.6 surfaces a pi 0.75.4
problem in the omos-with-pi smoke (3700 MB threshold trip, etc.),
both releases would fail in symmetric ways and recovery would be a
v0.75.4b/v1.15.6b pair. Same recovery muscle as v1.15.4 -> v1.15.4b
last week.

Built on opencode-devbox:base-latest, cache-hit on base-35ee5fe7861a
since v1.14.50b — base unchanged across both bumps.
2026-05-21 00:16:43 +02:00
joakimp ae6253ab23 AGENTS.md: documentation-drift sweep as explicit pre-commit step
Companion to the same addition in the cloud-init and ansible repos.
Caught real drift in those repos in a recent session only because
the user explicitly asked. Codify the sweep with concrete, repo-
specific drift hotspots rather than a vague 'watch for drift' rule
that gets ignored.

Each AGENTS.md addition lists the doc files most likely to fall
behind code changes here, plus a quick-triage one-liner using
'git diff --name-only HEAD | xargs grep -l ...' so the rule is
actionable not aspirational.
2026-05-20 23:11:59 +02:00
joakimp da21206e6e v0.75.3: bump pi 0.74.0 -> 0.75.3
Publish Docker Image / smoke (push) Successful in 4m47s
Publish Docker Image / publish (push) Successful in 11m25s
Publish Docker Image / update-description (push) Successful in 12s
pi @earendil-works/pi-coding-agent@0.74.0 -> 0.75.3 (one upstream minor
+ three patch releases since the initial pi-devbox release on 2026-05-14).

Validated: opencode-devbox v1.15.4b's smoke-with-pi and smoke-omos-with-pi
both passed with pi 0.75.3 baked in. Node v22.22.2 is comfortably above
pi's new minimum requirement of 22.19.0.

Built on joakimp/opencode-devbox:base-latest (cache hit on
base-35ee5fe7861a from 2026-05-14). PI_VERSION=latest in Dockerfile
resolves to 0.75.3 at build time. Image-side unchanged from v0.74.0
beyond the pi npm version.
2026-05-18 23:32:18 +02:00
joakimp 973c2efd5c Expand README + tweak DOCKER_HUB.md for users not cloning the repo
README rewrite:
- Two quick-start paths: 'no git clone' (curl docker-compose.yml +
  .env.example) and 'with git clone' for hackers/forkers
- New 'Authentication' section with subsections per provider
  (Anthropic, OpenAI, Gemini, AWS Bedrock static, AWS Bedrock SSO).
  AWS SSO path documents the ~/.aws bind-mount.
- Persistent state expanded: 5-row volume table + optional volumes
  table. Annotated what survives what.
- Configuration reference: full .env table.
- Versioning, building from source (with build args table),
  troubleshooting FAQ, related projects, license.
- 11 kB total — comprehensive but readable.

DOCKER_HUB.md tweaks:
- Quick-start now has a 'no git clone' path (curl two files), pointing
  users at the gitea README for the full setup guide. The git-clone
  path was overkill for the 90% case (just want to docker run).
- Explicit link to gitea README at the end of the quick-start block.
2026-05-15 17:58:06 +02:00
joakimp 5d472bd41f DOCKER_HUB.md: expand from stub to full Hub description
Replace the 1-line placeholder with a proper Hub README:
image variants table, quick start (docker run + docker compose),
inherited-from-base + added-by-pi-devbox feature lists, versioning
scheme, persistent volumes table, user-installed pi packages note,
source links.

Already PATCH'd live on Docker Hub manually — this commit keeps the
in-repo file in sync so the next tag-triggered update-description job
won't roll it back to the stub.
2026-05-15 08:47:23 +02:00
4 changed files with 362 additions and 35 deletions
+13
View File
@@ -35,3 +35,16 @@ Container image that adds pi coding-agent on top of the opencode-devbox base ima
- Do NOT call `mempalace-toolkit/install.sh` in the Dockerfile — the base entrypoint handles it - Do NOT call `mempalace-toolkit/install.sh` in the Dockerfile — the base entrypoint handles it
- `NPM_CONFIG_PREFIX=/usr` must be set per-RUN for any build-time `npm install -g` to keep baked binaries off the volume-shadowed path - `NPM_CONFIG_PREFIX=/usr` must be set per-RUN for any build-time `npm install -g` to keep baked binaries off the volume-shadowed path
- The smoke test threshold is 2200 MB — update if the image legitimately grows past it - The smoke test threshold is 2200 MB — update if the image legitimately grows past it
## Documentation drift sweep
Before committing any non-trivial change, check that prose still matches code. Drift hotspots in this repo:
- `README.md` — quick-start examples, env-var table, base-image reference (must match `FROM` in `Dockerfile`).
- `AGENTS.md` (this file) — `Key facts` block (pi binary path, `NPM_CONFIG_PREFIX`, base-image tag), smoke-test threshold number.
- `CHANGELOG.md` — promote `Unreleased` only on tag, but record post-release fixes in a fresh `Unreleased` block.
- `DOCKER_HUB.md` — hand-maintained slim Hub description; sync anything user-facing that changes (env vars, run command, base image).
- `.env.example` — hand-updated, must match Dockerfile/entrypoint env vars.
- `Dockerfile` `PI_VERSION` ARG default — if you intend to pin (rather than `latest`), bump it on release.
Quick triage: `git diff --name-only HEAD | xargs -I{} grep -l 'thing-you-changed' README.md AGENTS.md DOCKER_HUB.md CHANGELOG.md .env.example`.
+15
View File
@@ -8,6 +8,21 @@ Tags follow the pi npm version: `v{pi_version}[letter]` — bare tag for the fir
## Unreleased ## Unreleased
## v0.75.4 — 2026-05-21
pi `0.75.3``0.75.4` bump (one upstream patch release). Plus the AGENTS.md documentation-drift sweep clause that landed on `main` between v0.75.3 and now.
- **Bump:** pi `@earendil-works/pi-coding-agent@0.75.4` baked at `/usr/bin/pi` (via `PI_VERSION=latest` resolving to 0.75.4 at build time — no Dockerfile change needed).
- **AGENTS.md:** documentation drift sweep as explicit pre-commit workflow step (commit `ae6253a`). Companion clause added across the wider repo set the same day.
- No image-side changes beyond the pi npm version. Built on `joakimp/opencode-devbox:base-latest` which itself is unchanged (cache-hit on `base-35ee5fe7861a` since v1.14.50b).
## v0.75.3 — 2026-05-18
pi `0.74.0``0.75.3` bump (one upstream minor + three patch releases since the initial pi-devbox release on 2026-05-14).
- **Bump:** pi `@earendil-works/pi-coding-agent@0.75.3` baked at `/usr/bin/pi` (via `PI_VERSION=latest` resolving to 0.75.3 at build time).
- No image-side changes from the v0.74.0 baseline beyond the pi npm version. The pi-toolkit + pi-extensions clones, mempalace bridge symlink, and `NPM_CONFIG_PREFIX` named-volume setup all unchanged.
## v0.74.0 — 2026-05-14 ## v0.74.0 — 2026-05-14
Initial release. Initial release.
+99 -1
View File
@@ -1 +1,99 @@
pi coding-agent container — built on opencode-devbox base. Includes pi, pi-toolkit, pi-extensions, mempalace, AWS CLI, neovim, and full dev toolchain. See https://gitea.jordbo.se/joakimp/pi-devbox for full docs. # pi-devbox
A Docker container with [pi coding-agent](https://github.com/earendil-works/pi) pre-installed, built on top of [opencode-devbox](https://hub.docker.com/r/joakimp/opencode-devbox)'s base image. Pi gets a fully-loaded development environment in one `docker run`.
## Image variants
| Tag | Size (compressed) | What you get |
|---|---|---|
| `joakimp/pi-devbox:latest` | ~700 MB | Pi + companion repos, on top of the opencode-devbox base |
| `joakimp/pi-devbox:vX.Y.Z` | same | Pinned pi version (tracks the [pi npm package version](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)) |
Multi-arch: `linux/amd64`, `linux/arm64`.
## Quick start
One-shot, no persistence:
```bash
docker run -it --rm \
-v "$PWD":/workspace \
-v "$HOME/.ssh":/home/developer/.ssh:ro \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
joakimp/pi-devbox:latest pi
```
For a fully-configured environment with persistent settings, MemPalace memory, neovim plugins, and shell history surviving container recreation, use docker-compose. **You don't need to clone the repo** — just grab two template files:
```bash
mkdir -p ~/pi-devbox && cd ~/pi-devbox
curl -O https://gitea.jordbo.se/joakimp/pi-devbox/raw/branch/main/docker-compose.yml
curl -fsSL https://gitea.jordbo.se/joakimp/pi-devbox/raw/branch/main/.env.example -o .env
# Edit .env — set WORKSPACE_PATH, an LLM API key (ANTHROPIC_API_KEY,
# OPENAI_API_KEY, GEMINI_API_KEY, or AWS_*), and your git identity.
docker compose run --rm devbox pi
```
Full setup guide — authentication for each provider (Anthropic, OpenAI, Gemini, AWS Bedrock SSO + static), persistence model, configuration reference, build args, troubleshooting: **<https://gitea.jordbo.se/joakimp/pi-devbox#readme>**
## What's inside
Inherited from [opencode-devbox base](https://hub.docker.com/r/joakimp/opencode-devbox):
- **Debian trixie** (latest stable)
- **Node.js** (LTS), **uv** (Python tooling), **rustup** (Rust on-demand)
- **AWS CLI v2** + AWS Bedrock-ready config
- **MemPalace** + MCP server — persistent agent memory across sessions, queryable via `mempalace_*` tools inside pi
- **Gitea MCP** server
- **Dev tools**: neovim (LazyVim defaults), tmux, bat, eza, fzf, zoxide, ripgrep, git-lfs, make
- **Shell**: bash with history tuning, prefix-search bindings, fzf/zoxide integration
Added by pi-devbox:
- **pi** ([`@earendil-works/pi-coding-agent`](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)) — baked at `/usr/bin/pi`, version pinned at build time via the `PI_VERSION` build-arg
- **[pi-toolkit](https://gitea.jordbo.se/joakimp/pi-toolkit)** — keybindings (mosh/tmux-friendly Shift+Enter, Ctrl+J, Alt+J newline bindings), AWS env loader, settings template
- **[pi-extensions](https://gitea.jordbo.se/joakimp/pi-extensions)** — 7 user-facing extensions: `ext-toggle` (manage extensions interactively), `mcp-loader` (load MCP servers via settings.json), `todo`, `ssh-controlmaster`, `notify`, `git-checkpoint`, `confirm-destructive`
- **mempalace bridge** — MCP extension auto-symlinked from `/opt/mempalace-toolkit` so pi can read/write the same palace as opencode
The entrypoint deploys all of these on first container start. Re-running is idempotent and preserves user edits.
## Versioning
Tags follow the pi npm version: `v0.74.0`, `v0.75.0`, etc. `latest` always points at the most recent release. When pi cuts a new upstream version, this image is rebuilt and re-tagged to match.
For container-level rebuilds on the same pi version (security updates, base bumps, fixes) the tag gets a letter suffix: `v0.74.0b`, `v0.74.0c`, …
## Persistent state
User edits and pi-installed packages survive container recreation when you mount these named volumes. Use the included `docker-compose.yml` and they're set up automatically.
| Volume | Mount point | What it holds |
|---|---|---|
| `devbox-pi-config` | `/home/developer/.pi/` | pi settings, extension toggles, sessions, user-installed pi packages (`npm install -g`, `pi install npm:…`) |
| `devbox-shell-history` | `/home/developer/.cache/bash` | bash history |
| `devbox-zoxide` | `/home/developer/.local/share/zoxide` | zoxide directory jump database |
| `devbox-nvim-data` | `/home/developer/.local/share/nvim` | neovim plugin & Mason package state |
| `devbox-uv` | `/home/developer/.local/share/uv` | uv Python installs and tool cache |
Optional volumes for MemPalace (commented out by default — uncomment in `docker-compose.yml` to persist conversation memory across restarts):
| Volume | Mount point | What it holds |
|---|---|---|
| `devbox-palace` | `/home/developer/.mempalace` | palace data (drawers, knowledge graph, embeddings) |
| `devbox-chroma-cache` | `/home/developer/.cache/chroma` | ChromaDB embedding model cache (~80 MB, can be rebuilt) |
## User-installed pi packages
`NPM_CONFIG_PREFIX` is set inside the container to `/home/developer/.pi/npm-global`. Anything you `pi install npm:<pkg>` or `npm install -g` lands on the `devbox-pi-config` named volume — survives container recreation **and** image rebuilds. A user-installed `pi` wins over the baked one via `PATH` order, so you can pin a different pi version without rebuilding the image.
## Source
- **This image**: https://gitea.jordbo.se/joakimp/pi-devbox
- **Base image**: https://gitea.jordbo.se/joakimp/opencode-devbox (Hub: `joakimp/opencode-devbox`)
- **pi**: https://github.com/earendil-works/pi
- **pi-toolkit**: https://gitea.jordbo.se/joakimp/pi-toolkit
- **pi-extensions**: https://gitea.jordbo.se/joakimp/pi-extensions
## License
MIT (the image; pi and the bundled tools each carry their own licenses).
+235 -34
View File
@@ -1,58 +1,259 @@
# pi-devbox # pi-devbox
A Docker container image with [pi coding-agent](https://github.com/earendil-works/pi) pre-installed, built on the [opencode-devbox](https://gitea.jordbo.se/joakimp/opencode-devbox) base image. A Docker container with [pi coding-agent](https://github.com/earendil-works/pi) pre-installed, built on the [opencode-devbox](https://gitea.jordbo.se/joakimp/opencode-devbox) base image. Persistent state, full dev toolchain, MemPalace memory, and provider-agnostic LLM auth — in one `docker compose run`.
> **Hub:** [`joakimp/pi-devbox`](https://hub.docker.com/r/joakimp/pi-devbox) · multi-arch (amd64 + arm64)
> **Source:** [gitea.jordbo.se/joakimp/pi-devbox](https://gitea.jordbo.se/joakimp/pi-devbox)
---
## What's inside ## What's inside
Built on `opencode-devbox:base-latest`, which provides: Inherited from `opencode-devbox:base-latest`:
- **Debian trixie** (stable base) - **Debian trixie** (current stable)
- **Node.js** (LTS), **uv** (Python), **rustup** (Rust on-demand) - **Node.js** (LTS), **uv** (Python), **rustup** (Rust on-demand)
- **AWS CLI** v2 - **AWS CLI v2** (with Bedrock support)
- **MemPalace** + MCP server (persistent agent memory across sessions) - **MemPalace** + MCP server persistent agent memory across sessions; queryable via `mempalace_*` tools inside pi
- **Gitea MCP** server - **Gitea MCP** server
- **Dev tools**: neovim (LazyVim), tmux, bat, eza, fzf, zoxide, ripgrep, git-lfs, make - **Dev tools**: neovim (LazyVim), tmux, bat, eza, fzf, zoxide, ripgrep, jq, git-lfs, make
- **Shell**: bash with history tuning, prefix-search, fzf/zoxide integration - **Shell**: bash with history tuning, prefix-search, fzf/zoxide integration
This image adds: Added by pi-devbox:
- **pi** (`@earendil-works/pi-coding-agent`) — baked at `/usr/bin/pi` - **pi** ([`@earendil-works/pi-coding-agent`](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)) — baked at `/usr/bin/pi`, version pinned at build time
- **pi-toolkit** — keybindings, env loader, settings template (cloned to `/opt/pi-toolkit`) - **[pi-toolkit](https://gitea.jordbo.se/joakimp/pi-toolkit)** — mosh/tmux-friendly keybindings (Shift+Enter, Ctrl+J, Alt+J newline), AWS env loader, settings template
- **pi-extensions** — ext-toggle, todo, ssh-controlmaster, notify, git-checkpoint, mcp-loader, confirm-destructive (cloned to `/opt/pi-extensions`) - **[pi-extensions](https://gitea.jordbo.se/joakimp/pi-extensions)** — 7 extensions: `ext-toggle`, `mcp-loader`, `todo`, `ssh-controlmaster`, `notify`, `git-checkpoint`, `confirm-destructive`
- **mempalace bridge** — `mempalace.ts` extension symlinked from `/opt/mempalace-toolkit` - **mempalace bridge** — auto-symlinked MCP extension so pi reads/writes the same palace as opencode
## Quick start The entrypoint deploys all of these on first container start. Idempotent and preserves user edits.
---
## Quick start (no git clone)
If you just want to run pi-devbox and don't plan to modify the source, grab the two template files and go:
```bash ```bash
cp .env.example .env mkdir -p ~/pi-devbox && cd ~/pi-devbox
# edit .env — set WORKSPACE_PATH, GIT_USER_NAME, GIT_USER_EMAIL
docker compose run --rm devbox # Pull the docker-compose.yml and .env template
# inside the container: curl -O https://gitea.jordbo.se/joakimp/pi-devbox/raw/branch/main/docker-compose.yml
pi curl -fsSL https://gitea.jordbo.se/joakimp/pi-devbox/raw/branch/main/.env.example -o .env
# Edit .env — at minimum set WORKSPACE_PATH, an LLM API key, and your git identity
$EDITOR .env
# Pull and run pi
docker compose run --rm devbox pi
``` ```
`docker compose run --rm devbox` (no command) drops you into bash; you can then run `pi`, `aws sso login`, etc. manually.
To attach a second terminal to the same container (e.g. shell while pi is running):
```bash
docker compose exec -u developer devbox bash
```
---
## Quick start (with git clone)
If you want to follow upstream changes, run a customized fork, or rebuild the image yourself:
```bash
git clone https://gitea.jordbo.se/joakimp/pi-devbox
cd pi-devbox
cp .env.example .env
$EDITOR .env
docker compose run --rm devbox pi
```
---
## Authentication
pi reads provider credentials from environment variables, which the container picks up from `.env` automatically.
### Anthropic (Claude)
```ini
ANTHROPIC_API_KEY=sk-ant-...
```
Generate a key at <https://console.anthropic.com/settings/keys>.
### OpenAI
```ini
OPENAI_API_KEY=sk-...
```
### Google Gemini
```ini
GEMINI_API_KEY=...
```
### AWS Bedrock (e.g. Claude on Bedrock)
Two paths — pick one:
**A) Static credentials** (simplest, lower-trust environments only):
```ini
AWS_REGION=eu-west-1
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
```
**B) AWS SSO** (recommended for corporate AWS, requires mounting `~/.aws`):
```ini
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile
```
Then in your `docker-compose.yml`, uncomment the `~/.aws` bind-mount:
```yaml
volumes:
- ~/.aws:/home/developer/.aws
```
Inside the container, run `aws sso login` once per session. The token cache lives on the bind-mount, so subsequent `pi` invocations pick it up automatically. The pi-toolkit's `pi-env.zsh` (deployed to `~/.config/pi/`) auto-sources `AWS_PROFILE`/`AWS_REGION` whenever a shell starts.
### First-run pi configuration
On first start, pi reads `~/.pi/agent/settings.json` (auto-bootstrapped from the pi-toolkit template). Edit it inside the container to pick a default provider/model:
```bash
docker compose exec -u developer devbox bash
$EDITOR ~/.pi/agent/settings.json
```
The file is rewritten by pi at runtime (e.g. `lastChangelogVersion`), so it lives on the `devbox-pi-config` named volume — your edits persist across container recreation.
For pi's full configuration model (provider list, model overrides, MCP integration, themes, extensions): <https://github.com/earendil-works/pi#configuration>.
---
## Persistent state
Persistent state is what makes the difference between "use this once" and "make it my long-term coding environment". Everything important survives `docker compose down` and image upgrades; only `docker compose down -v` wipes the volumes.
| Volume | Mount point | What survives | Notes |
|---|---|---|---|
| `devbox-pi-config` | `/home/developer/.pi/` | pi settings.json, extension toggles, sessions, user-installed pi packages | `NPM_CONFIG_PREFIX` set inside the container so `pi install npm:…` and `npm install -g` lands here automatically |
| `devbox-shell-history` | `/home/developer/.cache/bash` | bash history | Across container recreate |
| `devbox-zoxide` | `/home/developer/.local/share/zoxide` | zoxide directory jump history | The `z`/`zi` shortcuts remember where you've been |
| `devbox-nvim-data` | `/home/developer/.local/share/nvim` | neovim plugin & Mason package state | LazyVim plugins persist |
| `devbox-uv` | `/home/developer/.local/share/uv` | uv-managed Python installs and tool cache | `uv tool install` results live here |
### Optional persistent volumes
These are commented out in `docker-compose.yml` by default. Uncomment them if you want the corresponding state to persist:
| Volume | Mount point | What survives |
|---|---|---|
| `devbox-palace` | `/home/developer/.mempalace` | MemPalace data — drawers, knowledge graph, embeddings. Treat as primary storage if you rely on agent memory. |
| `devbox-chroma-cache` | `/home/developer/.cache/chroma` | ChromaDB embedding model cache (~80 MB; disposable, re-downloads in seconds) |
### Workspace bind mount
`/workspace` is bind-mounted from `WORKSPACE_PATH` on the host (default `~/projects`). Source code never lives inside the container — your editor on the host and pi inside the container see the same files.
### SSH keys (read-only)
`~/.ssh` is mounted read-only at `/home/developer/.ssh` for git push/pull. The container does **not** write to it.
---
## Configuration reference
All config flows through `.env`. The full list (with annotations) is in [`.env.example`](https://gitea.jordbo.se/joakimp/pi-devbox/src/branch/main/.env.example). Here's the most relevant subset:
| Variable | Default | Purpose |
|---|---|---|
| `WORKSPACE_PATH` | `~/projects` | Host path mounted as `/workspace` |
| `SSH_KEY_PATH` | `~/.ssh` | Host path for SSH keys (read-only) |
| `GIT_USER_NAME` | (empty) | Sets `git config --global user.name` inside container |
| `GIT_USER_EMAIL` | (empty) | Sets `git config --global user.email` inside container |
| `ANTHROPIC_API_KEY` | (unset) | Anthropic provider auth |
| `OPENAI_API_KEY` | (unset) | OpenAI provider auth |
| `GEMINI_API_KEY` | (unset) | Google Gemini auth |
| `AWS_PROFILE` / `AWS_REGION` | (unset) | AWS Bedrock SSO flow |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | (unset) | AWS Bedrock static creds |
| `GITEA_ACCESS_TOKEN` / `GITEA_HOST` | (unset) | Gitea MCP server (optional) |
| `GITHUB_PERSONAL_ACCESS_TOKEN` | (unset) | GitHub MCP server / git ops over HTTPS |
| `LANG` / `LANGUAGE` / `LC_ALL` | `en_US.UTF-8` | Locale override |
---
## Versioning ## Versioning
Tags follow the pi npm version: `v0.74.0`, `v0.75.0`, etc. Tags follow the pi npm package version: `v0.74.0`, `v0.75.0`, `latest` always points at the most recent successful release.
`latest` always points at the most recent release.
## Persistence Container-level rebuilds on the same pi version (security updates, base bumps, fixes) get a letter suffix: `v0.74.0b`, `v0.74.0c`, …
| Volume | What it holds | When the upstream [pi npm package](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) cuts a new version, this image is rebuilt and re-tagged to match.
|--------|---------------|
| `devbox-pi-config` | pi settings, extensions toggle state, sessions (`~/.pi/`) |
| `devbox-shell-history` | bash history |
| `devbox-zoxide` | zoxide directory jump history |
| `devbox-nvim-data` | neovim plugins, Mason packages |
| `devbox-uv` | uv Python installs and tool cache |
## User-installed pi packages ---
`NPM_CONFIG_PREFIX` is set to `/home/developer/.pi/npm-global`, so any `pi install npm:...` or `npm install -g` as the `developer` user lands on the `devbox-pi-config` volume and survives container recreation and image rebuilds. A user-installed pi wins over the baked binary via `PATH` order. ## Building from source
## Source If you want to pin a specific pi version, change the base image, or hack on the Dockerfile:
- [pi-devbox](https://gitea.jordbo.se/joakimp/pi-devbox) — this repo ```bash
- [opencode-devbox](https://gitea.jordbo.se/joakimp/opencode-devbox) — base image source git clone https://gitea.jordbo.se/joakimp/pi-devbox
- [pi-toolkit](https://gitea.jordbo.se/joakimp/pi-toolkit) cd pi-devbox
- [pi-extensions](https://gitea.jordbo.se/joakimp/pi-extensions)
# Edit Dockerfile or override via build args:
docker compose build \
--build-arg PI_VERSION=0.73.0 \
--build-arg BASE_IMAGE=joakimp/opencode-devbox:base-latest
docker compose up -d
```
Build args supported:
| Arg | Default | Effect |
|---|---|---|
| `BASE_IMAGE` | `joakimp/opencode-devbox:base-latest` | Parent image — set to `joakimp/opencode-devbox:base-<sha>` for reproducible builds |
| `PI_VERSION` | `latest` | npm version of `@earendil-works/pi-coding-agent` |
| `PI_TOOLKIT_REF` | `main` | Git ref for [pi-toolkit](https://gitea.jordbo.se/joakimp/pi-toolkit) |
| `PI_EXTENSIONS_REF` | `main` | Git ref for [pi-extensions](https://gitea.jordbo.se/joakimp/pi-extensions) |
---
## Troubleshooting
**`pi --version` works but `pi` exits immediately.** First-run config probably hasn't been done. `docker compose exec -u developer devbox bash`, edit `~/.pi/agent/settings.json`, ensure a provider is set and the matching API key is exported.
**AWS SSO token expired.** `aws sso login` from inside the container. The token cache is on the `~/.aws` bind-mount, so it persists; expiration is the issue.
**Anthropic 401 / OpenAI 401.** Check the `.env` value made it in: `docker compose exec devbox env | grep ANTHROPIC` (etc).
**`pi` prompts for an extension/MCP server you don't recognize.** Either toggle it off via `/ext` inside pi, or rename the file: `mv ~/.pi/agent/extensions/<name>.ts{,.off}`.
**Container won't start, error about `/workspace`.** `WORKSPACE_PATH` in `.env` doesn't exist on the host. Create the directory or fix the path.
**Pi-toolkit symlinks lost after `docker compose down -v`.** That's expected — `-v` wipes named volumes. Don't do it unless you mean it. Container recreation without `-v` (the default) preserves all state.
---
## Related
- **[opencode-devbox](https://gitea.jordbo.se/joakimp/opencode-devbox)** — the base image. Use this if you want both opencode and pi (it has a `latest-with-pi` variant) or just opencode.
- **[pi-toolkit](https://gitea.jordbo.se/joakimp/pi-toolkit)** — keybindings, env loader, settings template. Cloned into `/opt/pi-toolkit` at image build time and `install.sh` runs on container start.
- **[pi-extensions](https://gitea.jordbo.se/joakimp/pi-extensions)** — extension source. Same install pattern.
- **[mempalace-toolkit](https://gitea.jordbo.se/joakimp/mempalace-toolkit)** — MemPalace bring-up. The `mempalace.ts` extension symlinked into `~/.pi/agent/extensions/` comes from here.
- **[pi (upstream)](https://github.com/earendil-works/pi)** — the coding-agent itself.
---
## License
MIT (this image and its source). Pi and the bundled tools each carry their own licenses.