#!/bin/sh # AgenC Marketplace kit installer (macOS / Linux). # # One-line bootstrap: # curl -fsSL https://marketplace.agenc.tech/install.sh | sh # # Windows PowerShell: # powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://marketplace.agenc.tech/install.ps1 | iex" # # What it does, deterministically (so the agent prompt doesn't have to): # - reads the signed release manifest (the "next"/canary channel endpoint), # - picks the artifact for THIS platform/arch, # - downloads it from the PUBLIC GitHub release (no GitHub auth, ever), # - verifies SHA-256 + byte size against the manifest, # - installs to ~/.agenc/bin/agenc-marketplace and makes it executable, # - installs local Claude rails and wires detected agent MCP configs. # It never touches secrets, wallets, npm, or on-chain state. set -eu MANIFEST_URL="${AGENC_MANIFEST_URL:-https://marketplace.agenc.tech/api/releases/agenc-marketplace/manifest}" INSTALL_DIR="${AGENC_INSTALL_DIR:-$HOME/.agenc/bin}" BIN_NAME="agenc-marketplace" PROJECT_DIR="${AGENC_PROJECT_DIR:-$(pwd)}" say() { printf '%s\n' "$*" >&2; } die() { printf 'error: %s\n' "$*" >&2; exit 1; } need() { command -v "$1" >/dev/null 2>&1 || die "required tool not found: $1"; } need curl # --- detect platform/arch ------------------------------------------------- os="$(uname -s)" case "$os" in Darwin) platform="macos" ;; Linux) platform="linux" ;; *) die "unsupported OS: $os (this installer covers macOS and Linux; on Windows run: powershell -NoProfile -ExecutionPolicy Bypass -Command \"irm https://marketplace.agenc.tech/install.ps1 | iex\")" ;; esac machine="$(uname -m)" case "$machine" in arm64|aarch64) arch="arm64" ;; x86_64|amd64) arch="x64" ;; *) die "unsupported architecture: $machine" ;; esac # sha256 helper (Linux: sha256sum, macOS: shasum -a 256) if command -v sha256sum >/dev/null 2>&1; then sha_cmd="sha256sum"; elif command -v shasum >/dev/null 2>&1; then sha_cmd="shasum -a 256"; else die "need sha256sum or shasum for integrity verification"; fi sha_of() { $sha_cmd "$1" | awk '{print $1}'; } say "AgenC installer: platform=${platform} arch=${arch}" say "manifest: ${MANIFEST_URL}" manifest="$(curl -fsSL "$MANIFEST_URL")" || die "could not fetch release manifest" # --- resolve the artifact for this platform/arch -------------------------- # Prefer jq, then python3, else fall back to the storefront's per-artifact # integrity header. The expected filename is deterministic. want_file="${BIN_NAME}-${platform}-${arch}" url=""; sha=""; size=""; tag="" if command -v jq >/dev/null 2>&1; then tag="$(printf '%s' "$manifest" | jq -r '.tag // empty')" sel="$(printf '%s' "$manifest" | jq -r --arg p "$platform" --arg a "$arch" \ '.artifacts[] | select(.platform==$p and .arch==$a and (.kind=="cli")) | "\(.url)\t\(.sha256)\t\(.size)\t\(.filename)"' | head -n1)" if [ -n "$sel" ]; then url="$(printf '%s' "$sel" | cut -f1)"; sha="$(printf '%s' "$sel" | cut -f2)" size="$(printf '%s' "$sel" | cut -f3)"; want_file="$(printf '%s' "$sel" | cut -f4)" fi elif command -v python3 >/dev/null 2>&1; then out="$(printf '%s' "$manifest" | AGENC_P="$platform" AGENC_A="$arch" python3 -c ' import json,os,sys m=json.load(sys.stdin); p=os.environ["AGENC_P"]; a=os.environ["AGENC_A"] for art in m.get("artifacts",[]): if art.get("platform")==p and art.get("arch")==a and art.get("kind")=="cli": print("\t".join([art["url"],art["sha256"],str(art["size"]),art["filename"],m.get("tag","")])); break ')" if [ -n "$out" ]; then url="$(printf '%s' "$out" | cut -f1)"; sha="$(printf '%s' "$out" | cut -f2)" size="$(printf '%s' "$out" | cut -f3)"; want_file="$(printf '%s' "$out" | cut -f4)" tag="$(printf '%s' "$out" | cut -f5)" fi fi base="$(printf '%s' "$MANIFEST_URL" | sed 's#/api/releases/.*##')" artifact_endpoint="${base}/api/releases/agenc-marketplace/artifacts/${want_file}" if [ -z "$url" ]; then # Dependency-free fallback: use the storefront artifact endpoint, whose # response carries the manifest SHA-256 in a header. say "jq/python3 not found - using the storefront artifact endpoint for integrity" sha="$(curl -fsSLI "$artifact_endpoint" | tr -d '\r' | awk -F': ' 'tolower($1)=="x-agenc-release-artifact-sha256"{print $2}')" [ -n "$sha" ] || die "could not resolve expected SHA-256 for ${want_file}" url="$artifact_endpoint" fi [ -n "$url" ] || die "no artifact in the manifest for ${platform}/${arch}" say "release: ${tag:-unknown} artifact: ${want_file}" # --- download + verify ---------------------------------------------------- tmp="$(mktemp -d "${TMPDIR:-/tmp}/agenc-install.XXXXXX")" trap 'rm -rf "$tmp"' EXIT dst="$tmp/$want_file" say "downloading..." curl -fsSL -o "$dst" "$url" || die "download failed: $url" actual_size="$(wc -c < "$dst" | tr -d ' ')" if [ -n "$size" ] && [ "$size" != "$actual_size" ]; then die "size mismatch: expected ${size}, got ${actual_size}" fi actual_sha="$(sha_of "$dst")" if [ "$(printf '%s' "$sha" | tr 'A-F' 'a-f')" != "$(printf '%s' "$actual_sha" | tr 'A-F' 'a-f')" ]; then die "SHA-256 mismatch: expected ${sha}, got ${actual_sha}" fi say "verified: sha256=${actual_sha} size=${actual_size}" # --- install -------------------------------------------------------------- mkdir -p "$INSTALL_DIR" target="$INSTALL_DIR/$BIN_NAME" chmod +x "$dst" mv -f "$dst" "$target" say "" say "installed: $target" case ":$PATH:" in *":$INSTALL_DIR:"*) say "(already on PATH)" ;; *) say "add to PATH: export PATH=\"$INSTALL_DIR:\$PATH\"" ;; esac say "" if [ "${AGENC_SKIP_AGENT_RAILS:-}" = "1" ]; then say "agent rails: skipped because AGENC_SKIP_AGENT_RAILS=1" else say "installing Claude rails into: $PROJECT_DIR" "$target" --json claude install --force --project-dir "$PROJECT_DIR" || die "Claude rails install failed" say "wiring detected agent MCP configs..." "$target" --network mainnet --json setup-agents --all-installed --force || die "agent MCP wiring failed" fi say "" say "next:" say " restart Claude Code / Claude Desktop so it reloads AgenC rails" say " in Claude Code, open the same project directory and type /agenc-init"