6.2 KiB
Clawdie ISO Builder
On xfce-operator-usb, builds a bootable FreeBSD 15.0 operator USB image with:
- XFCE desktop
- pre-LightDM live GPU detection
- Chromium browser
- Tailscale
- NetworkMgr launched via
mdo, notsudo - bundled npm globals (
pi,claude,gemini) - offline package repository
- bundled Clawdie-AI tarball for later phases
The ISO version is independent from the bundled Clawdie-AI ref:
ISO_VERSION="0.1.0"
BUILD_CHANNEL="dev" # dev | release
CLAWDIE_REF="main" # validation default
Release builds must pin a Clawdie-AI tag with --clawdie-version X.Y.Z.
Prerequisites
On the FreeBSD build host:
sudo pkg install -y curl node24 npm-node24 sudo
Also required:
- FreeBSD 15.0+
- 150 GB free build space recommended
- root or
sudofor image assembly - 32 GB USB key minimum for the default
IMAGE_SIZE=28G
Tailscale is packaged for live operator access. Authentication is expected later
from the running USB with mdo -u root tailscale up, after operator credentials
and other keys are available.
Quick Start
# Confirm you are building the intended branch/head first.
git status --short --branch
git log --oneline -5
# Full build: fetch + assemble.
sudo ./build.sh
Output:
tmp/output/clawdie-xfce-quindecim-usb-DD.MM.YY-abcdef0.img
Published/downloaded artifacts are compressed as .img.gz. Stream the
compressed image directly into dd:
gzip -dc clawdie-xfce-quindecim-usb-DD.MM.YY-abcdef0.img.gz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
sync
For Linux or FreeBSD downloads from the published HTTPS path, prefer resumable
curl with retries before flashing:
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-xfce-quindecim-usb-DD.MM.YY-abcdef0.img.gz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-xfce-quindecim-usb-DD.MM.YY-abcdef0.img.gz.sha256
For a build-local uncompressed image, plain dd is also fine:
sudo dd if=tmp/output/clawdie-xfce-quindecim-usb-DD.MM.YY-abcdef0.img of=/dev/daX bs=1M status=progress conv=fsync
sync
Use the whole USB device (/dev/daX), not a partition. See FLASHING.md
for Linux commands, checksum verification, and stale-label cleanup.
Useful Build Modes
# Download/cache FreeBSD, packages, npm globals, and Clawdie-AI only.
./build.sh --fetch-only
# Assemble using cached inputs.
sudo ./build.sh --skip-fetch
# Fetch packages but reuse the cached FreeBSD memstick image.
sudo ./build.sh --skip-memstick-fetch
# Dev/test image: set live user clawdie password to quindecim.
sudo ./build.sh --live-default-password
# Bundle a specific branch/tag/commit ref.
sudo ./build.sh --clawdie-ref main
sudo ./build.sh --clawdie-ref f04f35eb4e16b50150ae73bad2e271388dc88f82
# Release build from a pinned Clawdie-AI tag.
BUILD_CHANNEL=release sudo ./build.sh --clawdie-version 0.10.0
--skip-fetch is provenance-safe for Clawdie-AI: moving refs are resolved to a
commit and cached by that commit. If the commit cannot be resolved safely, the
script refuses a moving-ref skip-fetch build rather than producing misleading
manifest data.
Build Output and Provenance
The build header shows:
ISO : 0.1.0-dev
FreeBSD : 15.0-RELEASE amd64
Clawdie : main
Clawdie commit: <resolved-sha>
The image contains:
/usr/local/share/clawdie-iso/build-manifest.json
The installed system receives the same manifest. It records:
- ISO version and build channel
- FreeBSD version/arch
- bundled Clawdie-AI ref and commit
- ISO repo commit and dirty state
- UTC build timestamp
The final size output distinguishes:
- Image size — logical size that must fit on the USB key
- Allocated — sparse bytes used on the build host
Build Configuration
Edit build.cfg for persistent defaults:
ISO_VERSION="0.1.0"
BUILD_CHANNEL="${BUILD_CHANNEL:-dev}"
IMAGE_SIZE="28G"
CLAWDIE_REF="${CLAWDIE_REF:-main}"
DEFAULT_PKG_BRANCH="latest"
FEATURE_TAILSCALE="${FEATURE_TAILSCALE:-YES}"
Notes:
- Host pkg repo branch and ISO package branch are independent.
DEFAULT_PKG_BRANCH=latestis the ISO package source by default.- Provider keys, Telegram, and disk deployment are deferred on this branch.
Build Process
- Fetch FreeBSD memstick and verify checksum.
- Fetch all package archives for offline install.
- Build local pkg repository metadata.
- Fetch Clawdie-AI by resolved ref and prepare offline
node_modulestarball. - Create/attach the working image.
- Inject firstboot scripts, packages, XFCE live-session assets, bundled npm globals, Clawdie-AI tarball, build config, and manifest.
- Copy the final sparse image into
tmp/output/.
The build is intentionally cache-friendly. If in doubt before validation, run the
full sudo ./build.sh once after pulling current main.
Boot Flow Produced by the Image
- USB boots to XFCE live session.
/usr/local/etc/rc.d/clawdie_live_gpuruns before LightDM and selects a conservative GPU path.- LightDM autologins as
clawdie. - A desktop launcher opens the static Clawdie bootstrap page.
- The operator verifies browser,
pi, Tailscale, and local networking. - Later phases will add persistence, disk deployment, and upgrade/rescue flows.
Testing
Before writing to hardware, use bhyve when available:
sudo ./scripts/bhyve-pf-allow.sh
sudo ./scripts/bhyve-test.sh
See TESTING.md for the full validation checklist.
Troubleshooting
ERROR: missing package archive for <pkg>
A package was added after your cache was created. Run a full fetch/build:
sudo ./build.sh
pkg not found during unprivileged fetch
build.sh now sets a known FreeBSD tool PATH internally. If your shell still
cannot find pkg manually, add /usr/local/sbin to your login PATH.
npm ci falls back to npm install
The bundled Clawdie-AI ref has a package-lock mismatch. The build warns and falls back so validation can continue, but release refs should have a clean lock.
Image says small allocated size
The image is sparse on the build host. Use the logical image size when choosing a USB key.
Last updated: 16.maj.2026