Skip to content

feat(setup): first-run onboarding/setup wizard (provider sign-in → default model → theme), modeled on oh-my-pi's versioned scenes #1082

Description

@code-yeongyu

Problem

senpi/omo has no first-run onboarding flow. A brand-new user launches into a welcome header + an empty prompt, and everything after that is manual and error-driven:

  • Auth is /login, discovered only via the "No models available. Use /login ..." error text (packages/coding-agent/src/core/auth-guidance.ts:6-20).
  • Model selection is /model, also discovered via error guidance (auth-guidance.ts:19-20).
  • senpi has a first-time setup dialog (theme + analytics only), but shouldRunFirstTimeSetup() hard-gates it to the official Pi distribution (@earendil-works/pi-coding-agent, app name pi, config dir .pi) plus PI_EXPERIMENTAL=1 — so senpi/omo distributions never see it (packages/coding-agent/src/cli/startup-ui.ts:113-128, dialog at src/modes/interactive/components/first-time-setup.ts:31-117).
  • The omo layer's existing "onboarding" is a conversational tour skill, not setup: omo/packages/omo-senpi/src/components/onboarding/component.ts:23-65 injects a hidden bootstrap message that makes the agent read skills/onboarding/SKILL.md (6-lane tour). It configures no provider, no model, no auth — and it has a chicken-and-egg problem: the tour itself needs a working provider+model to run, which is exactly what a first-run user doesn't have.
  • omo setup (omo-native launcher) can detect/import sibling harness credentials (omo/packages/omo-native/bin/lib/setup-detect.js:99-137, setup-import.js:202-218) but only when the user explicitly types it; first launch just prints a one-line stderr hint (launcher.js:131-132,155-156).

Reference: how oh-my-pi does it (can1357/oh-my-pi @ v18.0.0, 96f4280976)

oh-my-pi ships a versioned, fullscreen TUI setup wizard worth copying structurally:

  • Trigger: cold launch compares persisted setupVersion against CURRENT_SETUP_VERSION (=2) and lazy-loads the wizard when stale (src/main.ts:525-531, src/modes/setup-version.ts:22). Explicit re-run via omp setup forces it (src/commands/setup.ts:30,57; non-TTY exits 1).
  • Scenes, in order (src/modes/setup-wizard/index.ts:17-23): providers (OAuth sign-in + web-search tabs) → default model (ModelBrowser) → glyph mode (nerd/unicode/ascii) → composer shape (minVersion: 2) → theme (live preview). Each scene has a minVersion, so upgrades replay only new scenes — the wizard doubles as upgrade onboarding.
  • UX: fullscreen overlay with animated splash (2.6s) → 420ms cross-dissolve → scenes → "Setup saved" outro (wizard-overlay.ts); Esc skips a scene; arrow/enter/mouse supported.
  • Gates (index.ts:39-63): never runs on non-TTY, on session resume, with OMP_SKIP_SETUP=1, or with startup.setupWizard: false.
  • Persistence: global config.yml + project .omp/config.yml for model roles; OAuth tokens in the agent DB; markSetupWizardComplete() writes setupVersion (index.ts:65-70).
  • Notable: no telemetry-consent scene; no non-interactive wizard.

Why this issue lives in senpi (not omo)

The wizard needs engine-level surfaces: pre-interactive TUI dialogs, the /login OAuth/API-key flows, the model selector, theme + shareAnalytics settings, and the existing (Pi-gated) first-time-setup.ts scaffolding. All of that is senpi runtime code. The omo plugin layer only gets extension events (session_start etc.) and can't render a wizard before the first prompt. omo-side work (credential import scene, tour chaining) hangs off an extension hook proposed below and can be a follow-up in oh-my-openagent.

Proposal

A. Gating & trigger

  • Add setupVersion to settings.json schema; introduce CURRENT_SETUP_VERSION = 1.
  • On interactive cold launch, run the wizard when: TTY && not resuming && not --print/-p && setupVersion < CURRENT_SETUP_VERSION && SENPI_SKIP_SETUP unset && startup.setupWizard !== false.
  • Generalize shouldRunFirstTimeSetup() (startup-ui.ts:113-128): drop the official-Pi-distribution hard gate and the PI_EXPERIMENTAL requirement; make it branding-aware so pi/senpi/omo distributions all qualify (keep custom-agent-dir exclusion).
  • Explicit re-run: senpi --setup (and/or a /setup slash command). Non-TTY invocation exits 1 with a clear message, mirroring omp setup.

B. Scenes (v1)

  1. Provider sign-in — reuse the /login flows (OAuth + API-key paste). Show already-detected credentials; Esc to skip. auth-guidance.ts messages should then point at the wizard too.
  2. Default model — reuse the /model selector; persist the default role.
  3. Theme — lift the existing dark/light step from first-time-setup.ts.
  4. Analytics opt-in — keep the existing shareAnalytics question.

Each scene carries a minVersion (oh-my-pi pattern) so future scenes replay for upgraders without re-running everything.

C. Extension hook (the omo integration point)

  • Let extensions contribute wizard scenes and/or a post-setup hook.
  • omo-senpi then: (a) contributes a "found credentials from Claude Code/opencode/... — import?" scene reusing omo-native setup-detect.js/setup-import.js logic, and (b) chains the existing conversational onboarding tour after wizard completion, so omo-onboarding:bootstrap fires only once a working provider+model exists. Ordering contract: wizard → auth+model guaranteed → tour.

D. Persistence

  • settings.json: setupVersion, theme, shareAnalytics, default model role. Credentials stay in the existing auth store. No new config files.

Acceptance criteria

  • Fresh install (no settings.json, no auth), interactive launch: wizard runs before the first prompt; completing it leaves a working provider + default model.
  • Wizard never runs: headless (-p/--print), non-TTY, session resume, SENPI_SKIP_SETUP=1, or startup.setupWizard: false.
  • Esc skips an individual scene; skipping everything still lands in the normal TUI with /login guidance intact.
  • Bumping CURRENT_SETUP_VERSION replays only scenes with a higher minVersion for existing users.
  • senpi --setup forces a full re-run; non-TTY exits 1.
  • omo/senpi distributions get the wizard (Pi-distribution gate removed); custom agent dirs still excluded.
  • Extensions can register a post-setup hook; on a true first run under omo, the onboarding tour fires after the wizard.
  • Tests mirror oh-my-pi's setup-wizard.test.ts coverage: scene selection/version gating, persistence, skip paths; first-time-setup component tests updated.

Out of scope / follow-ups

  • oh-my-openagent side: the credential-import scene + tour-chaining component work (file there once the senpi hook shape lands).
  • Glyph/composer-style appearance scenes beyond theme — add later via minVersion bumps.
  • Non-interactive/headless setup wizard (oh-my-pi doesn't have one either).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions