From 9e4feb08001c8901aa41ddf2ce1ec7e0b47331df Mon Sep 17 00:00:00 2001 From: koshkoshinsk Date: Mon, 4 May 2026 12:54:54 +0000 Subject: [PATCH] feat(setup): warn when host is below recommended hardware specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-flight check in nanoclaw.sh that detects available RAM and free disk on the project-root partition (Linux + macOS) before the bootstrap spinner runs. Below 3700 MB RAM or 20 GB free disk, surfaces a "likely cannot run" warning with a Try-anyway prompt defaulting to abort. The 3700 MB floor sits below 4 GB because "4 GB" VMs typically report 3700–3900 MB after kernel reserves (Hetzner CX21 ≈ 3814, AWS t3.medium ≈ 3800). Cheaper to fail here than to wait through pnpm install on a host that can't run the agent container. Diagnostic events fire on continue/abort. Co-Authored-By: Claude Opus 4.7 (1M context) --- nanoclaw.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/nanoclaw.sh b/nanoclaw.sh index 82d445a..c2b2614 100755 --- a/nanoclaw.sh +++ b/nanoclaw.sh @@ -137,6 +137,69 @@ write_header # NANOCLAW_BOOTSTRAPPED=1 and skips re-printing the wordmark. cat "$PROJECT_ROOT/assets/setup-splash.txt" +# ─── pre-flight: minimum hardware specs ──────────────────────────────── +# NanoClaw runs an agent container per session. Below these thresholds the +# host + container + agent will struggle (OOM under load, image + session +# DBs filling the disk). Soft warn — `df` only sees the partition that +# $PROJECT_ROOT lives on, which can underreport on hosts with separate +# /home or /var mounts, so the user can override. + +# RAM floor is set below 4 GB because "4 GB" VMs typically report 3700–3900 MB +# after kernel reserves (e.g. Hetzner CX21 ≈ 3814, AWS t3.medium ≈ 3800). +MIN_MEM_MB=3700 +MIN_DISK_GB=20 + +detect_mem_mb() { + case "$(uname -s)" in + Linux) + awk '/^MemTotal:/ {printf "%d", $2 / 1024}' /proc/meminfo 2>/dev/null + ;; + Darwin) + local bytes + bytes=$(sysctl -n hw.memsize 2>/dev/null || echo 0) + echo $(( bytes / 1024 / 1024 )) + ;; + esac +} + +detect_disk_gb() { + # -P: POSIX format (no line-wrapping); -k: 1024-byte blocks. Avail is col 4. + df -Pk "$PROJECT_ROOT" 2>/dev/null \ + | awk 'NR==2 { printf "%d", $4 / 1024 / 1024 }' +} + +MEM_MB=$(detect_mem_mb) +DISK_GB=$(detect_disk_gb) +: "${MEM_MB:=0}" +: "${DISK_GB:=0}" + +LOW_MEM=false; LOW_DISK=false +[ "$MEM_MB" -gt 0 ] && [ "$MEM_MB" -lt "$MIN_MEM_MB" ] && LOW_MEM=true +[ "$DISK_GB" -gt 0 ] && [ "$DISK_GB" -lt "$MIN_DISK_GB" ] && LOW_DISK=true + +if [ "$LOW_MEM" = true ] || [ "$LOW_DISK" = true ]; then + printf ' %s\n' "$(red 'Warning: this machine likely cannot run NanoClaw.')" + printf ' %s\n' "$(dim 'NanoClaw recommends a 4 GB+ machine with 20 GB+ free disk. Below this,')" + printf ' %s\n' "$(dim 'the host + agent container will run out of memory or disk under most')" + printf ' %s\n' "$(dim 'workloads. A stronger machine is strongly recommended.')" + [ "$LOW_MEM" = true ] && printf ' %s\n' "$(dim " · Detected RAM: ${MEM_MB} MB")" + [ "$LOW_DISK" = true ] && printf ' %s\n' "$(dim " · Free disk on $PROJECT_ROOT: ${DISK_GB} GB")" + printf '\n' + read -r -p " $(bold 'Try anyway?') [y/N] " SPECS_ANS