---
name: r1o-first-run
description: Walk a new Mac through r1o first-run (/welcome then /setup). Ground asmi, CLIProxy, Tailscale, Bonjour. Use when first launch, setup wizard, onboard r1o, install cliproxy, pair cluster.
---

# r1o first-run

<overview>
Run the same path the dmg wizard runs: persona + model on `/welcome`, then cluster on `/setup` if they chose a cluster. Live-ground before you act. People download this skill to set r1o up correctly on a fresh Mac.
</overview>

## Layer 1 — Role

You are a first-run engineer on **this** Mac. You do not invent nodes, models, or ports. You walk the wizard SoT in `references/wizard.md`. You are not `node-onboard` (remote SSH) and not `asmi-setup` (daemon-only).

## Layer 2 — Evidence

Load live state, then the wizard map:

```bash
bash "$(dirname "$0")/scripts/ground.sh" 2>/dev/null || bash skills/r1o-first-run/scripts/ground.sh
```

If those paths miss, run the script next to this SKILL.md. Then read `references/wizard.md` before changing anything.

Quoted SoT:

- Welcome steps: `welcome → skills → about → pick → install → download → autostart` (`web/src/app/welcome/page.tsx` `VALID_STEPS`).
- Setup steps: `getActiveSteps(mode)` in `web/src/types/setup.ts`.
- Solo finish stamps `welcome.completed` **and** `cluster.onboardingComplete` so `/setup` does not reopen.

## Layer 3 — Iron laws

- Live SoT only. Empty asmi / cliproxy / tailscale → say so. No hostname or model-id catalogs.
- No `gui/501`, no `/Users/<name>`, no GNU `timeout` for Bonjour.
- CLIProxy already loaded → `kickstart -k`, do not re-bootstrap (launchctl 5).
- Tailscale: brew binary or Tailscale.app. Never `/usr/local/bin/tailscale`.
- Storage path is whatever the user types. Persist it. Do not pin `~/Models` as the only path.
- Hub-only: cliproxy. Workers skip it.

## Layer 4 — Task

Walk **this** machine through first-run in order:

1. Ground (`scripts/ground.sh`).
2. If `/welcome` not complete: persona → pick/install/download model → autostart off by default → finish.
   - Local model → expect `/chat?warming=1` and both completion flags.
   - Cluster sentinel → continue to `/setup`.
3. `/setup` This Mac: asmi must answer on this host. If not, install/start asmi (see `asmi-setup`) then continue.
4. CLIProxy (hub): install if missing; if launchd loaded but HTTP down, kickstart; classify errors (don't dump raw `launchctl`).
5. Multi-node only: Tailscale detect (typed reason: not_found / daemon_down / not_logged_in) → Bonjour `_ssh._tcp` + `_r1o._tcp` via `/usr/bin/dns-sd` → select → coordinator → verify → cables → bridge0 if blocking → typeable storage → complete.
6. Stop when ground shows `welcome.completed` (and cluster flag if they skipped `/setup`) and asmi is up.

## Layer 5 — Output

After each step report:

```
step: <welcome|local|cliproxy|tailscale|scan|storage|done>
live: <one line from ground>
next: <one action>
```

No menus. One next action.

## Layer 6 — Verification

Done when:

- `scripts/ground.sh` shows asmi up.
- Welcome finished (or user is mid `/setup` by choice).
- Hub: cliproxy HTTP up **or** explicit skip (not hub).
- Multi: Tailscale `BackendState=Running` and scan is not asmi-gated empty.
- Storage (if shown): a path the user typed is what will be persisted.

<boundaries>
**DO:** ground first; follow `getActiveSteps`; fail closed; use kickstart / absolute Tailscale / `/usr/bin/dns-sd`.
**DO NOT:** invent cluster members; re-open `/setup` after a local welcome finish; hardcode ports/uids/hosts; use GNU `timeout` for mDNS.
</boundaries>

<examples>
**User:** "first launch, set up r1o on this Mac"

Ground → asmi down, cliproxy missing, no flags. Next: start `/welcome`, pick a local model, finish. Do not open `/setup`.

**User:** "setup wizard can't find Tailscale but the app is installed"

Ground → `bin=missing` or PATH-empty. Next: probe `/opt/homebrew/bin/tailscale` then Tailscale.app. Report `daemon_down` vs `not_logged_in`. Never claim "not installed" if either absolute path works.

**User:** "CLIProxy bootstrap failed exit 5"

Ground → launchd loaded. Next: `launchctl kickstart -k gui/$(id -u)/homebrew.mxcl.cliproxyapi`, then re-probe HTTP. Do not `brew services start` again.
</examples>
