From 7fa10cd954eb071d5c57a7016c7049b9a1431c3e Mon Sep 17 00:00:00 2001 From: 7418 <7418@openclaw.ai> Date: Fri, 27 Feb 2026 15:17:53 +0800 Subject: [PATCH] fix: macOS Node.js install fallback when Homebrew is unavailable, bump v0.17.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: - Install wizard on macOS failed with "Homebrew not found" when user didn't have Homebrew installed, blocking Claude Code installation entirely Fix (electron/main.ts): - Add fallback: when Homebrew is not found, download official Node.js v22.12.0 binary tarball from nodejs.org and extract to ~/.codepilot/node/ - No Homebrew or sudo required — curl + tar only - Detects architecture (arm64/x64) via process.arch - Add ~/.codepilot/node/bin to getExpandedShellPath() so the downloaded Node.js is found by subsequent install steps and server launcher Install flow now: Homebrew found → brew install node (existing) Homebrew missing → download tarball to ~/.codepilot/node/ (new) Co-Authored-By: Claude Opus 4.6 --- electron/main.ts | 25 ++++++++++++++++--------- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/electron/main.ts b/electron/main.ts index 03ea452..9925665 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -199,7 +199,7 @@ function getExpandedShellPath(): string { return [...new Set(allParts)].join(sep); } else { const basePath = `/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin`; - const raw = `${basePath}:${home}/.npm-global/bin:${home}/.local/bin:${home}/.claude/bin:${shellPath}`; + const raw = `${basePath}:${home}/.npm-global/bin:${home}/.local/bin:${home}/.claude/bin:${home}/.codepilot/node/bin:${shellPath}`; const allParts = raw.split(':').filter(Boolean); return [...new Set(allParts)].join(':'); } @@ -528,17 +528,24 @@ app.whenReady().then(async () => { let args: string[]; if (isMac) { - // Try Homebrew + // Try Homebrew first, fallback to official tarball download const brewPaths = ['/opt/homebrew/bin/brew', '/usr/local/bin/brew']; const brewPath = brewPaths.find(p => fs.existsSync(p)); - if (!brewPath) { - addLog('Homebrew not found. Cannot auto-install Node.js on macOS without Homebrew.'); - resolve(false); - return; + if (brewPath) { + cmd = brewPath; + args = ['install', 'node']; + addLog(`Running: ${brewPath} install node`); + } else { + // Fallback: download official Node.js binary tarball (no Homebrew/sudo needed) + const arch = process.arch === 'arm64' ? 'arm64' : 'x64'; + const nodeVersion = 'v22.12.0'; + const nodeDir = path.join(home, '.codepilot', 'node'); + const tarballUrl = `https://nodejs.org/dist/${nodeVersion}/node-${nodeVersion}-darwin-${arch}.tar.gz`; + addLog(`Homebrew not found. Downloading Node.js ${nodeVersion} from nodejs.org...`); + addLog(`Architecture: ${arch}, Target: ${nodeDir}`); + cmd = 'sh'; + args = ['-c', `mkdir -p "${nodeDir}" && curl -fsSL "${tarballUrl}" | tar xz --strip-components=1 -C "${nodeDir}"`]; } - cmd = brewPath; - args = ['install', 'node']; - addLog(`Running: ${brewPath} install node`); } else if (isWin) { cmd = 'winget'; args = ['install', '-e', '--id', 'OpenJS.NodeJS.LTS', '--accept-source-agreements', '--accept-package-agreements']; diff --git a/package-lock.json b/package-lock.json index d6ac675..b38a8af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codepilot", - "version": "0.17.5", + "version": "0.17.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codepilot", - "version": "0.17.5", + "version": "0.17.6", "dependencies": { "@ai-sdk/anthropic": "^3.0.47", "@ai-sdk/google": "^3.0.31", diff --git a/package.json b/package.json index e0ece37..d84e66e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codepilot", - "version": "0.17.5", + "version": "0.17.6", "private": true, "author": { "name": "op7418",