fix: rename setup.sh → install.sh; four installer gaps from #71
Some checks failed
CI / test (push) Failing after 21s

- Rename setup.sh to install.sh (standardise with cf-orch installer pattern)
- Remove hardcoded dev-machine path from activate_git_hooks(); go straight
  to .githooks/ core.hooksPath fallback — the absolute path was only valid
  on the author's machine and surprised self-hosters
- Add capture_license_key(): optional CFG-XXXX-… prompt after setup_env(),
  writes CF_LICENSE_KEY + HEIMDALL_URL into .env when a valid key is entered
- Fix next-steps port: read STREAMLIT_PORT from .env instead of hardcoding
  8501 (Docker default is 8502; users who customise the port saw a wrong URL)
- Update .env.example: STREAMLIT_PORT=8502 (Docker default, not bare-metal 8501)
- Fix stale git clone URL in docs/getting-started/installation.md:
  git.circuitforge.io → git.opensourcesolarpunk.com/Circuit-Forge/peregrine
- Update all setup.sh references across manage.sh, Makefile, CONTRIBUTING.md,
  README.md, and docs/ to install.sh

Closes #71
This commit is contained in:
pyr0ball 2026-04-05 23:33:51 -07:00
parent d2aa169dfb
commit 3458122537
11 changed files with 211 additions and 26 deletions

View file

@ -2,7 +2,7 @@
# Auto-generated by the setup wizard, or fill in manually. # Auto-generated by the setup wizard, or fill in manually.
# NEVER commit .env to git. # NEVER commit .env to git.
STREAMLIT_PORT=8501 STREAMLIT_PORT=8502
OLLAMA_PORT=11434 OLLAMA_PORT=11434
VLLM_PORT=8000 VLLM_PORT=8000
SEARXNG_PORT=8888 SEARXNG_PORT=8888

View file

@ -34,7 +34,7 @@ full instructions.
```bash ```bash
git clone https://git.opensourcesolarpunk.com/pyr0ball/peregrine.git git clone https://git.opensourcesolarpunk.com/pyr0ball/peregrine.git
cd peregrine cd peregrine
./setup.sh # installs deps, activates git hooks ./install.sh # installs deps, activates git hooks
./manage.sh start ./manage.sh start
``` ```

View file

@ -45,7 +45,7 @@ endif
PROFILE_ARG := $(if $(filter remote,$(PROFILE)),,--profile $(PROFILE)) PROFILE_ARG := $(if $(filter remote,$(PROFILE)),,--profile $(PROFILE))
setup: ## Install dependencies (Docker or Podman + NVIDIA toolkit) setup: ## Install dependencies (Docker or Podman + NVIDIA toolkit)
@bash setup.sh @bash install.sh
preflight: ## Check ports + system resources; write .env preflight: ## Check ports + system resources; write .env
@$(PYTHON) scripts/preflight.py @$(PYTHON) scripts/preflight.py

View file

@ -59,7 +59,7 @@ make start PROFILE=single-gpu
**3.** Open http://localhost:8501 — the setup wizard guides you through the rest. **3.** Open http://localhost:8501 — the setup wizard guides you through the rest.
> **macOS / Apple Silicon:** Docker Desktop must be running. For Metal GPU-accelerated inference, install Ollama natively before starting — `setup.sh` will prompt you to do this. See [Apple Silicon GPU](#apple-silicon-gpu) below. > **macOS / Apple Silicon:** Docker Desktop must be running. For Metal GPU-accelerated inference, install Ollama natively before starting — `install.sh` will prompt you to do this. See [Apple Silicon GPU](#apple-silicon-gpu) below.
> **Windows:** Not supported — use WSL2 with Ubuntu. > **Windows:** Not supported — use WSL2 with Ubuntu.
### Installing to `/opt` or other system directories ### Installing to `/opt` or other system directories
@ -103,7 +103,7 @@ After `./manage.sh setup`, log out and back in for docker group membership to ta
Docker Desktop on macOS runs in a Linux VM — it cannot access the Apple GPU. Metal-accelerated inference requires Ollama to run **natively** on the host. Docker Desktop on macOS runs in a Linux VM — it cannot access the Apple GPU. Metal-accelerated inference requires Ollama to run **natively** on the host.
`setup.sh` handles this automatically: it offers to install Ollama via Homebrew, starts it as a background service, and explains what happens next. If Ollama is running on port 11434 when you start Peregrine, preflight detects it, stubs out the Docker Ollama container, and routes inference through the native process — which uses Metal automatically. `install.sh` handles this automatically: it offers to install Ollama via Homebrew, starts it as a background service, and explains what happens next. If Ollama is running on port 11434 when you start Peregrine, preflight detects it, stubs out the Docker Ollama container, and routes inference through the native process — which uses Metal automatically.
To do it manually: To do it manually:

View file

@ -144,7 +144,7 @@ Shipped in v0.4.0. Ongoing maintenance and known decisions:
## Container Runtime ## Container Runtime
- ~~**Podman support**~~ — ✅ Done: `Makefile` auto-detects `docker compose` / `podman compose` / `podman-compose`; `compose.podman-gpu.yml` CDI override for GPU profiles; `setup.sh` detects existing Podman and skips Docker install. - ~~**Podman support**~~ — ✅ Done: `Makefile` auto-detects `docker compose` / `podman compose` / `podman-compose`; `compose.podman-gpu.yml` CDI override for GPU profiles; `install.sh` detects existing Podman and skips Docker install.
- **FastAPI migration path** — When concurrent-user scale demands it: port Streamlit pages to FastAPI + React/HTMX, keep `scripts/` layer unchanged, replace daemon threads with Celery + Redis. The `scripts/` separation already makes this clean. - **FastAPI migration path** — When concurrent-user scale demands it: port Streamlit pages to FastAPI + React/HTMX, keep `scripts/` layer unchanged, replace daemon threads with Celery + Redis. The `scripts/` separation already makes this clean.
--- ---

View file

@ -7,7 +7,7 @@ This page walks through a full Peregrine installation from scratch.
## Prerequisites ## Prerequisites
- **Git** — to clone the repository - **Git** — to clone the repository
- **Internet connection**`setup.sh` downloads Docker and other dependencies - **Internet connection**`install.sh` downloads Docker and other dependencies
- **Operating system**: Ubuntu/Debian, Fedora/RHEL, Arch Linux, or macOS (with Docker Desktop) - **Operating system**: Ubuntu/Debian, Fedora/RHEL, Arch Linux, or macOS (with Docker Desktop)
!!! warning "Windows" !!! warning "Windows"
@ -18,19 +18,19 @@ This page walks through a full Peregrine installation from scratch.
## Step 1 — Clone the repository ## Step 1 — Clone the repository
```bash ```bash
git clone https://git.circuitforge.io/circuitforge/peregrine git clone https://git.opensourcesolarpunk.com/Circuit-Forge/peregrine
cd peregrine cd peregrine
``` ```
--- ---
## Step 2 — Run setup.sh ## Step 2 — Run install.sh
```bash ```bash
bash setup.sh bash install.sh
``` ```
`setup.sh` performs the following automatically: `install.sh` performs the following automatically:
1. **Detects your platform** (Ubuntu/Debian, Fedora/RHEL, Arch, macOS) 1. **Detects your platform** (Ubuntu/Debian, Fedora/RHEL, Arch, macOS)
2. **Installs Git** if not already present 2. **Installs Git** if not already present
@ -40,10 +40,10 @@ bash setup.sh
6. **Creates `.env` from `.env.example`** — edit `.env` to customise ports and model storage paths before starting 6. **Creates `.env` from `.env.example`** — edit `.env` to customise ports and model storage paths before starting
!!! note "macOS" !!! note "macOS"
`setup.sh` installs Docker Desktop via Homebrew (`brew install --cask docker`) then exits. Open Docker Desktop, start it, then re-run the script. `install.sh` installs Docker Desktop via Homebrew (`brew install --cask docker`) then exits. Open Docker Desktop, start it, then re-run the script.
!!! note "GPU requirement" !!! note "GPU requirement"
For GPU support, `nvidia-smi` must return output before you run `setup.sh`. Install your NVIDIA driver first. The Container Toolkit installation will fail silently if the driver is not present. For GPU support, `nvidia-smi` must return output before you run `install.sh`. Install your NVIDIA driver first. The Container Toolkit installation will fail silently if the driver is not present.
--- ---
@ -107,7 +107,7 @@ The first-run wizard launches automatically. See [First-Run Wizard](first-run-wi
Only NVIDIA GPUs are supported. AMD ROCm is not currently supported. Only NVIDIA GPUs are supported. AMD ROCm is not currently supported.
Requirements: Requirements:
- NVIDIA driver installed and `nvidia-smi` working before running `setup.sh` - NVIDIA driver installed and `nvidia-smi` working before running `install.sh`
- CUDA 12.x recommended (CUDA 11.x may work but is untested) - CUDA 12.x recommended (CUDA 11.x may work but is untested)
- Minimum 8 GB VRAM for `single-gpu` profile with default models - Minimum 8 GB VRAM for `single-gpu` profile with default models
- For `dual-gpu`: GPU 0 is assigned to Ollama, GPU 1 to vLLM - For `dual-gpu`: GPU 0 is assigned to Ollama, GPU 1 to vLLM

View file

@ -12,7 +12,7 @@ Peregrine automates the full job search lifecycle: discovery, matching, cover le
# 1. Clone and install dependencies # 1. Clone and install dependencies
git clone https://git.circuitforge.io/circuitforge/peregrine git clone https://git.circuitforge.io/circuitforge/peregrine
cd peregrine cd peregrine
bash setup.sh bash install.sh
# 2. Start Peregrine # 2. Start Peregrine
make start # no GPU, API-only make start # no GPU, API-only

View file

@ -337,7 +337,7 @@ webhook_url: "https://discord.com/api/webhooks/..."
## .env ## .env
Docker port and path overrides. Created from `.env.example` by `setup.sh`. Gitignored. Docker port and path overrides. Created from `.env.example` by `install.sh`. Gitignored.
```bash ```bash
# Ports (change if defaults conflict with existing services) # Ports (change if defaults conflict with existing services)

View file

@ -0,0 +1,157 @@
# Forgejo Feedback API — Schema & Bug Bot Setup
## API Endpoints Used
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List labels | GET | `/repos/{owner}/{repo}/labels` |
| Create label | POST | `/repos/{owner}/{repo}/labels` |
| Create issue | POST | `/repos/{owner}/{repo}/issues` |
| Upload attachment | POST | `/repos/{owner}/{repo}/issues/{index}/assets` |
| Post comment | POST | `/repos/{owner}/{repo}/issues/{index}/comments` |
Base URL: `https://git.opensourcesolarpunk.com/api/v1`
---
## Issue Creation Payload
```json
POST /repos/{owner}/{repo}/issues
{
"title": "string",
"body": "markdown string",
"labels": [1, 2, 3] // array of label IDs (not names)
}
```
Response (201):
```json
{
"number": 42,
"html_url": "https://git.opensourcesolarpunk.com/pyr0ball/peregrine/issues/42"
}
```
---
## Issue Body Structure
The `build_issue_body()` function produces this markdown layout:
```markdown
## 🐛 Bug | ✨ Feature Request | 💬 Other
<user description>
### Reproduction Steps ← bug type only, when repro provided
<repro steps>
### Context
- **page:** Home
- **version:** v0.2.5-61-ga6d787f ← from `git describe`; "dev" inside Docker
- **tier:** free | paid | premium
- **llm_backend:** ollama | vllm | claude_code | ...
- **os:** Linux-6.8.0-65-generic-x86_64-with-glibc2.39
- **timestamp:** 2026-03-06T15:58:29Z
<details>
<summary>App Logs (last 100 lines)</summary>
```
... log content (PII masked) ...
```
</details>
### Recent Listings ← only when include_diag = True
- [Title @ Company](url)
---
*Submitted by: Name <email>* ← only when attribution consent checked
```
---
## Screenshot Attachment
Screenshots are uploaded as issue assets, then embedded inline via a follow-up comment:
```markdown
### Screenshot
![screenshot](https://git.opensourcesolarpunk.com/attachments/<uuid>)
```
This keeps the issue body clean and puts the screenshot in a distinct comment.
---
## Labels
| Label | Color | Applied when |
|-------|-------|-------------|
| `beta-feedback` | `#0075ca` | Always |
| `needs-triage` | `#e4e669` | Always |
| `bug` | `#d73a4a` | Type = Bug |
| `feature-request` | `#a2eeef` | Type = Feature Request |
| `question` | `#d876e3` | Type = Other |
Labels are looked up by name on each submission; missing ones are auto-created via `_ensure_labels()`.
---
## Bug Bot Account Setup
The token currently bundled in `.env` is pyr0ball's personal token. For beta distribution,
create a dedicated bot account so the token has limited scope and can be rotated independently.
### Why a bot account?
- Token gets bundled in beta testers' `.env` — shouldn't be tied to the repo owner's account
- Bot can be limited to issue write only (cannot push code, see private repos, etc.)
- Token rotation doesn't affect the owner's other integrations
### Steps (requires Forgejo admin panel — API admin access not available on this token)
1. **Create bot account** at `https://git.opensourcesolarpunk.com/-/admin/users/new`
- Username: `peregrine-bot` (or `cf-bugbot`)
- Email: a real address you control (e.g. `bot+peregrine@circuitforge.tech`)
- Set a strong password (store in your password manager)
- Check "Prohibit login" if you want a pure API-only account
2. **Add as collaborator** on `pyr0ball/peregrine`:
- Settings → Collaborators → Add `peregrine-bot` with **Write** access
- Write access is required to create labels; issue creation alone would need only Read+Comment
3. **Generate API token** (log in as the bot, or use admin impersonation):
- User Settings → Applications → Generate New Token
- Name: `peregrine-feedback`
- Scopes: `issue` (write) — no repo code access needed
- Copy the token — it won't be shown again
4. **Update environment**:
```
FORGEJO_API_TOKEN=<new bot token>
FORGEJO_REPO=pyr0ball/peregrine
FORGEJO_API_URL=https://git.opensourcesolarpunk.com/api/v1
```
Update both `.env` (dev machine) and any beta tester `.env` files.
5. **Verify** the bot can create issues:
```bash
curl -s -X POST https://git.opensourcesolarpunk.com/api/v1/repos/pyr0ball/peregrine/issues \
-H "Authorization: token <bot-token>" \
-H "Content-Type: application/json" \
-d '{"title":"[TEST] bot token check","body":"safe to close","labels":[]}'
```
Expected: HTTP 201 with `number` and `html_url` in response.
### Future: Heimdall token management
Once Heimdall is live, the bot token should be served by the license server rather than
bundled in `.env`. The app fetches it at startup using the user's license key → token is
never stored on disk and can be rotated server-side. Track as a future Heimdall feature.

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# setup.sh — Peregrine dependency installer # install.sh — Peregrine dependency installer
# Installs Docker, Docker Compose v2, and (optionally) NVIDIA Container Toolkit. # Installs Docker, Docker Compose v2, and (optionally) NVIDIA Container Toolkit.
# Supports: Ubuntu/Debian, Fedora/RHEL/CentOS, Arch Linux, macOS (Homebrew). # Supports: Ubuntu/Debian, Fedora/RHEL/CentOS, Arch Linux, macOS (Homebrew).
# Windows: not supported — use WSL2 with Ubuntu. # Windows: not supported — use WSL2 with Ubuntu.
@ -90,15 +90,11 @@ configure_git_safe_dir() {
} }
activate_git_hooks() { activate_git_hooks() {
local repo_dir hooks_installer local repo_dir
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
hooks_installer="/Library/Development/CircuitForge/circuitforge-hooks/install.sh" if [[ -d "$repo_dir/.githooks" ]]; then
if [[ -f "$hooks_installer" ]]; then
bash "$hooks_installer" --quiet
success "CircuitForge hooks activated (circuitforge-hooks)."
elif [[ -d "$repo_dir/.githooks" ]]; then
git -C "$repo_dir" config core.hooksPath .githooks git -C "$repo_dir" config core.hooksPath .githooks
success "Git hooks activated (.githooks/) — circuitforge-hooks not found, using local fallback." success "Git hooks activated (.githooks/)."
fi fi
} }
@ -341,6 +337,31 @@ setup_env() {
fi fi
} }
# ── License key (optional) ────────────────────────────────────────────────────
capture_license_key() {
[[ ! -t 0 ]] && return # skip in non-interactive installs (curl | bash)
local env_file
env_file="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.env"
[[ ! -f "$env_file" ]] && return # setup_env() creates it; nothing to write into yet
echo ""
info "License key (optional)"
echo -e " Peregrine works without a key for personal self-hosted use."
echo -e " Paid-tier users: enter your ${YELLOW}CFG-XXXX-…${NC} key to unlock cloud LLM and integrations."
echo ""
read -rp " CircuitForge license key [press Enter to skip]: " _key || true
if [[ -n "$_key" ]]; then
if echo "$_key" | grep -qE '^CFG-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$'; then
_update_env_key "$env_file" "CF_LICENSE_KEY" "$_key"
_update_env_key "$env_file" "HEIMDALL_URL" "https://license.circuitforge.tech"
success "License key saved — paid-tier features enabled."
else
warn "Key format looks wrong (expected CFG-XXXX-AAAA-BBBB-CCCC) — skipping."
info "Add it manually to .env as CF_LICENSE_KEY= later."
fi
fi
}
# ── Model weights storage ─────────────────────────────────────────────────────── # ── Model weights storage ───────────────────────────────────────────────────────
_update_env_key() { _update_env_key() {
# Portable in-place key=value update for .env files (Linux + macOS). # Portable in-place key=value update for .env files (Linux + macOS).
@ -416,8 +437,15 @@ main() {
fi fi
install_ollama_macos install_ollama_macos
setup_env setup_env
capture_license_key
configure_model_paths configure_model_paths
# Read the actual port from .env so next-steps reflects any customisation
local _script_dir _port
_script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_port="$(grep -E '^STREAMLIT_PORT=' "$_script_dir/.env" 2>/dev/null | cut -d= -f2-)"
_port="${_port:-8502}"
echo "" echo ""
success "All dependencies installed." success "All dependencies installed."
echo "" echo ""
@ -429,7 +457,7 @@ main() {
else else
echo -e " ${YELLOW}./manage.sh start --profile cpu${NC} # local Ollama inference (CPU)" echo -e " ${YELLOW}./manage.sh start --profile cpu${NC} # local Ollama inference (CPU)"
fi fi
echo -e " 2. Open ${YELLOW}http://localhost:8501${NC} — the setup wizard will guide you" echo -e " 2. Open ${YELLOW}http://localhost:${_port}${NC} — the setup wizard will guide you"
echo -e " (Tip: edit ${YELLOW}.env${NC} any time to adjust ports or model paths)" echo -e " (Tip: edit ${YELLOW}.env${NC} any time to adjust ports or model paths)"
echo "" echo ""
if groups "$USER" 2>/dev/null | grep -q docker; then if groups "$USER" 2>/dev/null | grep -q docker; then

View file

@ -84,7 +84,7 @@ case "$CMD" in
setup) setup)
info "Running dependency installer..." info "Running dependency installer..."
bash setup.sh bash install.sh
;; ;;
preflight) preflight)