PlanOpticon

planopticon / install.sh
Source Blame History 375 lines
42e9b20… noreply 1 #!/usr/bin/env bash
42e9b20… noreply 2 # PlanOpticon installer — cross-platform one-command setup
42e9b20… noreply 3 # Usage: curl -fsSL https://planopticon.dev/install.sh | bash
42e9b20… noreply 4 #
42e9b20… noreply 5 # Supports: macOS (Homebrew), Ubuntu/Debian (apt), Fedora/RHEL (dnf), Arch (pacman)
42e9b20… noreply 6 # Idempotent — safe to re-run.
42e9b20… noreply 7
42e9b20… noreply 8 set -euo pipefail
42e9b20… noreply 9
42e9b20… noreply 10 # --- Colors & helpers --------------------------------------------------------
42e9b20… noreply 11
42e9b20… noreply 12 RED='\033[0;31m'
42e9b20… noreply 13 GREEN='\033[0;32m'
42e9b20… noreply 14 YELLOW='\033[1;33m'
42e9b20… noreply 15 BLUE='\033[0;34m'
42e9b20… noreply 16 BOLD='\033[1m'
42e9b20… noreply 17 NC='\033[0m'
42e9b20… noreply 18
42e9b20… noreply 19 info() { printf "${BLUE}[info]${NC} %s\n" "$*"; }
42e9b20… noreply 20 ok() { printf "${GREEN}[ok]${NC} %s\n" "$*"; }
42e9b20… noreply 21 warn() { printf "${YELLOW}[warn]${NC} %s\n" "$*"; }
42e9b20… noreply 22 err() { printf "${RED}[error]${NC} %s\n" "$*" >&2; }
42e9b20… noreply 23 step() { printf "\n${BOLD}==> %s${NC}\n" "$*"; }
42e9b20… noreply 24
42e9b20… noreply 25 command_exists() { command -v "$1" >/dev/null 2>&1; }
42e9b20… noreply 26
42e9b20… noreply 27 # --- Detect OS & package manager ---------------------------------------------
42e9b20… noreply 28
42e9b20… noreply 29 detect_os() {
42e9b20… noreply 30 case "$(uname -s)" in
42e9b20… noreply 31 Darwin) OS="macos" ;;
42e9b20… noreply 32 Linux)
42e9b20… noreply 33 if [ -f /etc/os-release ]; then
42e9b20… noreply 34 . /etc/os-release
42e9b20… noreply 35 case "$ID" in
42e9b20… noreply 36 ubuntu|debian|pop|linuxmint|elementary) OS="debian" ;;
42e9b20… noreply 37 fedora|rhel|centos|rocky|alma) OS="fedora" ;;
42e9b20… noreply 38 arch|manjaro|endeavouros) OS="arch" ;;
42e9b20… noreply 39 *) OS="linux-unknown" ;;
42e9b20… noreply 40 esac
42e9b20… noreply 41 else
42e9b20… noreply 42 OS="linux-unknown"
42e9b20… noreply 43 fi
42e9b20… noreply 44 ;;
42e9b20… noreply 45 MINGW*|MSYS*|CYGWIN*)
42e9b20… noreply 46 err "Windows detected. Please use install.ps1 instead:"
42e9b20… noreply 47 err " irm https://planopticon.dev/install.ps1 | iex"
42e9b20… noreply 48 exit 1
42e9b20… noreply 49 ;;
42e9b20… noreply 50 *)
42e9b20… noreply 51 err "Unsupported OS: $(uname -s)"
42e9b20… noreply 52 exit 1
42e9b20… noreply 53 ;;
42e9b20… noreply 54 esac
42e9b20… noreply 55 }
42e9b20… noreply 56
42e9b20… noreply 57 # --- Python ------------------------------------------------------------------
42e9b20… noreply 58
42e9b20… noreply 59 MIN_PYTHON_MAJOR=3
42e9b20… noreply 60 MIN_PYTHON_MINOR=10
42e9b20… noreply 61
42e9b20… noreply 62 find_python() {
42e9b20… noreply 63 for cmd in python3 python; do
42e9b20… noreply 64 if command_exists "$cmd"; then
42e9b20… noreply 65 local ver
42e9b20… noreply 66 ver=$("$cmd" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null) || continue
42e9b20… noreply 67 local major minor
42e9b20… noreply 68 major=$(echo "$ver" | cut -d. -f1)
42e9b20… noreply 69 minor=$(echo "$ver" | cut -d. -f2)
42e9b20… noreply 70 if [ "$major" -ge "$MIN_PYTHON_MAJOR" ] && [ "$minor" -ge "$MIN_PYTHON_MINOR" ]; then
42e9b20… noreply 71 PYTHON="$cmd"
42e9b20… noreply 72 PYTHON_VERSION="$ver"
42e9b20… noreply 73 return 0
42e9b20… noreply 74 fi
42e9b20… noreply 75 fi
42e9b20… noreply 76 done
42e9b20… noreply 77 return 1
42e9b20… noreply 78 }
42e9b20… noreply 79
42e9b20… noreply 80 install_python() {
42e9b20… noreply 81 step "Installing Python 3.10+"
42e9b20… noreply 82 case "$OS" in
42e9b20… noreply 83 macos)
42e9b20… noreply 84 if command_exists brew; then
42e9b20… noreply 85 brew install [email protected]
42e9b20… noreply 86 else
42e9b20… noreply 87 err "Homebrew not found. Install it first: https://brew.sh"
42e9b20… noreply 88 exit 1
42e9b20… noreply 89 fi
42e9b20… noreply 90 ;;
42e9b20… noreply 91 debian)
42e9b20… noreply 92 sudo apt-get update -qq
42e9b20… noreply 93 sudo apt-get install -y -qq python3 python3-pip python3-venv
42e9b20… noreply 94 ;;
42e9b20… noreply 95 fedora)
42e9b20… noreply 96 sudo dnf install -y -q python3 python3-pip
42e9b20… noreply 97 ;;
42e9b20… noreply 98 arch)
42e9b20… noreply 99 sudo pacman -S --noconfirm python python-pip
42e9b20… noreply 100 ;;
42e9b20… noreply 101 *)
42e9b20… noreply 102 err "Cannot auto-install Python on this OS."
42e9b20… noreply 103 err "Please install Python ${MIN_PYTHON_MAJOR}.${MIN_PYTHON_MINOR}+ manually."
42e9b20… noreply 104 exit 1
42e9b20… noreply 105 ;;
42e9b20… noreply 106 esac
42e9b20… noreply 107 }
42e9b20… noreply 108
42e9b20… noreply 109 # --- FFmpeg ------------------------------------------------------------------
42e9b20… noreply 110
42e9b20… noreply 111 install_ffmpeg() {
42e9b20… noreply 112 step "Installing FFmpeg"
42e9b20… noreply 113 case "$OS" in
42e9b20… noreply 114 macos)
42e9b20… noreply 115 if command_exists brew; then
42e9b20… noreply 116 brew install ffmpeg
42e9b20… noreply 117 else
42e9b20… noreply 118 err "Homebrew not found. Install it first: https://brew.sh"
42e9b20… noreply 119 exit 1
42e9b20… noreply 120 fi
42e9b20… noreply 121 ;;
42e9b20… noreply 122 debian)
42e9b20… noreply 123 sudo apt-get update -qq
42e9b20… noreply 124 sudo apt-get install -y -qq ffmpeg
42e9b20… noreply 125 ;;
42e9b20… noreply 126 fedora)
42e9b20… noreply 127 sudo dnf install -y -q ffmpeg-free || {
42e9b20… noreply 128 warn "ffmpeg-free not available, trying RPM Fusion..."
42e9b20… noreply 129 sudo dnf install -y -q \
42e9b20… noreply 130 "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" 2>/dev/null || true
42e9b20… noreply 131 sudo dnf install -y -q ffmpeg
42e9b20… noreply 132 }
42e9b20… noreply 133 ;;
42e9b20… noreply 134 arch)
42e9b20… noreply 135 sudo pacman -S --noconfirm ffmpeg
42e9b20… noreply 136 ;;
42e9b20… noreply 137 *)
42e9b20… noreply 138 err "Cannot auto-install FFmpeg on this OS."
42e9b20… noreply 139 err "Please install FFmpeg manually: https://ffmpeg.org/download.html"
42e9b20… noreply 140 exit 1
42e9b20… noreply 141 ;;
42e9b20… noreply 142 esac
42e9b20… noreply 143 }
42e9b20… noreply 144
42e9b20… noreply 145 # --- Ollama (optional) -------------------------------------------------------
42e9b20… noreply 146
42e9b20… noreply 147 install_ollama() {
42e9b20… noreply 148 step "Installing Ollama"
42e9b20… noreply 149 if command_exists ollama; then
42e9b20… noreply 150 ok "Ollama already installed"
42e9b20… noreply 151 return 0
42e9b20… noreply 152 fi
42e9b20… noreply 153 case "$OS" in
42e9b20… noreply 154 macos)
42e9b20… noreply 155 if command_exists brew; then
42e9b20… noreply 156 brew install ollama
42e9b20… noreply 157 else
42e9b20… noreply 158 curl -fsSL https://ollama.com/install.sh | sh
42e9b20… noreply 159 fi
42e9b20… noreply 160 ;;
42e9b20… noreply 161 debian|fedora|arch|linux-unknown)
42e9b20… noreply 162 curl -fsSL https://ollama.com/install.sh | sh
42e9b20… noreply 163 ;;
42e9b20… noreply 164 esac
42e9b20… noreply 165 }
42e9b20… noreply 166
42e9b20… noreply 167 pull_ollama_models() {
42e9b20… noreply 168 info "Pulling recommended local models..."
42e9b20… noreply 169 ollama pull llama3.2 2>/dev/null || warn "Failed to pull llama3.2"
42e9b20… noreply 170 ollama pull llava 2>/dev/null || warn "Failed to pull llava (vision model)"
42e9b20… noreply 171 ok "Ollama models ready"
42e9b20… noreply 172 }
42e9b20… noreply 173
42e9b20… noreply 174 # --- Extras selection --------------------------------------------------------
42e9b20… noreply 175
42e9b20… noreply 176 select_extras() {
42e9b20… noreply 177 EXTRAS=""
42e9b20… noreply 178 printf "\n${BOLD}Optional extras:${NC}\n"
42e9b20… noreply 179 echo " 1) core — just the basics (default)"
42e9b20… noreply 180 echo " 2) cloud — Google Drive, Dropbox, S3 integrations"
42e9b20… noreply 181 echo " 3) pdf — PDF document ingestion"
42e9b20… noreply 182 echo " 4) sources — YouTube, RSS, web scraping"
42e9b20… noreply 183 echo " 5) all — everything"
42e9b20… noreply 184 echo ""
42e9b20… noreply 185 printf "Choose extras [1-5, default=1]: "
42e9b20… noreply 186
42e9b20… noreply 187 if [ -t 0 ]; then
42e9b20… noreply 188 read -r choice
42e9b20… noreply 189 else
42e9b20… noreply 190 choice="1"
42e9b20… noreply 191 echo "1 (non-interactive, using default)"
42e9b20… noreply 192 fi
42e9b20… noreply 193
42e9b20… noreply 194 case "${choice:-1}" in
42e9b20… noreply 195 2) EXTRAS="[cloud]" ;;
42e9b20… noreply 196 3) EXTRAS="[pdf]" ;;
42e9b20… noreply 197 4) EXTRAS="[sources]" ;;
42e9b20… noreply 198 5) EXTRAS="[all]" ;;
42e9b20… noreply 199 *) EXTRAS="" ;;
42e9b20… noreply 200 esac
42e9b20… noreply 201 }
42e9b20… noreply 202
42e9b20… noreply 203 # --- API key setup -----------------------------------------------------------
42e9b20… noreply 204
42e9b20… noreply 205 setup_api_keys() {
42e9b20… noreply 206 step "API key setup"
42e9b20… noreply 207 local env_file=".env"
42e9b20… noreply 208
42e9b20… noreply 209 if [ -f "$env_file" ]; then
42e9b20… noreply 210 ok "Found existing .env file, skipping API key setup"
42e9b20… noreply 211 return 0
42e9b20… noreply 212 fi
42e9b20… noreply 213
42e9b20… noreply 214 if [ ! -t 0 ]; then
42e9b20… noreply 215 warn "Non-interactive mode — skipping API key setup"
42e9b20… noreply 216 info "Create a .env file with at least one API key:"
42e9b20… noreply 217 info " OPENAI_API_KEY=sk-..."
42e9b20… noreply 218 info " ANTHROPIC_API_KEY=sk-ant-..."
42e9b20… noreply 219 info " GEMINI_API_KEY=..."
42e9b20… noreply 220 return 0
42e9b20… noreply 221 fi
42e9b20… noreply 222
42e9b20… noreply 223 printf "\n${BOLD}PlanOpticon needs at least one AI provider API key.${NC}\n"
42e9b20… noreply 224 echo "You can add more later in .env"
42e9b20… noreply 225 echo ""
42e9b20… noreply 226 echo " 1) OpenAI (OPENAI_API_KEY)"
42e9b20… noreply 227 echo " 2) Anthropic (ANTHROPIC_API_KEY)"
42e9b20… noreply 228 echo " 3) Google (GEMINI_API_KEY)"
42e9b20… noreply 229 echo " 4) Ollama (local, no key needed)"
42e9b20… noreply 230 echo " 5) Skip for now"
42e9b20… noreply 231 echo ""
42e9b20… noreply 232 printf "Choose provider [1-5]: "
42e9b20… noreply 233 read -r provider_choice
42e9b20… noreply 234
42e9b20… noreply 235 case "${provider_choice:-5}" in
42e9b20… noreply 236 1)
42e9b20… noreply 237 printf "Enter your OpenAI API key: "
42e9b20… noreply 238 read -r api_key
42e9b20… noreply 239 if [ -n "$api_key" ]; then
42e9b20… noreply 240 echo "OPENAI_API_KEY=$api_key" > "$env_file"
42e9b20… noreply 241 ok "Saved to .env"
42e9b20… noreply 242 fi
42e9b20… noreply 243 ;;
42e9b20… noreply 244 2)
42e9b20… noreply 245 printf "Enter your Anthropic API key: "
42e9b20… noreply 246 read -r api_key
42e9b20… noreply 247 if [ -n "$api_key" ]; then
42e9b20… noreply 248 echo "ANTHROPIC_API_KEY=$api_key" > "$env_file"
42e9b20… noreply 249 ok "Saved to .env"
42e9b20… noreply 250 fi
42e9b20… noreply 251 ;;
42e9b20… noreply 252 3)
42e9b20… noreply 253 printf "Enter your Google/Gemini API key: "
42e9b20… noreply 254 read -r api_key
42e9b20… noreply 255 if [ -n "$api_key" ]; then
42e9b20… noreply 256 echo "GEMINI_API_KEY=$api_key" > "$env_file"
42e9b20… noreply 257 ok "Saved to .env"
42e9b20… noreply 258 fi
42e9b20… noreply 259 ;;
42e9b20… noreply 260 4)
42e9b20… noreply 261 info "Using Ollama — no API key needed"
42e9b20… noreply 262 echo "OLLAMA_HOST=http://localhost:11434" > "$env_file"
42e9b20… noreply 263 ;;
42e9b20… noreply 264 5)
42e9b20… noreply 265 warn "Skipping API key setup. Add keys to .env later."
42e9b20… noreply 266 ;;
42e9b20… noreply 267 esac
42e9b20… noreply 268 }
42e9b20… noreply 269
42e9b20… noreply 270 # --- Main --------------------------------------------------------------------
42e9b20… noreply 271
42e9b20… noreply 272 main() {
42e9b20… noreply 273 printf "\n${BOLD}PlanOpticon Installer${NC}\n"
42e9b20… noreply 274 echo "====================================="
42e9b20… noreply 275 echo ""
42e9b20… noreply 276
42e9b20… noreply 277 detect_os
42e9b20… noreply 278 info "Detected OS: $OS"
42e9b20… noreply 279
42e9b20… noreply 280 # --- Python ---
42e9b20… noreply 281 step "Checking Python"
42e9b20… noreply 282 if find_python; then
42e9b20… noreply 283 ok "Python $PYTHON_VERSION found ($PYTHON)"
42e9b20… noreply 284 else
42e9b20… noreply 285 warn "Python ${MIN_PYTHON_MAJOR}.${MIN_PYTHON_MINOR}+ not found"
42e9b20… noreply 286 install_python
42e9b20… noreply 287 if ! find_python; then
42e9b20… noreply 288 err "Python installation failed. Please install Python ${MIN_PYTHON_MAJOR}.${MIN_PYTHON_MINOR}+ manually."
42e9b20… noreply 289 exit 1
42e9b20… noreply 290 fi
42e9b20… noreply 291 ok "Python $PYTHON_VERSION installed"
42e9b20… noreply 292 fi
42e9b20… noreply 293
42e9b20… noreply 294 # --- FFmpeg ---
42e9b20… noreply 295 step "Checking FFmpeg"
42e9b20… noreply 296 if command_exists ffmpeg; then
42e9b20… noreply 297 local ffmpeg_ver
42e9b20… noreply 298 ffmpeg_ver=$(ffmpeg -version 2>/dev/null | head -1 | awk '{print $3}') || ffmpeg_ver="unknown"
42e9b20… noreply 299 ok "FFmpeg found ($ffmpeg_ver)"
42e9b20… noreply 300 else
42e9b20… noreply 301 warn "FFmpeg not found"
42e9b20… noreply 302 install_ffmpeg
42e9b20… noreply 303 if command_exists ffmpeg; then
42e9b20… noreply 304 ok "FFmpeg installed"
42e9b20… noreply 305 else
42e9b20… noreply 306 err "FFmpeg installation failed. Please install manually."
42e9b20… noreply 307 exit 1
42e9b20… noreply 308 fi
42e9b20… noreply 309 fi
42e9b20… noreply 310
42e9b20… noreply 311 # --- pip install planopticon ---
42e9b20… noreply 312 step "Installing PlanOpticon"
42e9b20… noreply 313 select_extras
42e9b20… noreply 314
42e9b20… noreply 315 local pip_target="planopticon${EXTRAS}"
42e9b20… noreply 316 info "Installing: $pip_target"
42e9b20… noreply 317
42e9b20… noreply 318 if "$PYTHON" -m pip install --upgrade "$pip_target" 2>&1; then
42e9b20… noreply 319 ok "PlanOpticon installed"
42e9b20… noreply 320 else
42e9b20… noreply 321 warn "pip install failed, trying with --user flag"
42e9b20… noreply 322 "$PYTHON" -m pip install --user --upgrade "$pip_target"
42e9b20… noreply 323 ok "PlanOpticon installed (user)"
42e9b20… noreply 324 fi
42e9b20… noreply 325
42e9b20… noreply 326 # --- Ollama (optional) ---
42e9b20… noreply 327 if [ -t 0 ]; then
42e9b20… noreply 328 printf "\n${BOLD}Would you like to install Ollama for local AI? [y/N]: ${NC}"
42e9b20… noreply 329 read -r install_ollama_choice
42e9b20… noreply 330 if [[ "${install_ollama_choice:-n}" =~ ^[Yy] ]]; then
42e9b20… noreply 331 install_ollama
42e9b20… noreply 332 if command_exists ollama; then
42e9b20… noreply 333 printf "Pull recommended models? (llama3.2 + llava, ~6GB) [y/N]: "
42e9b20… noreply 334 read -r pull_choice
42e9b20… noreply 335 if [[ "${pull_choice:-n}" =~ ^[Yy] ]]; then
42e9b20… noreply 336 pull_ollama_models
42e9b20… noreply 337 fi
42e9b20… noreply 338 fi
42e9b20… noreply 339 fi
42e9b20… noreply 340 fi
42e9b20… noreply 341
42e9b20… noreply 342 # --- API keys ---
42e9b20… noreply 343 setup_api_keys
42e9b20… noreply 344
42e9b20… noreply 345 # --- Verify ---
42e9b20… noreply 346 step "Verifying installation"
42e9b20… noreply 347 if command_exists planopticon; then
42e9b20… noreply 348 local version
42e9b20… noreply 349 version=$(planopticon --version 2>/dev/null || echo "installed")
42e9b20… noreply 350 ok "planopticon CLI ready ($version)"
42e9b20… noreply 351 else
42e9b20… noreply 352 # Might need PATH update
42e9b20… noreply 353 warn "planopticon not in PATH — you may need to restart your shell"
42e9b20… noreply 354 info "Or run: $PYTHON -m video_processor.cli.commands --version"
42e9b20… noreply 355 fi
42e9b20… noreply 356
42e9b20… noreply 357 if planopticon list-models >/dev/null 2>&1; then
42e9b20… noreply 358 ok "Provider check passed"
42e9b20… noreply 359 else
42e9b20… noreply 360 warn "No AI providers configured yet — add an API key to .env"
42e9b20… noreply 361 fi
42e9b20… noreply 362
42e9b20… noreply 363 # --- Done ---
42e9b20… noreply 364 printf "\n${GREEN}${BOLD}Installation complete!${NC}\n"
42e9b20… noreply 365 echo ""
42e9b20… noreply 366 echo "Quick start:"
42e9b20… noreply 367 echo " planopticon process video.mp4 # Analyze a video"
42e9b20… noreply 368 echo " planopticon companion # Start AI companion"
42e9b20… noreply 369 echo " planopticon list-models # Check available models"
42e9b20… noreply 370 echo ""
42e9b20… noreply 371 echo "Docs: https://planopticon.dev"
42e9b20… noreply 372 echo ""
42e9b20… noreply 373 }
42e9b20… noreply 374
42e9b20… noreply 375 main "$@"

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button