Skip to content

fix(install): stop mise-node shadowing + JS CLI duplicate sprawl - #21

Draft
yulonglin wants to merge 1 commit into
mainfrom
worktree-fix-node-npm-dedupe
Draft

fix(install): stop mise-node shadowing + JS CLI duplicate sprawl#21
yulonglin wants to merge 1 commit into
mainfrom
worktree-fix-node-npm-dedupe

Conversation

@yulonglin

Copy link
Copy Markdown
Owner

Problem

Audit on the Linux box (2026-07-19) found the JS toolchain had drifted into duplicate sprawl:

  • npm resolved 4 ways: socket npm alias → mise node 24.18.0 (~/.local/share/mise) → distro /usr/bin/npm 9.2 → /bin/npm usr-merge dup. Plus an orphaned mise node 20.20.0.
  • codex installed 4 times: ~/.npm-global/bin (0.144.5, wins on PATH) → ~/.bun/bin (0.144.1, the one the daily updater maintains) → ~/.local/bin native standalone (0.144.3) → stale root-owned /usr/local/bin (Jan 2026).
  • System node stuck on stock Ubuntu 18.19.1 even though the NodeSource repo was configured with candidate 24.18.0.

Root causes

  1. install_node's skip-guard read node -v from PATH, so a mise-installed node 24 (manual drift — the repo convention says node is NodeSource/brew, never mise) satisfied the guard forever and the apt node never got upgraded.
  2. update-ai-tools runs bun add -g blind to PATH shadowing: ~/.npm-global/bin precedes ~/.bun/bin, so daily codex updates silently never took effect.

Fixes

  • system_node_path(): guard now checks the system node (/usr/bin/node, brew paths) — the one cron/systemd/shebangs actually resolve.
  • evict_mise_node(): converges any mise-managed node out (mise unuse -g + mise uninstall --all, flags verified against mise --help), but only once a healthy system node exists so it never deletes the box's only modern node.
  • dedupe_bun_shadows() in update-ai-tools: after each bun update, removes ~/.npm-global/bin duplicates (via npm uninstall -g with explicit prefix; ~/.npm-global remains the home for socket-cli only) and flags root-owned /usr/local/bin strays for manual sudo removal.
  • CLAUDE.md: documents the guard change, mise eviction, the "one home per JS CLI = bun global" convention, and that bun add -g X@latest lagging npm by ~7 days is the bunfig minimumReleaseAge quarantine working as intended, not a bug.

Not in this PR (needs sudo on the box)

sudo apt-get install -y nodejs   # NodeSource repo already configured; upgrades 18.19.1 → 24.18.0
mise unuse -g node && mise uninstall --all node
sudo rm /usr/local/bin/codex && sudo rm -rf /usr/local/lib/node_modules/@openai/codex
hash -r

Verdict on "retire mise?": no — mise correctly owns the 14+ fast-moving CLI tools (fzf, bat, rg, delta…) that apt ships years stale. The problem was node leaking into mise and JS CLIs having three homes; this PR enforces one owner per tool class instead.

https://claude.ai/code/session_01XNuZxDGsWjB5rMwHKUAYai

Audit on the Linux box found `npm` resolving 4 ways (socket alias, mise
node 24, distro /usr/bin/npm 9.2, usr-merge dup) and `codex` installed 4
times, with the PATH winner (~/.npm-global, 0.144.5) shadowing the bun
copy the daily updater maintained — so updates silently never took
effect. Root causes and fixes:

- install_node's skip-guard read `node -v` from PATH, so a mise-installed
  node 24 masked the stock Ubuntu node 18 forever (NodeSource repo was
  configured, candidate 24.18.0 never installed). Guard now checks the
  system node via system_node_path() (/usr/bin/node, brew paths), and
  evict_mise_node() converges any mise-managed node out once a healthy
  system node exists (mise unuse -g + mise uninstall --all; flags
  verified against mise --help).

- update-ai-tools updated the bun copy blind to PATH shadowing. New
  dedupe_bun_shadows() removes ~/.npm-global/bin duplicates after each
  bun update (via npm uninstall -g with explicit prefix) and flags
  root-owned strays in /usr/local/bin for manual sudo removal.

- CLAUDE.md: document system-node guard, mise eviction, and the "one
  home per JS CLI = bun global" convention; Learnings entry records the
  audit, incl. that bun add -g lags npm ~7 days by design (bunfig
  minimumReleaseAge quarantine), so bun-vs-npm version gaps are not bugs.

Claude-Session: https://claude.ai/code/session_01XNuZxDGsWjB5rMwHKUAYai
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0b2140b-db29-4e26-9532-7f6f059d54c9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-fix-node-npm-dedupe

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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