Setup wizard
Route /setup. On a first run it is the app: when no provider can answer a prompt, the wizard opens before anything else and the nav rail stays hidden until you finish it or postpone it. Afterwards it is reachable any time from Run setup wizard in Settings.
It walks the same sections as the command-line snowpea setup, in the same order, and writes the same settings.json keys — so it does not matter which one you use, and running either again changes one thing rather than resetting the rest.
The seven sections
| Section | What it asks |
|---|---|
| ① LLM provider | The vendor, its credential (API key, browser login, device code or a pasted OAuth token), the model — with the source of the model list — plus any further models, the default model, and which agent runs on what |
| ② Web search provider | Which search backend, and its API key or instance URL. The ★ default, ddgs, is free and needs neither |
| ③ Browser provider | What the browser_* tools drive. local_chromium by default |
| ④ Audio | Voice in and voice out, action-first: install the recommended CPU engine, or pin a specific one. Then the voice, whether replies are read aloud, and a button that says a test phrase |
| ⑤ Tool categories | Which groups of tools are on, and the skill registry's publisher token |
| ⑥ Messengers | Telegram, Discord and Slack: a bot token each, and your own account id on that platform |
| ⑦ Summary | Every section's state, then Save or Cancel |
The rail on the left carries each section's current answer rather than only its name, so the summary confirms something you have been reading all along. Pick any entry to go back to that section; the summary's Edit buttons do the same.
The audio section
This one is action-first rather than a list, because on a first run the useful question is "get me something that works", not "which of these nine".
Each direction — Voice in and Voice out — starts not set, which means that half of voice is off. The line at the top says so, and under it is the engine snowpea recommends, always one that runs on the processor: Recommended: SenseVoiceSmall (CPU) with an Install button that already has the keyboard focus. Anything else snowpea can fetch is offered beside it as Install <engine>….
Installing does not choose. Install fetches the engine and changes no setting; when it finishes the engine appears in the picker below, takes the focus and says installed — select it to use it. Selecting is what pins it, and the section's answer in the rail changes from not set to that engine.
Choose a specific engine… opens the picker: the engines that work on this machine right now, plus Off, a custom command and the paid hosted services. Each row there leads somewhere of its own — a command template to fill in, a key to paste, or simply being selected. Engines that are not installed are not in this picker, since pinning one would choose something the next turn cannot use; they are in Settings → Audio, which keeps the full list with an Install button per row.
Once an engine is pinned the step asks the two questions that follow from it: which language you will speak, for voice in, and which voice each language gets, for voice out. Both are the same controls Settings → Audio carries, so nothing here has to be redone later.
Skip leaves the whole section not set, which means voice stays off until you come back to it in Settings.
Credentials
Nothing is written until Save. Then the wizard makes one provider.configure call per vendor you gave credentials for, and one write to the global settings document carrying every section.
A secret never comes back out. Saved keys and tokens read as "already saved" and the field beside them stays empty — leaving it empty keeps what is stored, typing something replaces it.
Picking a provider marked paid · key required — Tavily for search, Browserbase or Firecrawl Cloud for the browser — opens a key field under the list. That key is not optional: the section will not move on without it, and Save refuses too, because a provider chosen without credentials reads as configured here and fails at the first tool call instead. The message names the two honest ways past it — pick another provider, or skip the section.
A provider marked key optional opens the same field without blocking: it works without one, and a key only buys a better tier.
A messenger without your user id is the other field that looks optional and is not. It can carry a conversation but can approve nothing: the gateway refuses every approval press from an unnamed account. Each platform hides your id somewhere different, and the hint under the field says where.
Search keys are stored under search.credentials.<provider>.api_key and browser keys under browser.credentials.<provider>.api_key.
Quick setup
On the first section, Quick setup takes the provider, credential and model you have entered, leaves search, browser, audio, tools and messengers on their defaults, and goes straight to the summary. The sections it skipped are marked there as default and can still be opened before you Save.
Skipping
Skip — keep defaults moves past a section keeping its seeded answer, which is then written like any other: an all-skip run still lands ddgs and local_chromium.
Skip for now leaves the wizard entirely on a first run. It records that setup was offered, opens the app, and leaves a banner reading Setup incomplete — no provider is configured, so prompts will not run, with a button back here. The banner has no dismiss; it goes when setup is done.
Cancel, on the summary, discards the run. Nothing is written.
Keyboard
The keyboard is on the list from the moment a section opens.
| Keys | Action |
|---|---|
↑ / ↓ | Move through the choices |
Space | Toggle a row on a checkbox section (tools, messengers) |
Enter | Take the highlighted choice and continue |
Esc | Close a dialog |
If it will not load
The catalog of vendors and providers comes from the core, so the wizard waits for a connection before it can offer anything. If it sits waiting, the problem is the core, not the wizard: the status bar says what happened, and Skip for now lets you into the app meanwhile.