Onboarding Bootstrap & lantern CLI โ Design Spec โ
Date: 2026-06-12 Status: Implemented 2026-07-13 on claude/repo-memory-skills-org-p0owiz (postinstall banner, .vscode folderOpen task, lantern bin with doctor/setup/onboard/dev/help, devcontainer pointer, guide updates). Adds onboard beyond the original table to wire the newer .agents/context/ layer. Closes #595. Companion guides: docs/engineering/guides/ONBOARDING.md, docs/engineering/guides/ENVIRONMENT_SETUP.mdTarget branch: dev
1. Problem โ
When a developer clones the repo for the first time, there is no reliable moment where the repo can greet them and steer onboarding โ unless they happen to be in a Codespace.
A bare git clone followed by opening a terminal triggers nothing from the repo:
- Git deliberately does not run repo-shipped hooks on clone (that would be remote code execution on clone).
.bashrc/.zshrcbelong to the developer's machine, not the repo.- Opening a terminal runs the developer's shell init, not ours.
What we have today only covers part of the surface:
| Entry point | Fires when | Status |
|---|---|---|
devcontainer postAttachCommand | every editor attach in Codespaces / Dev Containers | โ
prints ๐ฎ banner โ .devcontainer/devcontainer.json |
devcontainer postCreateCommand | container first build | โ installs Node + deps |
husky prepare | npm install | โ wires git hooks only โ no onboarding output |
npm postinstall | first npm install (everyone) | โ gap |
VS Code folderOpen task | opening folder locally (non-container) | โ no .vscode/tasks.json |
The uncovered persona is the plain local-clone developer: clones the repo, opens VS Code locally (no container), runs npm install, and gets no guidance toward npm run env:bootstrap, prerequisite checks, or the help index. Onboarding correctness is currently tribal knowledge spread across two guide docs.
A secondary problem: we have the substance of a CLI (npm run help reading scripts-info, env:bootstrap/env:check/env:sync, the Lantern Control VS Code panel) but no single discoverable entrypoint or health-check command. "Is my setup correct?" has no one-command answer.
2. Goal โ
- Give every fresh clone โ local or Codespace โ a single, idempotent onboarding nudge that points at the right next command.
- Provide
lantern doctor: one command that verifies a developer's environment (Node vs.nvmrc, gcloud auth,.env.localcompleteness, optional tooling) and prints actionable next steps. - Expose a thin local
lanternbin that dispatches to existing scripts โ no logic duplication, no published package.
Out of scope: a published @lantern/cli npm package (overkill for an internal monorepo โ adds versioning/publishing overhead for team-only tooling); rewriting bootstrap-env.mjs / sync-env.mjs (the CLI wraps them); changing the Codespace flow, which already works.
3. Approach โ
Three additive pieces, ordered by leverage. None removes or changes existing behavior.
3.1 postinstall onboarding banner โ
Add a postinstall script that prints a short, idempotent banner after npm install โ the one moment every fresh clone hits exactly once.
// package.json
"scripts": {
"postinstall": "node tooling/scripts/postinstall-banner.mjs"
}tooling/scripts/postinstall-banner.mjs (new):
- CI guard: no-op when
process.env.CIis set (keeps CI logs clean, avoids noise in automation). - Idempotent + cheap:
postinstallruns on every install, so the script must be a fastconsole.log, never heavy work. No network, no file writes. - Quiet on repeat (optional): skip the banner if
.env.localalready exists and is complete (i.e. the dev is past onboarding), so established devs aren't nagged on everynpm install. - Content: points at
npx lantern doctor,npm run env:bootstrap, andnpm run help.
This closes the row marked โ gap in ยง1 and is the single highest-coverage change โ npm install is unavoidable on a fresh clone.
3.2 .vscode/tasks.json folder-open task โ
A runOptions.runOn: "folderOpen" task that prints the same banner. Covers the VS Code-local developer before they run npm install, so they see guidance the moment they open the folder.
// .vscode/tasks.json (new)
{
"version": "2.0.0",
"tasks": [{
"label": "Lantern: onboarding hint",
"type": "shell",
"command": "node tooling/scripts/postinstall-banner.mjs --folder-open",
"presentation": { "reveal": "silent", "panel": "shared" },
"runOptions": { "runOn": "folderOpen" }
}]
}Reuses the same script (a --folder-open flag adjusts copy: "run npm install first"). Note VS Code prompts the user to allow folder-open auto-tasks the first time โ this is expected and acceptable.
3.3 Thin lantern bin โ
Add a bin field so lantern <cmd> is on PATH inside the repo after install:
// package.json
"bin": { "lantern": "tooling/scripts/lantern.mjs" }tooling/scripts/lantern.mjs (new) is a dispatcher, not a reimplementation. Subcommands shell out to existing scripts:
| Subcommand | Delegates to | Purpose |
|---|---|---|
lantern doctor | new check logic (ยง4) + sync-env.mjs --check | environment health check |
lantern setup | bootstrap-env.mjs | pull secrets from Secret Manager |
lantern dev | npm run dev | start web preview |
lantern help | help.mjs | grouped script index |
lantern (no arg) | prints doctor summary + help pointer | default landing |
doctor is the centerpiece โ it turns "is my setup right?" into one command and is the natural thing for the banner (ยง3.1) and the Codespace postAttachCommand to point at.
4. lantern doctor checks โ
Each check is non-fatal and prints a โ / โ ๏ธ / โ line plus a fix hint. Exit code is non-zero only if a required check fails, so it's usable in scripts.
| Check | How | Severity if failing |
|---|---|---|
| Node version | compare process.version against .nvmrc (24.16.0) and engines.node (>=24.0.0) | required |
| Dependencies installed | node_modules present + lockfile in sync | required |
| gcloud CLI | gcloud version (mirrors bootstrap-env.mjs:181) | optional โ only needed for secret pull |
| gcloud ADC | gcloud auth application-default print-access-token | optional |
.env.local completeness | reuse sync-env.mjs --check (npm run env:check) | warning |
| firebase-tools | firebase --version (emulators / rules) | optional |
| git hooks installed | .husky/_ present (husky prepare ran) | warning |
doctor reuses the prerequisite logic already in bootstrap-env.mjs rather than duplicating it โ extract checkGcloud()-style helpers into a shared module if needed, or call npm run env:check as a child process. No new secret-fetching logic.
5. Wiring existing entrypoints to the new CLI โ
- devcontainer
postAttachCommand(.devcontainer/devcontainer.json): append a pointer tonpx lantern doctorafter the existing ๐ฎ banner. The auth/bootstrap instructions stay as-is. ONBOARDING.md/ENVIRONMENT_SETUP.md: replace the hand-listed setup steps withnpx lantern doctorโnpx lantern setupas the canonical path, keeping the manual steps as a fallback section.- Lantern Control VS Code panel (shares
tooling/shared/script-groups.cjs): optionally surface a "Doctor" button later โ not required for v1.
6. Why not the alternatives โ
- direnv
.envrcโ auto-runs oncd, but requires every dev to install direnv and rundirenv allow. Higher friction than the install hook for strictly worse coverage. Rejected. - Git hook injected via husky โ
prepareruns on install and could print a banner, but conflates "wire hooks" with "onboard human"; hooks shouldn't be a UI surface. The dedicatedpostinstallis clearer. Rejected for the banner; husky keeps its existing job. - Published
@lantern/clipackage โ versioning, publishing, and a release cadence for tooling only this team uses. A repo-localbingets the discoverability (npx lantern) with none of the overhead. Rejected for now; revisit only if tooling is shared across repos. - Shell-rc injection โ invasive, modifies the developer's machine, hard to uninstall. Never. Rejected.
7. Risks & mitigations โ
postinstallnoise / CI breakage โ guarded byif (process.env.CI) returnand kept to a pureconsole.log. No writes, no network, fast.- Repeat-nag fatigue โ banner self-suppresses once
.env.localis complete (ยง3.1). - folderOpen task trust prompt โ VS Code asks to allow the auto-task once; documented in the onboarding guide so it's expected, not alarming.
- CLI drifts from npm scripts โ
lanterndelegates to the same scriptshelp.mjs/package.jsonexpose, so there's one source of truth.doctorreusesbootstrap-env.mjsprerequisite checks rather than forking them.
8. Implementation checklist โ
tooling/scripts/postinstall-banner.mjs(+ CI guard,--folder-openflag, completeness self-suppress).package.json: addpostinstallscript +binfield.tooling/scripts/lantern.mjsdispatcher withdoctor/setup/dev/help.lantern doctorchecks (ยง4), reusingbootstrap-env.mjsprerequisite helpers +env:check..vscode/tasks.jsonfolder-open task.- Append
npx lantern doctorpointer topostAttachCommand. - Update
ONBOARDING.md+ENVIRONMENT_SETUP.mdto lead with the CLI. - Add
scripts-infoentries so the new scripts show innpm run help.
9. Rollout โ
Single PR to dev. No migration, no data changes, no prod surface โ purely developer tooling. Verify by: fresh npm install (banner prints, CI run stays quiet), npx lantern doctor against both a complete and an incomplete .env.local, and a Codespace rebuild to confirm the postAttachCommand pointer renders.