The live seed importer merged the active agent's provider keys into the operator ~/.env, but colibri_daemon reads /usr/local/etc/colibri/provider.env (rc.conf colibri_daemon_provider_env). So a personalized seed carrying real provider keys never reached the daemon and no agent auto-spawned. Route the active agent's non-BW_* keys into provider.env (0600 root) in addition to ~/.env. The importer runs as root BEFORE LOGIN and colibri_daemon REQUIREs LOGIN, so the daemon starts after the keys land and auto-spawns the agent on first boot — no Join Hive click, no Vaultwarden round-trip, no typing. This makes a personalized seed the zero-touch onboarding primitive: the image stays generic/publishable, the FAT32 seed is the (offline) personalization layer. BW_* still route to vault-bootstrap.env for the vault-fetch path. Docs: seed README, START-HERE, and ONBOARDING-SIMPLIFICATION updated to describe the direct-keys path (supersedes the xdg-autostart plan). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.6 KiB
Onboarding Simplification — Decision Doc
2026-06-22 | colibri#143 (zot-rpc-driver) | clawdie-iso
Context
The ISO ships with a manual onboarding flow: operator opens START-HERE.txt in
Mousepad, types 3 Vaultwarden bootstrap credentials into a terminal
(clawdie-join-hive), waits for API key fetch, restarts the daemon.
A zot extension was proposed as an interactive replacement. That was rejected — the onboarding must be agent-independent (chicken-and-egg: zot needs DEEPSEEK_API_KEY, which onboarding fetches), and the existing shell flow already implements masked input, validation, and the full fetch→restart chain.
The real lever is removing the step, not reskinning it.
Current state (proven, live)
Manual path (no seed partition)
- Operator boots ISO
- START-HERE.txt opens in Mousepad (bootstrap autostart)
- Operator double-clicks "Join Hive" on desktop
- Prompted for BW_CLIENTID, BW_CLIENTSECRET (masked), BW_PASSWORD (masked)
clawdie-vault-fetchpulls API keys from Vaultwardencolibri_daemonrestarted- Pi agent auto-spawned and live
Seed partition path (one double-click)
Identical except step 4 is skipped — the seed importer (clawdie-live-seed,
rc.d BEFORE LOGIN) already wrote the BW creds to provider.env. The operator
just double-clicks "Join Hive" and the fetch runs automatically.
Files:
| Component | Path | Role |
|---|---|---|
| Seed importer | live/operator-session/clawdie-live-seed |
rc.d service, runs before login, mounts CLAWDIESEED, routes BW_* creds to provider.env |
| Vault fetcher | live/operator-session/clawdie-vault-fetch |
Standalone: login→unlock→fetch keys by name→write env |
| Join Hive | live/operator-session/clawdie-join-hive.sh |
Desktop launcher: checks for creds → prompts or auto-fetches |
| Seed README | live/operator-session/clawdie-live-seed.README.txt |
Operator-facing seed partition instructions |
Zero-touch: direct keys on the seed (implemented)
The click only existed to trigger the Vaultwarden round-trip. For a personalized stick that already holds the real provider keys, that round-trip is unnecessary — and the boot ordering already favors zero-touch:
clawdie_live_seedruns as root,BEFORE: LOGIN.colibri_daemonrunsREQUIRE: LOGIN— strictly after.
So the importer now merges the active agent's direct provider keys (everything
except BW_*) into the daemon's provider.env as well as the operator's
~/.env. The daemon starts afterward, finds DEEPSEEK_API_KEY, and
auto-spawns the agent (COLIBRI_AUTOSPAWN_PI=YES) — no click, no vault
round-trip, no typing. BW_* still route to ~/.config/vault-bootstrap.env
for operators who prefer the vault-fetch path.
This makes the personalized seed the onboarding primitive:
- The image stays generic and publishable; secrets are never baked in.
- The seed (FAT32
CLAWDIESEED) is the personalization layer and stays physical/offline —env(direct keys + optionalTAILSCALE_AUTH_KEY),harness.toml,soul/,ssh/authorized_keys, optional/shredto wipe keys off the stick after first import. - The seed can be generated by an agent (e.g. Hermes) that already holds the soul and key material, written straight onto the mounted partition.
This supersedes the earlier xdg-autostart "delete the click" plan: it removes the click for free without a first-login sentinel or a network dependency at first boot.
Related: one-secret path (future)
The 3-credential bootstrap (BW_CLIENTID + BW_CLIENTSECRET + BW_PASSWORD)
could collapse to a single pasted token via colibri-vault tenant
provisioning. The vault would pre-generate a one-time enrollment token;
the operator pastes it once; the host exchanges it for permanent API
credentials. This eliminates the Vaultwarden account setup step entirely.
Status: not yet designed. Depends on colibri-vault tenant provisioning (colibri#91).
Zot extensions — verdict
| Idea | Verdict | Rationale |
|---|---|---|
| Onboarding panel (zot ext) | ❌ Reject | Chicken-and-egg: zot needs secrets that onboarding fetches. Already solved by clawdie-join-hive.sh. |
| Guard (dangerous bash) | ⏸ Defer | Guards zot, not Pi (OOTB agent). String matcher is a nudge, not a boundary. Ship through first-party extension lane after zot is the runtime. |
| MCP bridge (zot↔Colibri) | ✅ Keeper | Sanctioned lane. Gated on zot-rpc-driver (colibri#143). First extension worth building — gives zot access to task board, vault, spawn, skills. |
Sequencing
- Now (no dependencies): seed-partition zero-touch — delete the one remaining click. Biggest simplification, zero dependency on the zot saga.
- Gated on colibri#143: MCP bridge extension — zot↔Colibri, gives zot reason to be the runtime.
- After zot is OOTB runtime: guard extension shipped through first-party extension lane, paired with jail confinement for the real boundary.