#!/usr/bin/env bash set -euo pipefail usage() { cat >&2 <<'EOF' Usage: deploy/semantic-index/install.sh [--dry-run] [--apply] [--start] [--no-system] [--skip-deps] Modes: --dry-run Print commands that would run. This is the default. --apply Install files, venv, dependencies, env template, and systemd units. --start With --apply, reload systemd and start only semantic-index.service. --no-system Skip sudo/systemd operations. Useful for tests and local validation. --skip-deps Skip venv creation and dependency install. The installer never runs backfill, never enables the refresh timer, and never passes --force-rebuild. EOF } mode=dry-run start_service=0 system_ops=1 skip_deps=0 while [[ $# -gt 0 ]]; do case "$1" in --dry-run) mode=dry-run shift ;; --apply) mode=apply shift ;; --start) start_service=1 shift ;; --no-system) system_ops=0 shift ;; --skip-deps) skip_deps=1 shift ;; -h|--help) usage exit 0 ;; *) usage exit 2 ;; esac done if [[ "$start_service" -eq 1 && "$mode" != "apply" ]]; then echo "--start requires --apply" >&2 exit 2 fi repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) install_dir=${SEMANTIC_INDEX_INSTALL_DIR:-/opt/semantic-index} env_file=${SEMANTIC_INDEX_ENV_FILE:-/etc/semantic-index.env} state_dir=${SEMANTIC_INDEX_STATE_DIR:-/var/lib/semantic-index} log_dir=${SEMANTIC_INDEX_LOG_DIR:-/var/log/semantic-index} systemd_dir=${SEMANTIC_INDEX_SYSTEMD_DIR:-/etc/systemd/system} python_bin=${PYTHON:-python3} run() { if [[ "$mode" == "dry-run" ]]; then printf 'would run:' printf ' %q' "$@" printf '\n' else "$@" fi } run_sudo() { if [[ "$system_ops" -eq 0 ]]; then run "$@" else run sudo "$@" fi } install_env_template() { if [[ "$mode" == "dry-run" ]]; then echo "would copy env template only if missing: $env_file" return fi if [[ -e "$env_file" ]]; then echo "keeping existing $env_file" return fi if [[ "$system_ops" -eq 0 ]]; then mkdir -p "$(dirname "$env_file")" cp "$repo_root/deploy/semantic-index/semantic-index.env.example" "$env_file" else sudo install -m 0640 "$repo_root/deploy/semantic-index/semantic-index.env.example" "$env_file" fi } print_next_steps_warning() { cat <