Not stable yet. WolOS is in active development and the current ISO is a test build: try it in a virtual machine or on a spare disk, not on a computer you depend on.

WolOS
Manual contents

Decisions

0032: Optional modules

AI, developer, creative and console stacks as removable modules and Kits.

Status: proposed (main, 2026-11-01, at the lead's request). Builds on 0016 (snapshot), 0021 (wopkg), 0023 (install plan), 0024 (first-use check), 0029 (repository split), 0013 (first run) and 0031 (shell plugins).

Context

WolOS ships one desktop for everyone and installs drivers online at first boot. People who code or create want Claude Code and other agents, local models, toolchains, editors, Blender-class apps and a serious console, the way macOS ships Xcode or Final Cut as installs, not as the base. Omarchy sets the UX bar (one menu, lazy mise installs, an agents panel, everything themed) but runs agents auto-approving and plugins unsandboxed. WolOS already has what Omarchy lacks: every agent action can pass wol mcp -> helper policy -> on-screen approval -> audit (crates/controller/src/mcp.rs, approve.rs, crates/core/src/automation/). The base must stay small and offline-installable; modules must never be mandatory and must stay pinned to the release.

Decision

  • A module is one meta package wolos-module-<id> in wolos-pkgbuilds (depends= on snapshot-pinned Arch and [wolos] packages, plus /usr/share/wolos/modules/<id>.json and config drop-ins), listed in packages. Anything outside Arch or [wolos] (Claude Code, PowerShell, Craft launcher, DaVinci) is never a pacman dependency: the module's enable step installs it as the user through wopkg (recipe or AppImage, ADR 0021) or mise, so the sealed system stays sealed and no root is needed.
  • Registry /usr/share/wolos/modules/<id>.json: {id, name, summary, icon, category, size_mb, packages, flatpaks, recipes, mise, post, offline, needs} read by wol_core::modules. Verbs: wol modules list|status (Read), wol modules install|remove (Admin, new capability modules), wol modules enable (Change, apps). pacman is the truth for packages; $XDG_STATE_HOME/wolos/modules.json holds per-user enablement.
  • Three doors, one registry: (a) installer Step::Modules between Account and Summary (checkboxes, none pre-ticked, a "Downloads N MB" badge, Plan.modules); install-run installs ticked modules in its existing online step and queues the rest in /var/lib/wolos/modules-pending, which firstboot drains like the NVIDIA driver; (b) Settings > Modules (toggle rows, same verbs); (c) App Store > Kits shelf, where a kit tile installs a set of apps or a module in one approval (the "Adobe kit" idea: the Kits concept is new).
  • Agents act through WolOS policy. wolos-module-ai-claude ships /etc/claude-code/managed-settings.json allowing the wol mcp server (not exclusive, so people keep their own servers), and its enable step runs claude mcp add --scope user wolos -- wol mcp per user. Agents change WolOS only through approve::decide; every action appears in Settings > Assistants & Automation. The gate itself does not change.
  • Productive by default, jailed by default (lead, 2026-11-01: "AI needs to be productive; the system needs to disappear; not too limiting, also for lazy people"). The WolOS agent runs in a workspace jail that needs no configuration: a per-project directory tree (default ~/Work/<project>), its own $XDG_* dirs, network allowed, no access to the rest of $HOME, implemented with Landlock + seccomp + a mount namespace by wol jail run (the technical model is github.com/akitaonrails/ai-jail, whose UX we do not copy). Inside the jail the agent does not ask: file edits, builds, tests, reports and MCP calls to other servers are approved by the jail itself. One approval sheet appears only when the agent reaches outside: another directory (the sheet offers "add this folder to the project"), a system change through wol (the existing gate), or a credential. Settings shows one switch, "Ask before every action", off by default. kleedolinux/claude-infinite (the lead's Claude memory tool) ships as part of ai-claude and is pre-wired so memory survives sessions.
  • Proprietary formats one click away, never default: a codecs entry in the module registry (ffmpeg full, gst-plugins-ugly/bad, libdvdcss, Microsoft fonts) offered by the Store and by the "can't play this file" sheet of the media apps; not on the ISO, not pre-ticked in the installer.
  • Agent-generated extensions stay in the existing sandboxes: Lua widgets and ADR 0031 plugins. The ai-claude module ships a skill (/usr/share/wolos/agents/skills/wolos/SKILL.md, linked into ~/.claude/skills and ~/.agents/skills) documenting the wol verb tree, the plugin manifest and wol plugin check, so an agent can author and self-check a plugin without root. Installing a plugin stays a Change capability with an approval sheet.
  • Pinning. pacman dependencies are pinned by the snapshot. mise ships /etc/mise/config.toml (global-only: lockfile=true, disable_backends=["asdf"], paranoid=["plugins","provenance"], no trusted project paths, python shims excluded) and a per-release mise.lock; its registry is pinned by the mise package version (registry_floating=false). Two vendor self-updaters are the deliberate exceptions, both user-side and vendor-signed, both labelled "updates on its own" in Software Update: Claude Code (stable channel, release manifest signature checked by the recipe) and the Craft launcher.
  • Security coexistence (ADR 0024, xguard): mise, Claude and wopkg write under /home, which xguard scans on first exec. The dev module adds a mise postinstall hook that runs wol-xguard scan on the install directory and tags files like a browser download. Interpreters stay the known gap and the copy says so. Models are data and are not scanned.
  • GPU for local AI reuses the hardware catalog: wol hw compute --json returns {backend: cuda|rocm|vulkan|cpu, vram_mb, gpu}; wolos-module-ai-local depends on ollama (CPU) and installs the matching backend package (ollama-cuda for NVIDIA Turing+, ollama-rocm for AMD gfx9+, ollama-vulkan otherwise). Settings shows the backend badge and a model picker sized by VRAM.
  • Sessions mean re-openable work: {workspace, cwd, kind: terminal|agent, command, title} saved by wol-shell at logout to $XDG_STATE_HOME/wolos/sessions.json; at login the shell offers "Reopen windows from last time?" and relaunches each terminal (foot -D <cwd>, zellij attach) and agent (claude --continue) in its workspace. Multiplexing inside a boot is zellij, themed by wol theme. No process survives a reboot; layout, place and the conversation pointer do.
  • Console: zsh stays the default login shell. One prompt engine, starship, themed from the tokens (toolkits/starship/palette.toml written by wol theme), with the pure-zsh prompt kept as fallback. fzf history (Ctrl+R), zoxide, eza, bat, fd, ripgrep wired behind command -v. fish, nushell, bash and PowerShell (wopkg recipe from Microsoft's tarball; no Arch package) get the same keys, colours and history size from the same tokens. Settings > Modules > Console chooses the default shell and terminal (foot default; ghostty, kitty optional).
  • Developer: mise for every runtime (never pacman), git, gh, docker or podman as a choice (docker group opt-in), Code-OSS or Zed themed by wol theme, lazygit and btop as floating TUI apps, ~/Work.
  • Creative: the Arch creative set (Blender, GIMP, Krita, Inkscape, OBS, darktable, Kdenlive, Ardour, Audacity), fonts, colord with per-display ICC, a switchable low-latency PipeWire profile (wol audio profile low-latency, Control Center toggle), DaVinci Resolve as a user-side wopkg recipe on NVIDIA/AMD only.
  • gpu-unlock is kernel work, not a module (lead's call): Zagitta/gpu-unlock (GPL-2.0, out-of-tree, lifts NVIDIA GeForce tensor-core FP16/BF16/TF32 half-rate caps before the stock driver binds; Ampere stable, Ada/Turing experimental) is carried in-tree on wonderlandos/linux wolos-7.3 as drivers/gpu/wolos_gpu_unlock/, CONFIG_WOLOS_GPU_UNLOCK=m, off by default. The NVIDIA firmware it depends on is never redistributed: wol hw boot --online fetches it into /usr/lib/firmware/wolos/gpu-unlock/ and the module loads it with request_firmware(). Built in-tree it is signed like every module (ADR 0025). Settings > Hardware gets an experimental toggle writing /etc/modprobe.d/wolos-gpu-unlock.conf. It is a driver, recorded in SERIES.md as such, exempt from the "under 100 lines" patch rule.
  • Craft Suite (storytold) is a Store kit, not a module: the craft-launcher AppImage (Apache-2.0/MIT, alpha, self-updating) installed user-side through wopkg with a pinned key, xguard-scanned; the launcher installs the Craft apps under the user. Not on the ISO.

Consequences

the base ISO does not grow. Every module is removable with pacman -R wolos-module-<id> plus wol modules remove for user-side parts. Each module gets a contract test in wolos-pkgbuilds/checks (dependencies exist at the snapshot) and a VM check in wolos-iso/tests. Rejected: everything on the ISO (3 to 6 GB more, not optional); Flatpak for everything (no CLI tools, no GPU compute, no mise); exclusive managed-mcp.json (blocks people's own servers); asdf plugins in mise (arbitrary shell); gpu-unlock as unsigned DKMS from AUR. Open for the lead: starship for all shells vs hand-written prompts; whether the two self-updaters are acceptable; the maintenance cost of carrying gpu-unlock in-tree against a small upstream.

Reference synced from wonderlandos/wolos docs/adr/0032-optional-modules.md.