Replace the linear 12-stage wizard interrogation with a menu-driven architecture. Key changes: - Main menu with drill-down sections: Quick Start, Providers, Agent Identity, Skills, Gateway, Advanced, Finish & Apply - Quick Start path: 3 questions (API key, admin email, password) with sensible defaults for everything else. Target: under 90 seconds. - Provider-first flow: LLM API key collection moves to the front of the wizard, with auto-detection of Anthropic vs OpenAI from key prefix - Deterministic intent/naming: user picks an intent category (general, software-dev, devops, research, content, custom) and gets a thematic agent name proposal (Mosaic, Forge, Sentinel, Atlas, Muse) - Headless backward compat: MOSAIC_ASSUME_YES=1 + env vars still work unchanged, with new MOSAIC_AGENT_NAME and MOSAIC_AGENT_INTENT vars - Version bump: 0.0.26 -> 0.0.27 Closes #438 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.9 KiB
IUV-M03 Design: Provider-first intelligent flow + drill-down main menu
Issue: #438
Branch: feat/install-ux-intent
Date: 2026-04-05
1. New first-run state machine
The linear 12-stage interrogation is replaced with a menu-driven architecture.
Flow overview
Welcome banner
|
v
Detect existing install (auto)
|
v
Main Menu (loop)
|-- Quick Start -> provider key + admin creds -> finalize
|-- Providers -> LLM API key config
|-- Agent Identity -> intent intake + naming (deterministic)
|-- Skills -> recommended / custom selection
|-- Gateway -> port, storage tier, hostname, CORS
|-- Advanced -> SOUL.md, USER.md, TOOLS.md, runtimes, hooks
|-- Finish & Apply -> finalize + gateway bootstrap
v
Done
Menu navigation
- Main menu is a
selectprompt. Each option drills into a sub-flow. - Completing a section returns to the main menu.
- Menu items show completion state:
[done]hint after configuration. Finish & Applyis always last and requires at minimum a provider key (or explicit skip).- The menu tracks configured sections in
WizardState.completedSections.
Headless bypass
When MOSAIC_ASSUME_YES=1 or !process.stdin.isTTY, the entire menu is skipped.
The wizard runs: defaults + env var overrides -> finalize -> gateway config -> bootstrap.
This preserves full backward compatibility with tools/install.sh --yes.
2. Quick Start path
Target: 3-5 questions max. Under 90 seconds for a returning user.
Questions asked
- Provider API key (Anthropic/OpenAI) -
textprompt with paste support - Admin email -
textprompt - Admin password - masked + confirmed
Questions skipped (with defaults)
| Setting | Default | Rationale |
|---|---|---|
| Agent name | "Mosaic" | Generic but branded |
| Port | 14242 | Standard default |
| Storage tier | local | No external deps |
| Hostname | localhost | Dev-first |
| CORS origin | http://localhost:3000 | Standard web UI port |
| Skills | recommended set | Curated by maintainers |
| Runtimes | auto-detected | No user input needed |
| Communication style | direct | Most popular choice |
| SOUL.md / USER.md / TOOLS.md | template defaults | Can customize later |
| Hooks | auto-install if Claude detected | Safe default |
Flow
Quick Start selected
-> "Paste your LLM API key (Anthropic recommended):"
-> [auto-detect provider from key prefix: sk-ant-* = Anthropic, sk-* = OpenAI]
-> Apply all defaults
-> Run finalize (sync framework, write configs, link assets, sync skills)
-> Run gateway config (headless-style with defaults + provided key)
-> "Admin email:"
-> "Admin password:" (masked + confirm)
-> Run gateway bootstrap
-> Done
3. Provider-first flow
Provider configuration (currently buried in gateway-config stage as "ANTHROPIC_API_KEY") moves to a dedicated top-level menu item and is the first question in Quick Start.
Provider detection
The API key prefix determines the provider:
sk-ant-api03-*-> Anthropic (Claude)sk-*-> OpenAI- Empty/skipped -> no provider (gateway starts without LLM access)
Storage
The provider key is stored in the gateway .env as ANTHROPIC_API_KEY or OPENAI_API_KEY.
For Quick Start, this replaces the old interactive prompt in collectAndWriteConfig.
Menu section: "Providers"
In the drill-down menu, "Providers" lets users:
- Enter/change their API key
- See which provider was detected
- Optionally configure a second provider
For v0.0.27, we support Anthropic and OpenAI keys only. The key is stored
in WizardState and written during finalize.
4. Intent intake + naming (deterministic fallback - Option B)
Rationale
At install time, the LLM provider may not be configured yet (chicken-and-egg). We use Option B: deterministic advisor for the install wizard.
Flow (Agent Identity menu section)
1. "What will this agent primarily help you with?"
-> Select from presets:
- General purpose assistant
- Software development
- DevOps & infrastructure
- Research & analysis
- Content & writing
- Custom (free text description)
2. System proposes a thematic name based on selection:
- General purpose -> "Mosaic"
- Software development -> "Forge"
- DevOps & infrastructure -> "Sentinel"
- Research & analysis -> "Atlas"
- Content & writing -> "Muse"
- Custom -> "Mosaic" (default)
3. "Your agent will be named 'Forge'. Press Enter to accept or type a new name:"
-> User confirms or overrides
Storage
- Agent name ->
WizardState.soul.agentName-> written to SOUL.md - Intent category ->
WizardState.agentIntent(new field) -> written to~/.config/mosaic/agent.json
Post-install LLM-powered intake (future)
A future mosaic configure identity command can use the configured LLM to:
- Accept free-text intent description
- Generate an expounded persona
- Propose a contextual name
This is explicitly out of scope for the install wizard.
5. Headless backward-compat
Supported env vars (unchanged)
| Variable | Used by |
|---|---|
MOSAIC_ASSUME_YES=1 |
Skip all prompts, use defaults + env overrides |
MOSAIC_ADMIN_NAME |
Gateway bootstrap |
MOSAIC_ADMIN_EMAIL |
Gateway bootstrap |
MOSAIC_ADMIN_PASSWORD |
Gateway bootstrap |
MOSAIC_GATEWAY_PORT |
Gateway config |
MOSAIC_HOSTNAME |
Gateway config (CORS derivation) |
MOSAIC_CORS_ORIGIN |
Gateway config (full override) |
MOSAIC_STORAGE_TIER |
Gateway config (local/team) |
MOSAIC_DATABASE_URL |
Gateway config (team tier) |
MOSAIC_VALKEY_URL |
Gateway config (team tier) |
MOSAIC_ANTHROPIC_API_KEY |
Provider config |
New env vars
| Variable | Purpose |
|---|---|
MOSAIC_AGENT_NAME |
Override agent name in headless mode |
MOSAIC_AGENT_INTENT |
Override intent category in headless mode |
tools/install.sh --yes
The install script sets MOSAIC_ASSUME_YES=1 and passes through env vars.
No changes needed to the script itself. The new wizard detects headless mode
at the top of runWizard and runs a linear path identical to the old flow.
6. Explicit non-goals
- No GUI — this is a terminal wizard only
- No multi-user install — single-user, single-machine
- No registry changes — npm publish flow is unchanged
- No LLM calls during install — deterministic fallback only
- No new dependencies — uses existing @clack/prompts and picocolors
- No changes to gateway API — only the wizard orchestration changes
- No changes to tools/install.sh — headless compat maintained via env vars
7. Implementation plan
Files to modify
packages/mosaic/src/types.ts— addMenuSection,AgentIntent,completedSections,agentIntent,providerKey,providerTypeto WizardStatepackages/mosaic/src/wizard.ts— replace linear flow with menu looppackages/mosaic/src/stages/mode-select.ts— becomes the main menupackages/mosaic/src/stages/provider-setup.ts— new: provider key collectionpackages/mosaic/src/stages/agent-intent.ts— new: intent intake + namingpackages/mosaic/src/stages/menu-gateway.ts— new: gateway sub-menu wrapperpackages/mosaic/src/stages/quick-start.ts— new: quick start linear pathpackages/mosaic/src/constants.ts— add intent presets and name mappingspackages/mosaic/package.json— version bump 0.0.26 -> 0.0.27
Files to add (tests)
packages/mosaic/src/stages/wizard-menu.spec.ts— menu navigation testspackages/mosaic/src/stages/quick-start.spec.ts— quick start path testspackages/mosaic/src/stages/agent-intent.spec.ts— intent + naming testspackages/mosaic/src/stages/provider-setup.spec.ts— provider detection tests
Migration strategy
The existing stage functions remain intact. The menu system wraps them — each menu item calls the appropriate stage function(s). The linear headless path calls them in the same order as before.