---
name: iso-build
description: Build the current Clawdie ISO image on the FreeBSD host from this repo, using the default tmux window workflow (`clawdie:3` / `iso`), repo-local tmp/ caches, step-by-step preflight, and the current operator-USB validation expectations.
---

# iso-build

Use this skill for the normal FreeBSD host build path from the checked-out
`clawdie-iso` repo. This is the current repo-local operator workflow, not the
older “clone elsewhere and publish to nginx” flow.

Run ISO builds only when the operator explicitly assigns one. For planning,
docs, package-list edits, or static inspection tasks, use static checks
instead of building.

## Current operator-USB expectations

- Default validation image size: `28G`
- Live browser: Firefox, not Chromium
- SDDM interactive login as `clawdie`; no live autologin
- `CLAWDIESEED` exists as FAT32 slice 3 for post-flash, pre-boot seed import
- Live CLI policy: ship `codex`, `pi`, `gemini`; omit `claude` from the live image
- Operator editors: `mousepad`, `geany`, and `micro`
- Hardware/custom-ISO report collector: `hw-report`
- Vulkan diagnostic tool: `vulkaninfo` from `vulkan-tools`; Zed remains deferred
  until Intel+AMD Vulkan are proven on hardware
- X blanking / DPMS disabled; NumLock off
- Power policy: `powerdxx` + `C3`, not `Cmax`
- Panel/runtime checks include `mixer`; `clipman` is intentionally dropped from
  the panel pending a D-Bus root-cause (see `doc/XFCE-PANEL-BUGS-HANDOFF.md`)
- Final graphical validation requires real hardware, not bhyve/nested VM only

## Workspace names

Keep the real paths as-is, but speak about them clearly:

- `tmp/output` = output image artifacts
- `tmp/cache` = build cache
- `tmp/cache/mnt` = mounted work image
- `tmp/cache/FreeBSD-*.img` = cached memstick base image
- `tmp/packages` = fetched package archives

## Manifest contract

The build workflow should emit or hand off `clawdie.iso.build.v1` results under
`tmp/colibri/iso-build/` when Colibri ingestion is part of the task. The image
itself also embeds `/usr/local/share/clawdie-iso/build-manifest.json` for live
runtime inspection. See `docs/ISO-MANIFESTS.md` for the schema fields and path
conventions.

## Preconditions

- Run on the FreeBSD build host, from the repo root
- Prefer `tmux` for long builds
- Use an elevated shell in the tmux pane so the build command itself runs
  without a `sudo` prefix
- Run each command individually so failures are visible and attributable;
  chain commands only when a prior success is required and verified
- Fetch before reporting remote state or starting a build
- If disk is tight, the image build was interrupted, or `tmp/cache/mnt` is
  still mounted, use `iso-build-cleanup` first

## Default tmux workflow

This is the default operator workflow and should be treated as the normal path.

### 1. Ensure the dedicated ISO window exists

```sh
tmux list-windows -t clawdie
```

If `clawdie:3` / `iso` does not exist, create it:

```sh
tmux new-window -t clawdie:3 -n iso
```

### 2. Inspect the pane before reusing it

```sh
tmux capture-pane -pt clawdie:3.1 -S -30
ps auxww | egrep '[b]uild.sh|[s]cript -q tmp/operator-usb-.*-build.log'
```

If a build is still active, preserve it — stop it deliberately or wait for
completion before reusing the pane.

### 3. Start clean after a failed attempt

When reusing the pane from a failed attempt:

- stop the foreground command with `Ctrl-C`
- return to repo root
- clear the pane with `Ctrl-L`
- emit a marker line so the next run is easy to identify in scrollback

Suggested marker:

```sh
echo "test build nr: $(ls tmp/operator-usb-*-build.log 2>/dev/null | wc -l | tr -d ' ') date: $(date +%d.%b.%y) ver: $(git rev-parse --short HEAD)"
```

### 4. Use the standard build command in `3:iso`

```sh
/usr/bin/script -q tmp/operator-usb-$(git rev-parse --short HEAD)-build.log ./build.sh --skip-memstick-fetch --live-default-password
```

If the operator explicitly asked for a baked SSH key, append:

```sh
--ssh-key '<public key>'
```

## Preflight

Run these before starting a build, one command at a time:

```sh
git fetch origin
git status --short --branch
git log --oneline -5
git rev-parse --short HEAD
df -h /home/clawdie /
du -xh -d 2 tmp | sort -h | tail -n 40
ls -lh tmp/output
du -xh -d 1 tmp/cache | sort -h
```

If you see stale mounts, md devices, or `work.img` still attached, stop and
switch to `iso-build-cleanup`.

### Colibri artifact preflight

The operator USB uses Colibri as its lightweight live control plane. The ISO
build stages FreeBSD-native Colibri artifacts from `/home/clawdie/ai/colibri`;
it does **not** build Rust while the image is mounted. Validation builds should
ship `colibri_daemon_enable=YES`; the rc.d service starts after LOGIN and
completes before SDDM/XFCE are user-facing, avoiding any startup delay.

Build Colibri on the FreeBSD/OSA host first; fall back to cross-shipping from
debby only if the native OSA build fails.

Run this before the ISO build:

```sh
cd /home/clawdie/ai/colibri
git fetch origin
git status --short --branch
git pull --ff-only
cargo build --workspace --release

ls -lh target/release/colibri-daemon \
       target/release/colibri \
       target/release/colibri-mcp

file target/release/colibri-daemon \
     target/release/colibri \
     target/release/colibri-mcp

# Development/validation helper. Required only when explicitly building with
# COLIBRI_STAGE_TEST_AGENT=YES; default release/prod images omit it.
if [ "${COLIBRI_STAGE_TEST_AGENT:-NO}" = "YES" ]; then
  ls -lh target/release/colibri-test-agent
  file target/release/colibri-test-agent
fi

# Optional in the staging script, but desired for this operator USB target.
if [ -x target/release/colibri-tui ]; then
  ls -lh target/release/colibri-tui
  file target/release/colibri-tui
else
  echo "WARN: optional colibri-tui artifact is missing"
fi

target/release/colibri --help | head
```

Then return to the ISO repo and run syntax/preflight checks:

```sh
cd /home/clawdie/ai/clawdie-iso
git fetch origin
git status --short --branch
git pull --ff-only
sh -n build.sh
sh -n scripts/stage-colibri-iso.sh
```

Important cleanup timing: **preserve Colibri artifacts until the ISO build
consumes them.** The ISO preflight/build reads from
`/home/clawdie/ai/colibri/target/release`. Clean Colibri only after the ISO
build or after deciding those artifacts are no longer needed:

```sh
cd /home/clawdie/ai/colibri
cargo clean
mkdir -p tmp/iso-build
rm -rf tmp/iso-build/*
```

`colibri-mcp` is part of the out-of-the-box operator USB. `colibri-tui` is
optional in the staging script, but desired for this operator USB target and
should be verified with the required binaries.

### Deployed-system Clawdie service boundary

`service clawdie` is reserved for installed disk/server targets, but the current
operator USB does not stage a `clawdie` rc.d service or mini-binary. The live USB
uses `colibri_daemon` directly. Add deployed-system service packaging only after
the real persistent host service implementation is chosen; keep the old
Colibri-side mini-binary for reference only until then.

### Next build: carry the XFCE operator-USB fixes

The next operator-USB image must retain the proven XFCE/live-GUI fixes
(`PLAN-OPERATOR-USB-NEXT.md`, `doc/AMD-ASUS-XFCE-LIVE-USB-FINDINGS.md`):

- **SDDM remains the supported live display manager** — load-bearing; retain
  SDDM until equivalent real-hardware proof validates any replacement for
  Intel + AMD live GUI boot.
- **`clawdie-live-gpu`** pre-SDDM rc.d KMS pick (conservative; NVIDIA/AMD safe).
- **Hardened USB-root power policy** (`b9290ab`): `powerdxx`, C3 C-state default,
  `hw.usb.no_suspend=1`, boot-time `power_profile`.
- Base fixes already landed: resolver bootstrap, internal-audio preference,
  touchpad XInput guards, loader branding, hardware-report capture.

Real hardware remains final proof for XFCE/session/input/audio — bhyve and
static image inspection are build gates only.

## Choose fetch mode

Use the lightest safe flag:

- `./build.sh`
  Fresh fetch of memstick + packages

- `./build.sh --skip-memstick-fetch`
  Reuse the cached FreeBSD memstick image, but refresh packages

- `./build.sh --skip-fetch`
  Reuse both memstick and package caches; use only when both caches are
  known-good

For the current operator workflow, the default is:

```sh
./build.sh --skip-memstick-fetch --live-default-password
```

## What to watch

Normal progress moves through:

1. Fetch/update package repo
2. Prepare Clawdie-AI offline tarball
3. Prepare work image
4. Inject payload
5. Write output image

Watch for these common blockers:

- `pkg-static ... conflicts with ...`
- `Write error` while extracting a package
- `database is locked` after a package failure
- `Not a directory` under `tmp/cache/mnt/usr/local/share/clawdie-iso/...`
- `mdconfig` devices left attached after interruption
- wrong ownership on `/opt/clawdie/npm-global`

If the build is interrupted or the work image gets wedged, stop and use
`iso-build-cleanup` before retrying.

## Output checks

After a successful build:

```sh
ls -lh tmp/output
find tmp/output -maxdepth 1 -type f -ls
```

Typical artifacts are:

- raw `.img`
- compressed `.img.xz`
- matching `.img.xz.sha256`

Public/test artifact names should include the source commit suffix.

## Static image expectations

Mounted-image checks should confirm:

- `firefox` is installed on the live rootfs
- `chromium` is not installed on the live rootfs
- `codex`, `pi`, and `gemini` are present
- `claude` is absent
- `mousepad`, `geany`, and `micro` are present
- `hw-report` and its desktop launcher are present
- `hw-probe`, `smartmontools`, `lscpu`, `lsblk`, `hwstat`, and `usbhid-dump` are present
- `libinput`, `xinput`, `xrandr`, and `glxinfo` are present for input/video diagnostics
- `vulkaninfo` is present for Intel+AMD Vulkan checks before any future Zed move
  to live rootfs
- `sudo` is absent
- live privileged commands use `mdo -u root ...`
- `CLAWDIESEED` exists as slice 3
- branded Start icon (`/usr/local/share/clawdie-iso/icons/clawdie-start.png`) and
  wallpaper (`/usr/local/share/clawdie-iso/wallpapers/clawdie-operator-bg.png`)
  are installed
- X blanking / DPMS are disabled
- NumLock is forced off
- `powerdxx` is installed and the live policy uses `C3`
- panel checks cover `mixer`; `clipman` is intentionally absent (dropped pending
  root-cause — see `doc/XFCE-PANEL-BUGS-HANDOFF.md`)

If you plan another rebuild soon, keep:

- `tmp/cache/FreeBSD-15.x-RELEASE-amd64-memstick.img`
- `tmp/cache/FreeBSD-15.x-RELEASE-amd64-memstick.img.SHA256`
- `tmp/packages/`
- `tmp/npm-globals/`

## Retry guidance

Use these rules:

- build failed after package refresh but memstick cache is fine:
  retry with `--skip-memstick-fetch`
- build failed because package cache looks wrong:
  retry without `--skip-fetch`
- build failed after leaving mounts, md devices, or a large stale `work.img`:
  run `iso-build-cleanup`, then retry
