#!/bin/sh set -eu err() { echo "capakit install: $*" >&2 exit 1 } need() { command -v "$1" >/dev/null 2>&1 || err "missing required command: $1" } expected_team_id() { echo "K9P6543F38" } target() { os=$(uname -s) arch=$(uname -m) [ "$os" = "Darwin" ] || err "only macOS is supported in this alpha" case "$arch" in arm64|aarch64) echo "aarch64-apple-darwin" ;; x86_64) if [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = "1" ]; then echo "aarch64-apple-darwin" else echo "x86_64-apple-darwin" fi ;; *) err "unsupported macOS architecture: $arch" ;; esac } sha256() { if command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}' elif command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}' else err "missing shasum or sha256sum" fi } download() { url=$1 dest=$2 curl -fsSL "$url" -o "$dest" } verify_signature() { bin=$1 team_id=$(codesign -dv --verbose=4 "$bin" 2>&1 | awk -F= '/^TeamIdentifier=/ { print $2; exit }') codesign --verify --strict "$bin" >/dev/null 2>&1 \ || err "downloaded capakit binary has an invalid code signature" [ "$team_id" = "$(expected_team_id)" ] \ || err "downloaded capakit binary was not signed by the expected CapaKit Developer ID" } profile_file() { shell_name=$(basename "${SHELL:-}") case "$shell_name" in zsh) echo "$HOME/.zshrc" ;; bash) echo "$HOME/.bashrc" ;; fish) echo "$HOME/.config/fish/conf.d/capakit.fish" ;; *) echo "$HOME/.profile" ;; esac } ensure_path() { [ "${CAPAKIT_NO_MODIFY_PATH:-0}" != "1" ] || return 0 case ":$PATH:" in *":$bin_dir:"*) return 0 ;; esac profile=$(profile_file) shell_name=$(basename "${SHELL:-}") mkdir -p "$(dirname "$profile")" if [ -f "$profile" ] && grep -q "CAPAKIT_INSTALL" "$profile"; then return 0 fi if [ "$shell_name" = "fish" ]; then { echo "" echo "# CapaKit" echo "set -gx CAPAKIT_INSTALL \"$install_root\"" echo "fish_add_path \"\$CAPAKIT_INSTALL/bin\"" } >> "$profile" else { echo "" echo "# CapaKit" echo "export CAPAKIT_INSTALL=\"$install_root\"" echo "export PATH=\"\$CAPAKIT_INSTALL/bin:\$PATH\"" } >> "$profile" fi echo "Added $bin_dir to PATH in $profile" } need curl need tar need awk need grep need chmod need codesign download_base=${CAPAKIT_DOWNLOAD_BASE_URL:-https://downloads.capakit.com/capakit} version=${CAPAKIT_VERSION:-} install_root=${CAPAKIT_INSTALL:-$HOME/.capakit} bin_dir=$install_root/bin exe=$bin_dir/capakit triple=$(target) archive=capakit-$triple.tar.gz tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/capakit-install.XXXXXXXXXX") trap 'rm -rf "$tmp_dir"' EXIT INT TERM if [ -z "$version" ] || [ "$version" = "latest" ]; then download "$download_base/latest.txt" "$tmp_dir/latest.txt" version=$(tr -d '[:space:]' < "$tmp_dir/latest.txt") fi [ -n "$version" ] || err "could not resolve latest version" case "$version" in *-dev.*|dev/*|*/dev/*) err "dev CLI builds are not installable through the public installer" ;; esac printf '%s\n' "$version" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$' \ || err "public installer only supports production versions shaped like vX.Y.Z" archive_url=$download_base/$version/$archive sums_url=$download_base/$version/SHA256SUMS download "$archive_url" "$tmp_dir/$archive" download "$sums_url" "$tmp_dir/SHA256SUMS" expected=$(grep " $archive\$" "$tmp_dir/SHA256SUMS" | awk '{print $1}') [ -n "$expected" ] || err "checksum missing for $archive" actual=$(sha256 "$tmp_dir/$archive") [ "$actual" = "$expected" ] || err "checksum mismatch for $archive" mkdir -p "$bin_dir" tar -xzf "$tmp_dir/$archive" -C "$tmp_dir" [ -f "$tmp_dir/capakit" ] || err "archive did not contain capakit" chmod +x "$tmp_dir/capakit" verify_signature "$tmp_dir/capakit" mv "$tmp_dir/capakit" "$exe" echo "CapaKit $version installed to $exe" ensure_path if command -v capakit >/dev/null 2>&1; then echo "Run 'capakit --help' to get started." else echo "Restart your shell, then run 'capakit --help'." echo "For this shell now, run: export PATH=\"$bin_dir:\$PATH\"" fi