PlanOpticon

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

Keyboard Shortcuts

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