Setup Launcher
- Run Locally — everything on this computer (private and offline). Needs a capable machine: minimum 16 GB RAM · 8 GB VRAM · ~14 GB disk.
- Use a Cloud Provider — pick a provider from a dropdown (OpenAI, Grok, DeepSeek, Kimi, Qwen, Mistral, Groq, OpenRouter, Together, Fireworks, Gemini, Cohere, Claude), paste its API key, and go. Parsing and the project index still live on this computer; only model calls (chat/answers and, for providers that offer them, embeddings/reranking) go to the provider.
The launcher itself needs only Python 3.10+ — no packages to install — so it can run on a fresh machine and do the installing for you.
Launching the launcher
Windows: double-click launch.bat macOS/Linux: ./launch.sh
Or from any OS:
bashpython launcher/launch.py
This starts a tiny server on http://127.0.0.1:8770 (a free port is picked if that one is busy) and opens the setup page in a native Electron window — it reuses the Electron binary installed for the desktop app, so the setup UI feels like part of the app, not a website. On a truly fresh machine where Electron has never been installed, it falls back to your default browser instead (the setup page installs Electron as part of the one-time setup).
The server is bound to 127.0.0.1 only — nothing is exposed to the network. Closing the launcher window stops the Python launcher server automatically. External links in the launcher (python.org, nodejs.org, ollama.com) always open in the system browser.
The launch pad — two buttons, plain words
The page is built for non-technical users; there is no setup checklist to walk through by hand.
- Local card — shows a short guide message (what's missing, or "everything is ready") plus exactly two buttons:
- ⬇️ Install — installs everything in one go (Python env, libraries, models, Node deps, Ollama). It never auto-launches.
- 🚀 Launch — enabled only when everything is ready (
ready_local: Python env + deps + all models + Node + frontend deps). When it's greyed out the guide message says exactly what to install first. - ⬇️ Individual model downloads is tucked behind a collapsed
<details>for the rare case someone wants to grab one missing model.
- API card — a provider dropdown (OpenAI, Grok, DeepSeek, Kimi, Qwen, Mistral, Groq, OpenRouter, Together, Fireworks, Gemini, Cohere, Claude) with per-provider defaults, an API key field, Test connection and 💾 Save & Launch. No model box to fill in: once a key is pasted, the launcher calls that provider's models endpoint and fills a dropdown with every model the key can actually use (defaulting to a sensible preset), so non-technical users never type a model name by hand. The list refreshes automatically when the key changes and after a successful connection test. Saved keys are never echoed back — each saved provider shows only a ✓ badge chip, clickable to reuse that key without re-typing it.
The minimums for local mode (16 GB RAM · 8 GB VRAM) are stated in the card subtitle and in the guide message, so nobody starts a 14 GB download on a machine that can't run it.
Tabs — Launch pad and System check
The page has two tabs. 🚀 Launch pad (the default) is the two-button view above. 🩺 System check holds the detailed hardware report — the readiness score, RAM / disk / VRAM tiles, GPU-vs-CPU model placement and any warnings — so curious users can inspect the machine without cluttering the simple launch view. The report refreshes every time the tab is opened.
Python environment detection
Local mode reuses whatever Python environment already exists instead of creating a fresh one. Detection priority (used everywhere the backend actually runs — state checks, deps check, model downloads and app launch):
.venvat the repo root (the launcher-created env)venv(classic name)- any system Python 3.10+ on PATH
When the app is launched, the detected interpreter is forwarded to the Electron process as LAWYER_PYTHON; the Electron bridge (venv-manager.ts) and the CLI backend runner (scripts/run-backend.mjs) both honor it, so the backend always runs with the exact environment the launcher detected. The launcher UI shows which one is active (.venv / venv / system Python).
Model downloads — per-model
The Local card lists every model individually with its download status and size, so you can grab exactly what's missing instead of re-running the whole setup:
- BGE-M3 (embeddings, ≈2.5 GB) →
models/bge-m3 - BGE-Reranker-v2-m3 (≈1.5 GB) →
models/bge-reranker-v2-m3 - Ollama LLM (≈5.5 GB pull) —
ollama pull lfm2.5:8b
Each missing model has its own ⬇️ Download button (plus a Download all missing shortcut). Downloads stream live progress into the same log console and progress bar the full setup uses, and only fetch what you asked for.
What "Run Locally" does
Clicking ⬇️ Install streams each step live to the log console:
- Python — detects a system Python 3.10+.
- Virtual environment — reuses
.venvorvenvif either exists, otherwise creates.venvat the repo root. - Python libraries —
pip install -r backend/requirements.txtpluspython-multipart(needed for uploads), into the detected environment. - AI models — downloads the missing HuggingFace models only (
BAAI/bge-m3→models/bge-m3,BAAI/bge-reranker-v2-m3→models/bge-reranker-v2-m3) — already-present ones are skipped, so a retry after a partial download finishes the remainder quickly. - Node.js — detects Node; the app UI needs it.
- App dependencies —
npm installinfrontend/andfrontend/electron/. - Ollama — fully automated: if the CLI is missing, the official installer is downloaded and run silently (Windows:
OllamaSetup.exe /S; macOS/Linux: the official install script). The daemon is then started viaollama servein the background (if it isn't already answering onhttp://localhost:11434) and the launcher waits until the HTTP API responds before moving on. The preferred model (lfm2.5:8b, override withLAWYER_OLLAMA_MODEL) is pulled automatically when absent. Non-fatal: search/scan still work without the LLM, but the step now installs, starts and pulls by itself instead of asking you to click through an installer. - Install finishes — it does NOT launch the app. The user then clicks 🚀 Launch (enabled by the fresh state), which calls
POST /api/launchand startsnpm run dev(Electron) detached, passing the detected Python asLAWYER_PYTHON; logs go tolauncher/logs/app-*.log.
A second setup or model-download request while one is running gets 409. Failed steps are marked in red and can be retried without redoing the ones that succeeded (already-downloaded models and installed deps are detected and skipped).
What "Use a Cloud Provider" does
- Pick a provider from the dropdown (or click a ✓ chip for a provider whose key is already saved).
- Paste the API key (e.g. Anthropic
sk-ant-…, OpenAIsk-…, Groqgsk_…). The model dropdown is pre-filled with a provider default. - Test connection — the launcher sends a one-token
pingto that provider's API (POST /api/api/configurewithtest: true) and reports latency. The key is never shown again after entry and never written to logs. - 💾 Save & Launch — validates, writes
backend/api_config.json(enabled: true, provider set, git-ignored) and opens the app.
The backend's API-provider mode (docs/API_PROVIDER.md) handles the provider's chat/answers; embeddings/reranking go to the provider when it offers them, otherwise they stay local (BGE-M3 / BGE-Reranker). A full end-to-end smoke test (POST /api/api/smoke-test) is still available server-side for advanced debugging.
Configuration file
The launcher reads/writes backend/api_config.json — the same file the backend's API-provider mode reads (see docs/API_PROVIDER.md). It is git-ignored so API keys never get committed.
Files
launch.bat # Windows double-click entry (root)
launch.sh # macOS/Linux entry (root)
launcher/
launch.py # cross-platform entry: start server + open Electron/browser
electron_main.js # minimal Electron window that shows the launcher page
server.py # stdlib-only HTTP server (state, system-check, setup SSE, models, configure, smoke-test, launch)
_download_models.py# venv-run helper; downloads models with progress lines (supports a single model id)
static/index.html # the setup UI (single file, no build step)
test_launcher.py # pytest suite (no network — HTTP is mocked)
logs/ # app + setup logs (created at runtime)
downloads/ # Ollama installer cache (created at runtime)
Troubleshooting
- "Python is not installed" — install Python 3.10+ from python.org and tick Add Python to PATH, then relaunch.
- Model download fails — check the log console; retry — the helper resumes (already-downloaded files are detected and skipped).
npm installfails infrontend/electron— often a transient Electron binary download issue; retry. The app needs these deps to launch.- Ollama missing — the launcher downloads the official installer and runs it silently, then starts
ollama serveand waits forlocalhost:11434to respond before pulling the model. If the silent install fails, install manually from ollama.com, then click Retry. Chat needs Ollama; search/scan don't. - Ollama server down after install — the launcher auto-starts
ollama servein the background and logs tolauncher/logs/ollama-serve.logif it can't bind the port. - Launcher port busy — a free port is chosen automatically; the browser opens the right one.