#!/usr/bin/env bash # # SourceVault one-line installer for Ubuntu/Debian Linux and WSL2 Ubuntu: # # curl -fsSL https://sourcevault.ai/install.sh | bash # # Pass installer flags after `-s --`, e.g. a preview without changes: # # curl -fsSL https://sourcevault.ai/install.sh | bash -s -- --dry-run # # What it does: downloads the latest SourceVault release tarball (published # on the public Homebrew tap's releases), verifies its sha256, extracts it # to ~/.sourcevault/app (preserving any existing index/history state), and # hands off to the bundled scripts/setup/install.sh — which installs # dependencies (Node 24, Ollama; no vector database — vectors live in a # local SQLite file, ChromaDB only with --with-chroma), generates secrets, # and registers systemd user services. macOS users: use Homebrew instead — # brew install sourcevault-ai/tap/sourcevault set -euo pipefail RELEASES_API="https://api.github.com/repos/sourcevault-ai/homebrew-tap/releases/latest" APP_HOME="${SOURCEVAULT_HOME:-$HOME/.sourcevault/app}" say() { printf '\033[1m[sourcevault]\033[0m %s\n' "$*"; } fail() { printf '\033[31m[sourcevault] %s\033[0m\n' "$*" >&2; exit 1; } case "$(uname -s)" in Linux) ;; Darwin) fail "On macOS, install with Homebrew: brew install sourcevault-ai/tap/sourcevault" ;; *) fail "Unsupported platform: $(uname -s). Supported: Ubuntu/Debian Linux, WSL2 Ubuntu, macOS (Homebrew)." ;; esac command -v curl >/dev/null 2>&1 || fail "curl is required" command -v tar >/dev/null 2>&1 || fail "tar is required" command -v sha256sum >/dev/null 2>&1 || fail "sha256sum is required (coreutils)" # ---- Resolve and download the latest release -------------------------------- say "Looking up the latest release…" RELEASE_JSON="$(curl -fsSL "$RELEASES_API")" || fail "could not reach GitHub releases API" TARBALL_URL="$(printf '%s' "$RELEASE_JSON" | grep -o '"browser_download_url": *"[^"]*\.tar\.gz"' | grep -v '\.sha256' | head -1 | sed 's/.*"\(https[^"]*\)"/\1/')" SHA_URL="$(printf '%s' "$RELEASE_JSON" | grep -o '"browser_download_url": *"[^"]*\.tar\.gz\.sha256"' | head -1 | sed 's/.*"\(https[^"]*\)"/\1/')" [[ -n "$TARBALL_URL" && -n "$SHA_URL" ]] || fail "could not find a release tarball — see https://sourcevault.ai/install/" VERSION="$(basename "$TARBALL_URL" .tar.gz)" say "Downloading $VERSION…" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT curl -fsSL -o "$WORK/app.tar.gz" "$TARBALL_URL" curl -fsSL -o "$WORK/app.tar.gz.sha256" "$SHA_URL" say "Verifying sha256…" EXPECTED="$(tr -d ' \n' < "$WORK/app.tar.gz.sha256")" ACTUAL="$(sha256sum "$WORK/app.tar.gz" | awk '{print $1}')" [[ "$EXPECTED" == "$ACTUAL" ]] || fail "sha256 mismatch (expected $EXPECTED, got $ACTUAL) — aborting" # ---- Extract, preserving state from a previous install ---------------------- say "Installing to $APP_HOME…" tar -xzf "$WORK/app.tar.gz" -C "$WORK" # extracts to $WORK/sourcevault if [[ -d "$APP_HOME/.sourcevault" ]]; then say "Preserving existing state (.sourcevault) across the update" mv "$APP_HOME/.sourcevault" "$WORK/sourcevault/.sourcevault" fi mkdir -p "$(dirname "$APP_HOME")" rm -rf "$APP_HOME" mv "$WORK/sourcevault" "$APP_HOME" # ---- Hand off to the real installer ------------------------------------------ # Default to a non-interactive dashboard install; any explicit flags win. ARGS=("$@") if [[ ${#ARGS[@]} -eq 0 ]]; then ARGS=(-y --dashboard-only) fi say "Running the SourceVault installer (${ARGS[*]})…" cd "$APP_HOME" exec bash scripts/setup/install.sh "${ARGS[@]}"