Overlay recipes¶
Ready-to-copy overlay fragments for common needs. Each recipe is a FROM-less
Dockerfile: drop it into .vibepod/overlay/Dockerfile to apply it to every
agent in the project, or into .vibepod/overlay/<agent>/Dockerfile for a
single agent. See the overview for how overlays are built and
cached.
Fragments compose — a single Dockerfile can combine several recipes.
apt packages¶
System packages from the distribution repositories. The smallest useful overlay.
# .vibepod/overlay/Dockerfile — no FROM line
RUN apt-get update && apt-get install -y --no-install-recommends \
jq ripgrep sqlite3 \
&& rm -rf /var/lib/apt/lists/*
--no-install-recommendsand theaptlist cleanup keep the overlay image small.- Agent base images are Debian-based; swap in
apk/dnfonly if you have overridden the base image with something else.
Python requirements¶
The overlay directory is the docker build context, so a fragment can COPY
files committed next to it.
# .vibepod/overlay/Dockerfile — no FROM line
COPY requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir -r /tmp/requirements.txt
Editing requirements.txt changes the overlay hash, so the image rebuilds on
the next run — no manual invalidation needed.
pixi package manager¶
pixi gives agents on-demand access to the conda-forge
ecosystem — PDF tools, image libraries, scientific stacks — without root or a
rebuild at runtime (pixi init && pixi add poppler). From
issue #140.
# .vibepod/overlay/Dockerfile — no FROM line
ADD https://github.com/prefix-dev/pixi/releases/download/v0.76.2/pixi-x86_64-unknown-linux-musl.tar.gz /tmp/pixi.tar.gz
RUN mkdir -p /opt/pixi/bin && tar -xzf /tmp/pixi.tar.gz -C /opt/pixi/bin && rm /tmp/pixi.tar.gz
ENV PATH="/opt/pixi/bin:${PATH}"
ADDfrom URL instead ofcurl | bash— works even when the base image ships no curl.- Fixed path
/opt/pixiinstead of$HOME/.pixi— several agents overrideHOMEat runtime, so a build-time~would not resolve to the same place.ENV PATHpersists in the image config regardless ofHOME. - Pinned version — with
latest, the overlay cache keeps whatever pixi version the first build downloaded until the fragment text changes. -
Architecture — the URL above is x86_64; on an arm64 host (Apple silicon), use the
pixi-aarch64-unknown-linux-musl.tar.gztarball. For a fragment that works on both, pick the tarball at build time withuname -m(matches pixi's tarball naming; requires curl in the base image). Overlays build with the classic builder, so BuildKit'sTARGETARCHarg is not available:
pixi + PDF/OCR toolchain¶
A real-world fragment by @ReimarBauer from issue #140: pixi with checksum verification, plus a pre-built environment with poppler, qpdf, ghostscript, and tesseract for PDF and OCR work. Described in his blog post on local AI-assisted PDF processing.
# .vibepod/overlay/Dockerfile — no FROM line
ENV PIXI_HOME=/opt/pixi
# Download pixi binary + official SHA256 checksum via Docker ADD (no curl/wget needed)
ADD https://github.com/prefix-dev/pixi/releases/latest/download/pixi-aarch64-unknown-linux-musl.tar.gz /tmp/pixi.tar.gz
ADD https://github.com/prefix-dev/pixi/releases/latest/download/pixi-aarch64-unknown-linux-musl.tar.gz.sha256 /tmp/pixi.sha256
# Verify checksum with sha256sum -c, then extract to $PIXI_HOME/bin
RUN set -ex && \
cd /tmp && \
sed 's|pixi-aarch64-unknown-linux-musl.tar.gz|/tmp/pixi.tar.gz|g' pixi.sha256 | sha256sum -c - && \
mkdir -p ${PIXI_HOME}/bin && \
tar xzf /tmp/pixi.tar.gz -C ${PIXI_HOME}/bin && \
chmod +x ${PIXI_HOME}/bin/pixi && \
rm -f /tmp/pixi.tar.gz /tmp/pixi.sha256
ENV PATH=/opt/pixi/bin:$PATH
RUN pixi --version
# Create vp_pixi project at /opt/vp_pixi (/opt to avoid overwriting user pixi installations)
RUN mkdir -p /opt/vp_pixi
WORKDIR /opt/vp_pixi
RUN pixi init
# Install PDF tools + OCR: poppler, qpdf, ghostscript, tesseract (all with checksum verification)
RUN pixi add poppler qpdf ghostscript tesseract
ENV PATH=/opt/vp_pixi/.pixi/envs/default/bin:$PATH
- Targets an arm64 host; on x86_64 replace
aarch64withx86_64in bothADDURLs and thesedpattern. - Uses
latest; pin a release (as in the previous recipe) for reproducibility.
pi + MCP servers (pi-mcp-adapter)¶
pi-mcp-adapter is the pi
extension that gives it MCP tools. The usual pi install npm:pi-mcp-adapter
does not survive as a build step: pi writes into $HOME/.pi, and $HOME
(/config) is a host mount at runtime, so anything installed there at build
time is shadowed. Install into /opt instead and point the project's
.pi/settings.json at it as a local-path package.
# .vibepod/overlay/pi/Dockerfile — no FROM line
#
# $HOME (/config) is a host mount at runtime, so `pi install` at build time
# would be shadowed. Install into /opt instead; the project's
# .pi/settings.json references it as a local-path package.
ARG PI_MCP_ADAPTER_VERSION=2.34.0
RUN node -e 'const [a,b]=process.versions.node.split(".").map(Number); if (a<22||(a===22&&b<18)) { console.error("pi-mcp-adapter needs Node >= 22.18, got "+process.version); process.exit(1) }' \
&& mkdir -p /opt/pi-packages \
&& cd /opt/pi-packages \
&& npm init -y >/dev/null \
&& npm install --omit=dev --no-audit --no-fund "pi-mcp-adapter@${PI_MCP_ADAPTER_VERSION}" \
&& npm cache clean --force \
&& chmod -R a+rX /opt/pi-packages
Commit the two project files pi reads at startup. .pi/settings.json loads
the baked-in extension:
.mcp.json lists the servers to expose (shared with other MCP-aware tools):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem@2026.8.31", "/workspace"]
}
}
}
- Per-agent overlay — the fragment lives under
.vibepod/overlay/pi/so other agents in the project do not pay for an extension only pi loads. - Absolute path in
settings.json— pi resolves relative package paths against the settings file, which sits in the workspace mount; the install is outside it, so the path must be absolute. chmod -R a+rX— the overlay builds as root but pi runs as the container user; without it the extension is unreadable at runtime.- Node check — the adapter's
enginesfield says Node 20, but parts of it (the token commands, for one) need 22.18+; failing the build early beats a silent load failure in pi. Drop the guard if your base image is known-good. - Pinned version via
ARG— bumpPI_MCP_ADAPTER_VERSIONto upgrade; the fragment text changes, so the overlay rebuilds. - Pinned server version in
.mcp.json—npx -yfetches the package on first use, so an unpinned name resolves to whatever is latest that day and needs registry access at runtime. Pin it, or bake the server into the overlay next to the adapter and pointcommandat it.
Agent tooling: RTK and Graphify¶
Fragments that install RTK and Graphify into the agent image — together with the hook or skill registration they need — live on the External tools page.
Contributing a recipe¶
Got an overlay other projects could reuse? Open an issue or PR with the fragment and a line on what it is for — this page is meant to grow from real-world use.