Step 4 of clawdie-enable-mother.sh rewrote provider.env in place with
`cat "$tmp" >"$f"`, which truncates the live secrets file before
streaming the new content. A crash, signal, disk-full, or concurrent
read during that window leaves provider.env empty or partial — and the
colibri_daemon prestart sources it for the provider key + BW_* creds.
Switch to the write-temp-then-rename pattern already used for
external-mcp.json in step 3: mktemp in provider.env's own directory (so
the rename stays on one filesystem and is atomic), chmod 0600 before the
swap, then mv. A reader now always sees a complete file, old or new.
Also add jq to the disk-install extras so disk-deployed hosts can run
the script post-deploy (step 3 hard-requires jq; the live image already
ships it).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The image shipped a hard pin (@earendil-works/pi-coding-agent@0.78.0) while
'pi upgrade' on hosts had moved to 0.80.2, so builds lagged. Switch Pi to the
@latest dist-tag so every image bundles the newest Pi.
To keep the floating spec traceable, record the version that actually got
fetched in build-manifest.json as pi_version, derived from the bundled tarball
name (earendil-works-pi-coding-agent-<version>.tgz) after fetch+install.
fetch-npm-globals.sh now also echoes the resolved tarball so the build log
shows the version a dist-tag resolved to.
Other globals (bw) stay pinned. Image is node24, compatible with current Pi
(the legacy-node20 dist-tag is for node20 only).
Verified: fetch resolves @latest → 0.80.2; version extraction matches npm.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move jq into the agent-jail section so the package list mirrors Colibri's agent-jail-bootstrap baseline, and apply Prettier to pulled markdown drift.\n\nValidation: ./scripts/check-format.sh; sh -n build.sh scripts/stage-colibri-iso.sh live/operator-session/clawdie-join-hive.sh live/operator-session/clawdie-enable-mother.sh live/operator-session/colibri-live-rebuild; ./scripts/test-release-gate.sh; git diff --check.
The MCP tooling needs jq on PATH to parse colibri-mcp / external MCP JSON-RPC
output. Add it to the live operator image (where the auto-spawned Pi and
colibri-mcp run) and to the jail package union. The jail entry mirrors the
matching addition in Colibri's agent-jail-bootstrap.sh (kept in sync per the
list header).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tier 1 of the hermes out-of-the-box dependency sweep. hermes is a Python/uv app
(requires-python >=3.11,<3.14) whose venvs use --system-site-packages, so system
py311-* pkgs satisfy compiled deps without building.
- ffmpeg: hermes runtime baseline (installer) + voice-transcription/media skills.
- py311-pillow: Pillow is a hermes CORE dependency; the --system-site-packages
venv picks up the prebuilt system pkg (no source build).
- python311 explicit (python3 = 3.11 after the default flip); python312 stays.
- Fix the stale "python312 owns python3" comment.
Covers hermes core + telegram gateway + voice. Tier 2 (discord-voice libsodium/
opus, astro vips, ollama/llama-cpp) pending confirmation of default integrations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stop fighting FreeBSD's PYTHON_DEFAULT=3.11: make python3 resolve to 3.11
(python312 stays installed and available as python3.12 for anything needing
newer). This also makes Pillow trivial — py311-pillow imports on plain python3,
so the image-render/screenshot skill needs no version gymnastics.
- build.sh: python3/python symlink → 3.11 (prefer python3.11, else lowest).
- pkg-list-live-operator.txt: add py311-pillow.
- clawdie-join-hive.sh: advertise image-render when `python3 -c import PIL`
works, and screenshot when $DISPLAY is set.
- BUILD.md: short note (python3=3.11; python3.12 available; image-render via
py311-pillow).
Validated: sh -n build.sh + join-hive clean; markdown gate clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FreeBSD pkg repos build against PYTHON_DEFAULT=3.11, so system packages
(git, libinput, npm-node24) pull python311 as transitive deps. We keep
python312 as the application Python — it wins the python3 symlink via
sort -V. Document this in BUILD.md, build.sh, package lists, and
bootstrap.html so the dual-version reality is explicit and intentional.
Add an agent-jail section to pkg-list-jails.txt mirroring Colibri agent-jail-bootstrap.sh, include python312, and use npm-node24 instead of generic npm. This satisfies issue #70 acceptance and resolves the npm package-name drift in favor of the node24-tied package.\n\nValidation: ./scripts/check-format.sh; sh -n build.sh; git diff --check
Two parallel, additive paths so a host gets its secrets out of the box;
the manual setup wizard stays the floor (no config = no-op).
clawdie-vault-fetch (new): language-neutral bw bridge. Reads a 0600
~/.config/vault-bootstrap.env, pulls keys from the agent-secrets
collection (item name = env var name, value in password field, so no jq),
prints KEY=VALUE or --write-env upserts 0600. Exit codes distinguish
skip (3, no bootstrap) / broken (1) / no bw (4). Pinned
@bitwarden/cli@2026.5.0 for offline bundling; staged in
configure_live_operator_session.
clawdie-live-seed: extend the CLAWDIESEED FAT32 importer from the
authorized_keys allowlist to a per-agent directory convention —
/<agent>/ with env (merged 0600), harness.toml (pi|zot|local), soul/
(staged), ssh/authorized_keys. Live USB single-agent (first dir = active);
extra dirs staged + flagged for deployed multi-agent. Optional
consume-and-shred. Import core is unit-testable via CLAWDIE_SEED_TEST.
README rewritten to document the per-agent contract and the operator
decision to allow plaintext secrets on the seed (seeded sticks are
secret-bearing media; 0600 landing + shred mitigations).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Standardize the ISO on the agreed Python 3.12 floor (operator + Hermes +
Claude consensus; see layered-soul/docs/TOOLCHAIN.md).
- pkg lists: python311->python312, py311-{pip,aider_chat,pillow}->py312-*
- build.sh: derive the installed python3.N for the python3/python symlink so a
future bump needs only a pkg-list change, never an edit here
- shell-deploy.sh: create the Aider venv with 'python3 -m venv' (resolves via
the symlink) instead of a hardcoded python3.11
- import-clawdie-skills.sh: python3 fallback instead of python3.11
- BUILD.md: doc references
Aider kept (bumped, not dropped): redundant coding tooling is intentional per
the agent matrix.
Pre-merge gate: confirm FreeBSD pkg coverage on osa —
pkg search '^py312-aider_chat' '^py312-pygobject'
(common modules pillow/pip are safe).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace stale colibri-smoke-agent references with colibri-test-agent, mark colibri-tui optional/desirable, update image-name comments, and avoid smoke wording in current build handoff docs.\n\nChecks: sh -n build.sh; sh -n scripts/test-release-gate.sh; ./scripts/check-format.sh; git diff --check.
Round 1 of the pre-final-build polish (Linux-safe, no FreeBSD runtime claims):
- Live rebuild lane now spans the whole agent stack, not just Colibri:
- add `go` to pkg-list-live-operator.txt (builds zot on the booted USB)
- seed the zot source snapshot at /home/clawdie/ai/zot via
seed_live_ai_source_repo (skipped automatically if the checkout is absent)
- docs/LIVE-COLIBRI-REBUILD.md: add the `go build` rebuild steps for zot and
list `go` under required live packages
- CHANGELOG: reconcile the stale Repository Status table to the current
zot (agent) + Colibri (control plane) architecture — pi demoted to spawnable
backend, clawdie-ai being pruned, clawdie-shell archived — and record that the
image version tracks the zot release (git describe), no invented ISO number.
Deferred to Round 2 (FreeBSD-validated): staging the `clawdie` binary and wiring
disk-install to run `clawdie apply` for the deployed-system service. That path
provisions ZFS + an rc.d service on the target and cannot be validated from
Linux, so it goes through the FreeBSD handoff rather than shipping unproven.
Checks: sh -n build.sh OK; prettier clean on changed docs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switch ISO staging/docs from colibri-smoke-agent to colibri-test-agent, include rust/pkgconf for live Colibri rebuilds, stage provider.env.sample, wire the provider env rc.conf path, and document LLM key setup on the Firefox bootstrap page.\n\nChecks: npx --yes prettier@3 --check docs/LIVE-COLIBRI-REBUILD.md live/operator-session/bootstrap.html BUILD.md TESTING.md README.md; sh -n scripts/stage-colibri-iso.sh; sh -n build.sh; fake Colibri staging + sh -n staged rc.d script; git diff --check.
Consolidates the operator-USB work into main now that the AMD ASUS hardware-evidence collection is closed and Codex is parked. Brings the live-session hardware lane (XInput/libinput touchpad guard, internal audio + resolver bootstrap, hw-report with gated public upload, operator-USB branding) and the config-only XFCE panel polish (Pass 1 + Pass 2: branded Whisker PNG, xkb text mode, panel 40px, systray square-icons).
Conflict: doc/LLM-PROVIDER-HARNESS.md was evolved on both sides. Resolved as a union with no content lost — the xfce-side harness/provider/fabric restructure is the base, and main's two unique blocks (Verifying Key Cleanup flow, the 2D Platform x Harness matrix + populate/add procedures) are preserved. The doc owner may later dedupe the overlap between the two 1D matrices and the 2D matrix.
Verification debt stays explicit and open (not closed by this merge): XFCE visual-polish confirmation and the next rebuilt-image hardware retest, per doc/XFCE-PANEL-BUGS-HANDOFF.md and PLAN-OPERATOR-USB-NEXT.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use packages/npm-globals.txt as the source of truth for offline npm CLI tarballs, update Pi to 0.75.5, and keep Claude Code out of the XFCE USB path.
---
Build: not run — ISO build not requested
Tests: pass — sh -n fetch-npm-globals and shell-npm-globals; pinned npm pack smoke passed
Live GUI installs now write runtime handoff files under /var/run/clawdie-installer, invoke bsdinstall script through a dedicated commit helper, persist the installed handoff for first HDD boot, and point the operator at /setup after reboot.
The live autologin user is restricted to a narrow sudoers rule for the commit helper and reboot only.
Build: pass
Tests: pass — sh -n + QML build + config-format + stubbed live-commit dry-run
Real-disk / bhyve install: NOT YET TESTED
mDNS resolves single-label names under .home.arpa (e.g.
mevy.home.arpa) but cannot resolve multi-label names like
blog.mevy.home.arpa because no single device "owns" the compound
name. The Clawdie multitenant naming policy uses hierarchical site
naming (<site>.<tenant>.<base>), so a local DNS resolver is required.
dnsmasq is a small (~2 MB) FreeBSD-native DNS server used by most
home routers and homelabs. Bundling it with the ISO removes the
"works on my machine" failure mode for fresh installs that try to
reach blog.mevy.home.arpa.
Mirrors the addition that will land in clawdie-ai's
infra/packages/host-baseline.txt once the multitenant naming policy
note is approved.
Bundles the 'just' command runner on the USB image. Provides
discoverable project commands via justfile in Clawdie-AI.
---
Build: pass | Tests: not run (Linux)
Add py311-aider_chat to host baseline for the controlplane harness
(Aider + Pi multi-agent orchestrator). Add forgejo package to jail
list for the code service. Bake ZAI_API_BASE into firstboot .env
to fix litellm endpoint mismatch discovered during Aider testing.
---
Build: pass | Tests: not run (Linux)
BREAKING CHANGE: Removes --target and --gpu-driver flags, unified ISO for all use cases
## Phase 0: GPU Fix + Unified ISO
### Core Changes
**GPU Package Installation (FIXES CRITICAL GAP):**
- Add clawdie_shell_nvidia_install() function to shell-nvidia.sh
- NVIDIA drivers now installed after detection (previously only configured)
- Works offline (USB packages) or online (pkg install)
- Resolves issue where rc.conf was set but driver not installed
**Unified ISO Architecture:**
- Remove --target flag from build.sh (no more vps/baremetal branching)
- Remove --gpu-driver flag from build.sh (runtime detection instead)
- All packages included on every ISO (desktop + all GPU drivers)
- Single image works on VPS, baremetal, and cloud
**Runtime Detection:**
- Add shell-desktop.sh for display detection at firstboot
- VPS/cloud: no display → lightdm disabled (headless)
- Baremetal: display detected → lightdm enabled (Lumina desktop)
- GPU detection always runs, installs correct driver version
**Sudo Unification:**
- Replace all doas references with sudo across entire codebase
- Update AGENTS.md with system configuration guidelines
- Update all documentation (BUILD.md, README.md, REQUIREMENTS.md, etc.)
- Admin panel now uses sudo for privileged operations
### Files Modified
**Core System:**
- build.sh: Remove target/gpu-driver logic, unified package selection
- firstboot/firstboot.sh: Add desktop detection module
- firstboot/shell-nvidia.sh: Add package installation function (+33 lines)
**New Files:**
- firstboot/shell-desktop.sh: Display detection and desktop enablement
- packages/pkg-list-nvidia-all.txt: All three NVIDIA driver versions (390/470/590)
- .opencode/plans/phase0-gpu-fix-unified-iso.md: Implementation plan
**Documentation:**
- PLAN-UNIFY.md: Update Step 3 for unified approach
- REQUIREMENTS.md: Simplify (no target choice), update for sudo
- BUILD.md: Update for unified ISO, sudo commands
- README.md: Update installation instructions
- AGENTS.md: Add system configuration section (sudo standardization)
- ADMIN-PANEL.md: Update privileged operations to use sudo
- CLAWDIE-SHELL.md: Update example commands to sudo
- CLAWDIE-ISO-REFACTORED.md: Update access paths to sudo
- REFACTOR-SUMMARY.md: Update permissions section to sudo
### Benefits
**Simplicity:**
- One build command: ./build.sh (no flags needed)
- One ISO to test and maintain
- No wrong choices for users
- No documentation explaining target differences
**Flexibility:**
- VPS can use GUI via VNC (wayvnc always available)
- Baremetal can run headless (disable lightdm)
- Repurpose hardware without reinstall
- All GPU drivers available for any hardware
**Technical:**
- Fixes critical GPU driver installation gap
- Runtime detection replaces build-time decisions
- Disk overhead: ~650MB (1-2% of 50GB - acceptable)
- No runtime overhead on VPS (services disabled by detection)
### Testing Required
- [ ] Build unified ISO: ./build.sh
- [ ] Test on VPS (no display): lightdm disabled, packages installed
- [ ] Test on baremetal (display): lightdm enabled, Lumina boots
- [ ] Test on NVIDIA hardware: driver installed and loaded
- [ ] Test sudo commands work without password prompts
- [ ] Verify all doas references removed
- Create packages/pkg-list-lumina.txt with Lumina desktop environment packages
- Delete pkg-list-xfce.txt, pkg-list-mate.txt, pkg-list-kde.txt
- Remove desktop-installer from pkg-list-desktop-base.txt
- build.cfg: DEFAULT_DESKTOP=lumina (sole supported DE)
- build.sh: use pkg-list-lumina.txt instead of pkg-list-xfce.txt
- BUILD.md: update DEFAULT_DESKTOP comment
- CLAWDIE-ISO.md: add deprecation notice, update all DE references to Lumina only
Lumina is the sole supported FreeBSD-native desktop environment as per
LUMINA-INTEGRATION.md and CLAWDIE-ISO-REFACTORED.md specifications.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Rename all modules: clawdie-shell-{func}.sh → shell-{func}.sh
- Update references in firstboot.sh and installerconfig
- Update self-detection case statements in each module
- Reduces naming redundancy and improves clarity
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Create versioned NVIDIA driver package lists to support 6 GPU-specific ISO variants:
- pkg-list-nvidia-590.txt: Maxwell & newer (GTX 750 Ti+, RTX 20/30/40)
- pkg-list-nvidia-470.txt: Kepler (GTX 600/700, Titan Black)
- pkg-list-nvidia-390.txt: Fermi (GTX 400/500)
Each includes the appropriate driver version and nvidia-settings for clean, per-variant bundling. The old pkg-list-nvidia.txt is deprecated but kept for reference.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
.forgejo/workflows/build.yml:
- Forgejo Actions pipeline: push to main + weekly cron + manual dispatch
- Two-stage: fetch-only (no root) → assemble ISO (root via sudo)
- Publishes ISO to CMS nginx downloads; Codeberg release entry (metadata only)
- Uploads packages/ as workflow artifact for pkg-cache seeding
packages/:
- pkg-list-host.txt — host baseline (mirrors clawdie-ai infra/packages/)
- pkg-list-jails.txt — union of all jail package lists
- pkg-list-desktop-base.txt — Xorg + drm base for all DEs
- pkg-list-xfce.txt / kde.txt / mate.txt / nvidia.txt — per-DE packages
build.sh:
- --fetch-only flag: downloads packages + memstick, no root, CI step 1
- Real pkg fetch loop: reads all pkg-list-*.txt, deduplicates, runs pkg fetch
- pkg repo step: generates offline repo metadata after fetch
- Resolves "latest" Clawdie version via Codeberg API
firstboot/firstboot.sh:
- Seeds zroot/pkg-cache from USB packages/ after desktop install
- npm run install-all runs fully offline — no internet needed for jails
- Creates ZFS dataset if not present, falls back to plain directory
runner/README.md:
- forgejo-runner install + register on FreeBSD
- Scoped sudoers entry (build.sh + publish.sh only)
- rc.d service setup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>