Keeps service clawdie as a deployed-system contract only, removes the old mini-binary FEATURE_CLAWDIE staging lane from the ISO build, and adds explicit Linux-vs-FreeBSD proof boundaries for provider/runtime claims.\n\nChecks: ./scripts/check-format.sh; git diff --check; sh -n over scripts/ firstboot/ live/operator-session/ executables
25 KiB
Firstboot — Modular Shell Pipeline
Audience: developers, operators, contributors maintaining the installed-system firstboot path.
Scope: this document describes the installed-system firstboot shell
pipeline in firstboot/. The current live operator USB graphical boot path
runs a separate pre-SDDM rc.d service (/usr/local/etc/rc.d/clawdie_live_gpu)
and does not exercise this pipeline. The shell-gpu.sh examples below describe
the installed-target firstboot/module flow.
This file consolidates and supersedes the earlier SHELL-ARCHITECTURE.md,
SHELL-MODULES.md, and firstboot/MODULE-MANIFEST.md.
Design Philosophy
Traditional installers do one of two things:
- Monolithic: single script that does everything — hard to test, debug, or reuse.
- Heavy framework: external runtime (Python, Perl, Ansible) with VM overhead and dependencies.
Clawdie Shell chooses a third path: modular POSIX-shell functions
organised by concern, sourceable independently, with no runtime dependencies
beyond /bin/sh.
Each module is:
- Standalone: can be sourced without others.
- Idempotent: safe to run twice — checks state first.
- Testable: functions have clear inputs/outputs and can be invoked in isolation.
- Debuggable:
clawdie_shell_gpu_detectcan be run from a shell to reproduce a step.
Why POSIX over Bash
| Aspect | POSIX /bin/sh |
Bash |
|---|---|---|
| Default on FreeBSD | yes | requires pkg install bash |
| First-boot availability | always | needs install first |
| Dependencies | none | libreadline, ncurses |
| Startup overhead | ~5 ms | ~50 ms |
All modules use POSIX shell only. No [[ ]], no ${var#pattern} outside POSIX-defined cases, no function keyword, no local (use _-prefixed plain variables instead), no set -o pipefail.
Why shell over Python or Node
| Aspect | Shell | Python | Node |
|---|---|---|---|
| Startup time | 5 ms | 100 ms | 300 ms |
| Footprint | one file | ~50 MB | ~100 MB |
| External deps | none | venv, pip | npm modules |
| First-boot overhead | negligible | 100+ ms | 300+ ms |
For a one-time installer, shell wins on speed and simplicity.
Architecture Overview
firstboot.sh
├─ Load GUI config (/tmp/clawdie-install.conf) or wizard input
├─ Source: shell-zfs.sh
├─ Source: shell-gpu.sh
├─ Source: shell-nvidia.sh
├─ Source: shell-pkg.sh
├─ Source: shell-ssh.sh
├─ Source: shell-env.sh
├─ Source: shell-system.sh
├─ Source: shell-desktop.sh
├─ Source: shell-pf.sh
├─ Source: shell-tailscale.sh
├─ Source: shell-npm-globals.sh
├─ Source: shell-deploy.sh
└─ Call functions in sequence:
├─ clawdie_shell_zfs_detect (baremetal only)
├─ clawdie_shell_gpu_detect
├─ clawdie_shell_nvidia_detect (only if GPU=nvidia)
├─ clawdie_shell_pkg_setup
├─ clawdie_shell_ssh_setup
├─ clawdie_shell_env_generate
├─ clawdie_shell_system_config
├─ clawdie_shell_desktop_detect
├─ clawdie_shell_pf
├─ clawdie_shell_tailscale_setup (optional)
├─ clawdie_shell_npm_globals_install
└─ clawdie_shell_deploy
Dependency Graph
[0.0 setup-import] (optional) → setup.txt + system.env import
↓
[0.1 zfs] (baremetal only) → CLAWDIE_BOOT_MODE
↓
[User Input]
↓
[1.1 env] → ASSISTANT_NAME, AGENT_DOMAIN, TZ, LLM_PROVIDER
↓
├→ [1.2 pkg] (optional: can run any time)
├→ [1.3 gpu] (optional: hardware detection)
├→ [1.3b nvidia] ← REQUIRES: DETECTED_GPU from [1.3]
├→ [1.3c ssh] ← REQUIRES: ASSISTANT_NAME from [1.1]
├→ [1.4 system] ← REQUIRES: TZ, AGENT_DOMAIN from [1.1]
├→ [1.4.1 pf] ← REQUIRES: ASSISTANT_NAME from [1.1]
├→ [1.4.2 desktop] ← PREFERS: GPU config from [1.3]
├→ [1.5 tailscale] (optional) ← PREFERS: repos from [1.2], pf from [1.4.1]
├→ [1.5.1 npm-globals] ← PREFERS: repos from [1.2]
└→ [1.6 deploy] ← REQUIRES: .env from [1.1], repos from [1.2]
← PREFERS: gpu config from [1.3]
Hard dependencies
- 1.1 must complete before 1.6 — deploy sources
.env. - 1.3 must complete before 1.3b — nvidia module checks
DETECTED_GPU. - 1.4 should run before 1.4.2 and 1.4.1 — system config writes rc.conf that affects desktop + PF.
- 1.4.1 should run before 1.5 — Tailscale updates PF rules.
Module Reference
0.0 — setup-import.sh
Read setup.txt and system.env from the writable USB config partition
before the wizard, for unattended installs.
Wizard inputs: none.
Outputs (exports): ASSISTANT_NAME, HOSTNAME, AGENT_DOMAIN, TZ,
optional pre-baked provider/channel values, ZFS_POOL, ZFS_LAYOUT,
ZFS_DATA_DISKS, ZFS_HOT_SPARES, ZFS_PREFIX, hardware hints.
Checkpoint: setup-import.
Skip: no CLAWDIE FAT32 partition, or setup.txt missing, or values
incomplete for non-interactive path.
Error handling: safe-fail back to wizard; never blocks an interactive
install on a missing partition.
0.1 — shell-zfs.sh
Detect existing ZFS pools and select boot mode.
Main function: clawdie_shell_zfs_detect().
Wizard inputs: none — automatic detection.
Outputs (exports):
CLAWDIE_BOOT_MODE—install|upgrade|maintenance.POOL_NAME— detected pool name when present.
Checkpoint: [ZFS].
Skip: TARGET=vps (ZFS not used).
Error handling: safe-fail to install if no pools found. If maintenance
mode selected, execs maintenance-mode.sh and exits.
1.1 — shell-env.sh
Generate a minimal .env seed (identity + feature flags).
Main function: clawdie_shell_env_generate().
Wizard inputs (Tier 1, required):
ASSISTANT_NAME— human name (e.g., "Clawdie Smith").AGENT_DOMAIN— public or local domain zone (default:${agentname}.home.arpa).TZ— timezone (e.g.,Europe/Ljubljana).
Wizard inputs (Tier 2, optional): provider/model values, provider API keys,
Telegram credentials — normally configured after first boot in /setup.
Outputs:
$ENV_FILE—/home/clawdie/.env(mode 0600), identity + feature flags.- Copied into
/home/clawdie/clawdie-ai/.envby shell-deploy (1.6). - Completed by Clawdie-AI onboarding (secrets + derived defaults).
Exports for downstream: AGENT_NAME (derived from ASSISTANT_NAME),
DETECTED_ABI (optional, from pkg config abi).
Functions:
clawdie_shell_env_generate # Main entry point
clawdie_shell_env_gen_secret # openssl rand -base64 32 (with /dev/urandom fallback)
clawdie_shell_env_derive_names # ASSISTANT_NAME → AGENT_NAME
clawdie_shell_env_derive_ips # Allocate jail IPs from AGENT_SUBNET_BASE
clawdie_shell_env_validate # Verify .env has required vars
Jail IP allocation (from AGENT_SUBNET_BASE, default 10.0.0):
| Slot | Service | Default IP |
|---|---|---|
| .1 | Gateway (host bridge) | 10.0.0.1 |
| .2 | Management jail | 10.0.0.2 |
| .3 | Database (PostgreSQL) | 10.0.0.3 |
| .4 | Code service (git mirror) | 10.0.0.4 |
| .5 | Web service (nginx) | 10.0.0.5 |
| .101+ | Worker jails (dynamic) | 10.0.0.101+ |
Checkpoint: [ENV].
Skip: .env exists AND contains AGENT_DOMAIN.
Error handling: fails if ASSISTANT_NAME, AGENT_DOMAIN, or TZ missing.
Validates .env has minimal required vars before marking complete.
Recovery: clawdie-firstboot --resume skips if [ENV] COMPLETE in progress
file. Re-runnable (idempotent via sysrc pattern).
1.2 — shell-pkg.sh
Configure FreeBSD package repositories (online + offline USB) and seed Bastille jail cache.
Main function: clawdie_shell_pkg_setup().
Wizard inputs: none — automatic from [1.1].
Inputs from [1.1]: DETECTED_ABI (optional, auto-detected if missing).
Outputs:
/etc/pkg/repos/FreeBSD.conf— online fallback, priority 10.- URL:
pkg+https://pkg.FreeBSD.org/${ABI}/latest.
- URL:
/etc/pkg/repos/Clawdie-USB.conf— offline USB repo, priority 100 (preferred).- URL:
file:///mnt/media/packages.
- URL:
/var/cache/pkg/bastille/— seeded with .pkg files from USB for offline jail provisioning.
Functions:
clawdie_shell_pkg_setup
clawdie_shell_pkg_detect_abi # pkg config abi or derive from uname
clawdie_shell_pkg_write_freebsd_conf # writes FreeBSD.conf
clawdie_shell_pkg_write_clawdie_conf # writes Clawdie-USB.conf
clawdie_shell_pkg_seed_cache # copies USB pkgs to bastille cache
Checkpoint: [PKG].
Skip: if both FreeBSD.conf AND Clawdie-USB.conf exist.
Error handling: safe-fail — missing USB packages → continues online only;
pkg update may fail in chroot (expected, logged). Cache seeding errors are non-fatal.
Recovery: re-runnable to refresh cache or update repo configs.
1.3 — shell-gpu.sh
Detect GPU hardware and select driver kernel module.
Scope: installed-target firstboot path. The live USB boot path uses
clawdie_live_gpu (an rc.d service) instead.
Main function: clawdie_shell_gpu_detect().
Wizard inputs: none.
Hardware detection (via pciconf -lv, class 0x030000):
| Vendor | Module(s) | Note |
|---|---|---|
| Intel | i915kms |
Intel integrated (iGPU) |
| AMD | amdgpu (or radeon on older HW) |
Radeon / RDNA |
| NVIDIA | nvidia-modeset nvidia |
branch chosen by shell-nvidia.sh |
| VMware | vmwgfx |
VMware SVGA 3D |
| (unknown) | (empty) | VESA software fallback |
Outputs:
/etc/rc.conf—kld_list="..."(idempotent; replaces existing line).
Exports for downstream: DETECTED_GPU — intel | amd | nvidia | vmware | vesa. Used by [1.3b] to decide run or skip.
Functions:
clawdie_shell_gpu_detect
clawdie_shell_gpu_detect_pci # pciconf -lv → vendor:device
clawdie_shell_gpu_match_driver # vendor → kld list
clawdie_shell_gpu_write_rcconf # rc.conf kld_list
clawdie_shell_gpu_load_live # optional kldload (may fail in chroot)
clawdie_shell_gpu_validate
Checkpoint: [GPU].
Skip: kld_list= already in rc.conf.
Error handling: pciconf may fail outside chroot (expected). Falls back
silently to vesa if detection fails. kldload live fails gracefully in chroot.
Recovery: re-runnable. Must run before [1.4 system] (which reads rc.conf)
and is required before [1.3b nvidia].
1.3b — shell-nvidia.sh
NVIDIA driver version selection (PC-BSD heritage).
Main function: clawdie_shell_nvidia_detect().
Skip if: DETECTED_GPU != "nvidia".
Wizard inputs (Tier 2, optional):
NVIDIA_DRIVER_VERSION—590|470|390(env var for unattended), or interactivebsddialogmenu.
Device ranges → driver:
| Range | Era | Driver |
|---|---|---|
| ≥0x2700 | Ada (RTX 40xx) | 590 |
| 0x2060–0x2500 | Turing/Ampere (RTX 20xx/30xx) | 590 |
| 0x1340–0x2186 | Maxwell (GTX 750–980 Ti) | 470 |
| 0x1180–0x139F | Kepler (GTX 650–780 Ti) | 390 |
| (unknown) | — | 590 (safe default) |
Outputs:
/etc/rc.conf—nvidia_driver_version="590"(or"470"/"390"), idempotent./var/run/nvidia_driver_version.txt— optional marker file (safe-fail).
Exports: NVIDIA_DRIVER_VERSION, used during package selection in [1.6].
Checkpoint: [NVIDIA].
Error handling: invalid version → warning + default 590. bsddialog
unavailable → silent default. /var/run write failure → non-fatal.
1.3c — shell-ssh.sh
Configure SSH access and system passwords.
Main function: clawdie_shell_ssh_setup().
Wizard inputs (Tier 1, required):
ASSISTANT_NAME— used for default user naming.ASSISTANT_PASSWORD— operator password.ROOT_PASSWORD— root password (optional if disabled).
Outputs:
/etc/master.passwdupdates viapw./home/clawdie/.ssh/authorized_keysif SSH key provided./etc/ssh/sshd_config— hardened defaults.
Checkpoint: [SSH].
Error handling: password prompts must succeed; missing SSH key is
non-fatal (password login allowed).
1.4 — shell-system.sh
System configuration (hostname, timezone, rc.conf, services).
Main function: clawdie_shell_system_config().
Inputs (from [1.1]):
TZ,AGENT_DOMAIN.
Outputs:
/etc/rc.conf—timezone,dbus_enable=YES,display_manager=sddm,sddm_enable=YES,linux_enable,zfs_enable,kld_list(idempotent via sysrc)./etc/hostname— single line:home.arpa(orAGENT_DOMAIN)./etc/profile.d/clawdie.sh— npmPATH,npm_config_prefix.
Functions:
clawdie_shell_system_config # orchestrator
clawdie_shell_system_write_rcconf
clawdie_shell_system_set_hostname
clawdie_shell_system_setup_env
clawdie_shell_system_enable_services
Checkpoint: [SYSTEM].
Skip: timezone= AND dbus_enable= already in rc.conf.
Error handling: hostname may fail in chroot (safe-fail). service
onestart fails gracefully in chroot (expected).
1.4.2 — shell-desktop.sh
Detect display hardware and enable the desktop stack when appropriate.
Main function: clawdie_shell_desktop_detect().
Inputs from [1.3]: DETECTED_GPU (used to decide which desktop bits to enable).
Outputs:
/etc/rc.conf— desktop service flags (e.g.,sddm_enable=YESwhen display detected;sddm_enable=NOfor headless VPS/cloud).
Checkpoint: [DESKTOP].
Skip: headless/VPS scenario detected, or desktop already enabled.
Error handling: detection failures fall back to headless mode.
1.4.1 — shell-pf.sh
Configure PF firewall with block-all default, SSH protection, jail NAT, glasspane VNC.
Main function: clawdie_shell_pf().
Wizard inputs: none.
Inputs from [1.1]: ASSISTANT_NAME; AGENT_NET (optional, default 192.168.100.0/24).
Outputs:
/etc/pf.conf:- block-all default
- SSH brute-force protection (
max-src-conn-rate 3/60) - NAT for agent jails (
192.168.0.0/16supernet) - HTTP/HTTPS pass rules
- commented Tailscale + glasspane VNC block (agent uncomments later)
/etc/rc.confappends:cloned_interfaces="bridge0"ifconfig_bridge0_name="warden0"ifconfig_${BRIDGE}="inet 192.168.100.1/24 up"gateway_enable="YES"pf_enable="YES"pf_reload_enable="YES"
/usr/local/etc/rc.d/pf_reload:REQUIRE: tailscaled- Fixes PF/Tailscale cold-boot race (resolves
tailscale0interface index).
Glasspane VNC: port 5900 (wayvnc → cage → browser), blocked on
ext_if, passed on tailscale0. Uncommented by agent when Tailscale enabled.
Checkpoint: [PF].
Skip: pf_enable="YES" already in rc.conf.
Error handling: fails if external interface cannot be detected (no
default route). Bridge creation and PF load may fail in chroot (expected,
non-fatal; loads on reboot).
Recovery: pf_reload pre-installed even without Tailscale — harmless
now, essential later. Must run before [1.5 tailscale].
1.5 — shell-tailscale.sh
Optional Tailscale enablement for secure remote access.
Main function: clawdie_shell_tailscale_setup().
Wizard inputs (Tier 2): FEATURE_TAILSCALE — YES/NO (default NO).
Outputs:
/etc/rc.conf—tailscaled_enable="YES".- Tailscale left unauthenticated; operator runs
tailscale upfrom the running system.
Checkpoint: [TAILSCALE].
Skip: FEATURE_TAILSCALE != YES.
Error handling: safe-fail — network or daemon issues are logged and do
not abort install. pkg install tailscale failure → warning + continue.
Recovery: service tailscaled start && tailscale up.
1.5.1 — shell-npm-globals.sh
Install bundled npm CLI tools (claude, gemini, pi) from ISO cache.
Main function: clawdie_shell_npm_globals_install().
Inputs preferred: offline repo cache from [1.2] (fully offline install).
Outputs:
/opt/clawdie/npm-global/bin/*— bundled CLI binaries./etc/profile.d/clawdie.sh—PATHupdate if missing.
Checkpoint: [NPM-GLOBALS].
Skip: npm globals already installed in /opt/clawdie/npm-global.
Error handling: missing cache → warning + skip (non-fatal).
1.6 — shell-deploy.sh
Extract Clawdie-AI (offline tarball incl. node_modules), run installer, start services.
Main function: clawdie_shell_deploy().
Hard inputs from [1.1]: .env at $ENV_FILE — sourced for
ASSISTANT_NAME, AGENT_DOMAIN, jail IPs, DB config. Missing .env →
hard exit.
Preferred (not required) inputs:
[1.2]— repos + pkg cache (speeds offline provisioning).[1.3]/[1.3b]—kld_list,nvidia_driver_version(used for jail pkg selection).
Outputs:
/home/clawdie/clawdie-ai/— extracted from/usr/local/share/clawdie-iso/clawdie-ai.tar.gz./home/clawdie/clawdie-ai/.env— seeded from[1.1].node_modules/bundled into the ISO tarball at build time.- Bastille jails created: worker, db, cms (optional mgmt).
just installruns as theclawdieuser.- PostgreSQL seeded in db jail; nginx configured in cms jail;
rc.dclawdieservice installed and enabled.
Functions:
clawdie_shell_deploy
clawdie_shell_deploy_extract_tarball # tar xzf → /home/clawdie, chown
clawdie_shell_deploy_run_install_all # just install
clawdie_shell_deploy_verify # jails up, service present, .env ok
Checkpoint: [DEPLOY].
Skip: package.json AND node_modules/ present → skip extraction; always run just install.
Error handling: missing .env → hard exit. Missing tarball → assume
already extracted (warning). Missing node_modules → fall back to npm ci
(needs network), fails hard if deps cannot install. Jail creation failures →
warning + continue. DB connectivity → deferred to runtime.
Recovery: idempotent re-run; failures block full system setup.
Execution Order
User input (wizard Tier 1 + optional Tier 2)
↓
1. zfs CONDITIONAL — baremetal only, sets boot mode
2. gpu RECOMMENDED — hardware detection
3. nvidia CONDITIONAL — only if GPU=nvidia
4. pkg OPTIONAL — early for offline support
5. ssh REQUIRED — user + password provisioning
6. env REQUIRED — creates .env with identity
7. system REQUIRED — system-level rc.conf
8. desktop CONDITIONAL — display detection + enablement
9. pf REQUIRED — firewall + jail NAT
10. tailscale OPTIONAL — remote access, modifies PF rules
11. npm-globals OPTIONAL — offline npm CLIs
12. deploy REQUIRED — depends on .env from env
↓
SUCCESS: Clawdie-AI ready for first boot
Error Handling and Recovery
Module pattern
#!/bin/sh
set -eu # exit on error and undefined vars (POSIX)
trap 'echo "ERROR in clawdie_shell_FUNCTION at line $LINENO" >&2; exit 1' ERR
clawdie_shell_FUNCTION() {
_status_file="/var/log/clawdie-firstboot.progress"
echo "[MODULE] FUNCTION_START" >> "$_status_file"
# validate inputs
if [ -z "${VAR:-}" ]; then
log_msg "ERROR: VAR not set"
return 1
fi
# do work
if ! some_command; then
log_msg "ERROR: some_command failed"
return 1
fi
echo "[MODULE] FUNCTION_COMPLETE" >> "$_status_file"
return 0
}
Logging
All errors land in /var/log/clawdie-firstboot.log:
[2026-03-23 15:34:12] [pkg] Starting package setup
[2026-03-23 15:34:15] [pkg] Detected ABI: FreeBSD:15:amd64
[2026-03-23 15:34:18] [pkg] ERROR at line 42: repo config failed
[2026-03-23 15:34:18] ERROR in clawdie_shell_pkg_setup at line 42
Operator can tail -100 /var/log/clawdie-firstboot.log, SSH in to debug, or
clawdie-firstboot --resume to skip completed checkpoints.
Resume
--resume parses the progress file and skips modules that logged
[MODULE] COMPLETE. Skip logic (pseudo-code):
grep -q "\[ENV\] COMPLETE" "$PROGRESS_FILE" && skip_env=1
grep -q "\[PKG\] COMPLETE" "$PROGRESS_FILE" && skip_pkg=1
grep -q "\[GPU\] COMPLETE" "$PROGRESS_FILE" && skip_gpu=1
grep -q "\[NVIDIA\] COMPLETE" "$PROGRESS_FILE" || [ "$DETECTED_GPU" != nvidia ] && skip_nvidia=1
# ...
Failure classes
- Soft failure (warning): module logs and continues. Examples: GPU
live-load fails,
pkg updatefails. Action on resume: re-run module (idempotent). - Hard failure (
exit 1): module exits shell. Examples:.envmissing in 1.6,AGENT_DOMAINnot set. Action on resume: fix input, re-run from start.
Testing
Each module is sourceable and runnable standalone:
# GPU detection
export RC_CONF=/tmp/test-rc.conf
. firstboot/shell-gpu.sh
clawdie_shell_gpu_detect
cat /tmp/test-rc.conf # should have kld_list
# Env generation
export ASSISTANT_NAME="Test"
export AGENT_DOMAIN=test.local
export TZ=UTC
export CLAWDIE_HOME=/tmp/test-clawdie
. firstboot/shell-env.sh
clawdie_shell_env_generate
cat /tmp/test-clawdie/.env # should have ~45 lines incl. JWT_SECRET
# Pkg setup
export PKG_CONF_DIR=/tmp/test-repos
export USB_PKG_PATH=/tmp/fake-usb/packages
mkdir -p "$USB_PKG_PATH" && touch "$USB_PKG_PATH/test.pkg"
. firstboot/shell-pkg.sh
clawdie_shell_pkg_setup
cat /tmp/test-repos/FreeBSD.conf
cat /tmp/test-repos/Clawdie-USB.conf
After install, the same modules can be re-sourced from
/usr/local/share/clawdie-iso/firstboot/ to troubleshoot or rerun a phase
without full reinstall.
Verifying module output
# After env module
grep ASSISTANT_NAME /home/clawdie/clawdie-ai/.env
# After pkg module
cat /etc/pkg/repos/Clawdie-USB.conf
# After gpu module
sysctl hw.pci.dump | grep -i vga
grep kld_list /etc/rc.conf
# After deploy module
jls -N # list jails
# service clawdie status # future deployed-system service acceptance
Adding a New Module
To add a new setup phase (e.g., shell-ollama.sh for local AI):
- Create
firstboot/shell-ollama.shwith aclawdie_shell_ollama_setup()function and the standard error/log/progress scaffolding. - Add a corresponding entry to this manifest: purpose, inputs, outputs, checkpoint, skip condition, error handling, recovery.
- Source and call it from
firstboot.shin the appropriate slot:. /usr/local/share/clawdie-iso/firstboot/shell-ollama.sh clawdie_shell_ollama_setup - Add a checkpoint to the resume table.
No framework changes needed.
POSIX Compliance — Rules
# Required
set -eu # POSIX: exit on error + undefined vars
trap '...' ERR # POSIX: error trap
# Forbidden (bash-only)
set -o pipefail # bash-only
[[ -f foo ]] # bash-only; use [ -f foo ]
function name { ... } # bash-only; use name() { ... }
local var=... # bash-only; use plain _var (prefixed)
FreeBSD vs Linux idioms
| Wrong (Linux) | Right (FreeBSD) |
|---|---|
systemctl start service |
service clawdie start |
apt-get install package |
pkg install package |
/dev/sda1 |
/dev/da0s1 |
Version History
- current dev ISO: live XFCE operator USB via SDDM, interactive login, 12 shell modules, ZFS/desktop/npm-globals.
- v0.9.0: 8 modules, runtime GPU detection, no ZFS/desktop/npm-globals.
- v0.5.0: 6 modules, PF firewall, glasspane VNC support.
- v1.1 (planned): add
shell-gpu-passthrough.sh,shell-upgrade.sh.
References
firstboot/firstboot.sh— orchestrator (sources all modules and runs the sequence).TESTING.md— bhyve + hardware validation procedures.BUILD.md— build flags and cache behaviour.- POSIX Shell Reference
- FreeBSD rc.d Services
- Bastille Jails Documentation