7.6 KiB
Installer Arc — Steal #5: One-Line Installer + Setup Wizard (2026-07-10)
Branch: feat/steal-5-installer (worktree .claude/worktrees/steal5-arc, off main b8c65c22).
Source: CowAgent teardown steal #5 (docs/analysis/cowagent-vs-waggle-2026-07-09.md §2.5).
Orchestration: Fable plans/gates/verifies; Opus executes; adversarial Opus verifier before merge.
Recon basis: 3 recon agents (sidecar boot surface · existing deploy story · CowAgent run.sh patterns), 2026-07-10.
1. Problem
Waggle has three run stories today: Tauri desktop binary (individuals), Docker team stack (Postgres/Redis/MinIO/Clerk — heavy), and "clone + two dev terminals" in README. There is no one-command headless self-host story for the solo sidecar — the exact surface the OSS funnel audience (VPS / homelab) needs, and the surface the channels arc (steal #4) just made valuable ("Waggle agent in my Telegram, on my server").
Verified facts the design leans on (recon, 2026-07-10):
- Solo sidecar =
packages/server/src/local/start.ts→service.ts:startService(). Default port 3333, binds loopback. Health at/health. Writesserver.pidunder dataDir already. - Zero required env. dataDir defaults
~/.waggle; vault (AES-256-GCM) is the canonical key store;WAGGLE_SKIP_LITELLM=1skips the optional Python LiteLLM subprocess entirely. - Zero-key boot confirmed: provider chain litellm → built-in anthropic-proxy → Ollama →
degraded;/api/chatecho mode keeps UI functional with no key (chat.ts:823-941). - Fresh-clone sequence:
npm install→npm run build:packages(mandatory — shared + hive-mind-core export only dist/) → optionallynpm run build(web UI; server serves SPA via dist candidate list orWAGGLE_FRONTEND_DIR,index.ts:2475-2505). - Web OnboardingWizard (model-gate step) already owns first-run API-key entry with test button + skip. CLI must not duplicate it.
- No prebuilt server artifact exists (release.yml ships desktop installers only) → v1 installs from source via git clone. Server tarball/GHCR image = explicitly out of scope (v2 candidate).
- #1 platform risk: sqlite-vec on Linux — root package.json pins only
sqlite-vec-windows-x64; Linux/macOS rely on sqlite-vec's own optional platform deps (UNVERIFIED). Mitigations: runtime require-check in installer +WAGGLE_SQLITE_VEC_PATHremedy + empirical CI smoke on ubuntu.
2. Design decisions (locked)
| # | Decision | Rationale |
|---|---|---|
| D1 | v1 ships install.sh only (Linux + macOS). Windows headless deferred; Windows users have the desktop .msi. |
Funnel audience is VPS/homelab; CowAgent ships bash-only too. |
| D2 | Installer ends at: prereqs → clone → build → tiny wizard → start → print URL. No API keys, no personas, no channels in CLI — web UI owns all of it. | OnboardingWizard model-gate is the polished existing flow; duplication = drift. |
| D3 | No sudo, ever. Missing prereq ⇒ print exact per-OS install command and exit. | Security differentiator vs CowAgent's silent sudo yum/apt; simplicity-first. |
| D4 | Wizard = 5 questions, all Enter-defaulted: install dir [~/waggle-os] · port [3333] · data dir [~/.waggle] · build web UI [Y] · start now [Y]. Reads from /dev/tty so curl | bash works. |
CowAgent's zero-key skippable wizard, minus everything the web UI owns. |
| D5 | Idempotent 3-way dir branch: dir + .waggle-installed marker ⇒ print usage/upgrade hint + exit · dir without marker ⇒ resume (skip clone) · no dir ⇒ clone. Timestamp-backup any config it would overwrite. |
CowAgent's proven re-run safety for curl | bash. |
| D6 | Injection-safe writes: all wizard answers pass as env vars into node -e that JSON.stringifys config / builds arguments. Never shell-interpolate user input into files or commands. |
CowAgent's env→json.dump heredoc pattern, ported to Node. |
| D7 | Process management via new scripts/waggle-server.sh (`start |
stop |
| D8 | --yes non-interactive mode (all defaults, no tty) + CI smoke job on ubuntu-latest: run installer → poll /health → assert 200 → waggle-server.sh stop. |
Only empirical way to verify Linux (dev box is Windows); settles sqlite-vec risk. |
| D9 | Source fetch = git clone --depth 1 over HTTPS from GitHub (integrity via git/TLS). Release-tag pinning + checksummed tarball = v2 with the (future) server artifact. |
No tarball exists to checksum yet; git clone is the honest v1. |
| D10 | Post-install runtime verification inside installer: node -e "require('better-sqlite3'); …sqlite-vec load" against the built tree; on failure print WAGGLE_SQLITE_VEC_PATH remedy + toolchain hints. |
Converts the #1 UNCERTAIN into a user-visible actionable check. |
3. Deliverables
install.sh(repo root) — thecurl -fsSL https://raw.githubusercontent.com/marolinik/waggle-os/main/install.sh | bashentry. Stages: preflight (bash≥4 warn-only, OS detect, git, node ≥20 perengines, npm; toolchain warn) → 3-way dir branch → clone →npm install --no-audit --no-fund→npm run build:packages→ optionalnpm run build→ wizard (D4) → runtime verify (D10) → delegate start towaggle-server.sh→ success card (URL, add-key-in-Settings pointer, channels pointer,waggle-server.shcheat-sheet). Flags:--yes,--dir,--port,--data-dir,--no-web,--no-start,--branch(defaultmain).scripts/waggle-server.sh—start|stop|status|logs [--port N] [--data-dir P]; start = nohup tsxsrc/local/start.tswithWAGGLE_SKIP_LITELLM=1,WAGGLE_FRONTEND_DIRset when web dist exists; stop = pidfile TERM, 3s grace, KILL; status = pidfile +/health; logs = tail dataDir log file.- CI:
installer-smokejob (new workflow or extend existing CI) — ubuntu-latest, run./install.sh --yes --no-web --dir "$RUNNER_TEMP/waggle"(clone-skip mode: point at checkout instead of cloning — installer supports--local-source <path>for CI/dev), poll health ≤120s, assert, stop. Cache npm. - Docs: README self-host section (the one-liner + what it does + security posture) +
docs/guides/getting-started.mdnew "Option: one-line self-host" + note indocs/guides/self-host*if exists.
4. Waves
Wave 1 (Opus exec): deliverables 1 + 2. Gate: bash -n both scripts; shellcheck if available; full real run in Git Bash on Windows against temp dir using --local-source (skip clone) — must reach healthy /health and stop cleanly; re-run idempotency check (3-way branch); --yes path exercised.
Wave 2 (Opus exec): deliverables 3 + 4. Gate: workflow YAML validated; docs factual against script flags; no marketing claims beyond behavior.
Verify (Opus adversarial): try to break: injection via dir/port answers, curl|bash with no tty, partial-failure resume, port conflict, missing node, dirty re-run, pidfile staleness, --local-source path traversal. VERDICT doc at docs/plans/VERIFIER-VERDICT-INSTALLER-2026-07-10.md.
Gates for every wave: no repo-wide side effects outside listed files; existing suites untouched (scripts are net-new; only README/getting-started/CI edited); commit per wave.
5. Out of scope (v2 candidates — do not build now)
systemd/launchd units · Windows install.ps1 · prebuilt server tarball + checksum/signature + release-tag pinning · GHCR image · CLI channel enablement · uninstaller beyond documented rm -rf note · nvm auto-install.