2. Adoption of Nixvim Architectural Patterns and Composability
Date: 2026-08-26
Status
Accepted
Context
As nixpi evolved into a declarative framework for configuring the Pi coding agent, it became necessary to benchmark its architecture against mature, large-scale Nix configuration frameworks. Neovim’s premier Nix framework, nixvim (with 450+ plugins, multi-platform integrations, and high composability), offers battle-tested design patterns for configuration management, module scaling, package distribution, and testing.
Key architectural gaps in early nixpi versions included:
- Lack of package composition: Evaluating a Pi package via
makePireturned an opaque derivation. Users could not easily inspect the evaluatedconfig/optionsor extend an already-configured instance (pkg.extend { ... }). - Boilerplate in module definitions: Extensions and skills required repetitive option definitions (
enable,package,settings,runtimePackages). - Platform wrapper fragmentation: Only Home Manager was integrated, with no native NixOS or nix-darwin system module wrappers.
- Flake output rigidity: Flake exports were tied to specific naming conventions without standardized aliases or unified builder endpoints.
Decision
We adopt the following architectural patterns from Nixvim into nixpi:
1. Package Distribution Strategy
- Nixpi separates declarative module abstractions from package definitions.
- Modules accept a
packageoption defaulting to either the internal package or an upstream package, allowing users to override the underlying derivation cleanly. - Direct escape hatches (
programs.pi.extraPackages,programs.pi.extraExtensions,programs.pi.extraSkills) allow injecting arbitrary derivations without needing dedicated modules.
2. Standalone Package Composability (passthru.extend)
makePinow wraps the resulting derivation withpassthru = { config, options, extend, unwrapped }.- Calling
pkg.extend { programs.pi.skills.commitStyle.enable = true; }evaluates a new Pi package by appending the additional modules to the base configuration, mirroring Nixvim’smakeNixvimcomposability.
3. Standardized Module Factories (lib.mkPiExtensionModule & lib.mkPiSkillModule)
- Introduce helper generators in
lib/module-factories.nixthat generate standardized module schemas:programs.pi.extensions.<name>.enableprograms.pi.extensions.<name>.packageprograms.pi.extensions.<name>.settingsprograms.pi.extensions.<name>.runtimePackages
- Reduces code duplication across extension and skill definitions by ~70%.
4. Multi-Platform Module Unification (integrations/)
- Establish a shared evaluation engine (
integrations/shared.nix) providing consistent options across:- Standalone:
lib.makePi/legacyPackages.${system}.makePiWithModule - Home Manager:
homeModules.default(withhomeManagerModulespreserved as a backwards-compatible alias) - NixOS:
nixosModules.defaultandnixosModules.pi - Nix-Darwin:
nixDarwinModules.defaultandnixDarwinModules.pi
- Standalone:
5. Strict Backwards Compatibility & Graceful Deprecations
- All existing flake outputs (
piModules,homeManagerModules,packages.*,lib.*) remain 100% functional. - Any naming modernizations (e.g.
homeModulesoverhomeManagerModules) provide transparent compatibility layers and non-breaking warnings.
Consequences
- Pre-configured Pi environments can be dynamically extended in devshells and downstream flakes using
.extend { ... }. - System-level configuration is now supported natively across Linux (NixOS) and macOS (nix-darwin).
- Authoring new extensions and skills requires significantly less boilerplate.
- Existing user configurations and test suites continue to work without any breaking changes.