Add install_node (bun-based) installer and service_books lifecycle module #76

Closed
opened 2026-04-19 10:49:39 +00:00 by mahmoud · 5 comments
Owner

Goal

hero_books now has docusaurus-based site generation, which needs bun (and by extension node) available on any machine running the stack. Following the existing installers.nu / services/*.nu pattern, this belongs in hero_skills, not in hero_books itself.

Why hero_skills and not hero_books

The Hero convention is:

  • hero_skills/tools/modules/installers.nu — shared tool installers (install_base, install_rust, install_ai, install_py). Ecosystem-wide prerequisites.
  • hero_skills/tools/modules/services/service_*.nu — per-service lifecycle (install | start | stop | status) for every Hero service.
  • Individual service repos — only Rust/source code and service-specific logic. The service binary stays --start / --stop / --status only.

bun is not hero_books-specific — future JS tooling (dioxus bindings, hero_whiteboard, etc.) will want it. It's a shared prerequisite.

Scope

1. Add install_node to tools/modules/installers.nu

  • New export def install_node [] alongside install_rust / install_py.
  • Installs bun via the official script: curl -fsSL https://bun.sh/install | bash.
  • Idempotent — checks if bun is already on PATH before installing.
  • Reports bun and node versions at the end (bun provides node).
  • Works on macOS and Linux; matches the platform detection pattern used in install_base.

2. Include it in install_core

  • Add install_node to the install_core orchestrator so a base Hero environment always has bun/node available.

3. Add or update tools/modules/services/service_books.nu

  • Follow the shape of service_proxy.nu / service_router.nu.
  • Expose install | start | stop | status subcommands.
  • install — clone/pull the repo, cargo build --release, and run bun install inside the docusaurus template directory so node_modules is primed.
  • start / stop / status — talk to hero_proc like other service modules.
  • If the module already exists, extend it; otherwise create it.

4. Wire into services.nu

  • Ensure hero_books is listed in the bin_map / service lists (service_complete already references it) and that the new service_books module is discoverable.

Acceptance criteria

  • A fresh environment running install_core ends up with bun --version and node --version both reporting successfully.
  • service_books install builds hero_books and primes the docusaurus template's node_modules.
  • service_books start launches hero_books via hero_proc; service_books status reports its state; service_books stop cleanly terminates it.
  • Re-running install_node on a system that already has bun is a no-op (no reinstall).
  • No install logic lands in the hero_books repo itself — the hero_books binary stays --start / --stop / --status only.

Optional split

If the reviewer load is heavy, split into two PRs:

  1. install_node + inclusion in install_core.
  2. service_books.nu and services.nu wiring.

Prefer a single PR unless review bandwidth is the bottleneck.

Dependency order

Independent of the hero_books work. Unblocks anyone provisioning a fresh environment and running the full stack.

## Goal hero_books now has docusaurus-based site generation, which needs `bun` (and by extension `node`) available on any machine running the stack. Following the existing `installers.nu` / `services/*.nu` pattern, this belongs in `hero_skills`, not in `hero_books` itself. ## Why hero_skills and not hero_books The Hero convention is: - **`hero_skills/tools/modules/installers.nu`** — shared tool installers (`install_base`, `install_rust`, `install_ai`, `install_py`). Ecosystem-wide prerequisites. - **`hero_skills/tools/modules/services/service_*.nu`** — per-service lifecycle (`install | start | stop | status`) for every Hero service. - **Individual service repos** — only Rust/source code and service-specific logic. The service binary stays `--start / --stop / --status` only. bun is not hero_books-specific — future JS tooling (dioxus bindings, hero_whiteboard, etc.) will want it. It's a shared prerequisite. ## Scope ### 1. Add `install_node` to `tools/modules/installers.nu` - [ ] New `export def install_node []` alongside `install_rust` / `install_py`. - [ ] Installs `bun` via the official script: `curl -fsSL https://bun.sh/install | bash`. - [ ] Idempotent — checks if `bun` is already on PATH before installing. - [ ] Reports bun and node versions at the end (bun provides node). - [ ] Works on macOS and Linux; matches the platform detection pattern used in `install_base`. ### 2. Include it in `install_core` - [ ] Add `install_node` to the `install_core` orchestrator so a base Hero environment always has bun/node available. ### 3. Add or update `tools/modules/services/service_books.nu` - [ ] Follow the shape of `service_proxy.nu` / `service_router.nu`. - [ ] Expose `install | start | stop | status` subcommands. - [ ] `install` — clone/pull the repo, `cargo build --release`, and run `bun install` inside the docusaurus template directory so `node_modules` is primed. - [ ] `start` / `stop` / `status` — talk to hero_proc like other service modules. - [ ] If the module already exists, extend it; otherwise create it. ### 4. Wire into `services.nu` - [ ] Ensure `hero_books` is listed in the `bin_map` / service lists (`service_complete` already references it) and that the new `service_books` module is discoverable. ## Acceptance criteria - [ ] A fresh environment running `install_core` ends up with `bun --version` and `node --version` both reporting successfully. - [ ] `service_books install` builds hero_books and primes the docusaurus template's `node_modules`. - [ ] `service_books start` launches hero_books via hero_proc; `service_books status` reports its state; `service_books stop` cleanly terminates it. - [ ] Re-running `install_node` on a system that already has bun is a no-op (no reinstall). - [ ] No install logic lands in the hero_books repo itself — the hero_books binary stays `--start / --stop / --status` only. ## Optional split If the reviewer load is heavy, split into two PRs: 1. `install_node` + inclusion in `install_core`. 2. `service_books.nu` and `services.nu` wiring. Prefer a single PR unless review bandwidth is the bottleneck. ## Dependency order Independent of the hero_books work. Unblocks anyone provisioning a fresh environment and running the full stack.
Owner

not correct,

the install can be done in service_books ...
there we can check if bun is there

in installers/... we can make a reusable installer for bun, we can reuse in service_books

not correct, the install can be done in service_books ... there we can check if bun is there in installers/... we can make a reusable installer for bun, we can reuse in service_books
mahmoud self-assigned this 2026-04-26 10:15:01 +00:00
mahmoud added this to the ACTIVE project 2026-04-26 10:15:04 +00:00
mahmoud added this to the now milestone 2026-04-26 10:15:06 +00:00
Author
Owner

Implementation Spec for Issue #76

Objective

Add a reusable, idempotent install_bun function to the Hero Shell installers module, and wire service_books install to use it (after a which bun check) before running bun install in the docusaurus template directory shipped with hero_books. Per maintainer feedback, bun is NOT added to install_core — it is pulled in on demand only by services that need it.

Requirements

  • New install_bun exported function in tools/modules/installers/installers.nu.
    • Idempotent: no-op if bun is already on PATH (i.e. which bun | is-not-empty).
    • Cross-platform: macOS + Linux. On macOS prefer brew install oven-sh/bun/bun when brew is available, falling back to the official curl script. On Linux use the official curl -fsSL https://bun.sh/install | bash script. Mirrors the platform-branching pattern used by install_chrome / install_onnxruntime.
    • Verifies bun is on PATH after install; raises an actionable error make if not (the bun installer drops shims into ~/.bun/bin and appends to ~/.bashrc / ~/.zshrc; within the same nushell session PATH won't auto-update, so we additionally check ~/.bun/bin/bun exists as a fallback before erroring).
    • Plain print output, no emojis, no AI attribution.
  • install_core is NOT modified (rejects original ask). install_bun stands on its own and is callable directly.
  • service_books install calls install_bun if bun is not on PATH, then runs bun install in the docusaurus template directory.
    • Docusaurus template directory: {forge_local}/crates/hero_books_docusaurus/src/template_files where forge_local comes from forge_ensure_local "lhumina_code/hero_books". This directory contains package.json declaring @docusaurus/core and "packageManager": "bun@1.2.5".
    • Run after the cargo build / svc_cargo_install step (since the source tree must be present).
    • Skip the bun install step idempotently when node_modules already exists in the template_files dir AND --reset was not passed.
    • Resolve the bun executable for the spawn step using which bun first, falling back to ~/.bun/bin/bun (same-session PATH limitation noted above).
  • template_install_bun in tools/modules/installers/template_install.nu is left unchanged. It targets ~template/.bun via the template_run sudo wrapper and the new install_bun targets the invoking user's $HOME — they are not interchangeable.
  • packages.nu line 73 (service_books install commented out) is left unchanged. Activating service_install_all for hero_books is out of scope here.

Files to Modify/Create

  • tools/modules/installers/installers.nu — add install_bun function. Do NOT add it to install_core.
  • tools/modules/services/service_books.nu — at the end of install, call install_bun (only if bun missing) and then run bun install in the docusaurus template_files directory. Add the use ../installers/installers.nu [install_bun] import at the top.

(No new files. No changes to mod.nu, packages.nu, or template_install.nu.)

Implementation Plan

Step 1: Add reusable install_bun to installers.nu

Files:

  • tools/modules/installers/installers.nu

Subtasks:

  • After the existing install_ai function add a new exported function install_bun.
  • Function body:
    1. If which bun | is-not-empty, print "bun already installed: <version>" and return.
    2. Branch on platform:
      • macOS: if which brew | is-not-empty, run ^brew install oven-sh/bun/bun. Otherwise fall through to the curl path.
      • Linux / fallback: ^bash -c "curl -fsSL https://bun.sh/install | bash".
    3. Post-install verification: re-check which bun; if still empty, also check ($env.HOME)/.bun/bin/bun exists. If neither resolves, raise error make with: "bun installer exited 0 but 'bun' not on PATH. Open a new shell (or source ~/.bashrc / ~/.zshrc) so ~/.bun/bin is on PATH, then re-run.".
    4. On success, print: "bun installed: <version-or-path>".
  • Add a top-of-function comment block matching the existing style explaining: idempotent, cross-platform, used by service_books install for the docusaurus template build, intentionally NOT in install_core.
  • Confirm install_bun does NOT appear in the install_core body.

Dependencies: none.

Step 2: Wire bun bootstrap + bun install into service_books install

Files:

  • tools/modules/services/service_books.nu

Subtasks:

  • Add an import: use ../installers/installers.nu [install_bun].
  • At the end of the install function (after the svc_cargo_install ... call), add a docusaurus bootstrap block:
    1. Compute let docs_dir = $"($info.path)/crates/hero_books_docusaurus/src/template_files".
    2. Guard that ($docs_dir | path exists); if not, print a warning and return.
    3. Skip-when-installed: if node_modules exists and not $reset, print explanatory line and return.
    4. Bun bootstrap: if which bun | is-empty, print and call install_bun.
    5. Resolve the bun executable: let bun_exec = if (which bun | is-not-empty) { "bun" } else { $"($env.HOME)/.bun/bin/bun" }.
    6. Run bun install in the docusaurus directory; check exit code and error make with stderr on failure.
    7. Print a closing summary line.
  • Update the function-level docstring to mention the docusaurus bun install step and that bun is auto-installed if missing.

Dependencies: Step 1 (uses install_bun).

Acceptance Criteria

  • install_bun exists in installers.nu, is exported, and is idempotent.
  • install_bun works on macOS (via brew when available) and Linux (via curl script).
  • install_bun raises a clear error if installer succeeds but bun is unreachable.
  • install_core does NOT call install_bun.
  • service_books install on a fresh machine without bun: detects missing bun, calls install_bun, then runs bun install in <hero_books>/crates/hero_books_docusaurus/src/template_files, populating node_modules.
  • service_books install on a machine where bun and node_modules already exist: skips both with explanatory print lines (idempotent).
  • service_books install --reset re-runs bun install even when node_modules exists.
  • template_install_bun in template_install.nu remains unchanged.
  • No emojis or AI attribution in any added code, comments, or output.

Notes

  • The bun official installer modifies ~/.bashrc / ~/.zshrc. Within the same nushell session, which bun may still return empty after install — Step 2 falls back to ~/.bun/bin/bun for the immediate bun install invocation.
  • The docusaurus dir path is verified against the hero_books repo: contains package.json (Docusaurus 3.7.0, "packageManager": "bun@1.2.5"), docusaurus.config.ts, sidebars.ts, and build.sh / develop.sh.
  • install already accepts --reset; reuse that flag to drive the bun install re-run.
  • forge_ensure_local is the source of truth for the local hero_books path. Do not hard-code paths.
  • macOS brew path avoids the same-session PATH issue (/opt/homebrew/bin/bun ends up on PATH automatically); on Linux the curl path requires the fallback to ~/.bun/bin/bun.
## Implementation Spec for Issue #76 ### Objective Add a reusable, idempotent `install_bun` function to the Hero Shell installers module, and wire `service_books install` to use it (after a `which bun` check) before running `bun install` in the docusaurus template directory shipped with hero_books. Per maintainer feedback, bun is NOT added to `install_core` — it is pulled in on demand only by services that need it. ### Requirements - New `install_bun` exported function in `tools/modules/installers/installers.nu`. - Idempotent: no-op if `bun` is already on PATH (i.e. `which bun | is-not-empty`). - Cross-platform: macOS + Linux. On macOS prefer `brew install oven-sh/bun/bun` when `brew` is available, falling back to the official curl script. On Linux use the official `curl -fsSL https://bun.sh/install | bash` script. Mirrors the platform-branching pattern used by `install_chrome` / `install_onnxruntime`. - Verifies `bun` is on PATH after install; raises an actionable `error make` if not (the bun installer drops shims into `~/.bun/bin` and appends to `~/.bashrc` / `~/.zshrc`; within the same nushell session PATH won't auto-update, so we additionally check `~/.bun/bin/bun` exists as a fallback before erroring). - Plain `print` output, no emojis, no AI attribution. - `install_core` is NOT modified (rejects original ask). `install_bun` stands on its own and is callable directly. - `service_books install` calls `install_bun` if `bun` is not on PATH, then runs `bun install` in the docusaurus template directory. - Docusaurus template directory: `{forge_local}/crates/hero_books_docusaurus/src/template_files` where `forge_local` comes from `forge_ensure_local "lhumina_code/hero_books"`. This directory contains `package.json` declaring `@docusaurus/core` and `"packageManager": "bun@1.2.5"`. - Run after the cargo build / `svc_cargo_install` step (since the source tree must be present). - Skip the `bun install` step idempotently when `node_modules` already exists in the template_files dir AND `--reset` was not passed. - Resolve the bun executable for the spawn step using `which bun` first, falling back to `~/.bun/bin/bun` (same-session PATH limitation noted above). - `template_install_bun` in `tools/modules/installers/template_install.nu` is left unchanged. It targets `~template/.bun` via the `template_run` sudo wrapper and the new `install_bun` targets the invoking user's `$HOME` — they are not interchangeable. - `packages.nu` line 73 (`service_books` install commented out) is left unchanged. Activating `service_install_all` for hero_books is out of scope here. ### Files to Modify/Create - `tools/modules/installers/installers.nu` — add `install_bun` function. Do NOT add it to `install_core`. - `tools/modules/services/service_books.nu` — at the end of `install`, call `install_bun` (only if `bun` missing) and then run `bun install` in the docusaurus template_files directory. Add the `use ../installers/installers.nu [install_bun]` import at the top. (No new files. No changes to `mod.nu`, `packages.nu`, or `template_install.nu`.) ### Implementation Plan #### Step 1: Add reusable `install_bun` to installers.nu Files: - `tools/modules/installers/installers.nu` Subtasks: - After the existing `install_ai` function add a new exported function `install_bun`. - Function body: 1. If `which bun | is-not-empty`, print `"bun already installed: <version>"` and `return`. 2. Branch on platform: - macOS: if `which brew | is-not-empty`, run `^brew install oven-sh/bun/bun`. Otherwise fall through to the curl path. - Linux / fallback: `^bash -c "curl -fsSL https://bun.sh/install | bash"`. 3. Post-install verification: re-check `which bun`; if still empty, also check `($env.HOME)/.bun/bin/bun` exists. If neither resolves, raise `error make` with: `"bun installer exited 0 but 'bun' not on PATH. Open a new shell (or source ~/.bashrc / ~/.zshrc) so ~/.bun/bin is on PATH, then re-run."`. 4. On success, print: `"bun installed: <version-or-path>"`. - Add a top-of-function comment block matching the existing style explaining: idempotent, cross-platform, used by `service_books install` for the docusaurus template build, intentionally NOT in `install_core`. - Confirm `install_bun` does NOT appear in the `install_core` body. Dependencies: none. #### Step 2: Wire bun bootstrap + `bun install` into service_books install Files: - `tools/modules/services/service_books.nu` Subtasks: - Add an import: `use ../installers/installers.nu [install_bun]`. - At the end of the `install` function (after the `svc_cargo_install ...` call), add a docusaurus bootstrap block: 1. Compute `let docs_dir = $"($info.path)/crates/hero_books_docusaurus/src/template_files"`. 2. Guard that `($docs_dir | path exists)`; if not, print a warning and `return`. 3. Skip-when-installed: if `node_modules` exists and `not $reset`, print explanatory line and `return`. 4. Bun bootstrap: if `which bun | is-empty`, print and call `install_bun`. 5. Resolve the bun executable: `let bun_exec = if (which bun | is-not-empty) { "bun" } else { $"($env.HOME)/.bun/bin/bun" }`. 6. Run `bun install` in the docusaurus directory; check exit code and `error make` with stderr on failure. 7. Print a closing summary line. - Update the function-level docstring to mention the docusaurus bun install step and that bun is auto-installed if missing. Dependencies: Step 1 (uses `install_bun`). ### Acceptance Criteria - [ ] `install_bun` exists in `installers.nu`, is exported, and is idempotent. - [ ] `install_bun` works on macOS (via brew when available) and Linux (via curl script). - [ ] `install_bun` raises a clear error if installer succeeds but `bun` is unreachable. - [ ] `install_core` does NOT call `install_bun`. - [ ] `service_books install` on a fresh machine without bun: detects missing bun, calls `install_bun`, then runs `bun install` in `<hero_books>/crates/hero_books_docusaurus/src/template_files`, populating `node_modules`. - [ ] `service_books install` on a machine where bun and node_modules already exist: skips both with explanatory print lines (idempotent). - [ ] `service_books install --reset` re-runs `bun install` even when `node_modules` exists. - [ ] `template_install_bun` in `template_install.nu` remains unchanged. - [ ] No emojis or AI attribution in any added code, comments, or output. ### Notes - The bun official installer modifies `~/.bashrc` / `~/.zshrc`. Within the same nushell session, `which bun` may still return empty after install — Step 2 falls back to `~/.bun/bin/bun` for the immediate `bun install` invocation. - The docusaurus dir path is verified against the hero_books repo: contains `package.json` (Docusaurus 3.7.0, `"packageManager": "bun@1.2.5"`), `docusaurus.config.ts`, `sidebars.ts`, and `build.sh` / `develop.sh`. - `install` already accepts `--reset`; reuse that flag to drive the `bun install` re-run. - `forge_ensure_local` is the source of truth for the local hero_books path. Do not hard-code paths. - macOS brew path avoids the same-session PATH issue (`/opt/homebrew/bin/bun` ends up on PATH automatically); on Linux the curl path requires the fallback to `~/.bun/bin/bun`.
Author
Owner

Test Results

This is a nushell-module change in hero_skills; there is no cargo test here. Validation done:

Parse / load checks (local)

File Check Result
tools/modules/installers/installers.nu nu -c "use installers.nu install_bun; help install_bun" passes — function loads, doc comment renders
tools/modules/services/service_books.nu nu -c "use service_books.nu; help service_books install" passes — function loads, updated docstring renders
Both use installers.nu *; use service_books.nu; print 'modules load ok' passes — no parser errors

Static checks

  • install_core body (lines 370–405) verified unchanged — install_bun not called from it.
  • template_install_bun in template_install.nu verified unchanged.
  • tools/modules/services/packages.nu verified unchanged (the commented-out service_books entry stays commented).
  • tools/modules/services/mod.nu unchanged.
  • is_macos / is_linux added to the use ../platform.nu [...] import list in installers.nu so the new code (and pre-existing install_chrome / install_onnxruntime / install_docker_btrfs calls) resolve them cleanly.

Behavioral coverage (by code reading)

  • install_bun returns early when which bun | is-not-empty (idempotent).
  • macOS path branches to brew install oven-sh/bun/bun when brew is on PATH; falls through to the curl script otherwise.
  • Linux path runs the official curl -fsSL https://bun.sh/install | bash script.
  • Post-install verification falls back to ~/.bun/bin/bun when which bun is still empty in the same shell session (PATH not refreshed yet).
  • Raises error make with an actionable message when neither resolves.
  • service_books install skips the docusaurus block when template_files/ is missing.
  • Skips bun install when node_modules/ exists and --reset is not passed.
  • Calls install_bun only when which bun | is-empty.
  • Resolves bun_exec to either bun (PATH) or ~/.bun/bin/bun (fresh install) before running bun install.
  • Errors with the trimmed stderr if bun install exits non-zero.

Not run here

  • A live end-to-end run of service_books install against a real hero_books checkout is not done in this PR — that requires a writable hero_books clone and is best validated on a target host where service_books install is actually invoked.
## Test Results This is a nushell-module change in `hero_skills`; there is no `cargo test` here. Validation done: ### Parse / load checks (local) | File | Check | Result | |---|---|---| | `tools/modules/installers/installers.nu` | `nu -c "use installers.nu install_bun; help install_bun"` | passes — function loads, doc comment renders | | `tools/modules/services/service_books.nu` | `nu -c "use service_books.nu; help service_books install"` | passes — function loads, updated docstring renders | | Both | `use installers.nu *; use service_books.nu; print 'modules load ok'` | passes — no parser errors | ### Static checks - `install_core` body (lines 370–405) verified unchanged — `install_bun` not called from it. - `template_install_bun` in `template_install.nu` verified unchanged. - `tools/modules/services/packages.nu` verified unchanged (the commented-out `service_books` entry stays commented). - `tools/modules/services/mod.nu` unchanged. - `is_macos` / `is_linux` added to the `use ../platform.nu [...]` import list in `installers.nu` so the new code (and pre-existing `install_chrome` / `install_onnxruntime` / `install_docker_btrfs` calls) resolve them cleanly. ### Behavioral coverage (by code reading) - `install_bun` returns early when `which bun | is-not-empty` (idempotent). - macOS path branches to `brew install oven-sh/bun/bun` when brew is on PATH; falls through to the curl script otherwise. - Linux path runs the official `curl -fsSL https://bun.sh/install | bash` script. - Post-install verification falls back to `~/.bun/bin/bun` when `which bun` is still empty in the same shell session (PATH not refreshed yet). - Raises `error make` with an actionable message when neither resolves. - `service_books install` skips the docusaurus block when `template_files/` is missing. - Skips `bun install` when `node_modules/` exists and `--reset` is not passed. - Calls `install_bun` only when `which bun | is-empty`. - Resolves `bun_exec` to either `bun` (PATH) or `~/.bun/bin/bun` (fresh install) before running `bun install`. - Errors with the trimmed stderr if `bun install` exits non-zero. ### Not run here - A live end-to-end run of `service_books install` against a real hero_books checkout is not done in this PR — that requires a writable hero_books clone and is best validated on a target host where `service_books install` is actually invoked.
Author
Owner

Implementation Summary

Implemented per the spec above and the maintainer's design feedback.

Files Changed

File Change
tools/modules/installers/installers.nu Added install_bun function (~38 lines after install_ai). Added is_macos, is_linux to the existing use ../platform.nu [...] import.
tools/modules/services/service_books.nu Added use ../installers/installers.nu [install_bun] at the top. Updated install docstring. Appended a docusaurus bootstrap block at the end of install (~33 lines).

Files Intentionally NOT Changed

  • installers.nu::install_core — bun is NOT added (per maintainer feedback: services pull bun on demand).
  • installers/template_install.nu::template_install_bun — left as-is (template-user-only via template_run wrapper; not interchangeable with the new reusable installer).
  • services/packages.nu — the commented-out service_books entry stays commented; activating service_install_all for hero_books is out of scope here.
  • services/mod.nu — already re-exports service_books, no changes needed.

Behavior

install_bun (reusable, callable from anywhere):

  • Idempotent — returns early with version line if bun is already on PATH.
  • macOS: prefers brew install oven-sh/bun/bun if brew is present, otherwise falls through to the curl script.
  • Linux: runs curl -fsSL https://bun.sh/install | bash.
  • Post-install verification with fallback to ~/.bun/bin/bun (since the bun installer modifies ~/.bashrc / ~/.zshrc, and the same nushell session won't see the new PATH until restarted).
  • Raises an actionable error make if neither which bun nor ~/.bun/bin/bun resolves after the install.

service_books install (extends the existing flow):

  • After cargo build / svc_cargo_install:
    • Resolves the docusaurus directory: <info.path>/crates/hero_books_docusaurus/src/template_files.
    • Skips with explanatory print line if the directory is absent.
    • Skips with explanatory print line if node_modules/ exists and --reset was not passed.
    • Calls install_bun only when which bun is empty.
    • Runs bun install (resolved via which bun or ~/.bun/bin/bun fallback) inside the docusaurus directory.
    • Errors out with stderr if bun install exits non-zero.

Acceptance Criteria — Status

  • install_bun exists in installers.nu, is exported, idempotent.
  • Cross-platform — macOS via brew (or curl fallback) and Linux via curl.
  • Raises clear error when installer succeeds but bun is unreachable.
  • install_core does NOT call install_bun (verified — install_core body unchanged).
  • service_books install on a fresh machine without bun: detects missing bun → calls install_bun → runs bun install in the docusaurus template_files dir.
  • service_books install on a machine with bun and node_modules present: skips both with print lines (idempotent).
  • service_books install --reset re-runs bun install even when node_modules exists (uses the existing --reset flag, no new flag introduced).
  • template_install_bun unchanged.
  • No emojis or attribution in any added code, comments, or output.

Notes / Caveats

  • A live end-to-end run of service_books install against a real hero_books checkout was not done — this is best validated on a target host where the command is actually invoked. Local parse / load checks all pass.
  • The fix to add is_macos / is_linux to the use ../platform.nu [...] import line was needed because the existing install_chrome / install_onnxruntime / install_docker_btrfs functions also call is_macos without it being in scope — a latent bug that would have surfaced on macOS deploys. Fixing it here keeps install_bun correct and patches the existing functions for free.
## Implementation Summary Implemented per the spec above and the maintainer's design feedback. ### Files Changed | File | Change | |---|---| | `tools/modules/installers/installers.nu` | Added `install_bun` function (~38 lines after `install_ai`). Added `is_macos`, `is_linux` to the existing `use ../platform.nu [...]` import. | | `tools/modules/services/service_books.nu` | Added `use ../installers/installers.nu [install_bun]` at the top. Updated `install` docstring. Appended a docusaurus bootstrap block at the end of `install` (~33 lines). | ### Files Intentionally NOT Changed - `installers.nu::install_core` — bun is NOT added (per maintainer feedback: services pull bun on demand). - `installers/template_install.nu::template_install_bun` — left as-is (template-user-only via `template_run` wrapper; not interchangeable with the new reusable installer). - `services/packages.nu` — the commented-out `service_books` entry stays commented; activating `service_install_all` for hero_books is out of scope here. - `services/mod.nu` — already re-exports `service_books`, no changes needed. ### Behavior `install_bun` (reusable, callable from anywhere): - Idempotent — `return`s early with version line if `bun` is already on PATH. - macOS: prefers `brew install oven-sh/bun/bun` if brew is present, otherwise falls through to the curl script. - Linux: runs `curl -fsSL https://bun.sh/install | bash`. - Post-install verification with fallback to `~/.bun/bin/bun` (since the bun installer modifies `~/.bashrc` / `~/.zshrc`, and the same nushell session won't see the new PATH until restarted). - Raises an actionable `error make` if neither `which bun` nor `~/.bun/bin/bun` resolves after the install. `service_books install` (extends the existing flow): - After cargo build / `svc_cargo_install`: - Resolves the docusaurus directory: `<info.path>/crates/hero_books_docusaurus/src/template_files`. - Skips with explanatory print line if the directory is absent. - Skips with explanatory print line if `node_modules/` exists and `--reset` was not passed. - Calls `install_bun` only when `which bun` is empty. - Runs `bun install` (resolved via `which bun` or `~/.bun/bin/bun` fallback) inside the docusaurus directory. - Errors out with stderr if `bun install` exits non-zero. ### Acceptance Criteria — Status - [x] `install_bun` exists in `installers.nu`, is exported, idempotent. - [x] Cross-platform — macOS via brew (or curl fallback) and Linux via curl. - [x] Raises clear error when installer succeeds but `bun` is unreachable. - [x] `install_core` does NOT call `install_bun` (verified — `install_core` body unchanged). - [x] `service_books install` on a fresh machine without bun: detects missing bun → calls `install_bun` → runs `bun install` in the docusaurus template_files dir. - [x] `service_books install` on a machine with bun and `node_modules` present: skips both with print lines (idempotent). - [x] `service_books install --reset` re-runs `bun install` even when `node_modules` exists (uses the existing `--reset` flag, no new flag introduced). - [x] `template_install_bun` unchanged. - [x] No emojis or attribution in any added code, comments, or output. ### Notes / Caveats - A live end-to-end run of `service_books install` against a real hero_books checkout was not done — this is best validated on a target host where the command is actually invoked. Local parse / load checks all pass. - The fix to add `is_macos` / `is_linux` to the `use ../platform.nu [...]` import line was needed because the existing `install_chrome` / `install_onnxruntime` / `install_docker_btrfs` functions also call `is_macos` without it being in scope — a latent bug that would have surfaced on macOS deploys. Fixing it here keeps `install_bun` correct and patches the existing functions for free.
Author
Owner

Closing — implementation landed in PR #137 ("Support bun installer"), merged 2026-04-26 14:49 UTC.

Verified on origin/development:

  • tools/modules/installers/installers.nu:113export def install_bun [] (idempotent; macOS via brew or curl fallback; Linux via curl; ~/.bun/bin/bun post-install fallback).
  • tools/modules/services/service_books.nu:54,217-218service_books install calls install_bun on demand when bun is not on PATH, then runs bun install inside the docusaurus template_files directory.

Per maintainer feedback in the thread, install_core was intentionally not changed — services pull bun on demand. All other acceptance criteria from the implementation summary above are satisfied.

Closing — implementation landed in PR #137 ("Support bun installer"), merged 2026-04-26 14:49 UTC. **Verified on `origin/development`:** - `tools/modules/installers/installers.nu:113` — `export def install_bun []` (idempotent; macOS via brew or curl fallback; Linux via curl; `~/.bun/bin/bun` post-install fallback). - `tools/modules/services/service_books.nu:54,217-218` — `service_books install` calls `install_bun` on demand when `bun` is not on PATH, then runs `bun install` inside the docusaurus `template_files` directory. Per maintainer feedback in the thread, `install_core` was intentionally **not** changed — services pull `bun` on demand. All other acceptance criteria from the implementation summary above are satisfied.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_skills#76
No description provided.