#!/usr/bin/env bash # # install.sh — install Fido into ~/.fido and wire it into your shell. # # Usage: # ./install.sh # install (or re-install) into $FIDO_HOME (default ~/.fido) # FIDO_HOME=/opt/fido ./install.sh # LLMORBITER_SRC=/path/to/llmorbiter ./install.sh # ./install.sh --uninstall # remove the install and the PATH entry # ./install.sh --help # # Environment: # FIDO_HOME install directory (default: ~/.fido) # LLMORBITER_SRC path to the llmorbiter checkout (default: sibling of this repo) # BASHRC shell rc file to edit (default: ~/.bashrc) # FIDO_SKIP_DEPS=1 skip `npm install` (useful for testing) # # What it does: # 1. Copies the app into $FIDO_HOME/app # 2. Bundles the llmorbiter dep $FIDO_HOME/llmorbiter (required by "file:../llmorbiter") # 3. Copies your config to $FIDO_HOME/.env # 4. Installs the launcher at $FIDO_HOME/bin/fido # 5. Runs `npm install` for the app and for llmorbiter # 6. Adds $FIDO_HOME/bin to PATH in ~/.bashrc # # All undo/suspend state lives under $FIDO_HOME/state//. set -euo pipefail FIDO_HOME="${FIDO_HOME:-$HOME/.fido}" # Directory of this script = the repo root. SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # llmorbiter is a sibling checkout by default; override with LLMORBITER_SRC. LLMORBITER_SRC="${LLMORBITER_SRC:-$SRC_DIR/../llmorbiter}" BASHRC="${BASHRC:-$HOME/.bashrc}" PATH_MARKER_BEGIN="# >>> fido >>>" PATH_MARKER_END="# <<< fido <<<" info() { printf '\033[36m▸\033[0m %s\n' "$*"; } warn() { printf '\033[33m!\033[0m %s\n' "$*" >&2; } die() { printf '\033[31m✖\033[0m %s\n' "$*" >&2; exit 1; } usage() { sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//' } # Copy a source tree, skipping build/state noise and dotfile cruft. copy_tree() { local src="$1" dst="$2" mkdir -p "$dst" if command -v rsync >/dev/null 2>&1; then rsync -a --delete \ --exclude 'node_modules' --exclude '.git' \ --exclude '.env' --exclude '.fido-*' \ "$src/" "$dst/" else local tmp tmp="$(mktemp -d)" tar -C "$src" \ --exclude=./node_modules --exclude=./.git \ --exclude=./.env --exclude='./.fido-*' \ -cf - . | tar -C "$tmp" -xf - rm -rf "$dst" mkdir -p "$dst" cp -a "$tmp/." "$dst/" rm -rf "$tmp" fi } add_to_path() { if [ -f "$BASHRC" ] && grep -qF "$PATH_MARKER_BEGIN" "$BASHRC"; then info "PATH entry already present in $BASHRC" return fi { printf '\n%s\n' "$PATH_MARKER_BEGIN" printf '# Added by the Fido installer — makes the "fido" launcher available.\n' printf 'export PATH="%s/bin:$PATH"\n' "$FIDO_HOME" printf '%s\n' "$PATH_MARKER_END" } >> "$BASHRC" info "Added $FIDO_HOME/bin to PATH in $BASHRC" } remove_from_path() { [ -f "$BASHRC" ] || return if grep -qF "$PATH_MARKER_BEGIN" "$BASHRC"; then sed -i "/^# >>> fido >>>$/,/^# <<< fido <<<$/d" "$BASHRC" info "Removed PATH entry from $BASHRC" fi } do_install() { command -v node >/dev/null 2>&1 || die "node not found in PATH — install Node.js first." command -v npm >/dev/null 2>&1 || die "npm not found in PATH." [ -f "$SRC_DIR/src/fido.js" ] || die "src/fido.js not found — run this script from the Fido repo root." [ -f "$SRC_DIR/bin/fido" ] || die "bin/fido not found — is this a complete checkout?" [ -d "$LLMORBITER_SRC" ] || die "llmorbiter dependency not found at: $LLMORBITER_SRC Set LLMORBITER_SRC=/path/to/llmorbiter and re-run." info "Installing Fido into $FIDO_HOME" mkdir -p "$FIDO_HOME/bin" "$FIDO_HOME/state" info "Copying app -> $FIDO_HOME/app" copy_tree "$SRC_DIR" "$FIDO_HOME/app" info "Bundling llmorbiter -> $FIDO_HOME/llmorbiter" copy_tree "$LLMORBITER_SRC" "$FIDO_HOME/llmorbiter" # Config: never clobber an existing install's .env (users edit it in place). if [ -f "$FIDO_HOME/.env" ]; then info "Keeping existing $FIDO_HOME/.env" elif [ -f "$SRC_DIR/.env" ]; then cp "$SRC_DIR/.env" "$FIDO_HOME/.env" info "Copied .env -> $FIDO_HOME/.env" else cp "$SRC_DIR/.env.example" "$FIDO_HOME/.env" warn "No .env found — wrote $FIDO_HOME/.env from .env.example." warn "Edit it and set OPENROUTER_API_KEY before running fido." fi info "Installing launcher -> $FIDO_HOME/bin/fido" cp "$SRC_DIR/bin/fido" "$FIDO_HOME/bin/fido" chmod +x "$FIDO_HOME/bin/fido" if [ "${FIDO_SKIP_DEPS:-0}" = "1" ]; then warn "FIDO_SKIP_DEPS=1 — skipping npm install." else info "Installing dependencies (npm install) — this may take a moment…" ( cd "$FIDO_HOME/llmorbiter" && npm install --no-audit --no-fund ) ( cd "$FIDO_HOME/app" && npm install --no-audit --no-fund ) fi add_to_path cat </ (undo.json + suspends/) Activate in this shell: source "$BASHRC" (or just open a new terminal.) Then run, from any project directory: fido # work on the current directory fido /path/to/project # work on a specific directory Remember to set OPENROUTER_API_KEY in $FIDO_HOME/.env. EOF } do_uninstall() { remove_from_path if [ -d "$FIDO_HOME" ]; then info "Removing $FIDO_HOME" rm -rf "$FIDO_HOME" else warn "$FIDO_HOME does not exist — nothing to remove." fi info "Fido uninstalled. Open a new shell (or re-source $BASHRC) to drop the PATH entry." } case "${1:-}" in ""|--install|-i) do_install ;; --uninstall|-u) do_uninstall ;; --help|-h) usage ;; *) die "Unknown argument: $1 (try --help)" ;; esac