Files
flynn/docs/plans/2026-02-10-setup-wizard-design.md
William Valentin 6b426a1e52 docs: add setup wizard design
Interactive setup wizard with two entry points: auto-trigger on
first run (no config detected) and explicit `flynn setup` command.
Minimal-first flow for quick start, menu-driven for reconfiguration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:14:45 -08:00

7.4 KiB

Setup Wizard Design

Date: 2026-02-10 Status: Draft

Overview

Interactive setup wizard for Flynn. Two entry points:

  1. Auto-triggerflynn start detects no config, offers to run the wizard
  2. Explicitflynn setup command, re-runnable for reconfiguration

Philosophy: minimal-first to get running fast, then menu-driven for advanced config.

First-Run Flow

When flynn start detects no config at ~/.config/flynn/config.yaml:

No configuration found. Would you like to run the setup wizard? [Y/n]

Sequential steps:

  1. Welcome — One-liner: "Let's get Flynn running. This takes about 2 minutes."
  2. Model provider — Pick from top tier (Anthropic/OpenAI/Ollama), or "More providers" for second tier (Gemini, OpenRouter, xAI, Bedrock, GitHub Models). Prompt for API key (or host for Ollama). Configured as default tier. Optionally configure fast tier with cheaper model from same provider.
  3. Channel — Suggest WebChat (zero external setup). Offer Telegram/Discord, or "More channels" for Slack/WhatsApp. Prompt for required fields only.
  4. Write config — Generate ~/.config/flynn/config.yaml, print path, show summary.
  5. Offer to start — "Start Flynn now? [Y/n]"
  6. Offer more — If declined: "Configure more features? [Y/n]" drops into the menu.

Menu-Driven Reconfiguration

Entry: flynn setup with existing config, or "configure more" after first-run.

Flynn Setup — Current Configuration
  Models:    anthropic (default tier)
  Channels:  webchat, telegram
  Memory:    keyword search (no embeddings)
  Automation: none
  Security:  default (no sandbox)
  Gateway:   port 3777, no auth

What would you like to configure?
  1. Model Providers
  2. Channels
  3. Memory
  4. Automation
  5. Security
  6. Gateway
  0. Done — save and exit
>

Each section: show current state, offer add/change/remove, return to menu.

On "Done": write config, offer restart (if daemon running) or start.

Config is buffered in memory; only written to disk on "Done". Ctrl+C exits cleanly with no partial writes.

Provider Setup Flows

Top Tier

Anthropic:

API key: sk-ant-••••••
Model [claude-sonnet-4-20250514]:

OpenAI:

API key: sk-••••••
Model [gpt-4.1]:

Ollama:

Host [http://localhost:11434]:
Model [llama3.3]:

Second Tier

OpenRouter, xAI, Gemini, Bedrock, GitHub Models — same pattern (API key + model with defaults). OpenRouter and xAI reuse OpenAI-compatible flow with different base URLs.

Tier Assignment

First provider → default tier. Then:

Configure a fast tier for compaction/delegation? [y/N]

If yes, suggest cheaper model from same provider (e.g., claude-haiku-4-5-20251001, gpt-4.1-mini, smaller Ollama model).

complex and local tiers skipped — power-user YAML territory.

Channel Setup Flows

WebChat (recommended, zero setup):

Gateway port [3777]:
✓ WebChat enabled — visit http://localhost:3777 after starting

Telegram:

Bot token (from @BotFather): 123456:ABC-••••••
Allowed chat IDs (comma-separated): 12345678, -100987654

Discord:

Bot token: MTIz••••••
Allowed guild IDs (comma-separated, or * for all): 123456789

Slack:

Bot token (xoxb-...): xoxb-••••••
App token (xapp-...): xapp-••••••
Allowed channel IDs (comma-separated, or * for all): C0123ABC

WhatsApp:

⚠ WhatsApp requires QR code authentication on first connect.
  It will appear in the terminal when Flynn starts.
Allowed phone numbers (comma-separated, or * for all): 61412345678

Input validation: Telegram tokens match \d+:.+, Slack tokens start with xoxb-/xapp-. Invalid input re-prompts.

After each channel: "Add another channel? [y/N]"

Menu Section Flows

Memory

Enable vector search for semantic memory? [y/N]
Embedding provider:
  1. OpenAI (recommended)
  2. Gemini
  3. Ollama (local)
  4. Voyage AI
API key [reuse from model provider? Y/n]:

Smart default: reuse API key if same provider already configured for models.

Automation

Enable cron scheduler? [y/N]
Enable webhook receiver? [y/N]
Enable Gmail watcher? [y/N]

Webhooks prompt for shared secret. Gmail prompts for OAuth credentials path. Cron jobs configured in YAML later.

Security

Enable Docker sandboxing? [y/N]
Enable DM pairing for unknown senders? [y/N]
Tool policy profile [full]: (minimal/messaging/coding/full)

Gateway

Port [3777]:
Set auth token? [y/N]
Enable Tailscale Serve? [y/N]
Enable gateway lock (single client)? [y/N]

File Structure

src/cli/setup.ts              — Command registration + main orchestrator
src/cli/setup/
  prompts.ts                  — Readline helpers (ask, choose, confirm, password)
  providers.ts                — Model provider setup flows
  channels.ts                 — Channel setup flows
  memory.ts                   — Memory/embeddings setup
  automation.ts               — Cron, webhooks, Gmail setup
  security.ts                 — Tool policy, sandbox, pairing, hooks
  gateway.ts                  — Port, auth, Tailscale, lock
  summary.ts                  — Config summary renderer

Dependencies

  • readline — Node built-in, same as minimal TUI
  • yaml — Round-trip YAML parsing to preserve comments when editing existing configs

No inquirer or prompts packages.

Prompt Helpers (prompts.ts)

  • ask(question, default?) — Free text input
  • choose(question, options[]) — Numbered list, return selection
  • confirm(question, default?) — Y/n boolean
  • password(question) — Hidden input for API keys

Config I/O Strategy

  • Load existing YAML with yaml package (round-trip, preserves comments)
  • Buffer all changes in memory
  • Write only on "Done" or end of first-run flow
  • Preserve ${ENV_VAR} references in existing configs — don't resolve them
  • mkdir -p ~/.config/flynn if directory doesn't exist

Secrets Handling

Secrets (API keys, bot tokens) entered inline and stored as plaintext in config.yaml. Users can manually replace with ${ENV_VAR} references later. The wizard's job is to minimize time-to-working-config.

Integration with Existing Systems

  • flynn start — Check for config, offer wizard if missing. After wizard, proceed to start.
  • flynn doctor — Validates the config the wizard produces. Wizard does not test API connectivity.
  • flynn setup — New command, re-runnable. With existing config: straight to menu.

Clean separation: wizard produces config, doctor validates it.

Testing Strategy

  • Unit tests for prompt helpers (ask, choose, confirm)
  • Unit tests for config generation — given answers, assert correct YAML structure
  • Unit tests for input validation (token formats, port ranges)
  • Integration test: mock readline, run full first-run flow, assert valid config

Edge Cases

  • Config directory missing → mkdir -p before writing
  • Ctrl+C during wizard → clean exit, no partial config
  • Existing config with ${VAR} references → preserve them
  • Re-running setup → load current values as defaults, don't overwrite untouched fields
  • Invalid input → re-prompt with explanation, never crash

Explicitly Out of Scope

  • Config migration between versions
  • Undo/rollback
  • Config backup (user has git)
  • Network validation of API keys (that's flynn doctor)
  • complex and local model tier configuration
  • Zhipu, Llama.cpp provider setup (niche, manual YAML)