happy-stacks 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +130 -74
  2. package/bin/happys.mjs +140 -9
  3. package/docs/edison.md +381 -0
  4. package/docs/happy-development.md +733 -0
  5. package/docs/menubar.md +54 -0
  6. package/docs/paths-and-env.md +141 -0
  7. package/docs/server-flavors.md +61 -2
  8. package/docs/stacks.md +55 -4
  9. package/extras/swiftbar/auth-login.sh +10 -7
  10. package/extras/swiftbar/git-cache-refresh.sh +130 -0
  11. package/extras/swiftbar/happy-stacks.5s.sh +175 -83
  12. package/extras/swiftbar/happys-term.sh +128 -0
  13. package/extras/swiftbar/happys.sh +35 -0
  14. package/extras/swiftbar/install.sh +99 -13
  15. package/extras/swiftbar/lib/git.sh +309 -1
  16. package/extras/swiftbar/lib/icons.sh +2 -2
  17. package/extras/swiftbar/lib/render.sh +279 -132
  18. package/extras/swiftbar/lib/system.sh +64 -10
  19. package/extras/swiftbar/lib/utils.sh +469 -10
  20. package/extras/swiftbar/pnpm-term.sh +2 -122
  21. package/extras/swiftbar/pnpm.sh +4 -14
  22. package/extras/swiftbar/set-interval.sh +10 -5
  23. package/extras/swiftbar/set-server-flavor.sh +19 -10
  24. package/extras/swiftbar/wt-pr.sh +10 -3
  25. package/package.json +2 -1
  26. package/scripts/auth.mjs +833 -14
  27. package/scripts/build.mjs +24 -4
  28. package/scripts/cli-link.mjs +3 -3
  29. package/scripts/completion.mjs +15 -8
  30. package/scripts/daemon.mjs +200 -23
  31. package/scripts/dev.mjs +230 -57
  32. package/scripts/doctor.mjs +26 -21
  33. package/scripts/edison.mjs +1828 -0
  34. package/scripts/happy.mjs +3 -7
  35. package/scripts/init.mjs +275 -46
  36. package/scripts/install.mjs +14 -8
  37. package/scripts/lint.mjs +145 -0
  38. package/scripts/menubar.mjs +81 -8
  39. package/scripts/migrate.mjs +302 -0
  40. package/scripts/mobile.mjs +59 -21
  41. package/scripts/run.mjs +222 -43
  42. package/scripts/self.mjs +3 -7
  43. package/scripts/server_flavor.mjs +3 -3
  44. package/scripts/service.mjs +190 -38
  45. package/scripts/setup.mjs +790 -0
  46. package/scripts/setup_pr.mjs +182 -0
  47. package/scripts/stack.mjs +2273 -92
  48. package/scripts/stop.mjs +160 -0
  49. package/scripts/tailscale.mjs +164 -23
  50. package/scripts/test.mjs +144 -0
  51. package/scripts/tui.mjs +556 -0
  52. package/scripts/typecheck.mjs +145 -0
  53. package/scripts/ui_gateway.mjs +248 -0
  54. package/scripts/uninstall.mjs +21 -13
  55. package/scripts/utils/auth_files.mjs +58 -0
  56. package/scripts/utils/auth_login_ux.mjs +76 -0
  57. package/scripts/utils/auth_sources.mjs +12 -0
  58. package/scripts/utils/browser.mjs +22 -0
  59. package/scripts/utils/canonical_home.mjs +20 -0
  60. package/scripts/utils/{cli_registry.mjs → cli/cli_registry.mjs} +71 -0
  61. package/scripts/utils/{wizard.mjs → cli/wizard.mjs} +1 -1
  62. package/scripts/utils/config.mjs +13 -1
  63. package/scripts/utils/dev_auth_key.mjs +169 -0
  64. package/scripts/utils/dev_daemon.mjs +104 -0
  65. package/scripts/utils/dev_expo_web.mjs +112 -0
  66. package/scripts/utils/dev_server.mjs +183 -0
  67. package/scripts/utils/env.mjs +94 -23
  68. package/scripts/utils/env_file.mjs +36 -0
  69. package/scripts/utils/expo.mjs +96 -0
  70. package/scripts/utils/handy_master_secret.mjs +94 -0
  71. package/scripts/utils/happy_server_infra.mjs +484 -0
  72. package/scripts/utils/localhost_host.mjs +17 -0
  73. package/scripts/utils/ownership.mjs +135 -0
  74. package/scripts/utils/paths.mjs +5 -2
  75. package/scripts/utils/pm.mjs +132 -22
  76. package/scripts/utils/ports.mjs +51 -13
  77. package/scripts/utils/proc.mjs +75 -7
  78. package/scripts/utils/runtime.mjs +1 -3
  79. package/scripts/utils/sandbox.mjs +14 -0
  80. package/scripts/utils/server.mjs +61 -0
  81. package/scripts/utils/server_port.mjs +9 -0
  82. package/scripts/utils/server_urls.mjs +54 -0
  83. package/scripts/utils/stack_context.mjs +23 -0
  84. package/scripts/utils/stack_runtime_state.mjs +104 -0
  85. package/scripts/utils/stack_startup.mjs +208 -0
  86. package/scripts/utils/stack_stop.mjs +255 -0
  87. package/scripts/utils/stacks.mjs +38 -0
  88. package/scripts/utils/validate.mjs +42 -1
  89. package/scripts/utils/watch.mjs +63 -0
  90. package/scripts/utils/worktrees.mjs +57 -1
  91. package/scripts/where.mjs +14 -7
  92. package/scripts/worktrees.mjs +135 -15
  93. /package/scripts/utils/{args.mjs → cli/args.mjs} +0 -0
  94. /package/scripts/utils/{cli.mjs → cli/cli.mjs} +0 -0
  95. /package/scripts/utils/{smoke_help.mjs → cli/smoke_help.mjs} +0 -0
@@ -0,0 +1,733 @@
1
+ # Happy component development (Happy Stacks)
2
+
3
+ This doc explains **how to develop the Happy components** using **Happy Stacks**:
4
+
5
+ - `happy` (UI)
6
+ - `happy-cli` (CLI + daemon)
7
+ - `happy-server-light` (SQLite “light” server)
8
+ - `happy-server` (Postgres “full” server)
9
+
10
+ It’s intended to be a “one-stop” guide for **humans and LLMs** to iterate safely and repeatably.
11
+
12
+ If you’re new to the project, start here:
13
+
14
+ - Self-hosting / running locally: `README.md`
15
+ - Worktrees + fork workflow: `docs/worktrees-and-forks.md`
16
+ - Stacks: `docs/stacks.md`
17
+ - Server flavors: `docs/server-flavors.md`
18
+ - Paths/env precedence: `docs/paths-and-env.md`
19
+ - Edison workflow (tasks/QA/evidence): `docs/edison.md`
20
+
21
+ ---
22
+
23
+ ## Core concepts (the mental model)
24
+
25
+ ### Components
26
+
27
+ Happy Stacks is a launcher/orchestrator repo. The actual product code lives in component repos under:
28
+
29
+ - `components/happy`
30
+ - `components/happy-cli`
31
+ - `components/happy-server-light`
32
+ - `components/happy-server`
33
+
34
+ Each component is its own Git repo.
35
+
36
+ ### Worktrees (where you do development)
37
+
38
+ **Never develop directly** in the default checkouts under `components/<component>`.
39
+ Treat them as **read-only launcher defaults**.
40
+
41
+ All development should happen inside **component worktrees** under:
42
+
43
+ ```
44
+ components/.worktrees/<component>/<owner>/<branch...>
45
+ ```
46
+
47
+ Worktrees make it easy to:
48
+
49
+ - keep your fork “distribution” branches stable
50
+ - create clean upstream PR branches
51
+ - work on multiple PRs/features in parallel
52
+
53
+ See: `docs/worktrees-and-forks.md`.
54
+
55
+ ### Stacks (how you test changes safely)
56
+
57
+ A **stack** is an isolated runtime environment (ports + dirs + DB + CLI home) stored under:
58
+
59
+ ```
60
+ ~/.happy/stacks/<stack>/...
61
+ ```
62
+
63
+ Stacks are configured by an env file:
64
+
65
+ ```
66
+ ~/.happy/stacks/<stack>/env
67
+ ```
68
+
69
+ You should test worktrees inside a non-`main` stack (recommended).
70
+
71
+ See: `docs/stacks.md`.
72
+
73
+ ### Server flavor (which backend you’re running)
74
+
75
+ You run exactly one server implementation per stack:
76
+
77
+ - **`happy-server-light`** (default): SQLite, serves built UI in “start” mode
78
+ - **`happy-server`** (full): Postgres + Redis + S3 (Minio), managed per stack (Docker Compose)
79
+
80
+ See: `docs/server-flavors.md`.
81
+
82
+ ---
83
+
84
+ ## Non‑negotiables (discipline that keeps stacks safe)
85
+
86
+ - **Use `happys` as the only entrypoint**
87
+ - Don’t run raw `pnpm`, `yarn`, `expo`, `tsc`, `docker`, etc. directly.
88
+ - Happy Stacks needs stack-scoped env + runtime bookkeeping to stay isolated.
89
+ - **Develop only in worktrees**
90
+ - Work inside `components/.worktrees/...`, not `components/<component>`.
91
+ - **Test/validate stack‑scoped**
92
+ - Prefer `happys stack <stack> ...` commands (typecheck/lint/build/test/dev/start).
93
+ - **Do not “kill all daemons”**
94
+ - Multiple stack daemons are expected. Stop stacks explicitly (`happys stack stop …` or `happys stop …`).
95
+ - **Main stack safety**
96
+ - Avoid repointing `main` stack component dirs to worktrees. Use a new stack.
97
+ - `happys wt use …` will warn/refuse for `main` unless you pass `--force`.
98
+
99
+ ---
100
+
101
+ ## Quickstarts (common development flows)
102
+
103
+ ### 1) UI-only change (Happy UI)
104
+
105
+ Create a stack and point it at a UI worktree:
106
+
107
+ ```bash
108
+ happys stack new ui1 --interactive
109
+
110
+ # Create a worktree (upstream-first recommended)
111
+ happys wt new happy pr/my-ui-change --from=upstream --use
112
+
113
+ # Pin the stack to that worktree
114
+ happys stack wt ui1 -- use happy slopus/pr/my-ui-change
115
+
116
+ # Run dev (server + daemon + Expo web)
117
+ happys stack dev ui1
118
+ ```
119
+
120
+ Validate:
121
+
122
+ ```bash
123
+ happys stack typecheck ui1 happy
124
+ happys stack lint ui1 happy
125
+ happys stack test ui1 happy
126
+ ```
127
+
128
+ ### 2) UI + CLI change (Happy + happy-cli)
129
+
130
+ ```bash
131
+ happys stack new feat1 --interactive
132
+
133
+ happys wt new happy pr/resume-ui --from=upstream --use
134
+ happys wt new happy-cli pr/resume-cli --from=upstream --use
135
+
136
+ happys stack wt feat1 -- use happy slopus/pr/resume-ui
137
+ happys stack wt feat1 -- use happy-cli slopus/pr/resume-cli
138
+
139
+ happys stack dev feat1
140
+ ```
141
+
142
+ Validate both:
143
+
144
+ ```bash
145
+ happys stack typecheck feat1 happy happy-cli
146
+ happys stack lint feat1 happy happy-cli
147
+ happys stack test feat1 happy happy-cli
148
+ ```
149
+
150
+ ### 3) Developing server changes (full server)
151
+
152
+ Create a stack that uses `happy-server`:
153
+
154
+ ```bash
155
+ happys stack new server1 --interactive
156
+ happys stack srv server1 -- use happy-server
157
+
158
+ happys wt new happy-server pr/my-server-fix --from=upstream --use
159
+ happys stack wt server1 -- use happy-server slopus/pr/my-server-fix
160
+
161
+ happys stack dev server1
162
+ ```
163
+
164
+ Notes:
165
+
166
+ - Full server stacks may manage per-stack infra automatically (Postgres/Redis/Minio) via Docker Compose.
167
+ - Use stack-safe commands to stop infra cleanly: `happys stack stop server1` (or `happys stop …`).
168
+
169
+ ### 4) Testing an upstream PR locally
170
+
171
+ ```bash
172
+ happys wt pr happy 123 --slug=123-fix-thing --use
173
+ happys stack new pr123
174
+ happys stack wt pr123 -- use happy slopus/pr/123-fix-thing
175
+ happys stack dev pr123
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Worktrees: upstream-first workflow + fork integration
181
+
182
+ Happy Stacks is designed for an **upstream-first** workflow:
183
+
184
+ - Implement on an **upstream-based** worktree/branch (`--from=upstream`).
185
+ - Open a clean PR to upstream (`slopus/*`) when appropriate.
186
+ - Then validate/ship to your fork via **test-merge → cherry-pick fallback** (in a fork-based worktree).
187
+
188
+ See the full guide: `docs/worktrees-and-forks.md`.
189
+
190
+ ### Concrete walkthrough: upstream PR → fork integration
191
+
192
+ This is the most common “ship it everywhere without polluting history” flow.
193
+
194
+ #### 1) Create an upstream-based worktree and implement
195
+
196
+ Example: implement a UI fix intended for upstream:
197
+
198
+ ```bash
199
+ happys wt new happy pr/my-ui-fix --from=upstream --use
200
+ ```
201
+
202
+ Notes:
203
+
204
+ - When you use `--from=upstream`, the worktree branch name is owner-prefixed. This example produces a branch named:
205
+ - `slopus/pr/my-ui-fix`
206
+
207
+ Do your work inside the worktree path under `components/.worktrees/...`.
208
+
209
+ When ready, push to upstream:
210
+
211
+ ```bash
212
+ happys wt push happy active --remote=upstream
213
+ ```
214
+
215
+ #### 2) Validate the same commits on your fork (test-merge)
216
+
217
+ Create a fork-based “integration” worktree (temporary branch) and try merging the upstream branch into it:
218
+
219
+ ```bash
220
+ happys wt new happy tmp/merge-pr-my-ui-fix --from=origin --use
221
+ ```
222
+
223
+ Then merge the upstream branch/commit(s) inside that worktree:
224
+
225
+ ```bash
226
+ # optional: confirm the upstream branch name before merging
227
+ happys wt status happy slopus/pr/my-ui-fix --json
228
+
229
+ happys wt git happy active -- merge --no-ff slopus/pr/my-ui-fix
230
+ ```
231
+
232
+ If it merges cleanly, push to your fork and open a fork PR:
233
+
234
+ ```bash
235
+ happys wt push happy active --remote=origin
236
+ ```
237
+
238
+ #### 3) If it conflicts: cherry-pick fallback
239
+
240
+ If the test-merge conflicts, abort the merge, then cherry-pick the upstream commits onto a fork PR branch/worktree and resolve conflicts there:
241
+
242
+ ```bash
243
+ happys wt git happy active -- merge --abort
244
+
245
+ # cherry-pick the upstream commits you want (examples):
246
+ happys wt git happy active -- cherry-pick <commit1> <commit2>
247
+ ```
248
+
249
+ Notes:
250
+
251
+ - This keeps the upstream PR history clean and makes fork PRs reproducible.
252
+ - The same pattern applies to `happy-cli` and server repos too.
253
+
254
+ ### Server repos: shipping the same change to both fork flavors
255
+
256
+ Server development has one extra twist: **our fork uses a single GitHub repo with two “main” branches**.
257
+
258
+ - **Upstream repo**: `slopus/happy-server` (base branch typically `main`)
259
+ - **Fork repo**: `leeroybrun/happy-server-light`
260
+ - full server fork “main” branch: `happy-server`
261
+ - light server fork “main” branch: `happy-server-light`
262
+
263
+ Local checkouts:
264
+
265
+ - `components/happy-server` and `components/happy-server-light` are **separate local repos** (separate clones) so branch names do not automatically exist in both.
266
+ - In these server repos, the fork remote name is often `fork` (not `origin`), but **`happys wt` normalizes `origin` ↔ `fork`** automatically.
267
+
268
+ #### Goal: one upstream PR, two fork PRs (one per target branch)
269
+
270
+ 1) Implement on an upstream-based worktree (recommended use the full server component):
271
+
272
+ ```bash
273
+ happys wt new happy-server pr/my-server-fix --from=upstream --use
274
+ ```
275
+
276
+ Push upstream (to open the upstream PR):
277
+
278
+ ```bash
279
+ happys wt push happy-server active --remote=upstream
280
+ ```
281
+
282
+ 2) Check out that upstream PR in the other local server component too (so you can reuse the exact same commits there).
283
+
284
+ Example (use the upstream PR URL/number):
285
+
286
+ ```bash
287
+ happys wt pr happy-server-light https://github.com/slopus/happy-server/pull/<N> --use
288
+ ```
289
+
290
+ 3) For each fork flavor, create a fork-based integration worktree and merge the PR branch into it, then push.
291
+
292
+ Full server fork branch (`happy-server`):
293
+
294
+ ```bash
295
+ happys wt new happy-server tmp/merge-pr-my-server-fix --from=origin --use
296
+ happys wt status happy-server --json
297
+ # merge the upstream PR branch name shown by wt/pr (example: slopus/pr/<N>-<slug>)
298
+ happys wt git happy-server active -- merge --no-ff slopus/pr/<N>-<slug>
299
+ happys wt push happy-server active --remote=origin
300
+ ```
301
+
302
+ Light server fork branch (`happy-server-light`):
303
+
304
+ ```bash
305
+ happys wt new happy-server-light tmp/merge-pr-my-server-fix --from=origin --use
306
+ happys wt status happy-server-light --json
307
+ # merge the upstream PR branch name shown by wt/pr (example: slopus/pr/<N>-<slug>)
308
+ happys wt git happy-server-light active -- merge --no-ff slopus/pr/<N>-<slug>
309
+ happys wt push happy-server-light active --remote=origin
310
+ ```
311
+
312
+ Then open **two PRs** to `leeroybrun/happy-server-light`:
313
+
314
+ - one targeting base branch `happy-server`
315
+ - one targeting base branch `happy-server-light`
316
+
317
+ If a merge conflicts, use the same **cherry-pick fallback** described above, but do it separately for each fork target branch/worktree.
318
+
319
+ High-signal commands:
320
+
321
+ - **Sync mirror branches** (update local `<owner>/<defaultBranch>` mirrors):
322
+
323
+ ```bash
324
+ happys wt sync-all
325
+ ```
326
+
327
+ - **Update worktrees** (rebase/merge against mirrors):
328
+
329
+ ```bash
330
+ happys wt update-all --dry-run
331
+ happys wt update-all --stash
332
+ ```
333
+
334
+ - **Switch active checkout**:
335
+
336
+ ```bash
337
+ happys wt use happy slopus/pr/my-feature
338
+ happys wt use happy default
339
+ ```
340
+
341
+ ---
342
+
343
+ ## Running: `start` vs `dev`
344
+
345
+ ### `happys start` (production-like)
346
+
347
+ - Runs the stack in a stable mode.
348
+ - Typically serves a built UI via `happy-server-light` (unless using full server with UI gateway).
349
+
350
+ ### `happys dev` (development)
351
+
352
+ Runs the “full local dev loop”:
353
+
354
+ - **server** (light or full, per stack)
355
+ - **daemon** (`happy-cli`) pointing at that server
356
+ - **UI** via Expo web dev server
357
+
358
+ ### Web UI origin isolation (IMPORTANT)
359
+
360
+ When running **non-main stacks**, Happy Stacks will use a stack-specific localhost hostname:
361
+
362
+ - `http://happy-<stack>.localhost:<uiPort>`
363
+
364
+ This intentionally creates a **unique browser origin per stack** so browser storage (localStorage/cookies) does not collide between stacks (which can otherwise cause “no machine” / auth confusion).
365
+
366
+ ### Browser auto-open (`--no-browser`)
367
+
368
+ In interactive TTY runs, `happys dev` / `happys start` may auto-open the UI in your browser.
369
+
370
+ - Disable: `--no-browser`
371
+ - Stack mode uses the stack-specific hostname shown above (not plain `localhost`) for correctness.
372
+
373
+ **Dev reliability features** (implemented in Happy Stacks):
374
+
375
+ - **Dependency install**: ensures component deps are installed when needed.
376
+ - **Schema readiness**:
377
+ - `happy-server` (Postgres): applies `prisma migrate deploy` (configurable via `HAPPY_STACKS_PRISMA_MIGRATE`)
378
+ - `happy-server-light` (SQLite): upstream dev normally runs `prisma db push` (toggle via `HAPPY_STACKS_PRISMA_PUSH`)
379
+ - **Auth seeding for new stacks** (non-main + non-interactive default):
380
+ - Uses the configured seed stack via `HAPPY_STACKS_AUTH_SEED_FROM` (default: `main`) when the stack looks uninitialized.
381
+ - Recommended for development: create + log into a dedicated seed stack once (usually `dev-auth`) and set:
382
+ - `HAPPY_STACKS_AUTH_SEED_FROM=dev-auth`
383
+ - `HAPPY_STACKS_AUTO_AUTH_SEED=1`
384
+ - This copies credentials/master secret and seeds the minimal DB rows (Accounts) without copying full DB files.
385
+
386
+ ---
387
+
388
+ ## “Smart builds” + watch mode (hot-reload-ish)
389
+
390
+ ### happy-cli build behavior
391
+
392
+ `happys dev` / `happys start` will ensure `happy-cli` is built when needed:
393
+
394
+ - If `dist/index.mjs` is missing, it builds.
395
+ - If source/deps changed since the last build, it rebuilds (git-based signature cache).
396
+
397
+ Controls:
398
+
399
+ - `HAPPY_STACKS_CLI_BUILD_MODE=auto|always|never` (legacy: `HAPPY_LOCAL_CLI_BUILD_MODE`)
400
+ - `HAPPY_STACKS_CLI_BUILD=0` to hard-disable build
401
+
402
+ ### Watch mode
403
+
404
+ In interactive TTY runs, `happys dev` enables a watcher by default (disable with `--no-watch`):
405
+
406
+ - **happy-cli changes** → rebuild CLI + restart daemon
407
+ - **happy-server changes** (full server only, where we run `start`) → restart server
408
+
409
+ Important:
410
+
411
+ - Server watch is **stack-only** and is enabled only when Happy Stacks can identify the current **stack-owned server PID**.
412
+ - If the server was already running and the PID can’t be resolved, `dev` will disable server watch and tell you to re-run with `--restart`.
413
+
414
+ Why only full server gets an external watcher:
415
+
416
+ - `happy-server-light` upstream `dev` already provides the correct dev loop.
417
+ - `happy-server` upstream `dev` is not stack-safe, so we run `start` and add our own watcher.
418
+
419
+ ### Runtime state + ports during restarts
420
+
421
+ When watchers restart components:
422
+
423
+ - Happy Stacks updates per-stack runtime state with the **new PIDs**
424
+ - It reuses the **same ports** for the run (restarts reuse the same `PORT`)
425
+ - Ports are allocated once per `stack dev/start` invocation and are kept stable for the lifetime of that run.
426
+
427
+ See “Process isolation + runtime state” below.
428
+
429
+ ---
430
+
431
+ ## Developer-only: set up a `dev-auth` seed stack + dev UI key
432
+
433
+ This is a **one-time developer machine setup**. LLM agents should **not** do this; agents should only consume existing seeds/keys.
434
+
435
+ ### Create the seed stack (wizard)
436
+
437
+ Run:
438
+
439
+ ```bash
440
+ happys stack create-dev-auth-seed
441
+ ```
442
+
443
+ This will (interactive, in a TTY):
444
+
445
+ - create (or reuse) the `dev-auth` stack
446
+ - start a temporary server + Expo UI
447
+ - guide you through creating/restoring an account in the UI
448
+ - prompt to save the dev key locally (never committed)
449
+ - run `happys stack auth dev-auth login` to authenticate the CLI/daemon for that seed stack
450
+
451
+ ### Make it the default seed for new stacks
452
+
453
+ Add to `~/.happy-stacks/env.local`:
454
+
455
+ ```bash
456
+ HAPPY_STACKS_AUTH_SEED_FROM=dev-auth
457
+ HAPPY_STACKS_AUTO_AUTH_SEED=1
458
+ ```
459
+
460
+ ### Repair / seed existing stacks (bulk)
461
+
462
+ ```bash
463
+ happys auth copy-from dev-auth --all --except=main,dev-auth
464
+ ```
465
+
466
+ If you have full-server (`happy-server`) stacks and want seeding to bring up infra automatically:
467
+
468
+ ```bash
469
+ happys auth copy-from dev-auth --all --except=main,dev-auth --with-infra
470
+ ```
471
+
472
+ ### Print the UI-accepted dev key format (for UI login / agents)
473
+
474
+ ```bash
475
+ happys auth dev-key --print
476
+ ```
477
+
478
+ By default, in a TTY this prints the UI “backup” format (`XXXXX-...`). For automation, use `--format=base64url`.
479
+
480
+ ---
481
+
482
+ ## Process isolation + runtime state (why stops/restarts are safe)
483
+
484
+ Happy Stacks is “stack-safe” by design:
485
+
486
+ - It tracks PIDs it starts (runner/server/UI/daemon)
487
+ - It refuses to kill processes unless they look **owned by the target stack**
488
+ - ownership is validated using process env (stack name + env file path)
489
+
490
+ ### Runtime state file
491
+
492
+ Non-persisted runtime details (ephemeral ports + PIDs) live in:
493
+
494
+ ```
495
+ ~/.happy/stacks/<stack>/stack.runtime.json
496
+ ```
497
+
498
+ This file is intentionally separate from the stack env file:
499
+
500
+ - Env file = stable configuration you *intend* to persist
501
+ - Runtime state = transient state for the currently running processes
502
+
503
+ ### Stopping stacks safely
504
+
505
+ Stop a single stack:
506
+
507
+ ```bash
508
+ happys stack stop <stack>
509
+ ```
510
+
511
+ Stop everything except main:
512
+
513
+ ```bash
514
+ happys stop --except-stacks=main --yes
515
+ ```
516
+
517
+ Useful flags:
518
+
519
+ - `--aggressive`: stops daemon-tracked sessions (but still only stack-owned)
520
+ - `--sweep-owned`: final “owned process sweep” (kills any remaining processes that still have the stack env in their process env)
521
+ - `--no-docker`: skip managed infra shutdown (when you know Docker is irrelevant)
522
+
523
+ ---
524
+
525
+ ## Validation commands (typecheck / lint / build / test)
526
+
527
+ Run against the **active checkouts**:
528
+
529
+ ```bash
530
+ happys typecheck
531
+ happys lint
532
+ happys build
533
+ happys test
534
+ ```
535
+
536
+ Run stack-scoped (recommended when developing):
537
+
538
+ ```bash
539
+ happys stack typecheck <stack> [component...]
540
+ happys stack lint <stack> [component...]
541
+ happys stack build <stack>
542
+ happys stack test <stack> [component...]
543
+ ```
544
+
545
+ Examples:
546
+
547
+ ```bash
548
+ happys stack typecheck exp1 happy happy-cli
549
+ happys stack lint exp1 happy
550
+ happys stack test exp1 happy-cli
551
+ ```
552
+
553
+ ---
554
+
555
+ ## CLI reference (high-signal)
556
+
557
+ Most commands support `--help` and `--json`.
558
+
559
+ ### Core run commands
560
+
561
+ - **`happys start`**: production-like run (no Expo)
562
+ - Flags: `--server=happy-server|happy-server-light`, `--restart`, `--no-daemon`, `--no-ui`, `--no-browser`
563
+ - **`happys dev`**: dev run (server + daemon + Expo web)
564
+ - Flags: `--server=happy-server|happy-server-light`, `--restart`, `--no-daemon`, `--no-ui`, `--watch`, `--no-watch`, `--no-browser`
565
+ - **`happys stop`**: stop stacks and related processes
566
+ - Flags: `--except-stacks=main,exp1`, `--yes`, `--aggressive`, `--sweep-owned`, `--no-docker`, `--no-service`
567
+
568
+ ### TUI (optional)
569
+
570
+ If you want a split-pane view while running a command:
571
+
572
+ ```bash
573
+ happys tui stack dev <stack>
574
+ ```
575
+
576
+ ### Stack-scoped commands
577
+
578
+ All `happys stack <name> ...` commands apply that stack’s env file (and keep stacks isolated).
579
+
580
+ - **Lifecycle**:
581
+ - `happys stack new <name> [--interactive] [--server=...] [--port=...] [--copy-auth-from=main|--no-copy-auth]`
582
+ - `happys stack dev <name>`
583
+ - `happys stack start <name>`
584
+ - `happys stack stop <name> [--aggressive] [--sweep-owned] [--no-docker]`
585
+ - `happys stack build <name>`
586
+ - **Quality**:
587
+ - `happys stack typecheck <name> [component...]`
588
+ - `happys stack lint <name> [component...]`
589
+ - `happys stack test <name> [component...]`
590
+ - **One-shot component overrides (do not persist)**:
591
+ - Many stack commands accept one-shot overrides like `--happy=...` / `--happy-cli=...` / `--happy-server-light=...` / `--happy-server=...`
592
+ - Example:
593
+
594
+ ```bash
595
+ happys stack typecheck exp1 --happy=slopus/pr/my-ui-pr happy
596
+ ```
597
+ - **Selection / diagnosis / auth**:
598
+ - `happys stack wt <name> -- <wt args...>`
599
+ - `happys stack srv <name> -- use happy-server|happy-server-light`
600
+ - `happys stack doctor <name>`
601
+ - `happys stack auth <name> status|login|copy-from <seed>`
602
+ - `happys stack audit --fix-workspace --fix-paths --fix-ports`
603
+
604
+ ### Worktrees
605
+
606
+ - `happys wt new <component> <branch> --from=upstream|origin --use`
607
+ - `happys wt pr <component> <pr-url|number> --use [--update] [--stash]`
608
+ - `happys wt use <component> <spec>`
609
+ - `happys wt sync-all`
610
+ - `happys wt update-all [--dry-run] [--stash]`
611
+
612
+ ### Edison wrapper (mandatory in this repo)
613
+
614
+ - `happys edison --stack=<stack> -- <edison args...>`
615
+ - `happys edison --stack=<stack> -- evidence capture <task-id>`
616
+
617
+ ---
618
+
619
+ ## Useful environment knobs (high-signal)
620
+
621
+ Happy Stacks uses `HAPPY_STACKS_*` as the canonical prefix; most settings also accept the legacy `HAPPY_LOCAL_*` alias.
622
+
623
+ - **Server flavor**:
624
+ - `HAPPY_STACKS_SERVER_COMPONENT=happy-server-light|happy-server`
625
+ - **Ports**:
626
+ - `HAPPY_STACKS_SERVER_PORT=<n>` (pinned)
627
+ - `HAPPY_STACKS_EPHEMERAL_PORTS=1` (prefer ephemeral ports for stacks; default for non-main stacks)
628
+ - **Full server infra** (happy-server):
629
+ - `HAPPY_STACKS_MANAGED_INFRA=0` (disable Docker-managed Postgres/Redis/Minio; provide URLs yourself)
630
+ - **Prisma behavior**:
631
+ - `HAPPY_STACKS_PRISMA_PUSH=0` (server-light: avoid `prisma db push` in dev mode)
632
+ - `HAPPY_STACKS_PRISMA_MIGRATE=0` (full server: disable `prisma migrate deploy`)
633
+ - **happy-cli build behavior**:
634
+ - `HAPPY_STACKS_CLI_BUILD_MODE=auto|always|never`
635
+ - `HAPPY_STACKS_CLI_BUILD=0` (hard-disable)
636
+
637
+ See also: `docs/paths-and-env.md` for env precedence and where the files live.
638
+
639
+ ---
640
+
641
+ ## Debug / inspect commands
642
+
643
+ - **“Where is this running from?”**:
644
+
645
+ ```bash
646
+ happys where
647
+ happys where --json
648
+ ```
649
+
650
+ - **Stack health / diagnosis**:
651
+
652
+ ```bash
653
+ happys stack doctor <stack>
654
+ ```
655
+
656
+ - **Fix common stack hygiene issues** (foreign component paths, inconsistent dirs, port collisions):
657
+
658
+ ```bash
659
+ happys stack audit --fix-workspace --fix-paths --fix-ports
660
+ ```
661
+
662
+ - **Stop stacks safely**:
663
+
664
+ ```bash
665
+ happys stack stop <stack>
666
+ happys stop --except-stacks=main --yes
667
+ ```
668
+
669
+ ---
670
+
671
+ ## Edison integration (tasks/QA/evidence/validation)
672
+
673
+ Edison is supported in this repo, but **does not provide isolation** here.
674
+ Isolation is provided by **Happy Stacks** (stacks + component worktrees).
675
+
676
+ Key rule: **do not run `edison ...` directly** in this repo.
677
+ Use the wrapper:
678
+
679
+ ```bash
680
+ happys edison --stack=<stack> -- evidence capture <task-id>
681
+ ```
682
+
683
+ This wrapper:
684
+
685
+ - forces stack-scoped env
686
+ - fingerprints the correct multi-repo state
687
+ - enables fail-closed guards (task → stack → worktrees)
688
+
689
+ See: `docs/edison.md`.
690
+
691
+ ---
692
+
693
+ ## Troubleshooting (high-signal fixes)
694
+
695
+ ### “No machine” / auth required
696
+
697
+ Check auth:
698
+
699
+ ```bash
700
+ happys stack auth <stack> status
701
+ ```
702
+
703
+ Login (interactive):
704
+
705
+ ```bash
706
+ happys stack auth <stack> login
707
+ ```
708
+
709
+ Non-interactive repair (copy credentials + seed accounts from `main`):
710
+
711
+ ```bash
712
+ happys stack auth <stack> copy-from <seed>
713
+ ```
714
+
715
+ Notes:
716
+
717
+ - `<seed>` should be the stack you use as your auth seed (recommended: `dev-auth`).
718
+ - Creating/logging into the seed stack is a **developer-only** setup step; agents should only consume it.
719
+
720
+ ### Port collisions / foreign component paths / weird stack dirs
721
+
722
+ Run the audit fixer:
723
+
724
+ ```bash
725
+ happys stack audit --fix-workspace --fix-paths --fix-ports
726
+ ```
727
+
728
+ ### Stack is unhealthy / can’t reach server
729
+
730
+ ```bash
731
+ happys stack doctor <stack>
732
+ ```
733
+