Use Jerboa artifact toolchain

ober

bda3c1b1db49fbc85c7ea46301f64a4625372040

diff --git a/.gitignore b/.gitignore
index a07850e..05ee0cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ petite_boot.h
 scheme_boot.h
 program_boot.h
 vendor/
+/.jerboa/
 signal_tui_shim.dylib
 signal_tui_shim.so
 signal_log_shim.dylib
diff --git a/Makefile b/Makefile
index 99960b7..ce49bd8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,23 @@
 # jerbuild bundles Chez Scheme + the jerboa stdlib under ~/.cache/jerbuild/,
 # so building jerboa-signal needs only `jerbuild` + a C compiler — no jerboa
 # source checkout and no separately-built Chez.
-JERBUILD ?= jerbuild
-JH := $(shell $(JERBUILD) --jerboa-home 2>/dev/null)
-ifeq ($(JH),)
-$(error jerbuild not found on PATH (or '$(JERBUILD) --jerboa-home' failed). Install jerbuild, or set JERBUILD=/path/to/jerbuild)
-endif
+JERBOA_VERSION ?= v0.2.0
+JERBOA_TOOL_DIR ?= $(CURDIR)/.jerboa/bin
+JERBUILD ?= $(shell if [ -x ./jerbuild ] && [ -x ./jerboa ]; then \
+	printf '%s\n' ./jerbuild; \
+elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ] && [ -x "$(JERBOA_TOOL_DIR)/jerboa" ]; then \
+	printf '%s\n' "$(JERBOA_TOOL_DIR)/jerbuild"; \
+elif [ -x ../jerboa/dist/jerbuild ] && [ -x ../jerboa/dist/jerboa ]; then \
+	printf '%s\n' ../jerboa/dist/jerbuild; \
+elif command -v jerbuild >/dev/null 2>&1 && command -v jerboa >/dev/null 2>&1; then \
+	command -v jerbuild; \
+else \
+	printf '%s\n' "$(JERBOA_TOOL_DIR)/jerbuild"; \
+fi)
+JH = $(shell "$(JERBUILD)" --jerboa-home 2>/dev/null)
 
-LIBDIRS := --libdirs $(CURDIR):$(JH)/lib
-JEXEC := $(JERBUILD) exec $(LIBDIRS)
+LIBDIRS = --libdirs $(CURDIR):$(JH)/lib
+JEXEC = $(JERBUILD) exec $(LIBDIRS)
 BIN := jerboa-signal
 BIN_DIR := $(HOME)/.local/bin
 TUI_SHIM_DIR := $(CURDIR)/vendor/termbox2
@@ -22,13 +31,13 @@ TUI_SHIM := $(TUI_SHIM_DIR)/signal_tui_shim.$(TUI_SHIM_EXT)
 LOG_SHIM := signal_log_shim.$(TUI_SHIM_EXT)
 SQLCIPHER_PREFIX := $(shell brew --prefix sqlcipher 2>/dev/null)
 
-.PHONY: all build binary run run-tui test install clean help vendor-deps tui-shim log-shim
+.PHONY: all build binary run run-tui test install clean help vendor-deps tui-shim log-shim ensure-jerboa-tools
 .DEFAULT_GOAL := help
 
 all: binary
 
 # Standalone native binary via .jerbuild (entry signal/main.ss -> jerboa-signal).
-binary:
+binary: ensure-jerboa-tools
 	$(JERBUILD) build
 
 build: binary
@@ -61,6 +70,24 @@ vendor/termbox2:
 	mkdir -p vendor
 	git clone --depth 1 https://github.com/termbox/termbox2.git vendor/termbox2
 
+ensure-jerboa-tools:
+	@if [ -x ./jerbuild ] && [ -x ./jerboa ]; then \
+	  echo "=== Using project-local ./jerbuild ==="; \
+	elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ] && [ -x "$(JERBOA_TOOL_DIR)/jerboa" ]; then \
+	  echo "=== Using downloaded Jerboa toolchain: $(JERBOA_TOOL_DIR) ==="; \
+	elif [ -x ../jerboa/dist/jerbuild ] && [ -x ../jerboa/dist/jerboa ]; then \
+	  echo "=== Using sibling Jerboa build: ../jerboa/dist/jerbuild ==="; \
+	elif command -v jerbuild >/dev/null 2>&1 && command -v jerboa >/dev/null 2>&1; then \
+	  echo "=== Using Jerboa toolchain from PATH: $$(command -v jerbuild) ==="; \
+	else \
+	  echo "=== Fetching Jerboa $(JERBOA_VERSION) release tools into $(JERBOA_TOOL_DIR) ==="; \
+	  sh support/ensure-jerboa.sh "$(JERBOA_VERSION)" "$(JERBOA_TOOL_DIR)"; \
+	fi
+	@"$(JERBUILD)" --jerboa-home >/dev/null || { \
+	  echo "ERROR: Jerboa toolchain is unavailable; set JERBUILD=/path/to/jerbuild or JERBOA_VERSION=<tag>"; \
+	  exit 1; \
+	}
+
 tui-shim: vendor/termbox2
 	@test -f $(TUI_SHIM) || \
 	  cc -shared -fPIC -DTB_OPT_ATTR_W=32 \
@@ -91,6 +118,7 @@ help:
 	@echo "  run-tui             Build shim and start the TUI"
 	@echo "  test                Run tests"
 	@echo "  install             Install ./jerboa-signal to ~/.local/bin"
+	@echo "  ensure-jerboa-tools Ensure jerboa/jerbuild are available"
 	@echo "  tui-shim            Build the termbox2 TUI shim"
 	@echo "  log-shim            Build the SQLCipher encrypted-logging shim"
 	@echo "  clean               Remove build artifacts"
diff --git a/README.md b/README.md
index 85f97b7..7a49d88 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,9 @@ jerboa-signal tui [-a +PHONE]                      # terminal UI shell
 ## Prerequisites
 
 - `signal-cli` on `PATH` (Homebrew: `brew install signal-cli`)
-- A Jerboa checkout next to this repo at `../jerboa`, or `JERBOA_HOME` set
+- Jerboa build tools. `make binary`/`make install` use project-local
+  `./jerbuild` first, then `.jerboa/bin`, then `../jerboa/dist`, then `PATH`,
+  and download the matching release artifact if none are available.
 - Optional, for the encrypted message log: `brew install sqlcipher`, then
   `make log-shim` (without it the TUI runs fine, just without logging)
 
diff --git a/support/ensure-jerboa.sh b/support/ensure-jerboa.sh
new file mode 100755
index 0000000..e96aed7
--- /dev/null
+++ b/support/ensure-jerboa.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+# Bootstrap a project-local Jerboa toolchain from SourceHut release artifacts.
+#
+# Usage:
+#   support/ensure-jerboa.sh v0.2.0 .jerboa/bin
+#
+# Override the artifact location with:
+#   JERBOA_RELEASE_BASE=https://example.org/releases/v0.2.0
+# or the SourceHut repo with:
+#   JERBOA_RELEASE_REPO=~lisp/jerboa
+# For testing or unusual hosts, override target detection with:
+#   JERBOA_RELEASE_TARGET=macos-arm64
+
+set -eu
+
+usage() {
+    echo "Usage: $0 VERSION [BINDIR]" >&2
+}
+
+[ "${1:-}" ] || { usage; exit 2; }
+
+version=$1
+bindir=${2:-.jerboa/bin}
+repo=${JERBOA_RELEASE_REPO:-~lisp/jerboa}
+origin=${JERBOA_RELEASE_ORIGIN:-https://git.sr.ht}
+
+if [ "${JERBOA_RELEASE_TARGET:-}" ]; then
+    target=$JERBOA_RELEASE_TARGET
+else
+    os=$(uname -s)
+    arch=$(uname -m)
+    case "$os-$arch" in
+        Darwin-arm64) target=macos-arm64 ;;
+        Linux-x86_64|Linux-amd64) target=linux-amd64 ;;
+        Linux-aarch64|Linux-arm64) target=linux-arm64 ;;
+        FreeBSD-amd64|FreeBSD-x86_64) target=freebsd-amd64 ;;
+        *)
+            echo "ERROR: unsupported platform for Jerboa release artifacts: $os $arch" >&2
+            echo "       set JERBUILD=/path/to/jerbuild or build Jerboa locally for this host" >&2
+            exit 1
+            ;;
+    esac
+fi
+
+case "$target" in
+    macos-arm64|linux-amd64|linux-arm64|freebsd-amd64) ;;
+    *)
+        echo "ERROR: unsupported release target: $target" >&2
+        exit 1
+        ;;
+esac
+
+file="jerboa-${version}-${target}.tar.gz"
+base=${JERBOA_RELEASE_BASE:-${origin}/${repo}/refs/download/${version}}
+url="${base%/}/${file}"
+sum_url="${url}.sha256"
+
+download() {
+    src=$1
+    dst=$2
+    if command -v curl >/dev/null 2>&1; then
+        curl -fsSL "$src" -o "$dst"
+    elif command -v fetch >/dev/null 2>&1; then
+        fetch -q -o "$dst" "$src"
+    elif command -v wget >/dev/null 2>&1; then
+        wget -q -O "$dst" "$src"
+    else
+        echo "ERROR: need curl, fetch, or wget to download Jerboa" >&2
+        exit 1
+    fi
+}
+
+sha256_file() {
+    path=$1
+    if command -v sha256sum >/dev/null 2>&1; then
+        sha256sum "$path" | awk '{print $1}'
+    elif command -v shasum >/dev/null 2>&1; then
+        shasum -a 256 "$path" | awk '{print $1}'
+    elif command -v sha256 >/dev/null 2>&1; then
+        sha256 -q "$path"
+    else
+        echo "ERROR: need sha256sum, shasum, or sha256" >&2
+        exit 1
+    fi
+}
+
+tmp=$(mktemp -d "${TMPDIR:-/tmp}/jerboa-bootstrap.XXXXXX")
+trap 'rm -rf "$tmp"' EXIT HUP INT TERM
+
+archive="$tmp/$file"
+sum_file="$tmp/$file.sha256"
+
+echo "fetching $url"
+download "$url" "$archive"
+download "$sum_url" "$sum_file"
+
+expected=$(awk '{print $1; exit}' "$sum_file")
+actual=$(sha256_file "$archive")
+if [ "$expected" != "$actual" ]; then
+    echo "ERROR: checksum mismatch for $file" >&2
+    echo "expected: $expected" >&2
+    echo "actual:   $actual" >&2
+    exit 1
+fi
+
+mkdir -p "$tmp/extract"
+tar -xzf "$archive" -C "$tmp/extract"
+root="$tmp/extract/jerboa-${version}-${target}"
+[ -x "$root/bin/jerboa" ] || {
+    echo "ERROR: archive did not contain bin/jerboa" >&2
+    exit 1
+}
+
+mkdir -p "$bindir"
+cp "$root/bin/jerboa" "$bindir/jerboa"
+chmod 0755 "$bindir/jerboa"
+for link in jmcp jlsp jerbuild jpkg; do
+    ln -sf jerboa "$bindir/$link"
+done
+
+echo "installed $bindir/{jerboa,jmcp,jlsp,jerbuild,jpkg}"