Apps and packages
Optional modules
AI, developer, creative and console stacks, installed after the base and removable.
What it is
A module is one package that brings a whole stack: Claude Code with WolOS's approval gate, local models, developer tools, the creative suite, or a richer console. None is pre-ticked; each can be removed again.
Why
The base image stays small and installs offline. People who code or create get their tools in one approval, the way other systems ship their pro apps as installs rather than as part of everyone's system.
How
Tick modules in the installer, turn them on in Settings > Modules, or pick a Kit in the Store. From a terminal: wol modules list, wol modules install <id>.
Reference
ADR 0032. The base stays small; AI, developer, creative and console stacks are installed after it, never pre-ticked, each removable. A module is one meta package wolos-module-<id> (wolos-pkgbuilds) whose depends= names snapshot-pinned Arch and [wolos] packages, plus one registry record. Anything outside Arch (Claude Code, PowerShell) is installed user-side by the module's enable step through wopkg recipes or mise, so the sealed system stays sealed and no root is needed for it.
Registry (/usr/share/wolos/modules/<id>.json, wol_core::modules)
| Field | Meaning |
|---|---|
id | [a-z][a-z0-9-]{0,31}, equals the file stem and the package suffix |
name, summary, icon, category | shown by the installer, Settings > Modules and the Store Kits shelf; category ai, developer, creative or console |
size_mb | the installer's "Downloads N MB" badge |
packages | what the meta package depends on (documentation here; pacman decides) |
recipes, mise, flatpaks | user-side parts enable installs (wopkg install, mise use -g, flatpak install --user) |
post | argv run as the user by enable, idempotent; a script under /usr/lib/wolos/ |
offline | installable from the ISO without network |
needs | words for the UI: network, anthropic-account, ... |
Records this release ships: ai-claude, ai-local, ai-sessions, dev, creative, console (files/usr/share/wolos/modules/, wol_core::modules::IDS; crates/controller/tests/modules.rs checks them).
State
| Fact | Source |
|---|---|
| installed | pacman -Qq lists wolos-module-<id> |
| enabled | $XDG_STATE_HOME/wolos/modules.json = {"enabled": ["dev"]}, per user, written by enable, cleared by remove; malformed = nothing enabled |
| pending | /var/lib/wolos/modules-pending, one id per line: ticked in the installer but not installable offline; firstboot drains it like the NVIDIA driver |
Status::state() is one word: enabled (installed and the user step ran), installed (needs enable, or has no user step), pending, available.
CLI (crates/controller/src/modules.rs)
| Command | Access | Does |
|---|---|---|
wol modules, wol modules list [--json] | Read (read) | every record with its state; JSON = Vec<Status> |
wol modules status [id] [--json] | Read (read) | one module (packages, recipes, needs, download), or the list |
wol modules install <id> | Admin (modules) | wol-admind pkg-install wolos-module-<id> (the administrator password as for wol restore activate); then says wol modules enable <id> when the module has a user step |
wol modules remove <id> | Admin (modules) | wol-admind pkg-remove wolos-module-<id>, then wopkg remove each recipe and drops the enablement |
wol modules enable <id> | Change (apps) | as the user: recipes, mise tools, Flatpaks, then post; recorded only when every step passed; repeatable |
wol hw compute [--json] | Read (read) | {"backend": "cuda|rocm|vulkan|cpu", "vram_mb": n, "gpu": "name"} for the local-AI module |
Helpers (wol mcp, scripts) get list, status, enable and hw compute through the usual gate (docs/modules/automation.md). install and remove join catalog::HELPER_VERBS once shared::shell::ApprovalRequest has a Module variant the shell runs; until then only people run them. Tests: WOL_MODULES_DIR and WOL_MODULES_PENDING point the verbs at a fake registry and pending file.
GPU backend (controller::hw::pick_gpu)
The hardware catalogue already decides the driver; the backend follows it: nvidia modules (Turing and newer) = cuda (ollama-cuda), amdgpu on Vega or newer = rocm (ollama-rocm), amdgpu on GCN 1-4 (PCI device ranges in AMD_PRE_VEGA), i915, xe, nouveau, radeon = vulkan (ollama-vulkan), a virtual GPU or none = cpu. With several GPUs the discrete one wins (cuda > rocm > vulkan). VRAM: nvidia-smi --query-gpu=memory.total for NVIDIA, /sys/bus/pci/devices/<addr>/mem_info_vram_total for amdgpu, else 0. ai-local depends on ollama only; its post (/usr/lib/wolos/ai-local) installs the backend package this verb names.
Recipes (wopkg/recipes/, ADR 0021)
| Recipe | Source | Checks |
|---|---|---|
claude-code | Anthropic's native linux-x64 binary, stable channel, one pinned version | sha256 of binary, release manifest and its OpenPGP signature; the build step imports Anthropic's release key (fingerprint 31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE, pinned by sha256), verifies the manifest signature, matches the binary checksum against the manifest. Self-updates afterwards (vendor-signed, user-side): Software Update labels it "updates on its own" |
powershell | Microsoft's powershell-<v>-linux-x64.tar.gz (MIT) | sha256 from the release's hashes.sha256; unpacked to ~/.local/lib/powershell, ~/.local/bin/pwsh launcher |
Invariants
- No module on the ISO or pre-ticked; the base does not grow (ADR 0032).
- pacman is the truth for installed; the enablement file never claims a package.
enableruns as the user and never asks for the administrator password;install/removealways do.- A failed user step is not recorded as enabled; running
enableagain is safe (every step idempotent by contract). - Agents reach these verbs only through
wol mcp-> policy -> approval -> audit, like every other verb.
Reference synced from wonderlandos/wolos docs/modules/modules.md.