← Back to PRs

#15475: fix(update): Handle Homebrew+Node Cellar path mismatch

by brandonwise open 2026-02-13 14:11 View on GitHub →
stale size: S
## Problem On Homebrew-installed Node.js, there's a path mismatch that causes `gateway update.run` to install to the wrong location: 1. Binary at `/opt/homebrew/Cellar/node/X.Y.Z/bin/openclaw` is a symlink to `../lib/node_modules/openclaw/openclaw.mjs` (Cellar path) 2. But `npm root -g` returns `/opt/homebrew/lib/node_modules` (not Cellar) 3. So `npm i -g openclaw@latest` installs to the wrong location 4. The actual binary still points to the old version **Symptoms:** - `openclaw --version` shows old version after update - User must manually run: `cd /opt/homebrew/Cellar/node/X.Y.Z/lib/node_modules && npm install openclaw@latest` ## Solution 1. **Detect Cellar paths** in `detectGlobalInstallManagerForRoot`: - Check if pkgRoot matches the Homebrew Cellar pattern - Return `npm` as manager even though paths don't match `npm root -g` 2. **Add `globalInstallArgsForCellar`**: - Generate `npm install --prefix <cellar-lib> openclaw@latest` instead of `npm i -g` - Targets the Cellar's node_modules directly 3. **Update runner uses Cellar args**: - When pkgRoot is a Cellar path, use the Cellar install args - Step name shows "(homebrew cellar)" for clarity ## Testing - Existing tests pass (13 tests in update-runner.test.ts) - Lint passes - Manually verified the path detection logic matches the Homebrew structure ## Related This issue is documented in our setup notes. The workaround was to manually install to the Cellar path. This PR automates that workaround. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adjusts global-update behavior to handle Homebrew Node “Cellar” installs where the `openclaw` binary symlink points into a versioned Cellar `lib/node_modules`, while `npm root -g` points to the non-Cellar prefix. It adds a Homebrew Cellar detection path in `detectGlobalInstallManagerForRoot`, introduces `globalInstallArgsForCellar` to install via `npm install --prefix <cellar-lib> ...`, and updates `runGatewayUpdate` to use those args and label the step accordingly. <h3>Confidence Score: 3/5</h3> - This PR is close to safe to merge, but has a real risk of selecting the wrong global manager on some systems. - Most changes are localized and align with the described Homebrew Cellar mismatch, but the new Cellar fallback in `detectGlobalInstallManagerForRoot` can return `pnpm` based solely on the path shape. If pnpm is installed and `pnpm root -g` succeeds, updates can run the wrong command and fail to update the intended install. - src/infra/update-global.ts <sub>Last reviewed commit: 2c1ae34</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs