Onboarding flow.

The onboarding is a single page. No sidebars, no stepper, no “Continue” between every stage. You answer a handful of questions; everything else runs itself.

State is persisted to onboarding/data/state.json after every transition, so a refresh or a reboot resumes where you left off.

Hello.

A warm greeting cycles through several languages. Tap anywhere (or press Enter) to continue. This is also where the audio context is unlocked for later stages.

Fresh, or returning?

Pick one:

  • Fresh — new install. You'll pick a wake phrase and a color, name the home, and hand over Home Assistant admin credentials.
  • Restore — migrate from another Pi. Upload a .sudo-bundle and enter its passphrase. Sudo decrypts, restores Home Assistant state, and brings services up without the fresh-setup form.

Wake phrase.

Pick one of the preset wake phrases (Hey Sudo, Okay Sudo, Computer). The choice is written to state.assistant.wakeWord and later into voice-loop/config.yaml as the openWakeWord phrase.

Color.

Pick an accent color: sage, amber (default), or sky. The orb's gradient updates live as you preview — your assistant adopts the color before you commit. It's also applied to every subsequent screen.

Place.

Name the home. “Home” is the default — skip to keep it, or type something else (“The Loft”, “The Den”). The name surfaces in the final greeting and is used as the top-level Home Assistant area label.

Home Assistant login.

(Fresh branch only.) A compact form with two fields:

  • Username — the HA admin username that will be created.
  • Password — at least 6 characters.

Your Claude API key is not collected here — it's baked into .env at install time (see the Install doc). Timezone is auto-detected from the browser.

Settling in.

A single stage that runs four backend steps in sequence, auto-advancing through each. The orb morphs through its thinking shapes; the ticker below shows the latest log line, and Show details opens a 500-line scrollback.

  1. Foundation. Detects missing host packages (Docker CE, docker-compose-plugin, portaudio, make) and installs them via apt-get.
  2. Engines. docker compose up -d brings up Home Assistant and the voice stack. Pulls retry on transient i/o timeouts so large image layers resume rather than fail.
  3. Hello. Drives Home Assistant's first-run onboarding over its REST API, creates a non-admin sudo_agent user, mints a long-lived token, writes mcp_server: to configuration.yaml, restarts HA, and drives the MCP config flow — no human in the HA UI.
  4. Last mile. Runs make test-ha and then make smoke-mcp. Claude is asked to list lights via MCP, then to flip input_boolean.mcp_test. If the state-change assertion passes, so does the smoke test.

Ready.

Smoke test passes → the orb blooms and the wizard fades out, replaced by a greeting: “Hi, I'm Sudo. I live at [home name].” Below the greeting: an Export bundle control and an upgrade banner when a newer manifest is available. That's the app's home screen from here on.

If something errors

Any failing step shows a muted-red orb, the last stderr line, and a Try again button. Errors are also written to state.lastError; the next visit re-opens on the failing step. You can re-run as many times as needed without affecting earlier state.