#!/bin/sh # hmn installer for macOS Apple Silicon. No sudo or build toolchain required. # The entry point is last so a truncated transfer cannot start installation. set -eu hmn_install() { version='0.1.0' url='https://h.hmbrd.dev/releases/0.1.0/hmn-darwin-arm64.tar.gz' expected='2e460d3b9b8d1b6a550d9b7f00b89781aafbfce023ea279ff2ee0028862ba6e1' case "$(uname -s)/$(uname -m)" in Darwin/arm64) ;; *) printf '%s\n' 'This release supports macOS Apple Silicon (arm64). Run outside Rosetta.' >&2; exit 1 ;; esac : "${HOME:?HOME must be set}" root="$HOME/.local/share/hmn" bin="$HOME/.local/bin" for tool in curl tar shasum cmp; do command -v "$tool" >/dev/null 2>&1 || { printf 'Missing required command: %s\n' "$tool" >&2; exit 1; } done umask 077 mkdir -p "$root/versions" "$bin" lock="$root/install.lock" mkdir "$lock" 2>/dev/null || { printf 'Another install is running, or a stale lock exists: %s\n' "$lock" >&2; exit 1; } stage='' trap 'test -z "$stage" || rm -rf "$stage"; rmdir "$lock" 2>/dev/null || :' EXIT trap 'exit 130' INT trap 'exit 143' TERM HUP stage=$(mktemp -d "$root/versions/.install-XXXXXXXX") printf 'Downloading hmn %s for macOS Apple Silicon...\n' "$version" curl --fail --show-error --location --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 --connect-timeout 20 --max-time 600 "$url" -o "$stage/bundle.tar.gz" actual=$(shasum -a 256 "$stage/bundle.tar.gz" | awk '{print $1}') [ "$actual" = "$expected" ] || { printf '%s\n' 'Download checksum mismatch; nothing installed.' >&2; exit 1; } mkdir "$stage/files" tar -xzf "$stage/bundle.tar.gz" -C "$stage/files" for file in hmn hmn-core release.json LICENSE THIRD_PARTY_NOTICES.md UPSTREAM GO-LICENSE; do [ -f "$stage/files/$file" ] && [ ! -L "$stage/files/$file" ] || { printf 'Invalid archive: %s\n' "$file" >&2; exit 1; } done chmod 755 "$stage/files/hmn" "$stage/files/hmn-core" "$stage/files/hmn" --version "$stage/files/hmn-core" --version target="$root/versions/$version" if [ -e "$target" ] || [ -L "$target" ]; then [ -d "$target" ] && [ ! -L "$target" ] || { printf 'Invalid install path: %s\n' "$target" >&2; exit 1; } for file in hmn hmn-core release.json LICENSE THIRD_PARTY_NOTICES.md UPSTREAM GO-LICENSE; do cmp -s "$stage/files/$file" "$target/$file" || { printf 'Existing version differs: %s. Move it aside before reinstalling.\n' "$target" >&2; exit 1; } done else mv "$stage/files" "$target" fi if [ -e "$bin/hmn" ] && [ ! -L "$bin/hmn" ]; then printf 'Existing non-symlink at %s/hmn; move it aside to finish installation.\n' "$bin" >&2; exit 1 fi ln -s "$target/hmn" "$stage/hmn-link" mv -f "$stage/hmn-link" "$bin/hmn" # Standard macOS login shells load these files. Append once, without evaluating paths. case "${SHELL:-/bin/zsh}" in */bash) startup="$HOME/.bash_profile" ;; *) startup="$HOME/.zprofile" ;; esac line='export PATH="$HOME/.local/bin:$PATH"' if [ ! -e "$startup" ] || ! grep -Fq "$line" "$startup"; then printf '\n# hmn command-line tools\n%s\n' "$line" >> "$startup" fi printf '\nhmn %s installed in %s\n\n' "$version" "$bin" printf '%s\n' 'Open a new terminal, or run: export PATH="$HOME/.local/bin:$PATH"' '' 'Then:' ' hmn login # enter your token once' ' hmn --yolo # native agent' ' hmn --runtime orbstack --yolo # optional Kali download on first run' '' 'Set the target in the chat. OrbStack must already be installed for Kali.' } hmn_install