5.3 KiB
Phase 10.1: Add a real fruix system command for FreeBSD system artifacts
Date: 2026-04-02
Goal
Start Optional Phase 10 by replacing one of the remaining prototype-only workflows with a real user-facing Fruix command.
The concrete target for this subphase was:
- expose the declarative FreeBSD operating-system machinery through a true
fruixCLI entry point, - stop relying solely on ad hoc phase-specific harness scripts for closure/image materialization,
- and validate that the new command can build the existing declarative system outputs.
Result
A minimal user-facing fruix command now exists in this repository.
New entry points:
bin/fruixscripts/fruix.scm
Supported commands in this first cut:
fruix system build OS-FILEfruix system image OS-FILEfruix system rootfs OS-FILE ROOTFS-DIR
Supported options:
--system NAME--store DIR--disk-capacity SIZE--rootfs DIR--help
The command loads a declarative operating-system definition from a Scheme file, resolves the selected operating-system binding, and then calls the existing Fruix FreeBSD system materializers directly:
materialize-operating-systemmaterialize-rootfsmaterialize-bhyve-image
The command prints machine-readable key=value metadata for the produced artifacts.
Why this matters
Up through Phase 9, the project had already achieved a real booted Fruix guest, but the operator-facing path for producing those artifacts still lived mostly in phase-specific test harnesses such as:
tests/system/run-phase7-system-closure.shtests/system/run-phase8-system-image.shtests/system/run-phase9-xcpng-boot.sh
Those were valuable validation tools, but they were not yet a real Fruix interface.
This subphase moves the project one step closer to a genuine OS workflow by making system artifact generation available through a Fruix CLI surface.
Implementation details
bin/fruix
Added a shell wrapper that:
- locates the repository root,
- locates the Guile and Guile-extra validation prefixes already used elsewhere in the project,
- ensures the required local Guile/Fibers/Shepherd pieces exist,
- prepares
GUILE_LOAD_PATHfor:modules/~/repos/guix
- and runs the Guile entry point.
This keeps the new command aligned with the currently validated local FreeBSD Guile toolchain rather than inventing a separate runtime path.
scripts/fruix.scm
Added the actual CLI implementation.
It currently:
- parses
fruix system ...actions, - supports
--help, - loads an operating-system definition file,
- resolves the selected OS variable via
--system NAMEor a small fallback list of conventional names, - validates the operating-system object,
- dispatches to the existing FreeBSD system materializers,
- and emits stable
key=valuemetadata.
tests/system/run-phase10-fruix-system-command.sh
Added a dedicated validation harness for the new command.
The test verifies that:
fruix system buildmaterializes a closure under/frx/store- the returned closure contains the generated activation path
fruix system imagematerializes a disk image under/frx/store- the command emits the expected metadata fields for both operations
Validation
Successful validation run:
PASS phase10-fruix-system-command- workdir:
/tmp/phase10-fruix-cmd-1775117490
The new command successfully produced both:
- a Fruix system closure path under
/frx/store/*-fruix-system-fruix-freebsd - a Fruix image path under
/frx/store/*-fruix-bhyve-image-fruix-freebsd/disk.img
Example usage:
sudo env HOME="$HOME" ./bin/fruix system build \
tests/system/phase7-minimal-operating-system.scm \
--system phase7-operating-system
sudo env HOME="$HOME" ./bin/fruix system image \
tests/system/phase7-minimal-operating-system.scm \
--system phase7-operating-system \
--disk-capacity 5g
Current limitations
This is intentionally a first Phase 10 step, not the final Fruix command surface.
Notable current limitations:
- system/image materialization still expects the currently validated local Guile/Shepherd build prefixes
- writing into
/frx/storeand building disk images still typically requiressudo - the command currently targets only the FreeBSD system prototype path already implemented in
modules/fruix/system/freebsd.scm - it does not yet integrate with the larger upstream Guix command framework; it is a Fruix-native CLI wrapper in this repo
Assessment
This subphase successfully replaces an important transitional layer with a more OS-like Fruix interface.
The project can now say not only that it can declaratively define and boot a Fruix FreeBSD system, but also that it has a direct user-facing command for materializing the resulting system artifacts.
Recommended next step
Continue Phase 10 by reducing another transitional seam behind fruix system, most likely one of:
- add a
fruix system vm/ deploy-oriented flow on top of the now-working image path - replace the current compatibility symlink handling for locally built Guile/Shepherd prefixes with a more native store-path-aware runtime arrangement
- factor the phase-specific system test harnesses to call
bin/fruixdirectly where practical, so the command becomes the canonical operator path rather than just an additional wrapper