Skip to content

feat: replace bun with deno for npm tools and runtime#186

Draft
fredrikaverpil wants to merge 4 commits into
mainfrom
claude/deno-package-tools
Draft

feat: replace bun with deno for npm tools and runtime#186
fredrikaverpil wants to merge 4 commits into
mainfrom
claude/deno-package-tools

Conversation

@fredrikaverpil

@fredrikaverpil fredrikaverpil commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Why?

  • Try deno as the JS runtime to play better with Nix: npm CLIs run inside deno's Node compat layer instead of as standalone node binaries, removing the dynamic-linking issue that kept packageTools.npmPackages macOS-only.
  • Unlike bun/bunx, deno is now actually on PATH everywhere (home.packages), so MCP configs no longer depend on an environment that happens to provide the runner.

What?

  • nix/shared/home/package-tools.nix: install via deno install --global --allow-all --name <bin> npm:<pkg>; shims in ~/.deno/bin
  • packageTools.npmPackages entries are now { package, bin } — shim names come from the package.json bin field and can't be derived (@googleworkspace/cligws); also fixes the install check, which looked for the wrong filename and reinstalled on every rebuild
  • Render an npm-tools-upgrade script from the declared package list (deno has no bun update -g); rebuild.sh --update/--update-unstable calls it
  • Drop the Darwin-only guards so npm tools install on Linux/NixOS too
  • Stow configs: bunxdeno run -A npm:<pkg> (gemini, copilot, opencode); code_runner runs TS via deno run -A; pi npmCommandnpm (deno is not argv-compatible with the npm CLI)
  • Evict remaining bun: dev shell, nvim-deps PATH, stale npm-tools/ gitignore entry; docs updated
packageTools.npmPackages = [
  { package = "@google/gemini-cli"; bin = "gemini"; }
];

Notes

  • No nix in the dev container — relying on CI + a local ./rebuild.sh on a Mac to validate that gemini, codex and pi actually work under deno's Node compat. Test on rpi5-homelab before declaring npm tools in Linux configs; revert the "enable on Linux" commit if they misbehave there.
  • Deno shims hardcode the Nix store path of the deno that installed them: after a GC that removes an old generation, a shim can go stale while the presence check still says "already installed". Re-running npm-tools-upgrade re-creates the shims.
  • pi's npmCommand: ["npm"] relies on npm from nodejs (nvim-deps PATH) — the same availability domain bun had, but worth a sanity check in a pi session.
  • Playwright MCP under deno may need PLAYWRIGHT_BROWSERS_PATH verified when it downloads/locates browsers.

@fredrikaverpil
fredrikaverpil force-pushed the claude/deno-package-tools branch 2 times, most recently from e2a2bb0 to 9381f85 Compare July 13, 2026 07:57
Deno's runtime executes the npm CLIs directly, which paves the way for
enabling packageTools.npmPackages on NixOS (bun/node binaries had
dynamic linking issues there). The Darwin-only guard stays in place
until the tools are validated under Deno's Node compatibility layer.

npmPackages entries are now { package, bin } attrsets: shim names come
from the package.json "bin" field and cannot be derived from the
package name (@googleworkspace/cli installs "gws"). This also fixes
the install check, which previously looked for the wrong filename and
reinstalled every package on each rebuild.

Deno has no equivalent of `bun update -g`, so the module renders an
npm-tools-upgrade script from the declared package list, and rebuild.sh
calls it on --update/--update-unstable. deno is also added to
home.packages so the runtime is on PATH everywhere, which bun never
was.
With deno as the installer/runtime, the npm CLIs run inside deno's
Node compatibility layer instead of as standalone node binaries, so
the NixOS dynamic-linking restriction no longer applies. Drop the
Darwin guards from PATH, the upgrade helper, and the activation
script, and remove the macOS-only gotcha from the docs.

Needs validation on rpi5-homelab before declaring any npm tools in
Linux/NixOS configs; revert this commit if the tools misbehave there.
MCP servers (gemini, copilot, opencode) now launch via
`deno run -A npm:<pkg>` instead of bunx, and code_runner runs
TypeScript through deno directly. Unlike bunx, deno is guaranteed on
PATH since it is in home.packages.

pi's npmCommand must be argv-compatible with the npm CLI (`<cmd>
install <pkg>`), which deno is not, so pi falls back to npm (available
where nodejs is on PATH, e.g. the nvim-deps environment) — same
availability domain bun had.

Also update the Claude instructions to prefer deno over npm/bunx.
Swap bun for deno in the dotfiles-toolchain dev shell, drop bun from
the nvim-only tool PATH (deno is on the regular PATH via
home.packages, so Neovim inherits it), and delete the stale
npm-tools/ gitignore entry left over from the pre-Nix npm-tools setup.
@fredrikaverpil
fredrikaverpil force-pushed the claude/deno-package-tools branch from 9381f85 to 4ebf7c4 Compare July 17, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant