clawdie-iso/FIRSTBOOT.md
Sam & Claude 0e6d8cbe53 Drop unresolved Clawdie service staging from USB (Sam & Codex)
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
2026-06-13 12:12:34 +02:00

25 KiB
Raw Permalink Blame History

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:

  1. Monolithic: single script that does everything — hard to test, debug, or reuse.
  2. 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_detect can 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_MODEinstall | 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/.env by 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.
  • /etc/pkg/repos/Clawdie-USB.conf — offline USB repo, priority 100 (preferred).
    • URL: file:///mnt/media/packages.
  • /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.confkld_list="..." (idempotent; replaces existing line).

Exports for downstream: DETECTED_GPUintel | 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_VERSION590 | 470 | 390 (env var for unattended), or interactive bsddialog menu.

Device ranges → driver:

Range Era Driver
≥0x2700 Ada (RTX 40xx) 590
0x20600x2500 Turing/Ampere (RTX 20xx/30xx) 590
0x13400x2186 Maxwell (GTX 750980 Ti) 470
0x11800x139F Kepler (GTX 650780 Ti) 390
(unknown) 590 (safe default)

Outputs:

  • /etc/rc.confnvidia_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.passwd updates via pw.
  • /home/clawdie/.ssh/authorized_keys if 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.conftimezone, dbus_enable=YES, display_manager=sddm, sddm_enable=YES, linux_enable, zfs_enable, kld_list (idempotent via sysrc).
  • /etc/hostname — single line: home.arpa (or AGENT_DOMAIN).
  • /etc/profile.d/clawdie.sh — npm PATH, 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=YES when display detected; sddm_enable=NO for 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/16 supernet)
    • HTTP/HTTPS pass rules
    • commented Tailscale + glasspane VNC block (agent uncomments later)
  • /etc/rc.conf appends:
    • 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 tailscale0 interface index).

Glasspane VNC: port 5900 (wayvnccage → 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_TAILSCALEYES/NO (default NO).

Outputs:

  • /etc/rc.conftailscaled_enable="YES".
  • Tailscale left unauthenticated; operator runs tailscale up from 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.shPATH update 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 .envhard 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 install runs as the clawdie user.
  • PostgreSQL seeded in db jail; nginx configured in cms jail; rc.d clawdie service 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 update fails. Action on resume: re-run module (idempotent).
  • Hard failure (exit 1): module exits shell. Examples: .env missing in 1.6, AGENT_DOMAIN not 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):

  1. Create firstboot/shell-ollama.sh with a clawdie_shell_ollama_setup() function and the standard error/log/progress scaffolding.
  2. Add a corresponding entry to this manifest: purpose, inputs, outputs, checkpoint, skip condition, error handling, recovery.
  3. Source and call it from firstboot.sh in the appropriate slot:
    . /usr/local/share/clawdie-iso/firstboot/shell-ollama.sh
    clawdie_shell_ollama_setup
    
  4. 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