#!/usr/bin/env bash # Robin — manage.sh # Usage: ./manage.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" APP_NAME="robin" RELEASE_BIN="$SCRIPT_DIR/src-tauri/target/release/$APP_NAME" DEBUG_BIN="$SCRIPT_DIR/src-tauri/target/debug/$APP_NAME" ICON="$SCRIPT_DIR/src-tauri/icons/128x128.png" LOG_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/tech.circuitforge.robin/logs/Robin.log" cmd="${1:-help}" # ── Helpers ─────────────────────────────────────────────────────────────────── _find_binary() { if [[ -f "$RELEASE_BIN" ]]; then echo "$RELEASE_BIN" elif [[ -f "$DEBUG_BIN" ]]; then echo "$DEBUG_BIN" else echo "" fi } _require_binary() { local bin bin="$(_find_binary)" if [[ -z "$bin" ]]; then echo "Robin binary not found. Run one of:" echo " ./manage.sh build (release, requires Node + Tauri CLI)" echo " ./manage.sh build-debug (debug, requires Rust only)" exit 1 fi echo "$bin" } # ── Commands ────────────────────────────────────────────────────────────────── case "$cmd" in run) # Run the binary in the foreground (logs to terminal). # Use this for manual testing; Ctrl+C to quit. bin="$(_require_binary)" echo "Starting Robin ($bin)..." export DISPLAY="${DISPLAY:-:0}" export RUST_LOG="${RUST_LOG:-robin_lib=info,warn}" exec "$bin" ;; start) # Start Robin in the background (daemonised via nohup). if pgrep -x "$APP_NAME" > /dev/null 2>&1; then echo "Robin is already running (PID $(pgrep -x "$APP_NAME"))" exit 0 fi bin="$(_require_binary)" echo "Starting Robin in background..." export DISPLAY="${DISPLAY:-:0}" export RUST_LOG="${RUST_LOG:-robin_lib=info,warn}" mkdir -p "$(dirname "$LOG_FILE")" nohup "$bin" >> "$LOG_FILE" 2>&1 & echo "Started (PID $!). Logs: $LOG_FILE" ;; stop) if pgrep -x "$APP_NAME" > /dev/null 2>&1; then pkill -x "$APP_NAME" echo "Robin stopped." else echo "Robin is not running." fi ;; restart) "$0" stop || true sleep 1 "$0" start ;; status) if pgrep -x "$APP_NAME" > /dev/null 2>&1; then echo "Robin is running (PID $(pgrep -x "$APP_NAME"))" else echo "Robin is not running." fi ;; logs) if [[ -f "$LOG_FILE" ]]; then tail -f "$LOG_FILE" else echo "No log file yet at $LOG_FILE" echo "Start Robin first: ./manage.sh start" fi ;; dev) echo "Starting Robin in dev mode (hot-reload)..." cd "$SCRIPT_DIR" npm run tauri dev ;; build) echo "Building Robin release binary + installers..." cd "$SCRIPT_DIR" npm run tauri build ;; build-debug) echo "Building Robin debug binary (Rust only, no Node needed)..." cargo build --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml" echo "Binary: $DEBUG_BIN" ;; test) echo "Running Rust tests..." cargo test --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml" --lib ;; install-deps) echo "Installing system dependencies (Debian/Ubuntu/Mint)..." sudo apt-get install -y \ libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev \ librsvg2-dev \ libgtk-3-dev \ libssl-dev \ pkg-config echo "Installing Rust dependencies..." cargo fetch --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml" ;; install-deps-arch) echo "Installing system dependencies (Arch/Manjaro/CachyOS)..." paru -S --needed \ webkit2gtk-4.1 \ libayatana-appindicator \ librsvg \ gtk3 \ openssl \ pkg-config cargo fetch --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml" ;; desktop-install) # Install .desktop entry so Robin appears in the system app menu. bin="$(_require_binary)" APPS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications" mkdir -p "$APPS_DIR" cat > "$APPS_DIR/robin.desktop" </dev/null || true echo "Robin added to application menu." echo "Entry: $APPS_DIR/robin.desktop" ;; desktop-remove) DESKTOP="${XDG_DATA_HOME:-$HOME/.local/share}/applications/robin.desktop" if [[ -f "$DESKTOP" ]]; then rm "$DESKTOP" update-desktop-database "$(dirname "$DESKTOP")" 2>/dev/null || true echo "Robin removed from application menu." else echo "No desktop entry found at $DESKTOP" fi ;; autostart-enable) # Start Robin automatically when the desktop session begins. bin="$(_require_binary)" AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart" mkdir -p "$AUTOSTART_DIR" cat > "$AUTOSTART_DIR/robin.desktop" <