Skip to content

Desktop: onboarding overlay re-appears on every app restart #37554

Description

@oVservant

Description

After completing initial setup (bootstrap + onboarding provider config), closing and re-opening the Hermes Desktop app shows the onboarding/install prompt again, as if the user never completed configuration.

Steps to Reproduce

  1. Install Hermes Desktop and complete first-launch bootstrap (install.sh) + onboarding (provider/model setup)
  2. Confirm the main chat UI loads correctly
  3. Close the app (Cmd+Q or window close)
  4. Re-open Hermes Desktop
  5. Actual: The onboarding overlay ("Add a provider credential before sending your first message") or install overlay reappears instead of the main chat UI
  6. Closing and re-opening again repeats the cycle indefinitely

Expected Behavior

After successful first-time setup, subsequent launches should go straight to the main chat UI without re-prompting for provider/install configuration.

Root Cause (traced)

There are two overlays that gate the main UI, and both have persistence issues:

1. DesktopOnboardingOverlay (primary issue)

The overlay uses localStorage['hermes-desktop-onboarded-v1'] as an initial optimistic cache, but re-evaluates every time the gateway opens via evaluateRuntimeReadiness(), which calls:

  • setup.status — returns provider_configured: boolean
  • setup.runtime_check — returns ok: boolean

When the backend reports provider_configured: false (or the runtime check fails), the store resets configured → false and shows the overlay again, overwriting the localStorage cache.

So even though localStorage reads '1', the store re-evaluates and flips it to false on every boot.

Relevant code paths:

  • src/store/onboarding.tsrefreshOnboarding() line 385-407: calls checkRuntime(), and if !runtime.ready, sets configured: false + writeCachedConfigured(false)
  • src/components/desktop-onboarding-overlay.tsx line 153: if (onboarding.configured === true && !onboarding.manual) return null — so returning users get the overlay
  • src/lib/runtime-readiness.ts line 82-138: interpretRuntimeReadiness() — determines readiness from gateway responses

2. DesktopInstallOverlay (edge case)

The bootstrap-complete marker (~/.hermes/hermes-agent/.hermes-bootstrap-complete) is checked correctly in main.cjs via isBootstrapComplete() and should suppress re-install. However, if the venv is missing, the marker alone won't suffice — the check also requires fileExists(getVenvPython(VENV_ROOT)).

Environment

  • macOS 26.5 (M1 Pro)
  • Hermes Desktop v0.15.1
  • Hermes Agent head (self-built from source)

Additional Context

Full trace available at electron/main.cjsresolveHermesBackend(), isBootstrapComplete(), and src/store/onboarding.tsrefreshOnboarding().

The core issue is that localStorage is an unreliable persistence mechanism for onboarding state — any gateway response discrepancy resets it. A durable marker on disk (similar to the bootstrap-complete marker) or a dedicated setup.onboarded config flag would fix this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existstype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions