This is the multi-page printable view of this section. Click here to print.
Addons
1 - Overview
Addons
aibox uses the Debian runtime image family (base-debian-v0.26.x for legacy releases, base-debian-runtime-v0.27.0+ after the image-tag cutover) with 36 composable addons that install language runtimes, tool bundles, documentation frameworks, and AI coding agents into your container.
Managing Addons
Via CLI
# See all available addons
aibox get addon
# Add an addon (updates aibox.toml and runs apply)
aibox set addon python
# Remove an addon
aibox delete addon python
# View addon details (tools, versions)
aibox describe addon rust
# Emit the machine-readable addon catalog index
aibox describe addon-catalog -o json
Via aibox.toml
[addons.python.tools]
python = { version = "3.14" }
uv = { version = "0.12.5" }
[addons.rust.tools]
rustc = { version = "1.97.1" }
clippy = {}
rustfmt = {}
[addons.node.tools]
node = { version = "26" }
pnpm = { version = "11.22.0" }
Each addon has default-enabled tools that are included automatically, and optional tools you can enable explicitly. Tools with version selection let you pick from curated, tested versions.
Language addons also expose composable nested groups. For example,
[addons.go.quality], [addons.go.supply-chain], and
[addons.go.release] select the canonical go-quality, supply-chain, and
go-release recipes and expand their dependencies automatically. Nested
[addons.<language>.<group>.tools] entries use the same version and
enabled overrides as flat addons.
aibox describe addon-catalog -o json emits the stable aibox.addon-catalog.v0
index used by downstream automation. It includes each addon’s profile intent,
automation usage class, supported aibox profiles, exported surfaces,
dependencies, and tool metadata. Canonical processkit Artifact{kind=addon-spec}
emission remains gated on the upstream processkit schema release.
After editing aibox.toml, run aibox apply to regenerate the Dockerfile and rebuild.
Available Addons
Language Runtimes
| Addon | Default Tools | Optional Tools |
|---|---|---|
python | python (3.12/3.13/3.14), uv (0.7/0.11.10/0.11.11/0.11.15/0.11.19/0.11.26/0.12.0/0.12.5) | poetry (1.8/2.0/2.4.1), pdm (2.22/2.26.9/2.27.0/2.28.0/2.28.1) |
rust | rustc (1.90/1.91/1.92/1.93/1.94/1.94.1/1.96.0/1.96.1/1.97.1), clippy, rustfmt | — |
node | node (20/22/24/26), pnpm (9/10/11.1.3/11.5.2/11.10.0/11.18.0/11.20.0/11.21.0/11.22.0) | yarn (4/4.16.0/4.17.0), bun (1.2/1.3.14) |
go | go (1.25/1.26/1.26.3/1.26.4/1.26.5/1.26.6) | — |
go-quality | goimports, staticcheck, golangci-lint, govulncheck, gosec | — |
typst | typst (0.13.1/0.14.2/0.15.0) | — |
latex | texlive-core, texlive-recommended, texlive-fonts, biber, texlive-code, texlive-diagrams, texlive-math | texlive-music, texlive-chemistry |
Tool Bundles
| Addon | Default Tools | Optional Tools |
|---|---|---|
infrastructure | opentofu, ansible, packer | podman (rootless engine and Compose) |
supply-chain | gitleaks, osv-scanner, syft, grype, cosign | — |
release | shellcheck, hadolint | — |
go-release | goreleaser (requires go and release) | — |
git-ui | gh, lazygit | — |
preview-archive | chafa, librsvg, poppler, timg, mupdf, entr, p7zip, resvg | — |
preview-enhanced | rich, ffmpeg, ghostscript | — |
data-preview | sqlite3, csvkit | — |
audio-voice | sox, pulseaudio-utils, ALSA PulseAudio plugins | — |
kubernetes | kubectl, helm, kustomize | k9s |
cloud-aws | aws-cli | — |
cloud-gcp | gcloud-cli | — |
cloud-azure | azure-cli | — |
browser-testing | @playwright/test, @axe-core/playwright, Chromium | Firefox, WebKit |
Documentation Frameworks
| Addon | Tools |
|---|---|
docs-mkdocs | mkdocs + mkdocs-material |
docs-zensical | zensical |
docs-docusaurus | docusaurus |
docs-starlight | starlight |
docs-mdbook | mdbook |
docs-hugo | hugo |
AI Harnesses
AI harnesses are selected under [ai], not as public addon blocks. aibox still
uses internal install recipes for container CLIs when install = true.
[ai]
harnesses = [
{ harness = "claude", enable = true, install = true },
{ harness = "codex", enable = true, install = true, version = "latest" },
]
Legacy [addons.ai-*.tools] entries are accepted for compatibility, but fresh
scaffolding keeps AI configuration in the [ai] section.
Addons and Skills
As of v0.16.0, all skills live in processkit.
Projects using context.mode = "processkit" install processkit skills under
context/skills/ independently from addons. Projects using
context.mode = "harness-only" do not install processkit skills at all. There
is no longer an addon-driven “auto-deploy a skill” mechanism.
The relevant skills for each addon’s tooling are still in the catalogue — agents pick them up via skill descriptions, not via addon membership:
| Addon | Naturally relevant skills |
|---|---|
python | python-best-practices, fastapi-patterns, pandas-polars |
rust | rust-conventions, concurrency-patterns |
go | concurrency-patterns and the Go-flavoured patterns shipped upstream |
node | typescript-patterns, tailwind |
latex / typst | documentation |
git-ui | git-workflow |
kubernetes | container-orchestration |
cloudflare | Cloudflare Tunnel workflows |
infrastructure | terraform-flavoured patterns shipped upstream |
See Skills (via processkit) for the full split.
How Addons Work
When you run aibox apply, the CLI:
- Reads
[addons]fromaibox.toml - Looks up each addon definition from YAML files in
~/.config/aibox/addons/ - Merges your tool selections with addon defaults
- Generates Dockerfile builder stages (for heavy builds like Rust, LaTeX)
- Generates runtime
RUN/COPYcommands - Builds the container image
Addons that need compilation (Rust, LaTeX, infrastructure, Kubernetes) use multi-stage Docker builds – heavy compilation happens in isolated builder stages, and only the final binaries are copied into the runtime image.
Addon Definition Format
Addon definitions are YAML files stored in ~/.config/aibox/addons/ with category subdirectories (languages/, tools/, docs/, ai/). They are installed automatically by the install script and updated when you upgrade aibox.
Extra Packages
For one-off apt packages not covered by addons, use extra_packages:
[container]
extra_packages = ["universal-ctags", "graphviz", "postgresql-client"]
These are installed during aibox apply via the generated Dockerfile. They persist across container restarts but are reinstalled on image rebuild.
Version Selection
Each tool in an addon has a curated list of supported versions. Use aibox describe addon <name> to see available versions:
$ aibox describe addon python
Add-on: python
Recipe version: 1.0.0
TOOL DEFAULT VERSION SUPPORTED
python yes 3.14 3.12, 3.13, 3.14
uv yes 0.12.5 0.7, 0.11.10, 0.11.11, 0.11.15, 0.11.19, 0.11.26, 0.12.0, 0.12.5
poetry no 2.4.1 1.8, 2.0, 2.4.1
pdm no 2.28.1 2.22, 2.26.9, 2.27.0, 2.28.0, 2.28.1
Tools marked “DEFAULT: yes” are included automatically when you set the addon. Tools marked “no” must be explicitly listed in your aibox.toml to be installed.
2 - Language Runtimes
Language Runtime Addons
Language runtimes install compilers, interpreters, and package managers into your container.
Python
[addons.python.tools]
python = { version = "3.14" } # 3.12, 3.13, 3.14
uv = { version = "0.12.5" } # 0.7, 0.11.10, 0.11.11, 0.11.15, 0.11.19, 0.11.26, 0.12.0, 0.12.5
# poetry = { version = "2.4.1" } # Optional: 1.8, 2.0, 2.4.1
# pdm = { version = "2.28.1" } # Optional: 2.22, 2.26.9, 2.27.0, 2.28.0, 2.28.1
Installs Python, pip, venv, and uv (fast package manager). The base image pins uv to the curated default instead of following a floating latest image tag. Poetry and PDM are available but not enabled by default.
Rust
[addons.rust.tools]
rustc = { version = "1.97.1" } # 1.90, 1.91, 1.92, 1.93, 1.94, 1.94.1, 1.96.0, 1.96.1, 1.97.1
clippy = {} # Linter (no version selection)
rustfmt = {} # Formatter (no version selection)
Installs the Rust toolchain via rustup with clippy and rustfmt. Uses a multi-stage Docker build — compilation happens in a builder stage and only the toolchain is copied to the runtime image.
Node.js
[addons.node.tools]
node = { version = "26" } # 20, 22, 24, 26
pnpm = { version = "11.22.0" } # 9, 10, 11.1.3, 11.5.2, 11.10.0, 11.18.0, 11.20.0, 11.21.0, 11.22.0
# yarn = { version = "4.17.0" } # Optional: 4, 4.16.0, 4.17.0
# bun = { version = "1.3.14" } # Optional
Installs Node.js via NodeSource, plus pnpm as default package manager. Yarn and Bun are available but not enabled by default.
Go
[addons.go.tools]
go = { version = "1.26.6" } # 1.25, 1.26, 1.26.3, 1.26.4, 1.26.5, 1.26.6
Installs Go and sets up GOPATH.
Production Go groups
Go projects can compose production tooling without bloating the base runtime:
[addons.go]
[addons.go.infrastructure]
[addons.go.quality.tools]
staticcheck = { enabled = false } # optional per-tool override
[addons.go.supply-chain]
[addons.go.release]
# Optional nested container engine without the other infrastructure defaults:
[addons.go.infrastructure.tools]
opentofu = { enabled = false }
ansible = { enabled = false }
packer = { enabled = false }
podman = {}
quality installs goimports, staticcheck, golangci-lint,
govulncheck, and gosec, plus the Linux compiler and libc headers required
by go test -race ./.... supply-chain adds gitleaks, osv-scanner,
syft, grype, and cosign. release adds GoReleaser, ShellCheck, and
Hadolint. The built-in gofmt, go vet, go test, fuzzing, and coverage
commands remain part of the Go toolchain and need no extra binary.
The optional podman selection installs a rootless container engine and its
Compose provider. The explicit disables keep OpenTofu, Ansible, and Packer out
when the project only needs nested container operations.
The same infrastructure, security/supply-chain, and release group names
are accepted below every language addon. Go additionally exposes quality
and its lint alias.
Typst
[addons.typst.tools]
typst = { version = "0.15.0" } # 0.13.1, 0.14.2, 0.15.0
Installs the Typst typesetting system for modern document creation.
LaTeX
[addons.latex.tools]
texlive-core = {} # Base TeX Live installation
texlive-recommended = {} # Common packages
texlive-fonts = {} # Font packages
biber = {} # Bibliography processor
texlive-code = {} # Code listing packages
texlive-diagrams = {} # TikZ, PGF, circuit diagrams
texlive-math = {} # Math packages
# texlive-music = {} # Optional: LilyPond, MusiXTeX
# texlive-chemistry = {} # Optional: chemfig, mhchem
Installs TeX Live via a multi-stage Docker build. The full TeX Live installation happens in a builder stage and only the final tree is copied to the runtime image, keeping layer sizes manageable.
Use the LaTeX build and preview workflow to define named
documents, run reproducible latexmk builds and watchers inside the development
container, and serve completed PDFs through the read-only EmbedPDF sidecar.
Emoji rendering with LuaLaTeX
The runtime image ships fonts-noto-color-emoji so emoji glyphs render
correctly in LuaLaTeX documents. To wire it up, add the following to
your preamble:
\directlua{luaotfload.add_fallback("emojifallback",{"NotoColorEmoji:mode=harf;"})}
\setmainfont{FreeSans}[Scale=0.95,RawFeature={fallback=emojifallback}]
Without the fallback configured, emoji characters render as missing-glyph boxes even though the font is installed.
3 - Tool Bundles
Tool Bundle Addons
Tool bundles install infrastructure, orchestration, and cloud CLI tools.
Supply Chain
[addons.supply-chain.tools]
gitleaks = {}
osv-scanner = {}
syft = {}
grype = {}
cosign = {}
This language-neutral bundle covers secret scanning, dependency and artifact vulnerability checks, SBOM generation, and Sigstore signing. Release archives are pinned and checked against upstream-published checksums.
Release Validation
[addons.release.tools]
shellcheck = {}
hadolint = {}
The language-neutral release bundle validates shell scripts and Dockerfiles.
Go projects should normally select [addons.go.release], which composes this
bundle with the go-release recipe and GoReleaser.
Git UI
[addons.git-ui.tools]
gh = {} # GitHub CLI
lazygit = {} # Interactive Git TUI
The git-ui addon is optional. Select it when a project needs GitHub CLI
automation or lazygit inside the container; omit it to avoid installing those
tools. This aibox repo may enable it for maintenance workflows such as release
checks and GitHub issue/release work, but downstream projects do not need it by
default.
Browser Visual Testing
The browser-testing addon provides a pinned Node-based Playwright Test stack
(@playwright/test plus @axe-core/playwright) for headless browser checks.
Playwright-managed full Chromium is enabled by default; Firefox and WebKit are
opt-in so a project can keep its image smaller when cross-engine coverage is
not required.
[addons.browser-testing.tools]
# Playwright Test and @axe-core/playwright are enabled by default.
# Optional cross-engine coverage:
firefox = { enabled = true }
webkit = { enabled = true }
The v0.x catalog currently couples Playwright 1.62.1 with
@axe-core/playwright 4.13.0 and the matching browser revisions. The addon
provides that pinned runner/browser environment; keep the derived project’s
package.json and lockfile authoritative, and install the packages locally
when the project’s package manager does not resolve the environment’s global
packages. After applying the configuration, a derived project can keep its
tests and baselines beside the application, for example:
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./tests/browser",
use: {
baseURL: "http://127.0.0.1:4173",
...devices["Desktop Chrome"],
colorScheme: "light",
reducedMotion: "reduce",
},
projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
});
// tests/browser/home.spec.ts
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
test("home page is keyboard reachable and accessible", async ({ page }) => {
await page.goto("/");
await expect(page.getByRole("main")).toBeVisible();
await page.keyboard.press("Tab");
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
The example is only a starting point. The derived project owns the responsive viewport set, focus and keyboard flows, light/dark themes, reduced-motion behavior, accessibility assertions, and screenshot-baseline matrix. aibox tests validate the addon installation, generated contract, browser launch, and a minimal fixture; they do not prescribe an application’s visual matrix.
Preview and Archive Tools
[addons.preview-archive.tools]
chafa = {}
timg = {}
poppler = {}
mupdf = {}
entr = {}
p7zip = {}
resvg = {}
preview-archive contains the terminal image/PDF/SVG/archive helper binaries
used by Yazi previews and watch-mode document workflows. Keep it disabled for
lean headless projects that do not inspect media or generated documents inside
the terminal.
preview-enhanced layers Markdown, EPS, video, and Ghostscript support on top
of preview-archive.
Data Preview
[addons.data-preview.tools]
sqlite3 = {}
csvkit = {}
data-preview adds read-only SQLite inspection and CSV, TSV, XLS, and XLSX
formatting for the generated Yazi preview plugins.
Audio and Voice
[audio]
enabled = true
Audio bridging uses the internal audio-voice recipe for Sox, PulseAudio
client tools, and ALSA PulseAudio plugins. aibox selects this recipe
automatically when [audio] enabled = true and install = true; projects normally do not need to add
[addons.audio-voice.tools] manually.
Infrastructure
[addons.infrastructure.tools]
opentofu = {} # Infrastructure-as-code (Terraform alternative)
ansible = {} # Configuration management
packer = {} # Machine image builder
podman = {} # Optional rootless container engine + Compose
OpenTofu defaults to 1.12.5, Packer to 1.16.0, and Ansible to 14.3.1.
OpenTofu and Packer are installed in a multi-stage builder. Ansible is installed via pip.
Podman is optional and installs the Debian-packaged rootless engine, Compose
provider, user-namespace helpers, and overlay/networking prerequisites. Nested
containers still depend on the outer runtime allowing user namespaces; FUSE
overlay is used when /dev/fuse is available, with Podman’s normal fallback
otherwise.
Kubernetes
[addons.kubernetes.tools]
kubectl = {} # Kubernetes CLI
helm = {} # Package manager
kustomize = {} # Configuration customization
# k9s = {} # Optional: terminal UI for Kubernetes
kubectl defaults to 1.36.3, Helm to 4.2.4, Kustomize to 5.8.1, and k9s to 0.51.0. All tools are downloaded as static binaries in a multi-stage builder.
Cloud Providers
AWS
[addons.cloud-aws.tools]
aws-cli = {}
Installs the AWS CLI v2.
Google Cloud
[addons.cloud-gcp.tools]
gcloud-cli = {}
Installs the Google Cloud CLI via the official APT repository.
Azure
[addons.cloud-azure.tools]
azure-cli = {}
Installs the Azure CLI via pip.
4 - Documentation Frameworks
Documentation Framework Addons
Documentation addons install static site generators and documentation tools.
| Addon | Tool | Install Method |
|---|---|---|
docs-mkdocs | MkDocs + Material theme | uv |
docs-zensical | Zensical | uv |
docs-docusaurus | Docusaurus | npm |
docs-starlight | Starlight (Astro) | npm |
docs-mdbook | mdBook | Binary download |
docs-hugo | Hugo Extended | Binary download |
Current curated pins are Docusaurus 3.10.1, Hugo 0.165.0, mdBook 0.5.4,
MkDocs 1.6.1 with Material 9.7.7, and Zensical 0.0.55. Starlight remains
scaffolded through the upstream create-starlight package.
Example
[addons.docs-docusaurus.tools]
docusaurus = {}
After aibox apply, the documentation tool is available inside the container. Initialize your docs project as usual (e.g., npx create-docusaurus@latest docs classic).
5 - LaTeX Build and Preview
LaTeX Build and Preview
The latex addon supplies TeX Live, latexmk, bibliography tools, fonts, and
common package groups. aibox adds a project-level build contract on top so
humans and agents use the same engine, cache, output paths, and document names.
Configure documents
Enable the addon and declare one or more documents:
[addons.latex.tools]
texlive-core = {}
texlive-recommended = {}
texlive-fonts = {}
biber = {}
[latex]
engine = "lualatex"
cache_dir = ".latex-cache"
options = []
[[latex.documents]]
name = "overview"
source = "docs/overview/overview.tex"
output_dir = ".latex-cache/overview"
[[latex.documents]]
name = "appendix"
source = "docs/appendix/appendix.tex"
output_dir = ".latex-cache/appendix"
[latex.preview]
enabled = true
engine = "embedpdf"
bind = "127.0.0.1"
port = 8765
# document = "overview" # optional compatibility-route default
allow_public = false
Supported engines are lualatex, pdflatex, xelatex, and tectonic.
Continuous watch mode uses latexmk, so tectonic configurations support
one-shot builds only.
Build and watch
Run these commands inside the development container. aibox apply generates
them under .aibox-home/.local/bin, which is already on the container PATH:
aibox-latex-build # every configured document
aibox-latex-build overview # one configured document
aibox-latex-watch overview # foreground watcher; stop with Ctrl-C
Builds use non-interactive, file-and-line-error, halt-on-error flags. Watch mode
adds latexmk -pvc -view=none, leaving browser preview ownership to the sidecar.
TEXMFVAR and TEXMFCONFIG live below latex.cache_dir, so TeX does not write
mutable state to the user’s global TeX tree.
Compilation never runs on the host or in the preview sidecar. The scripts use
the TeX installation in the main development container, keep the watch process
in the foreground, and write PDFs below each configured output_dir. Run one
watcher per document when several documents should rebuild concurrently.
Running aibox apply adds a concise, conditional aibox-managed LaTeX section
to AGENTS.md. This is the primary instruction surface for AI agents and gives
them the configured container commands, companion health check, preview URLs,
and document paths without adding another root-level guidance file.
Live PDF preview
When preview is enabled, aibox apply generates a dedicated Compose sidecar and
port mapping. Host-side aibox up starts that sidecar, which serves every
configured document from the project workspace mounted read-only. The sidecar
does not contain a TeX toolchain and cannot modify the workspace.
latex.preview.document chooses the preferred document used by compatibility
routes; it does not exclude the others.
Inspect its logs with:
docker compose -f .devcontainer/docker-compose.yml logs <project-container-name>-latex-preview
aibox down stops the sidecar with the rest of the Compose project. A
subsequent aibox up starts it again. With multiple documents, the root URL
displays a selection page. Each PDF also has a stable direct URL:
http://127.0.0.1:8765/
http://127.0.0.1:8765/documents/overview/
http://127.0.0.1:8765/documents/appendix/
The stable URL is http://127.0.0.1:8765/. The service watches the completed
PDF output for every document, waits for its metadata to remain stable across
multiple polls, and then sends a document-specific SSE revision event. This
prevents the browser from fetching a partially-written PDF. The browser
requests a versioned PDF URL on reload so a stale cache cannot hide a new
build. Page and zoom state are retained separately for each document.
The viewer uses the pinned
@embedpdf/snippet
browser package. Its default toolbar provides navigation, zoom, search,
thumbnails, and outline support when the PDF contains an outline. The browser
must be able to reach jsDelivr to load the pinned viewer module; the PDF itself
is served by the local preview sidecar.
Host and network access
The preview helper listens on 0.0.0.0:8765 inside its isolated sidecar. The
generated Compose mapping publishes that internal port only on the configured
host address and port. The secure default is therefore accessible from the
host browser but not from other machines:
[latex.preview]
enabled = true
bind = "127.0.0.1"
port = 8765
allow_public = false
Run aibox apply after changing this configuration, then run aibox up on the
host. Do not add a manual override mapping;
aibox generates 127.0.0.1:8765:8765 in .devcontainer/docker-compose.yml.
For access from another machine on the local network, explicitly expose the unauthenticated endpoint:
[latex.preview]
enabled = true
bind = "0.0.0.0"
port = 8765
allow_public = true
This generates 0.0.0.0:8765:8765. Open http://<host-ip>:8765/ and ensure
the host firewall permits the port. Prefer the loopback default plus SSH
forwarding when possible.
Remote hosts over SSH
The default bind address is loopback and is suitable for SSH forwarding:
ssh -L 8765:127.0.0.1:8765 user@remote-host
Then open http://127.0.0.1:8765/ locally. Publishing on a non-loopback host
address is rejected unless allow_public = true is also set. That opt-in
exposes an unauthenticated PDF endpoint; prefer an SSH tunnel.