clawdie-ai/setup.sh
Mevy Assistant 7a0d3888d5 fix: update all stale PostgreSQL 17 references to 18
data17 path and postgresql17 package refs were never updated when PG was
upgraded to 18. Fixes setup scripts, skills, docs, tests, and archived
playbooks to match the running system (PG 18.3, /var/db/postgres/data).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 09:12:48 +00:00

280 lines
7.1 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# setup.sh — Bootstrap script for Clawdie AI
# Handles Node.js/npm setup, then hands off to the Node.js setup modules.
# This is the only bash script in the setup flow.
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="$PROJECT_ROOT/logs/setup.log"
# shellcheck source=scripts/date-format.sh
. "$PROJECT_ROOT/scripts/date-format.sh"
mkdir -p "$PROJECT_ROOT/logs"
log() { echo "[$(format_display_timestamp_now)] [bootstrap] $*" >> "$LOG_FILE"; }
# --- Platform detection ---
detect_platform() {
local uname_s
uname_s=$(uname -s)
case "$uname_s" in
FreeBSD*) PLATFORM="freebsd" ;;
*)
echo "ERROR: Clawdie AI requires FreeBSD. Detected: $uname_s" >&2
exit 1
;;
esac
IS_ROOT="false"
if [ "$(id -u)" -eq 0 ]; then
IS_ROOT="true"
fi
log "Platform: $PLATFORM, Root: $IS_ROOT"
}
# --- Host package baseline ---
install_host_pkg_baseline() {
HOST_PKG_BASELINE_STATUS="skipped"
HOST_PKG_BASELINE_MISSING=""
HOST_PKG_BASELINE_INSTALL_CMD="none"
[ "$PLATFORM" = "freebsd" ] || return
local -a missing_pkgs=()
local package_file="$PROJECT_ROOT/infra/packages/host-baseline.txt"
local pkg
while IFS= read -r pkg; do
[ -n "$pkg" ] || continue
case "$pkg" in
\#*) continue ;;
node24)
command -v node >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
npm)
command -v npm >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
bsddialog)
command -v bsddialog >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
bastille)
command -v bastille >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
git)
command -v git >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
tmux)
command -v tmux >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
python311)
command -v python3 >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
uv)
command -v uv >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
ripgrep)
command -v rg >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
fd)
command -v fd >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
rsync)
command -v rsync >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
postgresql18-client)
command -v psql >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
rust)
command -v rustc >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
py311-pillow)
python3 -c "import PIL" >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
dejavu)
[ -f /usr/local/share/fonts/dejavu/DejaVuSansMono.ttf ] || missing_pkgs+=("$pkg")
;;
*)
command -v "$pkg" >/dev/null 2>&1 || missing_pkgs+=("$pkg")
;;
esac
done < "$package_file"
if [ "${#missing_pkgs[@]}" -eq 0 ]; then
HOST_PKG_BASELINE_STATUS="already_present"
log "Host package baseline already present"
return
fi
HOST_PKG_BASELINE_MISSING="${missing_pkgs[*]}"
if [ "$IS_ROOT" = "true" ]; then
HOST_PKG_BASELINE_INSTALL_CMD="pkg install -y ${HOST_PKG_BASELINE_MISSING}"
elif command -v sudo >/dev/null 2>&1; then
HOST_PKG_BASELINE_INSTALL_CMD="sudo pkg install -y ${HOST_PKG_BASELINE_MISSING}"
else
HOST_PKG_BASELINE_STATUS="missing_no_sudo"
log "Host package baseline missing and sudo unavailable: ${HOST_PKG_BASELINE_MISSING}"
return
fi
log "Installing missing host package baseline: ${HOST_PKG_BASELINE_MISSING}"
if $HOST_PKG_BASELINE_INSTALL_CMD >> "$LOG_FILE" 2>&1; then
HOST_PKG_BASELINE_STATUS="installed"
log "Host package baseline installed successfully"
else
HOST_PKG_BASELINE_STATUS="install_failed"
log "Host package baseline installation failed"
fi
}
# --- Node.js check ---
check_node() {
NODE_OK="false"
NODE_VERSION="not_found"
NODE_PATH_FOUND=""
if command -v node >/dev/null 2>&1; then
NODE_VERSION=$(node --version 2>/dev/null | sed 's/^v//')
NODE_PATH_FOUND=$(command -v node)
local major
major=$(echo "$NODE_VERSION" | cut -d. -f1)
if [ "$major" -ge 24 ] 2>/dev/null; then
NODE_OK="true"
fi
log "Node $NODE_VERSION at $NODE_PATH_FOUND (major=$major, ok=$NODE_OK)"
else
log "Node not found"
fi
}
# --- bsddialog check ---
check_bsddialog() {
BSDDIALOG_OK="false"
BSDDIALOG_PATH="not_found"
if command -v bsddialog >/dev/null 2>&1; then
BSDDIALOG_OK="true"
BSDDIALOG_PATH=$(command -v bsddialog)
fi
log "bsddialog: $BSDDIALOG_OK (${BSDDIALOG_PATH:-not_found})"
}
# --- npm install ---
install_deps() {
DEPS_OK="false"
if [ "$NODE_OK" = "false" ]; then
log "Skipping npm install — Node not available"
return
fi
cd "$PROJECT_ROOT"
# npm install with --unsafe-perm if root (needed for native modules)
local npm_flags=""
if [ "$IS_ROOT" = "true" ]; then
npm_flags="--unsafe-perm"
log "Running as root, using --unsafe-perm"
fi
log "Running npm install $npm_flags"
if npm install $npm_flags >> "$LOG_FILE" 2>&1; then
DEPS_OK="true"
log "npm install succeeded"
else
log "npm install failed"
return
fi
}
# --- Build tools check ---
check_build_tools() {
HAS_BUILD_TOOLS="false"
if command -v cc >/dev/null 2>&1 && command -v make >/dev/null 2>&1; then
HAS_BUILD_TOOLS="true"
fi
log "Build tools: $HAS_BUILD_TOOLS"
}
# --- Main ---
log "=== Bootstrap started ==="
detect_platform
install_host_pkg_baseline
check_node
check_bsddialog
install_deps
check_build_tools
# Emit status block
STATUS="success"
if [ "$HOST_PKG_BASELINE_STATUS" = "missing_no_sudo" ] || [ "$HOST_PKG_BASELINE_STATUS" = "install_failed" ]; then
STATUS="host_packages_failed"
elif [ "$NODE_OK" = "false" ]; then
STATUS="node_missing"
elif [ "$DEPS_OK" = "false" ]; then
STATUS="deps_failed"
fi
cat <<EOF
=== CLAWDIE SETUP: BOOTSTRAP ===
PLATFORM: $PLATFORM
IS_ROOT: $IS_ROOT
HOST_PKG_BASELINE_STATUS: $HOST_PKG_BASELINE_STATUS
HOST_PKG_BASELINE_MISSING: ${HOST_PKG_BASELINE_MISSING:-none}
HOST_PKG_BASELINE_INSTALL_CMD: ${HOST_PKG_BASELINE_INSTALL_CMD:-none}
NODE_VERSION: $NODE_VERSION
NODE_OK: $NODE_OK
NODE_PATH: ${NODE_PATH_FOUND:-not_found}
DEPS_OK: $DEPS_OK
HAS_BUILD_TOOLS: $HAS_BUILD_TOOLS
BSDDIALOG_OK: $BSDDIALOG_OK
BSDDIALOG_PATH: ${BSDDIALOG_PATH:-not_found}
STATUS: $STATUS
LOG: logs/setup.log
=== END ===
EOF
log "=== Bootstrap completed: $STATUS ==="
if [ "$HOST_PKG_BASELINE_STATUS" = "missing_no_sudo" ] || [ "$HOST_PKG_BASELINE_STATUS" = "install_failed" ]; then
exit 1
fi
if [ "$NODE_OK" = "false" ]; then
exit 2
fi
if [ "$DEPS_OK" = "false" ]; then
exit 1
fi
# Wire tracked git hooks (idempotent)
git config core.hooksPath hooks/ 2>/dev/null || true
log "Git hooks path set to hooks/"
# Detect host locale silently — reads $LANG / locale / ~/.login_conf from the FreeBSD install
# Falls back to en-US on neutral/cloud environments. No prompt needed.
log "Detecting host locale"
npx tsx setup/index.ts --step profile --accept-detected >> "$LOG_FILE" 2>&1 || true
if [ "${CLAWDIE_SKIP_ONBOARDING:-0}" != "1" ] \
&& [ -t 0 ] \
&& [ -t 1 ]; then
log "Launching interactive onboarding"
echo
echo "Launching interactive onboarding..."
npm run wizard
fi