#!/usr/bin/env fish
# Magellan install script — fish shell
# Usage: fish install/install.fish [--no-service] [--no-hook]
set MAGELLAN_VERSION "4.9.1"
set INSTALL_SERVICE 1
set INSTALL_HOOK 1
set HOOK_THRESHOLD 15
for arg in $argv
switch $arg
case --no-service
set INSTALL_SERVICE 0
case --no-hook
set INSTALL_HOOK 0
case '*'
echo "[magellan] ERROR: Unknown flag: $arg" >&2
exit 1
end
end
function info
echo "[magellan] $argv"
end
function warn
echo "[magellan] WARN: $argv" >&2
end
function die
echo "[magellan] ERROR: $argv" >&2
exit 1
end
# ── Prerequisites ─────────────────────────────────────────────────────────
if not command -q cargo
die "Rust toolchain not found. Install from https://rustup.rs and re-run."
end
if not command -q git
die "git not found."
end
if not command -q jq
warn "jq not found — pre-commit blast-radius hook requires it."
end
# ── Install binary ────────────────────────────────────────────────────────
info "Installing magellan $MAGELLAN_VERSION via cargo..."
cargo install magellan --version $MAGELLAN_VERSION --locked
set MAGELLAN_BIN (set -q CARGO_HOME; and echo "$CARGO_HOME/bin/magellan"; or echo "$HOME/.cargo/bin/magellan")
if not test -x $MAGELLAN_BIN
die "Binary not found at $MAGELLAN_BIN after install."
end
info "Installed: "(magellan --version)
# ── Directory layout ──────────────────────────────────────────────────────
set MAGELLAN_HOME "$HOME/.magellan"
set CONFIG_DIR "$HOME/.config/magellan"
mkdir -p $MAGELLAN_HOME $CONFIG_DIR
info "Data directory: $MAGELLAN_HOME"
# ── Fish environment setup ────────────────────────────────────────────────
set FISH_CONFIG_DIR "$HOME/.config/fish/conf.d"
mkdir -p $FISH_CONFIG_DIR
set ENV_FILE "$FISH_CONFIG_DIR/magellan.fish"
if not test -f $ENV_FILE
info "Writing fish env → $ENV_FILE"
echo '# Magellan environment — auto-generated by install.fish' > $ENV_FILE
echo 'set -gx MAGELLAN_HOME "$HOME/.magellan"' >> $ENV_FILE
echo '# Uncomment to set a default DB for a primary project:' >> $ENV_FILE
echo '# set -gx MAGELLAN_DB "$HOME/.magellan/myproject/myproject.db"' >> $ENV_FILE
echo '# Uncomment to set MIRAGE_DB (avoids --db on every mirage call):' >> $ENV_FILE
echo '# set -gx MIRAGE_DB "$HOME/.magellan/myproject/myproject.db"' >> $ENV_FILE
else
info "Fish env already exists at $ENV_FILE — skipping."
end
# ── Pre-commit blast-radius hook ──────────────────────────────────────────
set HOOK_SCRIPT "$HOME/.local/bin/pre-commit-blast-radius"
mkdir -p "$HOME/.local/bin"
if test $INSTALL_HOOK -eq 1
info "Installing pre-commit blast-radius hook → $HOOK_SCRIPT"
# Hook is bash for portability (git runs hooks via /bin/sh or bash)
echo '#!/usr/bin/env bash' > $HOOK_SCRIPT
echo '# Magellan blast-radius warning hook — warn only, never blocks commit.' >> $HOOK_SCRIPT
echo "# Env vars: BLAST_RADIUS_THRESHOLD (default $HOOK_THRESHOLD), BLAST_RADIUS_MAX_SYMBOLS (default 8), BLAST_RADIUS_DEPTH (default 2)" >> $HOOK_SCRIPT
cat >> $HOOK_SCRIPT << 'HOOK_EOF'
set -euo pipefail
THRESHOLD="${BLAST_RADIUS_THRESHOLD:-15}"
MAX_SYMBOLS="${BLAST_RADIUS_MAX_SYMBOLS:-8}"
DEPTH="${BLAST_RADIUS_DEPTH:-2}"
PROJECT=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")
MAGELLAN_DB="$HOME/.magellan/$PROJECT/$PROJECT.db"
[[ ! -f "$MAGELLAN_DB" ]] && exit 0
STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null \
| grep -E '\.(rs|py|c|cpp|h|hpp|ts|js|go)$' || true)
[[ -z "$STAGED" ]] && exit 0
WARNED=0; CHECKED=0
for file in $STAGED; do
[[ "$CHECKED" -ge "$MAX_SYMBOLS" ]] && break
SYMBOLS=$(magellan query --db "$MAGELLAN_DB" --file "$file" --output json 2>/dev/null \
| jq -r '.data.symbols[].name' 2>/dev/null || true)
for sym in $SYMBOLS; do
[[ "$CHECKED" -ge "$MAX_SYMBOLS" ]] && break
CHECKED=$((CHECKED + 1))
RESULT=$(magellan context impact --db "$MAGELLAN_DB" --name "$sym" --depth "$DEPTH" --output json 2>/dev/null || true)
[[ -z "$RESULT" ]] && continue
TOTAL=$(echo "$RESULT" | jq -r '.data.total_records // 0' 2>/dev/null || echo 0)
if [[ "$TOTAL" -gt "$THRESHOLD" ]]; then
[[ "$WARNED" -eq 0 ]] && echo "" && echo "BLAST RADIUS WARNING (warn-only, commit proceeds)" && echo "──────────────────────────────────────────────────"
echo " ⚠ $sym → $TOTAL symbols affected (depth $DEPTH) [$file]"
WARNED=1
fi
done
done
if [[ "$WARNED" -eq 1 ]]; then
echo ""
echo "Inspect: magellan context impact --db $MAGELLAN_DB --name <symbol> --depth 3"
echo "──────────────────────────────────────────────────"
echo ""
fi
exit 0
HOOK_EOF
chmod +x $HOOK_SCRIPT
info "Hook installed. Enable per-project: ln -sf ~/.local/bin/pre-commit-blast-radius .git/hooks/pre-commit"
end
# ── systemd user service (Linux only) ────────────────────────────────────
if test $INSTALL_SERVICE -eq 1; and command -q systemctl
set SERVICE_DIR "$HOME/.config/systemd/user"
mkdir -p $SERVICE_DIR
set SERVICE_FILE "$SERVICE_DIR/magellan.service"
echo '[Unit]' > $SERVICE_FILE
echo 'Description=Magellan code intelligence service daemon' >> $SERVICE_FILE
echo 'Documentation=https://github.com/oldnordic/magellan/blob/main/MANUAL.md' >> $SERVICE_FILE
echo 'After=network.target' >> $SERVICE_FILE
echo '' >> $SERVICE_FILE
echo '[Service]' >> $SERVICE_FILE
echo 'Type=simple' >> $SERVICE_FILE
echo 'ExecStart=%h/.cargo/bin/magellan service-daemon' >> $SERVICE_FILE
echo 'Restart=on-failure' >> $SERVICE_FILE
echo 'RestartSec=5' >> $SERVICE_FILE
echo 'KillMode=process' >> $SERVICE_FILE
echo 'TimeoutStopSec=30' >> $SERVICE_FILE
echo '' >> $SERVICE_FILE
echo '[Install]' >> $SERVICE_FILE
echo 'WantedBy=default.target' >> $SERVICE_FILE
systemctl --user daemon-reload
systemctl --user enable magellan.service
systemctl --user start magellan.service
info "systemd service enabled and started."
info "Status: systemctl --user status magellan"
end
# ── Done ──────────────────────────────────────────────────────────────────
info ""
info "Installation complete — magellan $MAGELLAN_VERSION"
info ""
info "Quick start:"
info " magellan init --path /your/project"
info " magellan watch --root /your/project/src --db ~/.magellan/<project>/<project>.db --scan-initial"
info " magellan orient --db ~/.magellan/<project>/<project>.db --repo /your/project"
info ""
info "Reload fish env: source ~/.config/fish/conf.d/magellan.fish"
info "Full manual: https://github.com/oldnordic/magellan/blob/main/MANUAL.md"