feat(distribution): binary release pipeline + brew + winget
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

- .github/workflows/release-cli.yml: build self-contained binaries via
  `bun build --compile` for darwin/linux/windows × x64/arm64 on every
  cli-v* tag, attach to GitHub Release with SHA256SUMS, auto-bump the
  homebrew tap on non-prerelease versions.
- packaging/homebrew/claudemesh.rb.template: formula template for the
  homebrew-claudemesh tap.
- packaging/winget/claudemesh.yaml.template: winget manifest template.
- /install script now detects absence of Node and downloads the
  platform-appropriate binary from the GitHub Release, installs to
  ~/.claudemesh/bin, and shims into ~/.local/bin — zero Node required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-15 02:42:16 +01:00
parent 43f2728283
commit ccf95ff382
4 changed files with 275 additions and 33 deletions

View File

@@ -30,42 +30,87 @@ say "\${BOLD}claudemesh-cli installer\${RESET}"
say "$(printf '%.0s─' {1..40})"
# --- preflight ------------------------------------------------------
# Prefer npm when Node 20+ is present. Otherwise fall back to a
# self-contained binary download from GitHub Releases (installs to
# ~/.claudemesh/bin and adds a shim at ~/.local/bin/claudemesh).
if ! command -v node >/dev/null 2>&1; then
err "Node.js is not installed."
say " Install Node.js 20 or newer: \${BOLD}https://nodejs.org\${RESET}"
say " Or via nvm: \${DIM}curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash\${RESET}"
exit 1
detect_os() {
case "$(uname -s)" in
Darwin) echo darwin ;;
Linux) echo linux ;;
*) echo "" ;;
esac
}
detect_arch() {
case "$(uname -m)" in
x86_64|amd64) echo x64 ;;
arm64|aarch64) echo arm64 ;;
*) echo "" ;;
esac
}
install_via_binary() {
local os arch url target dir shim
os=$(detect_os); arch=$(detect_arch)
if [ -z "$os" ] || [ -z "$arch" ]; then
err "No precompiled binary for $(uname -s)/$(uname -m). Install Node 20+ or build from source."
exit 1
fi
dir="\${HOME}/.claudemesh/bin"
mkdir -p "$dir"
target="\${dir}/claudemesh"
url="https://github.com/alezmad/claudemesh/releases/latest/download/claudemesh-\${os}-\${arch}"
say "Downloading \${BOLD}\${url}\${RESET}…"
if ! curl -fsSL "$url" -o "$target"; then
err "Download failed. Falling back to npm."
return 1
fi
chmod +x "$target"
shim="\${HOME}/.local/bin/claudemesh"
mkdir -p "\${HOME}/.local/bin"
printf '#!/bin/sh\\nexec "%s" "$@"\\n' "$target" > "$shim"
chmod +x "$shim"
ok "claudemesh binary installed → \${target}"
case ":$PATH:" in
*":\${HOME}/.local/bin:"*) : ;;
*)
say ""
say "\${BOLD}Add \${HOME}/.local/bin to PATH\${RESET} (add to your shell rc):"
say " export PATH=\\"\${HOME}/.local/bin:\$PATH\\""
;;
esac
return 0
}
install_via_npm() {
ok "Node.js $(node -v)"
ok "npm $(npm -v)"
say ""
say "Installing \${BOLD}claudemesh-cli\${RESET} from npm…"
if ! npm install -g claudemesh-cli; then
err "npm install failed."
say " If this is a permissions error on macOS/Linux, try:"
say " \${DIM}sudo npm install -g claudemesh-cli\${RESET}"
say " or configure npm to use a user-owned prefix:"
say " \${DIM}https://docs.npmjs.com/resolving-eacces-permissions-errors\${RESET}"
exit 1
fi
ok "claudemesh-cli installed ($(claudemesh --version))"
}
if command -v node >/dev/null 2>&1; then
NODE_MAJOR=$(node -p "process.versions.node.split('.')[0]" 2>/dev/null || echo 0)
if [ "$NODE_MAJOR" -ge 20 ] && command -v npm >/dev/null 2>&1; then
install_via_npm
else
say "Node.js < 20 or no npm — using standalone binary."
install_via_binary || install_via_npm
fi
else
say "Node.js not detected — installing standalone binary (no Node required)."
install_via_binary
fi
NODE_MAJOR=$(node -p "process.versions.node.split('.')[0]")
if [ "$NODE_MAJOR" -lt 20 ]; then
err "Node.js $(node -v) is too old — claudemesh-cli needs >= 20."
say " Upgrade: \${BOLD}https://nodejs.org\${RESET}"
exit 1
fi
ok "Node.js $(node -v)"
if ! command -v npm >/dev/null 2>&1; then
err "npm is not installed (usually ships with Node)."
exit 1
fi
ok "npm $(npm -v)"
# --- install --------------------------------------------------------
say ""
say "Installing \${BOLD}claudemesh-cli\${RESET} from npm…"
if ! npm install -g claudemesh-cli; then
err "npm install failed."
say " If this is a permissions error on macOS/Linux, try:"
say " \${DIM}sudo npm install -g claudemesh-cli\${RESET}"
say " or configure npm to use a user-owned prefix:"
say " \${DIM}https://docs.npmjs.com/resolving-eacces-permissions-errors\${RESET}"
exit 1
fi
ok "claudemesh-cli installed ($(claudemesh --version))"
# --- register MCP + hooks ------------------------------------------
say ""