---
title: Onboarding Guardian (a quiet hint when setup stalls)
---

# Onboarding Guardian

## What it is

### What it is

The **Onboarding Guardian** is an invisible AI assistant that quietly watches a new user move through the **Setup v2** cinematic onboarding flow and the **interactive tour**. It stays silent almost all of the time and surfaces a single gentle hint ONLY when you appear genuinely stuck — for example, when you idle on a step with no forward progress. It can also *act* on your behalf during onboarding — highlight the control you need, open the right panel, or launch your first task — but it never does anything destructive and never runs outside onboarding.

It is **on by default** and you can turn it off any time from Settings (the `onboardingGuardianEnabled` toggle). Because it only runs while the Setup v2 flow or the tour is active, it stays completely **dormant — and spends nothing —** until that newer onboarding is your live first-run experience.

A hint appears as an ordinary dismissible toast (the same surface as coaching tips), with an optional action button and a "Don't show again" option — never a blocking popup.

## Where to find it

Nowhere to open — it is active during **Setup v2** and the **interactive tour**, and its one hint arrives as an ordinary in-app toast. It is on by default and only ever speaks while onboarding is running.

## How it behaves

### How to use it

1. **There's nothing to launch.** When onboarding (Setup v2 / the tour) is active and the Guardian is enabled, it observes your progress in the background.
2. **A hint only when you're stuck.** If you idle on a step past a short threshold with no progress, the Guardian may show ONE gentle hint — a short message and, sometimes, a button that does the next step for you (highlight a control, open the right panel).
3. **Dismiss or silence it.** Every hint is dismissible; "Don't show again" silences the Guardian for the rest of that onboarding session.
4. **Turn it off entirely.** Turn off the Onboarding Guardian in Settings (`onboardingGuardianEnabled`). The opt-out is honored immediately — a disabled Guardian never observes, decides, or acts.

## For agents

### How it works

The Guardian is a small renderer feature module in [src/renderer/src/features/onboarding/guardian/](../../src/renderer/src/features/onboarding/guardian/) with five thin, independently-testable layers: **signals** (a bounded ring buffer of progress events, plus a tracker of your real interaction — key presses, clicks, scrolls — and the exact step you are on), a pure **stuck detector** (`evaluateStuck`) that measures idleness from the LATER of your last step and your last interaction — so it never nudges you while you are actively typing, clicking, or scrolling, and only wakes once you have genuinely gone quiet on a step — the **brain** (`decideIntervention`), a **dispatcher** that enforces the "rarely intervene" cadence (cooldown, per-session cap, in-flight guard, session-silence), and an **orchestrator** ([use-onboarding-guardian.ts](../../src/renderer/src/features/onboarding/guardian/use-onboarding-guardian.ts)) mounted once at app root that drives observe → detect → decide.

The decision "brain" is a **company-funded** one-shot OpenAI Luna call that runs in the **main** process ([guardian-brain-service.ts](../../src/main/services/onboarding/guardian-brain-service.ts)) — never on your own account or API key, so it works even before you have connected any provider. The renderer forwards only a tiny, non-personal context (the step id and how long you have idled — never your name, content, or files) over the `GUARDIAN_DECIDE` IPC channel; all authority stays in main. The call is feature-gated, only fires while onboarding is active, is IPC-rate-limited and bounded by a per-day sub-budget below the shared company cap, and is entirely **non-fatal**: if it is disabled, over budget, times out, or returns anything unexpected, the Guardian simply stays silent. `GUARDIAN_DECIDE` is blocked on the mobile/web bridge — the Guardian is desktop-onboarding only.

When the brain decides to act, the action runs through a **fail-closed executor** in main ([guardian-action-executor.ts](../../src/main/services/onboarding/guardian-action-executor.ts)). The AI never holds a token — it emits an action *intent* and main validates it against an allowlist (highlight a control, open a panel, navigate, focus the reply box, launch a starter task, raise an alert) before running it. Destructive actions are refused, paid task spawns are capped, and any handler error is swallowed so the Guardian can never break your onboarding. The visible effect (spotlight a control, drop the cursor in the reply box, or open a panel) is then carried out by a small, error-contained renderer receiver ([use-guardian-ui-actions.ts](../../src/renderer/src/features/onboarding/guardian/use-guardian-ui-actions.ts)) that reuses the tour's existing highlight and reply-box machinery; a target that is not on screen is simply ignored, and the receiver is desktop-only. So the Guardian can point at a real control (its prompt carries the setup step's anchor names) instead of only describing the next step.

Hints render through the shared coaching-tip toast (`notify('general', 'info', …)`), so they are non-blocking, dismissible, themed, and mobile-safe for free. The feature is registered as `onboarding-guardian` in [unreleased-features.ts](../../src/shared/unreleased-features.ts) (`status: 'shipped'`, `defaultOn: true`); the runtime gate reads the setting, so the opt-out works.

## Related

### Related

- [first-time-setup.md](first-time-setup.md) — the Setup v2 onboarding flow the Guardian watches
- [app-tour.md](app-tour.md) — the interactive tour the Guardian also observes
- [notifications-and-silence.md](notifications-and-silence.md) — the toast surface the Guardian's hints reuse

