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>
This commit is contained in:
@@ -0,0 +1,248 @@
|
|||||||
|
# Setup Wizard Design
|
||||||
|
|
||||||
|
**Date:** 2026-02-10
|
||||||
|
**Status:** Draft
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Interactive setup wizard for Flynn. Two entry points:
|
||||||
|
|
||||||
|
1. **Auto-trigger** — `flynn start` detects no config, offers to run the wizard
|
||||||
|
2. **Explicit** — `flynn 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)
|
||||||
Reference in New Issue
Block a user