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>
7.4 KiB
Setup Wizard Design
Date: 2026-02-10 Status: Draft
Overview
Interactive setup wizard for Flynn. Two entry points:
- Auto-trigger —
flynn startdetects no config, offers to run the wizard - Explicit —
flynn setupcommand, 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:
- Welcome — One-liner: "Let's get Flynn running. This takes about 2 minutes."
- 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
defaulttier. Optionally configurefasttier with cheaper model from same provider. - Channel — Suggest WebChat (zero external setup). Offer Telegram/Discord, or "More channels" for Slack/WhatsApp. Prompt for required fields only.
- Write config — Generate
~/.config/flynn/config.yaml, print path, show summary. - Offer to start — "Start Flynn now? [Y/n]"
- 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 inputchoose(question, options[])— Numbered list, return selectionconfirm(question, default?)— Y/n booleanpassword(question)— Hidden input for API keys
Config I/O Strategy
- Load existing YAML with
yamlpackage (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/flynnif 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 -pbefore 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) complexandlocalmodel tier configuration- Zhipu, Llama.cpp provider setup (niche, manual YAML)