# scripts — local install & run One-command setup and launch for the prospector operator app on this machine. All are reachable through `./run` (preferred) or by direct execution. | Script | `./run` | Purpose | |--------|---------|---------| | `install.sh` | `./run install` | Deps → env files → DB + migrations → build API + web → tray app → MCP. Idempotent. `--launch` opens the app after. Skip steps with `SKIP_DB`/`SKIP_TRAY`/`SKIP_MCP`. | | `app.sh` | `./run app` | Start API + the vite-preview front door, health-check, open Chrome as an app window. `--build` rebuilds first; `--detach` runs in the background (used by the tray). Reuses an already-running instance. | | `stop.sh` | `./run stop` | Stop the detached app — kills only the PIDs in `.run/app.pids`, never a blanket node kill. | | `make-tray.sh` | `./run tray` | Build the `Prospector.app` menu-bar tray (~/Applications): ❖ status icon with Open / Stop / Quit. AppleScript-ObjC + built-in icon tooling, no Swift/deps. | | `migrate.sh` | `./run db:migrate` | Apply pending `migrations/*.sql`, tracked in a `_prospector_migrations` ledger (each file runs once). | | `lib.sh` | — | Shared helpers (logging, `.env.local` loading, psql locating). Sourced, not run. | | `mcp/install-mcp.sh` | `./run install:mcp` | Register the agent/coworker MCP ("prospector") into Claude Desktop + global `~/.claude/mcp-config.json` (for Claude Code / desktop coworker). Builds the mcp package, handles secrets from .env or vault, safe edits. | ## Quick start ```bash ./run install --launch # set up everything and open the app # or, step by step: ./run install # set up ./run app # launch + open the Chrome app window ./run install:mcp # (separate) register the prospector MCP for agents in Claude ``` ## Requirements - **Node 20+** and **npm**. - **PostgreSQL** reachable per `.env.local` (`PROSPECTOR_DB_*`). The installer finds `psql` on PATH or in common macOS installs (Homebrew, Postgres.app); set `PSQL=/path/to/psql` to override. No psql → DB step is skipped with a hint. - **Google Chrome** for the app-window experience (falls back to default browser). ## How the pieces fit - The **API** (`dist/main.js`) listens on `PROSPECTOR_API_PORT` (3210) and owns its Postgres DB. Routes are guarded by a bearer service token. - The **panel** is the built `web/dist`, served by `vite preview`, which proxies `/api/*` → the API and injects the token (so it never lives in browser JS). This is the same proxy `vite` uses in dev — see `web/vite.config.ts`. - `app.sh` starts both, waits for `/health`, then opens `http://localhost:/#/markets` as a Chrome `--app` window. Ctrl-C stops only the processes it started (never a blanket node kill). ## Env files (created by the installer if absent) - `.env.local` — API config (port, `PROSPECTOR_DB_*`, service token, upstreams). - `web/.env.local` — `PROSPECTOR_API_URL` + `PROSPECTOR_SERVICE_TOKEN` for the panel proxy. Keep its token equal to the API's. Re-running `install` never overwrites existing env files. ## Remote / mesh access (optional, gated) By default the panel binds **localhost only** — not reachable from the mesh. To use it from another mesh host (this laptop is `10.9.0.3` on the WG mesh): 1. **Set a passcode** in `web/.env.local` — the panel has no login of its own, so this gate is required before exposing it: ``` PROSPECTOR_PANEL_PASSCODE=your-passcode ``` Empty = gate off (localhost-only). The passcode is checked by the `vite preview` front door (HMAC cookie, HttpOnly); the service token is never injected until a valid session exists. 2. **Bind beyond localhost** and relaunch: ``` ./run stop && ./run app --host # all interfaces (mesh + LAN) ./run app --host=10.9.0.3 # mesh IP only ``` Then open `http://10.9.0.3:4173/#/markets` from the other host and enter the passcode. `./run app --host` without a passcode set prints a loud warning. The API itself (`:3210`) is bearer-guarded regardless; only the panel front door needs the passcode. The API does not need to be mesh-exposed — the panel proxies to it over localhost.