@happier-dev/stack 0.1.0-preview.5.1

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 (439) hide show
  1. package/README.md +501 -0
  2. package/bin/hstack.mjs +348 -0
  3. package/docs/codex-mcp-resume.md +129 -0
  4. package/docs/edison.md +74 -0
  5. package/docs/forking-and-branding.md +189 -0
  6. package/docs/happy-development.md +22 -0
  7. package/docs/isolated-linux-vm.md +243 -0
  8. package/docs/menubar.md +244 -0
  9. package/docs/mobile-ios.md +322 -0
  10. package/docs/monorepo-migration.md +20 -0
  11. package/docs/paths-and-env.md +154 -0
  12. package/docs/remote-access.md +43 -0
  13. package/docs/server-flavors.md +147 -0
  14. package/docs/stacks.md +330 -0
  15. package/docs/tauri.md +60 -0
  16. package/docs/worktrees-and-forks.md +133 -0
  17. package/extras/swiftbar/auth-login.sh +29 -0
  18. package/extras/swiftbar/git-cache-refresh.sh +122 -0
  19. package/extras/swiftbar/hstack-term.sh +133 -0
  20. package/extras/swiftbar/hstack.5s.sh +296 -0
  21. package/extras/swiftbar/hstack.sh +35 -0
  22. package/extras/swiftbar/icons/happy-green.png +0 -0
  23. package/extras/swiftbar/icons/happy-orange.png +0 -0
  24. package/extras/swiftbar/icons/happy-red.png +0 -0
  25. package/extras/swiftbar/icons/logo-white.png +0 -0
  26. package/extras/swiftbar/install.sh +265 -0
  27. package/extras/swiftbar/lib/git.sh +629 -0
  28. package/extras/swiftbar/lib/icons.sh +92 -0
  29. package/extras/swiftbar/lib/render.sh +999 -0
  30. package/extras/swiftbar/lib/system.sh +244 -0
  31. package/extras/swiftbar/lib/utils.sh +717 -0
  32. package/extras/swiftbar/set-interval.sh +65 -0
  33. package/extras/swiftbar/set-server-flavor.sh +61 -0
  34. package/extras/swiftbar/wt-pr.sh +140 -0
  35. package/node_modules/@happier-dev/cli-common/README.md +6 -0
  36. package/node_modules/@happier-dev/cli-common/dist/index.d.ts +4 -0
  37. package/node_modules/@happier-dev/cli-common/dist/index.d.ts.map +1 -0
  38. package/node_modules/@happier-dev/cli-common/dist/index.js +4 -0
  39. package/node_modules/@happier-dev/cli-common/dist/index.js.map +1 -0
  40. package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts +18 -0
  41. package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts.map +1 -0
  42. package/node_modules/@happier-dev/cli-common/dist/links/index.js +25 -0
  43. package/node_modules/@happier-dev/cli-common/dist/links/index.js.map +1 -0
  44. package/node_modules/@happier-dev/cli-common/dist/links.d.ts +2 -0
  45. package/node_modules/@happier-dev/cli-common/dist/links.d.ts.map +1 -0
  46. package/node_modules/@happier-dev/cli-common/dist/links.js +2 -0
  47. package/node_modules/@happier-dev/cli-common/dist/links.js.map +1 -0
  48. package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts +67 -0
  49. package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts.map +1 -0
  50. package/node_modules/@happier-dev/cli-common/dist/update/index.js +259 -0
  51. package/node_modules/@happier-dev/cli-common/dist/update/index.js.map +1 -0
  52. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts +17 -0
  53. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts.map +1 -0
  54. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js +80 -0
  55. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js.map +1 -0
  56. package/node_modules/@happier-dev/cli-common/package.json +26 -0
  57. package/package.json +77 -0
  58. package/scripts/auth.mjs +1829 -0
  59. package/scripts/auth_copy_from_pglite_lock_in_use.integration.test.mjs +90 -0
  60. package/scripts/auth_copy_from_runCapture.integration.test.mjs +447 -0
  61. package/scripts/auth_help_cmd.test.mjs +28 -0
  62. package/scripts/auth_login_flow_in_tty.test.mjs +100 -0
  63. package/scripts/auth_login_force_default.test.mjs +66 -0
  64. package/scripts/auth_login_guided_server_no_expo.test.mjs +126 -0
  65. package/scripts/auth_login_method_override.test.mjs +67 -0
  66. package/scripts/auth_login_print_includes_configure_links.test.mjs +99 -0
  67. package/scripts/auth_status_server_validation.integration.test.mjs +140 -0
  68. package/scripts/build.mjs +266 -0
  69. package/scripts/bundleWorkspaceDeps.mjs +38 -0
  70. package/scripts/bundleWorkspaceDeps.test.mjs +77 -0
  71. package/scripts/ci.mjs +135 -0
  72. package/scripts/ci.test.mjs +50 -0
  73. package/scripts/cli-link.mjs +57 -0
  74. package/scripts/completion.mjs +395 -0
  75. package/scripts/contrib.mjs +333 -0
  76. package/scripts/daemon.mjs +1160 -0
  77. package/scripts/daemon.status_scope.test.mjs +51 -0
  78. package/scripts/daemon_cmd.mjs +26 -0
  79. package/scripts/daemon_dist_guard.test.mjs +171 -0
  80. package/scripts/daemon_invalid_auth_reseed_stack_name.integration.test.mjs +608 -0
  81. package/scripts/daemon_server_scoped_state.test.mjs +49 -0
  82. package/scripts/daemon_start_verification.integration.test.mjs +296 -0
  83. package/scripts/dev.mjs +545 -0
  84. package/scripts/doctor.mjs +340 -0
  85. package/scripts/doctor_cmd.test.mjs +22 -0
  86. package/scripts/doctor_ui_index_missing.test.mjs +37 -0
  87. package/scripts/eas.mjs +367 -0
  88. package/scripts/eas_platform_parsing.test.mjs +63 -0
  89. package/scripts/edison.mjs +1848 -0
  90. package/scripts/env.mjs +149 -0
  91. package/scripts/env_cmd.test.mjs +118 -0
  92. package/scripts/exit_cleanup_kills_detached_children_on_crash.integration.test.mjs +80 -0
  93. package/scripts/happier.mjs +82 -0
  94. package/scripts/import.mjs +1327 -0
  95. package/scripts/init.mjs +464 -0
  96. package/scripts/install.mjs +550 -0
  97. package/scripts/lint.mjs +177 -0
  98. package/scripts/menubar.mjs +202 -0
  99. package/scripts/migrate.mjs +318 -0
  100. package/scripts/mobile.mjs +353 -0
  101. package/scripts/mobile_dev_client.mjs +87 -0
  102. package/scripts/monorepo.mjs +2234 -0
  103. package/scripts/monorepo_port.apply.integration.test.mjs +680 -0
  104. package/scripts/monorepo_port.conflicts.integration.test.mjs +454 -0
  105. package/scripts/monorepo_port.validation.integration.test.mjs +486 -0
  106. package/scripts/orchestrated_stack_auth_flow.test.mjs +134 -0
  107. package/scripts/orchestrated_stack_auth_flow_resolve_port.test.mjs +98 -0
  108. package/scripts/orchestrated_stack_auth_flow_webapp_url.test.mjs +119 -0
  109. package/scripts/pack.mjs +257 -0
  110. package/scripts/pack.test.mjs +68 -0
  111. package/scripts/pglite_lock.integration.test.mjs +152 -0
  112. package/scripts/provision/linux-ubuntu-e2e.sh +132 -0
  113. package/scripts/provision/linux-ubuntu-review-pr.sh +66 -0
  114. package/scripts/provision/macos-lima-happy-vm.sh +192 -0
  115. package/scripts/provision/macos-lima-hstack-e2e.sh +100 -0
  116. package/scripts/release.mjs +53 -0
  117. package/scripts/release_binary_smoke.integration.test.mjs +159 -0
  118. package/scripts/review.mjs +1752 -0
  119. package/scripts/review_pr.mjs +435 -0
  120. package/scripts/run.mjs +561 -0
  121. package/scripts/run_script_with_stack_env.restart_port_reuse.test.mjs +30 -0
  122. package/scripts/self.mjs +465 -0
  123. package/scripts/self_host.mjs +9 -0
  124. package/scripts/self_host_binary_smoke.integration.test.mjs +94 -0
  125. package/scripts/self_host_runtime.mjs +883 -0
  126. package/scripts/self_host_runtime.test.mjs +82 -0
  127. package/scripts/self_host_systemd.real.integration.test.mjs +367 -0
  128. package/scripts/server_flavor.mjs +148 -0
  129. package/scripts/service.mjs +868 -0
  130. package/scripts/service_mode_help.test.mjs +27 -0
  131. package/scripts/setup.mjs +1324 -0
  132. package/scripts/setup_non_interactive_flag.test.mjs +60 -0
  133. package/scripts/setup_pr.mjs +605 -0
  134. package/scripts/setup_pr_orchestrated_auth_flow_util_import.test.mjs +117 -0
  135. package/scripts/stack/command_arguments.mjs +91 -0
  136. package/scripts/stack/copy_auth_from_stack.mjs +111 -0
  137. package/scripts/stack/delegated_script_commands.mjs +92 -0
  138. package/scripts/stack/help_text.mjs +110 -0
  139. package/scripts/stack/port_reservation.mjs +74 -0
  140. package/scripts/stack/repo_checkout_resolution.mjs +31 -0
  141. package/scripts/stack/run_script_with_stack_env.mjs +634 -0
  142. package/scripts/stack/stack_daemon_command.mjs +219 -0
  143. package/scripts/stack/stack_delegated_help.mjs +81 -0
  144. package/scripts/stack/stack_environment.mjs +151 -0
  145. package/scripts/stack/stack_environment.sanitization.test.mjs +75 -0
  146. package/scripts/stack/stack_happier_passthrough_command.mjs +63 -0
  147. package/scripts/stack/stack_info_snapshot.mjs +167 -0
  148. package/scripts/stack/stack_mobile_install_command.mjs +61 -0
  149. package/scripts/stack/stack_resume_command.mjs +76 -0
  150. package/scripts/stack/stack_stop_command.mjs +34 -0
  151. package/scripts/stack/stack_workspace_command.mjs +83 -0
  152. package/scripts/stack/transient_repo_overrides.mjs +29 -0
  153. package/scripts/stack.mjs +2388 -0
  154. package/scripts/stack_archive_cmd.integration.test.mjs +31 -0
  155. package/scripts/stack_audit_fix_light_env.test.mjs +129 -0
  156. package/scripts/stack_background_pinned_stack_json.test.mjs +81 -0
  157. package/scripts/stack_copy_auth_server_scoped.test.mjs +243 -0
  158. package/scripts/stack_daemon_cmd.integration.test.mjs +484 -0
  159. package/scripts/stack_eas_help.test.mjs +72 -0
  160. package/scripts/stack_editor_workspace_monorepo_root.test.mjs +102 -0
  161. package/scripts/stack_env_cmd.test.mjs +107 -0
  162. package/scripts/stack_guided_login_bundle_error_parse.test.mjs +20 -0
  163. package/scripts/stack_guided_login_inner_invocation.test.mjs +46 -0
  164. package/scripts/stack_happy_cmd.integration.test.mjs +263 -0
  165. package/scripts/stack_info_snapshot_running_status.test.mjs +186 -0
  166. package/scripts/stack_interactive_monorepo_group.test.mjs +128 -0
  167. package/scripts/stack_monorepo_defaults.test.mjs +31 -0
  168. package/scripts/stack_monorepo_repo_dev_token.test.mjs +32 -0
  169. package/scripts/stack_monorepo_server_light_from_happy_spec.test.mjs +37 -0
  170. package/scripts/stack_new_name_normalize_cmd.test.mjs +38 -0
  171. package/scripts/stack_pr_name_normalize_cmd.test.mjs +84 -0
  172. package/scripts/stack_resume_cmd.integration.test.mjs +134 -0
  173. package/scripts/stack_server_flavors_defaults.test.mjs +64 -0
  174. package/scripts/stack_shorthand_cmd.integration.test.mjs +74 -0
  175. package/scripts/stack_stop_sweeps_legacy_infra_without_kind.integration.test.mjs +44 -0
  176. package/scripts/stack_stop_sweeps_when_runtime_missing.integration.test.mjs +42 -0
  177. package/scripts/stack_stop_sweeps_when_runtime_stale.integration.test.mjs +50 -0
  178. package/scripts/stack_wt_list.test.mjs +117 -0
  179. package/scripts/start_ui_required_default.test.mjs +63 -0
  180. package/scripts/stop.mjs +190 -0
  181. package/scripts/stopStackWithEnv_no_autosweep_when_runtime_missing.integration.test.mjs +95 -0
  182. package/scripts/swiftbar_git_monorepo_cmd.test.mjs +75 -0
  183. package/scripts/swiftbar_render_monorepo_wt_actions.integration.test.mjs +116 -0
  184. package/scripts/swiftbar_utils_cmd.test.mjs +92 -0
  185. package/scripts/swiftbar_wt_pr_backcompat.test.mjs +162 -0
  186. package/scripts/systemd_unit_info.test.mjs +24 -0
  187. package/scripts/tailscale.mjs +490 -0
  188. package/scripts/test_ci.mjs +36 -0
  189. package/scripts/test_cmd.mjs +274 -0
  190. package/scripts/test_cmd.test.mjs +133 -0
  191. package/scripts/test_integration.mjs +33 -0
  192. package/scripts/testkit/auth_testkit.mjs +121 -0
  193. package/scripts/testkit/doctor_testkit.mjs +68 -0
  194. package/scripts/testkit/monorepo_port_testkit.mjs +157 -0
  195. package/scripts/testkit/stack_archive_command_testkit.mjs +55 -0
  196. package/scripts/testkit/stack_new_monorepo_testkit.mjs +83 -0
  197. package/scripts/testkit/stack_script_command_testkit.mjs +27 -0
  198. package/scripts/testkit/stack_stop_sweeps_testkit.mjs +172 -0
  199. package/scripts/testkit/worktrees_monorepo_testkit.mjs +53 -0
  200. package/scripts/tools.mjs +70 -0
  201. package/scripts/tui.mjs +914 -0
  202. package/scripts/tui_stopStackForTuiExit_no_autosweep.integration.test.mjs +95 -0
  203. package/scripts/typecheck.mjs +178 -0
  204. package/scripts/ui_gateway.mjs +247 -0
  205. package/scripts/uninstall.mjs +179 -0
  206. package/scripts/utils/auth/credentials_paths.mjs +181 -0
  207. package/scripts/utils/auth/credentials_paths.test.mjs +187 -0
  208. package/scripts/utils/auth/daemon_gate.mjs +66 -0
  209. package/scripts/utils/auth/daemon_gate.test.mjs +116 -0
  210. package/scripts/utils/auth/decode_jwt_payload_unsafe.mjs +16 -0
  211. package/scripts/utils/auth/dev_key.mjs +163 -0
  212. package/scripts/utils/auth/files.mjs +56 -0
  213. package/scripts/utils/auth/guided_pr_auth.mjs +86 -0
  214. package/scripts/utils/auth/guided_stack_web_login.mjs +56 -0
  215. package/scripts/utils/auth/handy_master_secret.mjs +42 -0
  216. package/scripts/utils/auth/interactive_stack_auth.mjs +70 -0
  217. package/scripts/utils/auth/login_ux.mjs +105 -0
  218. package/scripts/utils/auth/orchestrated_stack_auth_flow.mjs +291 -0
  219. package/scripts/utils/auth/sources.mjs +28 -0
  220. package/scripts/utils/auth/stable_scope_id.mjs +91 -0
  221. package/scripts/utils/auth/stable_scope_id.test.mjs +51 -0
  222. package/scripts/utils/auth/stack_guided_login.mjs +438 -0
  223. package/scripts/utils/cli/arg_values.mjs +23 -0
  224. package/scripts/utils/cli/arg_values.test.mjs +43 -0
  225. package/scripts/utils/cli/args.mjs +17 -0
  226. package/scripts/utils/cli/cli.mjs +24 -0
  227. package/scripts/utils/cli/cli_registry.mjs +440 -0
  228. package/scripts/utils/cli/cwd_scope.mjs +158 -0
  229. package/scripts/utils/cli/cwd_scope.test.mjs +154 -0
  230. package/scripts/utils/cli/flags.mjs +17 -0
  231. package/scripts/utils/cli/log_forwarder.mjs +157 -0
  232. package/scripts/utils/cli/normalize.mjs +16 -0
  233. package/scripts/utils/cli/prereqs.mjs +103 -0
  234. package/scripts/utils/cli/prereqs.test.mjs +33 -0
  235. package/scripts/utils/cli/progress.mjs +141 -0
  236. package/scripts/utils/cli/smoke_help.mjs +44 -0
  237. package/scripts/utils/cli/verbosity.mjs +11 -0
  238. package/scripts/utils/cli/wizard.mjs +139 -0
  239. package/scripts/utils/cli/wizard_promptSelect.test.mjs +44 -0
  240. package/scripts/utils/cli/wizard_prompt_worktree_source_lazy.test.mjs +132 -0
  241. package/scripts/utils/cli/wizard_worktree_slug.test.mjs +33 -0
  242. package/scripts/utils/crypto/tokens.mjs +14 -0
  243. package/scripts/utils/dev/daemon.mjs +232 -0
  244. package/scripts/utils/dev/daemon_watch_resilience.test.mjs +224 -0
  245. package/scripts/utils/dev/expo_dev.buildEnv.test.mjs +35 -0
  246. package/scripts/utils/dev/expo_dev.mjs +478 -0
  247. package/scripts/utils/dev/expo_dev.test.mjs +89 -0
  248. package/scripts/utils/dev/expo_dev_restart_port_reservation.test.mjs +120 -0
  249. package/scripts/utils/dev/expo_dev_verbose_logs.test.mjs +60 -0
  250. package/scripts/utils/dev/server.mjs +180 -0
  251. package/scripts/utils/dev_auth_key.mjs +7 -0
  252. package/scripts/utils/edison/git_roots.mjs +30 -0
  253. package/scripts/utils/edison/git_roots.test.mjs +49 -0
  254. package/scripts/utils/env/config.mjs +52 -0
  255. package/scripts/utils/env/dotenv.mjs +32 -0
  256. package/scripts/utils/env/dotenv.test.mjs +32 -0
  257. package/scripts/utils/env/env.mjs +130 -0
  258. package/scripts/utils/env/env_file.mjs +98 -0
  259. package/scripts/utils/env/env_file.test.mjs +49 -0
  260. package/scripts/utils/env/env_local.mjs +25 -0
  261. package/scripts/utils/env/load_env_file.mjs +34 -0
  262. package/scripts/utils/env/read.mjs +30 -0
  263. package/scripts/utils/env/sandbox.mjs +13 -0
  264. package/scripts/utils/env/scrub_env.mjs +69 -0
  265. package/scripts/utils/env/scrub_env.test.mjs +102 -0
  266. package/scripts/utils/env/values.mjs +13 -0
  267. package/scripts/utils/expo/command.mjs +65 -0
  268. package/scripts/utils/expo/expo.mjs +139 -0
  269. package/scripts/utils/expo/expo_state_running.test.mjs +48 -0
  270. package/scripts/utils/expo/metro_ports.mjs +101 -0
  271. package/scripts/utils/expo/metro_ports.test.mjs +35 -0
  272. package/scripts/utils/fs/atomic_dir_swap.mjs +55 -0
  273. package/scripts/utils/fs/atomic_dir_swap.test.mjs +54 -0
  274. package/scripts/utils/fs/file_has_content.mjs +10 -0
  275. package/scripts/utils/fs/fs.mjs +11 -0
  276. package/scripts/utils/fs/json.mjs +25 -0
  277. package/scripts/utils/fs/ops.mjs +29 -0
  278. package/scripts/utils/fs/package_json.mjs +8 -0
  279. package/scripts/utils/fs/tail.mjs +12 -0
  280. package/scripts/utils/git/dev_checkout.mjs +127 -0
  281. package/scripts/utils/git/dev_checkout.test.mjs +115 -0
  282. package/scripts/utils/git/git.mjs +67 -0
  283. package/scripts/utils/git/parse_name_status_z.mjs +21 -0
  284. package/scripts/utils/git/refs.mjs +26 -0
  285. package/scripts/utils/git/worktrees.mjs +323 -0
  286. package/scripts/utils/git/worktrees_monorepo.test.mjs +60 -0
  287. package/scripts/utils/git/worktrees_pathstyle.test.mjs +53 -0
  288. package/scripts/utils/llm/assist.mjs +260 -0
  289. package/scripts/utils/llm/codex_exec.mjs +61 -0
  290. package/scripts/utils/llm/codex_exec.test.mjs +46 -0
  291. package/scripts/utils/llm/hstack_runner.mjs +59 -0
  292. package/scripts/utils/llm/tools.mjs +56 -0
  293. package/scripts/utils/llm/tools.test.mjs +67 -0
  294. package/scripts/utils/menubar/swiftbar.mjs +121 -0
  295. package/scripts/utils/menubar/swiftbar.test.mjs +85 -0
  296. package/scripts/utils/mobile/config.mjs +35 -0
  297. package/scripts/utils/mobile/dev_client_links.mjs +59 -0
  298. package/scripts/utils/mobile/identifiers.mjs +46 -0
  299. package/scripts/utils/mobile/identifiers.test.mjs +41 -0
  300. package/scripts/utils/mobile/ios_xcodeproj_patch.mjs +128 -0
  301. package/scripts/utils/mobile/ios_xcodeproj_patch.test.mjs +131 -0
  302. package/scripts/utils/net/bind_mode.mjs +39 -0
  303. package/scripts/utils/net/dns.mjs +10 -0
  304. package/scripts/utils/net/lan_ip.mjs +24 -0
  305. package/scripts/utils/net/ports.mjs +110 -0
  306. package/scripts/utils/net/tcp_forward.mjs +162 -0
  307. package/scripts/utils/net/url.mjs +30 -0
  308. package/scripts/utils/net/url.test.mjs +29 -0
  309. package/scripts/utils/paths/canonical_home.mjs +15 -0
  310. package/scripts/utils/paths/canonical_home.test.mjs +28 -0
  311. package/scripts/utils/paths/localhost_host.mjs +112 -0
  312. package/scripts/utils/paths/localhost_host.test.mjs +58 -0
  313. package/scripts/utils/paths/paths.mjs +302 -0
  314. package/scripts/utils/paths/paths_env_win32.test.mjs +36 -0
  315. package/scripts/utils/paths/paths_monorepo.test.mjs +58 -0
  316. package/scripts/utils/paths/paths_server_flavors.test.mjs +50 -0
  317. package/scripts/utils/paths/runtime.mjs +41 -0
  318. package/scripts/utils/pglite_lock.mjs +107 -0
  319. package/scripts/utils/proc/commands.mjs +33 -0
  320. package/scripts/utils/proc/exit_cleanup.mjs +57 -0
  321. package/scripts/utils/proc/happy_monorepo_deps.mjs +37 -0
  322. package/scripts/utils/proc/happy_monorepo_deps.test.mjs +89 -0
  323. package/scripts/utils/proc/ownership.mjs +217 -0
  324. package/scripts/utils/proc/ownership_killProcessGroupOwnedByStack.test.mjs +216 -0
  325. package/scripts/utils/proc/ownership_listPidsWithEnvNeedles.test.mjs +88 -0
  326. package/scripts/utils/proc/package_scripts.mjs +38 -0
  327. package/scripts/utils/proc/package_scripts.test.mjs +58 -0
  328. package/scripts/utils/proc/parallel.mjs +25 -0
  329. package/scripts/utils/proc/pids.mjs +11 -0
  330. package/scripts/utils/proc/pm.mjs +478 -0
  331. package/scripts/utils/proc/pm_spawn.integration.test.mjs +131 -0
  332. package/scripts/utils/proc/pm_stack_cache_env.test.mjs +313 -0
  333. package/scripts/utils/proc/proc.mjs +331 -0
  334. package/scripts/utils/proc/proc.test.mjs +85 -0
  335. package/scripts/utils/proc/terminate.mjs +69 -0
  336. package/scripts/utils/proc/terminate.test.mjs +54 -0
  337. package/scripts/utils/proc/watch.mjs +63 -0
  338. package/scripts/utils/review/augment_runner_integration.test.mjs +105 -0
  339. package/scripts/utils/review/base_ref.mjs +82 -0
  340. package/scripts/utils/review/base_ref.test.mjs +89 -0
  341. package/scripts/utils/review/chunks.mjs +55 -0
  342. package/scripts/utils/review/chunks.test.mjs +107 -0
  343. package/scripts/utils/review/detached_worktree.mjs +61 -0
  344. package/scripts/utils/review/detached_worktree.test.mjs +61 -0
  345. package/scripts/utils/review/findings.mjs +278 -0
  346. package/scripts/utils/review/findings.test.mjs +203 -0
  347. package/scripts/utils/review/head_slice.mjs +132 -0
  348. package/scripts/utils/review/head_slice.test.mjs +117 -0
  349. package/scripts/utils/review/instructions/deep.md +20 -0
  350. package/scripts/utils/review/prompts.mjs +279 -0
  351. package/scripts/utils/review/prompts.test.mjs +77 -0
  352. package/scripts/utils/review/run_reviewers_safe.mjs +12 -0
  353. package/scripts/utils/review/run_reviewers_safe.test.mjs +45 -0
  354. package/scripts/utils/review/runners/augment.mjs +91 -0
  355. package/scripts/utils/review/runners/augment.test.mjs +64 -0
  356. package/scripts/utils/review/runners/claude.mjs +92 -0
  357. package/scripts/utils/review/runners/claude.test.mjs +47 -0
  358. package/scripts/utils/review/runners/coderabbit.mjs +105 -0
  359. package/scripts/utils/review/runners/coderabbit.test.mjs +32 -0
  360. package/scripts/utils/review/runners/codex.mjs +129 -0
  361. package/scripts/utils/review/runners/codex.test.mjs +115 -0
  362. package/scripts/utils/review/slice_mode.mjs +20 -0
  363. package/scripts/utils/review/slice_mode.test.mjs +69 -0
  364. package/scripts/utils/review/sliced_runner.mjs +39 -0
  365. package/scripts/utils/review/sliced_runner.test.mjs +57 -0
  366. package/scripts/utils/review/slices.mjs +140 -0
  367. package/scripts/utils/review/slices.test.mjs +41 -0
  368. package/scripts/utils/review/targets.mjs +23 -0
  369. package/scripts/utils/review/targets.test.mjs +31 -0
  370. package/scripts/utils/review/tool_home_seed.mjs +106 -0
  371. package/scripts/utils/review/tool_home_seed.test.mjs +124 -0
  372. package/scripts/utils/review/uncommitted_ops.mjs +77 -0
  373. package/scripts/utils/review/uncommitted_ops.test.mjs +117 -0
  374. package/scripts/utils/sandbox/review_pr_sandbox.mjs +105 -0
  375. package/scripts/utils/server/apply_server_light_env_defaults.mjs +14 -0
  376. package/scripts/utils/server/flavor_scripts.mjs +138 -0
  377. package/scripts/utils/server/flavor_scripts.test.mjs +115 -0
  378. package/scripts/utils/server/infra/happy_server_infra.mjs +444 -0
  379. package/scripts/utils/server/mobile_api_url.mjs +60 -0
  380. package/scripts/utils/server/mobile_api_url.test.mjs +58 -0
  381. package/scripts/utils/server/port.mjs +55 -0
  382. package/scripts/utils/server/prisma_import.mjs +36 -0
  383. package/scripts/utils/server/prisma_import.test.mjs +78 -0
  384. package/scripts/utils/server/server.mjs +109 -0
  385. package/scripts/utils/server/ui_build_check.mjs +37 -0
  386. package/scripts/utils/server/ui_build_check.test.mjs +70 -0
  387. package/scripts/utils/server/ui_env.mjs +13 -0
  388. package/scripts/utils/server/ui_env.test.mjs +57 -0
  389. package/scripts/utils/server/urls.mjs +100 -0
  390. package/scripts/utils/server/validate.mjs +60 -0
  391. package/scripts/utils/server/validate.test.mjs +76 -0
  392. package/scripts/utils/service/autostart_darwin.mjs +198 -0
  393. package/scripts/utils/service/autostart_darwin.test.mjs +49 -0
  394. package/scripts/utils/service/autostart_darwin_keepalive.test.mjs +19 -0
  395. package/scripts/utils/stack/cli_identities.mjs +29 -0
  396. package/scripts/utils/stack/context.mjs +19 -0
  397. package/scripts/utils/stack/dirs.mjs +26 -0
  398. package/scripts/utils/stack/editor_workspace.mjs +126 -0
  399. package/scripts/utils/stack/interactive_stack_config.mjs +266 -0
  400. package/scripts/utils/stack/interactive_stack_config.port_validation.test.mjs +93 -0
  401. package/scripts/utils/stack/interactive_stack_config.remote_validation.test.mjs +122 -0
  402. package/scripts/utils/stack/interactive_stack_config.stack_name_validation.test.mjs +76 -0
  403. package/scripts/utils/stack/interactive_stack_config_testkit.mjs +18 -0
  404. package/scripts/utils/stack/names.mjs +27 -0
  405. package/scripts/utils/stack/names.test.mjs +26 -0
  406. package/scripts/utils/stack/pr_stack_name.mjs +16 -0
  407. package/scripts/utils/stack/runtime_state.mjs +88 -0
  408. package/scripts/utils/stack/stacks.mjs +40 -0
  409. package/scripts/utils/stack/startup.mjs +370 -0
  410. package/scripts/utils/stack/startup_server_light_dirs.test.mjs +119 -0
  411. package/scripts/utils/stack/startup_server_light_generate.test.mjs +20 -0
  412. package/scripts/utils/stack/startup_server_light_legacy.test.mjs +79 -0
  413. package/scripts/utils/stack/startup_server_light_testkit.mjs +106 -0
  414. package/scripts/utils/stack/stop.mjs +284 -0
  415. package/scripts/utils/stack_context.mjs +1 -0
  416. package/scripts/utils/stack_runtime_state.mjs +1 -0
  417. package/scripts/utils/stacks.mjs +1 -0
  418. package/scripts/utils/tailscale/ip.mjs +116 -0
  419. package/scripts/utils/tauri/stack_overrides.mjs +22 -0
  420. package/scripts/utils/test/collect_test_files.mjs +29 -0
  421. package/scripts/utils/time/get_today_ymd.mjs +7 -0
  422. package/scripts/utils/tui/cleanup.mjs +38 -0
  423. package/scripts/utils/ui/ansi.mjs +47 -0
  424. package/scripts/utils/ui/browser.mjs +31 -0
  425. package/scripts/utils/ui/browser.test.mjs +56 -0
  426. package/scripts/utils/ui/clipboard.mjs +38 -0
  427. package/scripts/utils/ui/layout.mjs +44 -0
  428. package/scripts/utils/ui/qr.mjs +17 -0
  429. package/scripts/utils/ui/terminal_launcher.mjs +129 -0
  430. package/scripts/utils/ui/text.mjs +16 -0
  431. package/scripts/utils/update/auto_update_notice.mjs +93 -0
  432. package/scripts/utils/validate.mjs +5 -0
  433. package/scripts/where.mjs +138 -0
  434. package/scripts/worktrees.mjs +2174 -0
  435. package/scripts/worktrees_archive_cmd.integration.test.mjs +228 -0
  436. package/scripts/worktrees_cursor_monorepo_root.test.mjs +23 -0
  437. package/scripts/worktrees_list_specs_no_recurse.test.mjs +32 -0
  438. package/scripts/worktrees_monorepo_testkit.test.mjs +29 -0
  439. package/scripts/worktrees_monorepo_use_group.test.mjs +41 -0
@@ -0,0 +1,189 @@
1
+ ## Forking + branding while staying upstream-compatible
2
+
3
+ This doc describes a **recommended hstack workflow** for maintaining:
4
+
5
+ - an **upstream-compatible** branch/worktree (no branding changes; safe to upstream later)
6
+ - a **branded fork** branch/worktree (custom app name/bundle id/icons/Firebase/EAS, etc)
7
+
8
+ The goal is to keep day-to-day development clean and to make syncing changes reliable.
9
+
10
+ ---
11
+
12
+ ## Core idea
13
+
14
+ - **Do product/feature work on an upstream-compatible branch** (example: `happier-dev/dev`).
15
+ - **Keep branding + fork-only config on a separate branch** (example: `happier-dev/happier`).
16
+ - Periodically **merge** upstream-compatible changes into the branded fork branch.
17
+
18
+ The branded branch should ideally contain only:
19
+
20
+ - assets (icons/splash/logos)
21
+ - configuration files that are *unavoidably different* (Firebase, EAS linkage)
22
+ - optional small “glue” needed to make config configurable via environment variables
23
+
24
+ Everything else should stay identical to the upstream-compatible branch so merges stay low-conflict.
25
+
26
+ ---
27
+
28
+ ## Golden rules (hstack)
29
+
30
+ - **Do not develop in the stable checkout** (typically `<workspace>/main`). Use `<workspace>/dev` or worktrees under `<workspace>/{pr,local,tmp}/...`.
31
+ - **Use `hstack` entrypoints** (not raw `yarn`, `expo`, etc) when you’re running stack/dev/build/test commands.
32
+ - **Do not commit generated native directories** for Expo apps:
33
+ - `apps/ui/ios/`
34
+ - `apps/ui/android/`
35
+ These are generated by `expo prebuild` and should be treated as build artifacts.
36
+
37
+ ---
38
+
39
+ ## Recommended branch/worktree layout
40
+
41
+ Example (Happier monorepo):
42
+
43
+ - Upstream-compatible dev checkout:
44
+ - `<workspace>/dev`
45
+ - Branch: `dev`
46
+ - Branded fork worktree (example):
47
+ - `<workspace>/local/<owner>/happier`
48
+ - Branch: `feature/happier-branding` (or similar)
49
+
50
+ Pin your branded stack to the branded worktree (recommended):
51
+
52
+ ```bash
53
+ hstack stack wt happier -- use local/happier
54
+ ```
55
+
56
+ Keep your stable/main stack on defaults, and use `happier` (or another stack) for branded testing/building.
57
+
58
+ ---
59
+
60
+ ## How to keep merges low-conflict
61
+
62
+ ### Keep fork-only changes “small and isolated”
63
+
64
+ Prefer fork-only changes to live in these buckets:
65
+
66
+ - **Brand assets**:
67
+ - `apps/ui/sources/assets/images/*` (icon/splash/logo/favicon, etc)
68
+ - **Fork-only identity/config** (when not configurable via env):
69
+ - Firebase files (`google-services.json`, `GoogleService-Info.plist`)
70
+ - EAS project linkage (projectId/updates URL/channel)
71
+
72
+ Avoid sprinkling branding changes throughout core logic; it increases conflict surface area.
73
+
74
+ ### Prefer configuration via environment variables
75
+
76
+ When possible, drive identity via environment variables so the upstream-compatible branch keeps upstream defaults.
77
+
78
+ For Expo identity, a common pattern is:
79
+
80
+ - Keep defaults in `app.config.js`
81
+ - Allow overrides via generic Expo-style vars (examples):
82
+ - `EXPO_APP_NAME`
83
+ - `EXPO_APP_BUNDLE_ID`
84
+ - `EXPO_APP_SCHEME`
85
+ - `EXPO_APP_SLUG`
86
+ - `EXPO_APP_OWNER`
87
+ - `EXPO_EAS_PROJECT_ID`
88
+ - `EXPO_UPDATES_URL`
89
+ - `EXPO_UPDATES_CHANNEL`
90
+ - `EXPO_ANDROID_GOOGLE_SERVICES_FILE`
91
+ - `EXPO_IOS_GOOGLE_SERVICES_FILE`
92
+
93
+ Then set those **per stack** (in the stack env file) so the behavior is isolated to your branded stack.
94
+
95
+ ---
96
+
97
+ ## Day-to-day workflow
98
+
99
+ ### 1) Do feature work on the upstream-compatible branch
100
+
101
+ Work in:
102
+
103
+ - `<workspace>/dev`
104
+
105
+ Keep it upstream-friendly:
106
+
107
+ - no branding changes
108
+ - no fork-only credentials/config
109
+
110
+ ### 2) Periodically sync branded fork branch with upstream-compatible branch
111
+
112
+ In the branded worktree:
113
+
114
+ ```bash
115
+ hstack wt git happier-dev/happier -- merge happier-dev/dev
116
+ ```
117
+
118
+ Resolve conflicts (if any), then continue.
119
+
120
+ ### When merges conflict
121
+
122
+ Conflicts usually mean a file is changing in both branches.
123
+
124
+ Best practice:
125
+
126
+ - **Move shared “configurability logic” into `dev`**, so it only has to merge one way.
127
+ - Keep branded values/assets in `happier`.
128
+
129
+ If a file must remain fork-only and conflicts often, consider:
130
+
131
+ - extracting brand-specific settings into separate files referenced by env, or
132
+ - cherry-picking specific commits from `dev` instead of merging (for a short period), then returning to merges.
133
+
134
+ ---
135
+
136
+ ## Mobile + EAS specifics
137
+
138
+ ### Prebuild is local-only; don’t commit the generated dirs
139
+
140
+ Local:
141
+
142
+ ```bash
143
+ hstack stack mobile happier --prebuild --platform=ios --clean --no-metro
144
+ ```
145
+
146
+ This regenerates `apps/ui/ios` and installs pods. Treat this as build output.
147
+
148
+ ### EAS builds are easiest when identity comes from env
149
+
150
+ Use the EAS wrapper (stack-scoped):
151
+
152
+ ```bash
153
+ hstack stack eas happier whoami
154
+ hstack stack eas happier build --platform ios --profile production --no-wait
155
+ ```
156
+
157
+ For cloud builds, ensure your EAS project has the correct environment variables configured on expo.dev (or in `eas.json` profile `env`).
158
+
159
+ ---
160
+
161
+ ## What should live only on the branded branch?
162
+
163
+ As a rule:
164
+
165
+ - **Yes (fork-only)**:
166
+ - icons/splashes/logos
167
+ - Firebase app configs (matching your bundle id/package)
168
+ - App Store / Play Store metadata
169
+ - any integrations that cannot reasonably be driven by env/config
170
+
171
+ - **No (should stay shared / upstream-compatible)**:
172
+ - core app logic
173
+ - shared tooling changes (anything under `apps/stack/scripts/` that improves workflows)
174
+ - general configurability hooks (e.g. “support `EXPO_*` overrides”)
175
+
176
+ ---
177
+
178
+ ## Quick checklist
179
+
180
+ - **Upstream-compatible branch (`dev`)**:
181
+ - can be upstreamed
182
+ - runs with upstream defaults
183
+ - minimal / no fork-only config
184
+
185
+ - **Branded fork branch (`happier`)**:
186
+ - pinned to its own stack
187
+ - overrides identity via env
188
+ - contains only necessary fork-only files
189
+ - periodically merges from `dev`
@@ -0,0 +1,22 @@
1
+ # Happier development (hstack)
2
+
3
+ hstack is the recommended workflow for developing **Happier** locally.
4
+
5
+ Key principles:
6
+
7
+ - Use **repo worktrees** under `<workspace>/{pr,local,tmp}/...`
8
+ - Keep `<workspace>/main` as the stable checkout (treat it as read-only)
9
+ - Use `<workspace>/dev` as the default dev checkout (created by `hstack setup --profile=dev`)
10
+ - Run feature work in isolated **stacks** (ports + dirs + env file)
11
+
12
+ Quickstart (dev profile):
13
+
14
+ ```bash
15
+ npx --yes -p @happier-dev/stack hstack setup --profile=dev
16
+ ```
17
+
18
+ Common flows:
19
+
20
+ - Worktrees: `docs/worktrees-and-forks.md`
21
+ - Stacks: `docs/stacks.md`
22
+ - Paths/env precedence: `docs/paths-and-env.md`
@@ -0,0 +1,243 @@
1
+ # Isolated Linux VM (Apple Silicon) for `review-pr`
2
+
3
+ If you want to validate `hstack review-pr` on a **fresh system** (no existing `~/.happier-stack`, no host tooling), the simplest repeatable approach on Apple Silicon is a Linux VM managed by **Lima** (it uses Apple’s Virtualization.framework).
4
+
5
+ This avoids Docker/container UX issues (browser opening, Expo networking, file watching) while still being truly “clean”.
6
+
7
+ ## Option A (recommended): Lima + Ubuntu ARM64
8
+
9
+ ### 1) Install Lima (macOS host)
10
+
11
+ ```bash
12
+ brew install lima
13
+ ```
14
+
15
+ ### 1b) Automated E2E smoke test (optional)
16
+
17
+ On your macOS host (this repo):
18
+
19
+ ```bash
20
+ ./scripts/provision/macos-lima-hstack-e2e.sh happy-e2e
21
+ ```
22
+
23
+ What it validates (best-effort):
24
+ - `hstack setup --profile=selfhost` in a fully isolated sandbox (no auth / tailscale / autostart / menubar)
25
+ - server health endpoint (`/health`)
26
+ - UI is served by server-light (`/` returns HTML)
27
+ - monorepo worktree creation (`hstack wt new ...`)
28
+
29
+ Notes:
30
+ - This runs inside the VM (Linux) and uses `npx` by default.
31
+ - You can pin the version under test: `HSTACK_VERSION=0.6.14 ./scripts/provision/macos-lima-hstack-e2e.sh happy-e2e`.
32
+ - If you’re testing a fork, you can point the runner at your fork’s raw scripts:
33
+ `HSTACK_RAW_BASE=https://raw.githubusercontent.com/<owner>/<repo>/<ref>/apps/stack ./scripts/provision/macos-lima-hstack-e2e.sh happy-e2e`.
34
+ - If you’re testing unpublished local changes, copy a packed tarball into the VM and run:
35
+ `HSTACK_TGZ=./happier-dev-stack-*.tgz /tmp/linux-ubuntu-e2e.sh`.
36
+
37
+ ### 2) Create + configure a VM (recommended script)
38
+
39
+ On your macOS host (this repo):
40
+
41
+ ```bash
42
+ ./scripts/provision/macos-lima-happy-vm.sh happy-test
43
+ ```
44
+
45
+ This creates the VM if needed and configures **localhost port forwarding** for the port ranges used by our VM defaults.
46
+ (This is important because the Expo web app uses WebCrypto and needs a secure context like `http://localhost`.)
47
+
48
+ It also sets a higher default VM memory size (to avoid Expo/Metro getting OOM-killed and exiting with `code=137`).
49
+ Override if needed:
50
+
51
+ ```bash
52
+ LIMA_MEMORY=12GiB ./scripts/provision/macos-lima-happy-vm.sh happy-test
53
+ ```
54
+
55
+ Port ranges note:
56
+ - `review-pr` runs in a **fully isolated sandbox** (separate hstack home dir), so VM defaults written to
57
+ `~/.happier-stack/env.local` inside the VM won’t be read automatically.
58
+ - Prefer passing `--vm-ports` (or explicit `--stack-port-start=...`) to `review-pr` so the sandbox uses the forwarded ranges.
59
+
60
+ ### 2b) Manual setup (if you prefer)
61
+
62
+ ```bash
63
+ limactl create --name happy-pr --tty=false template://ubuntu-24.04
64
+ limactl start happy-pr
65
+ ```
66
+
67
+ If you run `review-pr` (Expo web / Metro) inside the VM, **allocate enough memory** (recommend **8GiB+**).
68
+ Edit `~/.lima/happy-pr/lima.yaml` on the macOS host and set:
69
+
70
+ ```yaml
71
+ memory: "8GiB"
72
+ ```
73
+
74
+ ### 2c) Host access (ports + browser URLs)
75
+
76
+ When you want to open Happier/Expo URLs in your macOS browser, **use localhost port forwarding**.
77
+
78
+ Why this matters: the Expo web app uses WebCrypto (`crypto.subtle`) via `expo-crypto` for things like key derivation.
79
+ Browsers only expose WebCrypto in **secure contexts**:
80
+ - `https://...`
81
+ - `http://localhost`, `http://127.0.0.1`, and `http://*.localhost`
82
+
83
+ If you open the UI via a VM LAN IP like `http://192.168.x.y:PORT`, the browser treats it as **insecure** and you can hit errors like:
84
+ `TypeError: Cannot read properties of undefined (reading 'digest')`.
85
+
86
+ #### Configure port forwarding (recommended)
87
+
88
+ Edit the instance config on the **macOS host**:
89
+
90
+ ```bash
91
+ limactl stop happy-pr || true
92
+ open -a TextEdit ~/.lima/happy-pr/lima.yaml
93
+ ```
94
+
95
+ Add a `portForwards` section to forward the hstack VM port ranges to your host `localhost`:
96
+
97
+ ```yaml
98
+ portForwards:
99
+ # Stack/server ports (default VM range from our provision script)
100
+ - guestPortRange: [13000, 13999]
101
+ hostPortRange: [13000, 13999]
102
+
103
+ # Expo dev-server (web) ports (default VM range from our provision script)
104
+ - guestPortRange: [18000, 19099]
105
+ hostPortRange: [18000, 19099]
106
+ ```
107
+
108
+ Then restart the VM:
109
+
110
+ ```bash
111
+ limactl start happy-pr
112
+ ```
113
+
114
+ #### Optional: IP-based access (only when you need LAN)
115
+
116
+ If you explicitly need to access guest services by VM IP (e.g. for testing from another device), you can enable `vzNAT`:
117
+
118
+ ```bash
119
+ limactl stop happy-pr || true
120
+ limactl start happy-pr --network vzNAT
121
+ ```
122
+
123
+ Note: IP-based URLs (like `http://192.168...`) may break web-only crypto flows unless you use HTTPS or a browser dev override.
124
+
125
+ ### 3) Provision the VM (Node + build deps)
126
+
127
+ ```bash
128
+ limactl shell happy-pr
129
+ ```
130
+
131
+ Inside the VM:
132
+
133
+ ```bash
134
+ curl -fsSL https://raw.githubusercontent.com/happier-dev/happier/main/apps/stack/scripts/provision/linux-ubuntu-review-pr.sh -o /tmp/linux-ubuntu-review-pr.sh \
135
+ && chmod +x /tmp/linux-ubuntu-review-pr.sh \
136
+ && /tmp/linux-ubuntu-review-pr.sh
137
+ ```
138
+
139
+ ### 3b) (Optional) Run the hstack dev setup wizard
140
+
141
+ If your goal is to **work on changes** (not just review a PR), you can run the dev profile:
142
+
143
+ ```bash
144
+ npx --yes -p @happier-dev/stack@latest hstack setup --profile=dev --bind=loopback
145
+ ```
146
+
147
+ Notes:
148
+ - This bootstraps a workspace (clones repos, installs deps, sets up worktrees/stacks tooling).
149
+ - On Linux VMs you typically want `--no-mobile` workflows (iOS dev-client requires Xcode/macOS).
150
+
151
+ ### 4) Run `review-pr` via `npx` (published package)
152
+
153
+ Inside the VM:
154
+
155
+ ```bash
156
+ npx --yes -p @happier-dev/stack@latest hstack review-pr \
157
+ --repo=https://github.com/happier-dev/happier/pull/<PR_NUMBER> \
158
+ --vm-ports \
159
+ --no-mobile \
160
+ --keep-sandbox \
161
+ --verbose \
162
+ -- --bind=loopback
163
+ ```
164
+
165
+ Notes:
166
+ - `--no-mobile` keeps the validation focused (Expo mobile dev-client adds more host requirements).
167
+ - You can also add `--keep-sandbox` if you want to inspect the sandbox contents after a failure.
168
+ - For full reproducibility, pin the version: `npx --yes -p @happier-dev/stack@0.3.0 hstack review-pr ...`
169
+ - `--vm-ports` forces the stack/server and Expo dev-server (web) ports into the forwarded VM ranges
170
+ (pairs with the `portForwards` config in this doc).
171
+
172
+ ### Optional: test **unreleased local changes**
173
+
174
+ If you need to test changes that aren’t published to npm yet:
175
+
176
+ 1) On your Mac (repo checkout):
177
+
178
+ ```bash
179
+ npm pack
180
+ ```
181
+
182
+ 2) Copy the generated `happier-dev-stack-*.tgz` into the VM (any method you like), then inside the VM:
183
+
184
+ ```bash
185
+ npx --yes ./happier-dev-stack-*.tgz hstack review-pr ...
186
+ ```
187
+
188
+ ## Option B: GUI VM (UTM) – simplest when you want a “real desktop”
189
+
190
+ If you want the most realistic “reviewer” experience (open browser, etc.), a GUI VM is great:
191
+
192
+ 1. Install UTM (macOS host): `brew install --cask utm`
193
+ 2. Create an Ubuntu 24.04 ARM64 VM (UTM wizard).
194
+ 3. Run the same provisioning + `node bin/hstack.mjs review-pr ...` inside the VM.
195
+
196
+ ## Option C: Apple “container” / Docker
197
+
198
+ Containers are excellent for server-only validation, but are usually **not** the best fit for end-to-end `review-pr` UX because:
199
+ - opening the host browser from inside the container is awkward
200
+ - Expo/dev-server workflows and networking tend to require extra port mapping and host interaction
201
+
202
+ Use containers only if you explicitly want “CLI-only” checks and are okay opening URLs manually.
203
+
204
+ ---
205
+
206
+ ## Resetting / starting fresh
207
+
208
+ ### Full reset (recommended): recreate the VM
209
+
210
+ On the macOS host:
211
+
212
+ ```bash
213
+ limactl stop happy-pr || true
214
+ limactl delete happy-pr
215
+ limactl create --name happy-pr --tty=false template:ubuntu-24.04
216
+ limactl start happy-pr
217
+ ```
218
+
219
+ Then re-run the provisioning step (Node + build deps) from this doc.
220
+
221
+ ### Soft reset: keep the VM, delete hstack state
222
+
223
+ If you want a “clean-ish” rerun without recreating the VM, delete the hstack home + any workspace you chose:
224
+
225
+ Inside the VM:
226
+
227
+ ```bash
228
+ rm -rf ~/.happier-stack ~/.happier ~/.happy
229
+ ```
230
+
231
+ Why these paths:
232
+ - `~/.happier-stack`: stack runtime home (shims/runtime/cache/logs).
233
+ - `~/.happier`: stack storage root (`~/.happier/stacks/<name>/...` env/state/data).
234
+ - `~/.happy`: legacy pre-monorepo location that older migrations/import tooling may still reference.
235
+
236
+ If you used `hstack setup --profile=dev` and picked a custom workspace directory (outside `~/.happier-stack/workspace`), delete that directory too.
237
+
238
+ ---
239
+
240
+ ## Notes / scope
241
+
242
+ - This doc targets **web-only** validation (`--no-mobile`) on Ubuntu ARM64 VMs.
243
+ - On-device iOS testing via `--mobile` requires a macOS host with Xcode (not possible inside the Linux VM).
@@ -0,0 +1,244 @@
1
+ # Menu bar (SwiftBar)
2
+
3
+ `hstack` ships a macOS menu bar plugin powered by [SwiftBar](https://swiftbar.app/).
4
+
5
+ SwiftBar runs a script on an interval and renders its output as native macOS menu items.
6
+
7
+ ## Features
8
+
9
+ - **Status at a glance** with dynamic icons (green/orange/red)
10
+ - Server health
11
+ - Daemon status (PID + optional control server probe)
12
+ - Autostart LaunchAgent status
13
+ - Tailscale Serve status / URL (if configured)
14
+ - **Quick controls**
15
+ - Start / stop / restart the stack
16
+ - Restart just the daemon (stack-safe)
17
+ - Install / enable / disable / uninstall autostart
18
+ - Enable / disable Tailscale Serve
19
+ - **Details**
20
+ - PID, CPU %, RAM MB, uptime (where available)
21
+ - Useful URLs and file paths
22
+ - Stack details include aggregate CPU/RAM (server+daemon+autostart) when running
23
+ - Open logs in Console.app
24
+ - **Refresh control**
25
+ - Manual refresh
26
+ - In-menu refresh interval toggles (includes slower intervals like 10m/15m/30m/1h/6h/12h/1d)
27
+ - Uses a small helper script (`extras/swiftbar/set-interval.sh`) to avoid SwiftBar quoting issues
28
+ - **Stacks + services layout**
29
+ - Main stack is shown directly (no extra nesting level)
30
+ - Each stack shows service rows (Server/Daemon/Autostart/Tailscale) with per-service submenus
31
+ - **Components (git/worktrees)**
32
+ - Available under a top-level **Components** submenu (to keep the main menu clean)
33
+ - Shows repo/worktree status for the active monorepo checkout (`<workspace>/main`, `<workspace>/dev`, or a worktree under `<workspace>/{pr,local,tmp}/...`)
34
+ - Each repo entry includes a **Worktrees** submenu listing all worktrees, with actions to switch/open
35
+ - Quick actions: `wt status/sync/update`, PR worktree prompt, open shells/editors (`wt shell/code/cursor`)
36
+ - Shows **origin** and **upstream** comparisons for the repo’s main branch (based on your last `git fetch`)
37
+ - Uses a **Git cache** by default so SwiftBar refresh stays fast even with many stacks/worktrees
38
+
39
+ ## Modes: selfhost vs dev
40
+
41
+ The menu supports two modes:
42
+
43
+ - **Selfhost mode** (`selfhost`): lightweight “control panel” for running Happier.
44
+ - Shows only the main stack essentials (Server/Daemon/Autostart/Tailscale) plus a small **Maintenance** section.
45
+ - Hides developer-oriented sections like stacks enumeration, git/worktrees, and worktree tooling.
46
+ - **Dev mode** (`dev`): full stack control plane (stacks + git/worktrees + worktree tooling).
47
+
48
+ ### How to switch modes
49
+
50
+ - In the menu, use the **Mode** section at the top, or
51
+ - From a terminal:
52
+
53
+ ```bash
54
+ hstack menubar mode selfhost
55
+ hstack menubar mode dev
56
+ ```
57
+
58
+ ## Stacks (multiple instances)
59
+
60
+ If you create additional stacks (see `docs/stacks.md`), the plugin shows:
61
+
62
+ - **Main stack** (the default, stack name `main`)
63
+ - **Stacks** section listing each stack found under `~/.happier/stacks/<name>/env`
64
+
65
+ Each stack row renders the same “mini control panel” (server/daemon/autostart/logs + a few actions) with stack-specific ports, dirs, and LaunchAgent label.
66
+
67
+ The menu also includes:
68
+
69
+ - `stack new --interactive` (create stacks)
70
+ - `stack edit <name> --interactive` (edit stack port/server flavor/repo checkout)
71
+ - `stack wt <name> -- use --interactive` (switch the stack’s repo checkout/worktree)
72
+ - “PR worktree into this stack (prompt)” (creates `wt pr ... --use` scoped to the stack env)
73
+
74
+ ## Worktrees (quick entry points)
75
+
76
+ The menu also provides “jump off” actions for the worktree tooling:
77
+
78
+ - `hstack wt use --interactive`
79
+ - `hstack wt new --interactive`
80
+ - `hstack wt sync-all`
81
+ - `hstack wt update-all --dry-run` / `hstack wt update-all`
82
+ - `hstack wt pr ...` (via an in-menu prompt)
83
+
84
+ For stack-specific worktree selection (which worktree a stack uses), use:
85
+
86
+ - `hstack stack edit <name> --interactive`
87
+ - or `hstack stack wt <name> -- use --interactive`
88
+
89
+ ### Note (worktree switching)
90
+
91
+ Happier is a single monorepo, so switching worktrees is always a **repo-level** action. Use:
92
+
93
+ - `hstack stack wt <name> -- use --interactive`
94
+
95
+ ## Implementation notes
96
+
97
+ - **Entry script**: `extras/swiftbar/hstack.5s.sh` (installed into SwiftBar as `hstack.<interval>.sh`)
98
+ - **Shared functions**: `extras/swiftbar/lib/*.sh` (sourced by the entry script)
99
+ - **Helper scripts**:
100
+ - `extras/swiftbar/set-interval.sh`
101
+ - `extras/swiftbar/set-server-flavor.sh`
102
+
103
+ ## Install
104
+
105
+ ### 1) Install SwiftBar
106
+
107
+ ```bash
108
+ brew install --cask swiftbar
109
+ ```
110
+
111
+ ### 2) Install the plugin
112
+
113
+ ```bash
114
+ hstack menubar install
115
+ ```
116
+
117
+ If you want a different default refresh interval at install time:
118
+
119
+ ```bash
120
+ HAPPIER_STACK_SWIFTBAR_INTERVAL=15m hstack menubar install
121
+ ```
122
+
123
+ ### 3) Open the active SwiftBar plugin folder
124
+
125
+ SwiftBar can be configured to use a custom plugin directory. To open the *active* one:
126
+
127
+ ```bash
128
+ hstack menubar open
129
+ ```
130
+
131
+ ## Uninstall
132
+
133
+ Remove the installed SwiftBar plugin files (does not delete your stacks/workspace):
134
+
135
+ ```bash
136
+ hstack menubar uninstall
137
+ ```
138
+
139
+ ## How refresh works (important)
140
+
141
+ SwiftBar’s refresh interval is controlled by the **filename** suffix:
142
+
143
+ - `hstack.30s.sh` → every 30 seconds
144
+ - `hstack.5m.sh` → every 5 minutes
145
+ - `hstack.1h.sh` → every 1 hour
146
+
147
+ The plugin defaults to a slower interval (recommended), and also sets:
148
+
149
+ - `refreshOnOpen=false` (recommended) to avoid surprise refreshes while you’re navigating the menu.
150
+
151
+ You can also change the interval directly from the menu via **Refresh interval** (it renames the plugin file and restarts SwiftBar).
152
+
153
+ ## Git cache (important for performance)
154
+
155
+ Git/worktree inspection is the most expensive part of the menu when you have many stacks.
156
+ By default, the plugin runs in **cached mode**:
157
+
158
+ - It renders git/worktree info from an on-disk cache under `~/.happier-stack/cache/swiftbar/git`.
159
+ - Normal menu refreshes do **not** run git commands (so refresh stays snappy).
160
+ - The cache is refreshed explicitly (via menu actions), and can optionally refresh on TTL expiry.
161
+
162
+ Controls and settings:
163
+
164
+ - **Refresh now**: open **Components → Git cache** and run:
165
+ - “Refresh now (main components)”
166
+ - “Refresh now (all stacks/components)”
167
+ - or “Refresh now (this stack)” from a stack’s Components menu
168
+ - **TTL**: `HAPPIER_STACK_SWIFTBAR_GIT_TTL_SEC` (default `21600` seconds = 6 hours)
169
+ - **Mode**: `HAPPIER_STACK_SWIFTBAR_GIT_MODE=cached|live` (default `cached`)
170
+ - (Optional) **Background auto-refresh**: `HAPPIER_STACK_SWIFTBAR_GIT_AUTO_REFRESH_SCOPE=main|all|off` (default `main`)
171
+
172
+ Notes:
173
+
174
+ - Cached git info can be stale; it’s meant for at-a-glance signal.
175
+ - Actions like worktree switching/build/dev are always live (they use `hstack`); only *displayed git status* is cached.
176
+
177
+ ## Maintenance (selfhost mode)
178
+
179
+ In **selfhost** mode, the menu includes a **Maintenance** section that can:
180
+
181
+ - show whether a `hstack` update is available (from cached `~/.happier-stack/cache/update.json`)
182
+ - run:
183
+ - `hstack self check`
184
+ - `hstack self update`
185
+
186
+ ## Terminal preference for interactive actions
187
+
188
+ Many menu actions open a terminal (interactive wizards, long-running dev servers, etc).
189
+ The plugin uses helper scripts so these run in your preferred terminal, using the same env var as `wt shell`:
190
+
191
+ - `HAPPIER_STACK_WT_TERMINAL=auto|ghostty|iterm|terminal|current`
192
+
193
+ Notes:
194
+ - `auto` tries ghostty → iTerm → Terminal → current.
195
+ - Ghostty is best-effort; if your Ghostty build can’t execute the command automatically, the command is copied to your clipboard and Ghostty is opened in the repo directory.
196
+
197
+ ## Start SwiftBar at login (optional)
198
+
199
+ SwiftBar is independent from the hstack LaunchAgent/service.
200
+
201
+ - In SwiftBar Preferences, enable **Launch at Login**, or
202
+ - Add SwiftBar to macOS **Login Items**.
203
+
204
+ ## Troubleshooting
205
+
206
+ ### Plugin doesn’t show up
207
+
208
+ - Ensure SwiftBar is running.
209
+ - Check which plugin folder SwiftBar is using:
210
+ - SwiftBar → Preferences → Plugin Folder
211
+ - Open the active folder:
212
+ - `hstack menubar open`
213
+
214
+ ### Daemon shows “auth required” / “no machine”
215
+
216
+ This happens on a **fresh machine** (or any new stack) when the daemon does not yet have credentials in the
217
+ stack-specific CLI home directory.
218
+
219
+ **What’s going on**
220
+
221
+ - The daemon stores credentials in `access.key` under the CLI home directory.
222
+ - For stacks (including main), that’s typically:
223
+ - `~/.happier/stacks/<name>/cli/access.key`
224
+ - When `access.key` is missing, `happy-cli daemon start` enters an interactive auth flow and won’t become a “machine” until it completes.
225
+ - Under `launchd` (autostart), this shows up as **no machine** and the daemon may appear “stopped”.
226
+
227
+ **If it still needs auth**
228
+
229
+ - In SwiftBar, open the **Daemon** section:
230
+ - If it shows `auth_required`, click **Auth login (opens browser)**
231
+ - Or run manually:
232
+
233
+ ```bash
234
+ hstack auth login
235
+ ```
236
+
237
+ ### “Daemon stale” even though it’s running
238
+
239
+ The plugin checks:
240
+
241
+ - `daemon.state.json` **PID is alive**, and
242
+ - (optionally) the daemon control server responds.
243
+
244
+ If the daemon is running but the menu is stale, refresh and check the **PID** line under “Daemon”.