From 4d67cce6e115ad9e3c9874c9461cc3ec398e9ed1 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 04:14:24 -0600 Subject: [PATCH] =?UTF-8?q?##=20CHANGES=20-=20Enforced=20strict=20Node=20v?= =?UTF-8?q?ersioning=20with=20`.npmrc`=20engine-strict=20enabled=20?= =?UTF-8?q?=E2=9A=99=EF=B8=8F=20-=20Declared=20Node.js=20>=3D20=20requirem?= =?UTF-8?q?ent=20via=20`package.json`=20engines=20field=20=F0=9F=9A=80=20-?= =?UTF-8?q?=20Added=20early=20WSL2=20environment=20checks=20during=20app?= =?UTF-8?q?=20startup=20=F0=9F=95=B5=EF=B8=8F=20-=20Introduced=20WSL=20det?= =?UTF-8?q?ector=20utility=20to=20identify=20WSL=20and=20cache=20results?= =?UTF-8?q?=20=F0=9F=A7=A0=20-=20Detects=20`/mnt/`=20Windows-mount?= =?UTF-8?q?=20paths=20to=20prevent=20common=20breakages=20=F0=9F=A7=AD=20-?= =?UTF-8?q?=20Emits=20clear=20warnings=20for=20WSL=20mount=20risks:=20sock?= =?UTF-8?q?ets,=20Electron,=20npm,=20git=20=F0=9F=94=A5=20-=20Added=20user?= =?UTF-8?q?-friendly=20WSL=20warning=20message=20with=20fix=20steps=20and?= =?UTF-8?q?=20docs=20link=20=F0=9F=93=A3=20-=20Expanded=20installation=20d?= =?UTF-8?q?ocs=20with=20WSL2=20best-practice=20cloning=20guidance=20?= =?UTF-8?q?=F0=9F=93=98=20-=20Added=20troubleshooting=20playbook=20for=20W?= =?UTF-8?q?SL2=20errors=20and=20proven=20remedies=20=F0=9F=9B=A0=EF=B8=8F?= =?UTF-8?q?=20-=20Polished=20File=20Explorer=20status=20bar=20styling=20wi?= =?UTF-8?q?th=20rounded=20bordered=20container=20=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .npmrc | 1 + docs/installation.md | 46 +++++++++ docs/troubleshooting.md | 57 ++++++++++++ package.json | 3 + src/main/index.ts | 4 + src/main/utils/wslDetector.ts | 93 +++++++++++++++++++ src/renderer/components/FileExplorerPanel.tsx | 4 +- 7 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 .npmrc create mode 100644 src/main/utils/wslDetector.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..b6f27f13 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/docs/installation.md b/docs/installation.md index 24091423..07e16af8 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -20,3 +20,49 @@ Download the latest release for your platform from the [Releases](https://github - [OpenAI Codex](https://github.com/openai/codex) - OpenAI's coding agent - [OpenCode](https://github.com/sst/opencode) - Open-source AI coding assistant - Git (optional, for git-aware features) + +## WSL2 Users (Windows Subsystem for Linux) + + +When developing or running Maestro with WSL2, always clone and run from the **native Linux filesystem** (e.g., `/home/username/maestro`), NOT from Windows-mounted paths (`/mnt/c/...`, `/mnt/d/...`). + + +Using Windows mounts causes several critical issues: + +| Issue | Symptom | +|-------|---------| +| Socket binding failures | `EPERM: operation not permitted` when starting dev server | +| Electron sandbox crashes | `FATAL:sandbox_host_linux.cc` errors | +| npm install failures | Timeouts, `ENOTEMPTY` rename errors | +| Git corruption | Missing index files, spurious lock files | + +### Recommended WSL2 Setup + +```bash +# Clone to Linux filesystem (not /mnt/...) +cd ~ +git clone https://github.com/pedramamini/maestro.git +cd maestro + +# Install dependencies +npm install + +# Run in development mode +npm run dev +``` + +### Accessing Files from Windows + +You can browse your WSL2 files from Windows Explorer using: +``` +\\wsl$\Ubuntu\home\\maestro +``` + +### Troubleshooting WSL2 + +If you encounter `electron-rebuild` failures, try setting the temp directory: +```bash +TMPDIR=/tmp npm run rebuild +``` + +For persistent issues, see [Troubleshooting](./troubleshooting) for additional WSL-specific guidance diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 7e1384de..953d973c 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -78,6 +78,63 @@ The debug package is designed to be **safe to share publicly**: - Before: `/Users/johndoe/Projects/MyApp` - After: `~/Projects/MyApp` +## WSL2 Issues (Windows) + +If you're running Maestro through WSL2, most issues stem from using Windows-mounted paths. See the [WSL2 installation guide](./installation#wsl2-users-windows-subsystem-for-linux) for the recommended setup. + +### Common WSL2 Problems + +**"EPERM: operation not permitted" on socket binding** + +The Vite dev server or Electron cannot bind to ports when running from `/mnt/...` paths. + +**Solution:** Move your project to the native Linux filesystem: +```bash +mv /mnt/c/projects/maestro ~/maestro +cd ~/maestro +npm install +npm run dev +``` + +**"FATAL:sandbox_host_linux.cc" Electron crash** + +The Electron sandbox cannot operate correctly on Windows-mounted filesystems. + +**Solution:** Run from the Linux filesystem (`/home/...`), not from `/mnt/...`. + +**npm install timeouts or ENOTEMPTY errors** + +Cross-filesystem operations between WSL and Windows are unreliable for npm's file operations. + +**Solution:** Clone and install from the Linux filesystem: +```bash +cd ~ +git clone https://github.com/pedramamini/maestro.git +cd maestro +npm install +``` + +**electron-rebuild failures** + +The Windows temp directory may be inaccessible from WSL. + +**Solution:** Override the temp directory: +```bash +TMPDIR=/tmp npm run rebuild +``` + +**Git index corruption or lock file errors** + +NTFS and Linux inode handling are incompatible, causing git metadata issues. + +**Solution:** If you see "missing index" or spurious `.git/index.lock` errors: +```bash +rm -f .git/index.lock +git checkout -f +``` + +For new projects, always clone to the Linux filesystem from the start. + ## Getting Help - **GitHub Issues**: [Report bugs or request features](https://github.com/pedramamini/Maestro/issues) diff --git a/package.json b/package.json index 6dbc85c4..05b5ffbb 100644 --- a/package.json +++ b/package.json @@ -289,5 +289,8 @@ "vite": "^5.0.11", "vite-plugin-electron": "^0.28.2", "vitest": "^4.0.15" + }, + "engines": { + "node": ">=20.0.0" } } diff --git a/src/main/index.ts b/src/main/index.ts index 4aebd209..084a377e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -24,6 +24,7 @@ import { DEMO_MODE, DEMO_DATA_PATH } from './constants'; import type { SshRemoteConfig } from '../shared/types'; import { initAutoUpdater } from './auto-updater'; import { readDirRemote, readFileRemote, statRemote, directorySizeRemote } from './utils/remote-fs'; +import { checkWslEnvironment } from './utils/wslDetector'; // ============================================================================ // Custom Storage Location Configuration @@ -738,6 +739,9 @@ app.whenReady().then(async () => { logLevel }); + // Check for WSL + Windows mount issues early + checkWslEnvironment(process.cwd()); + // Initialize core services logger.info('Initializing core services', 'Startup'); processManager = new ProcessManager(); diff --git a/src/main/utils/wslDetector.ts b/src/main/utils/wslDetector.ts new file mode 100644 index 00000000..93ef5359 --- /dev/null +++ b/src/main/utils/wslDetector.ts @@ -0,0 +1,93 @@ +import * as fs from 'fs'; +import { logger } from './logger'; + +/** + * WSL (Windows Subsystem for Linux) environment detection utilities. + * + * When running in WSL2, using Windows-mounted paths (/mnt/c, /mnt/d, etc.) + * causes critical issues with Electron, socket binding, npm, and git. + * These utilities help detect and warn about such configurations. + */ + +let wslDetectionCache: boolean | null = null; + +/** + * Detect if the current environment is WSL (Windows Subsystem for Linux). + * Result is cached after first call. + */ +export function isWsl(): boolean { + if (wslDetectionCache !== null) { + return wslDetectionCache; + } + + if (process.platform !== 'linux') { + wslDetectionCache = false; + return false; + } + + try { + if (fs.existsSync('/proc/version')) { + const version = fs.readFileSync('/proc/version', 'utf8').toLowerCase(); + wslDetectionCache = version.includes('microsoft') || version.includes('wsl'); + return wslDetectionCache; + } + } catch { + // Ignore read errors + } + + wslDetectionCache = false; + return false; +} + +/** + * Check if a path is on a Windows-mounted filesystem in WSL. + * Windows mounts are typically at /mnt/c, /mnt/d, etc. + */ +export function isWindowsMountPath(filepath: string): boolean { + return /^\/mnt\/[a-zA-Z](\/|$)/.test(filepath); +} + +/** + * Check if running from a Windows mount in WSL and log a warning. + * This should be called early in the application lifecycle. + * + * @param cwd - The current working directory to check + * @returns true if running from a problematic Windows mount path + */ +export function checkWslEnvironment(cwd: string): boolean { + if (!isWsl()) { + return false; + } + + if (isWindowsMountPath(cwd)) { + logger.warn( + '[WSL] Running from Windows mount path - this may cause socket binding failures, ' + + 'Electron sandbox crashes, npm install issues, and git corruption. ' + + 'Consider moving your project to the Linux filesystem (e.g., ~/projects/maestro).', + 'WSLDetector', + { cwd } + ); + return true; + } + + logger.debug('[WSL] Running from Linux filesystem - OK', 'WSLDetector', { cwd }); + return false; +} + +/** + * Get a user-friendly warning message for WSL + Windows mount issues. + */ +export function getWslWarningMessage(): string { + return ( + 'You appear to be running Maestro from a Windows-mounted path in WSL2. ' + + 'This configuration causes critical issues including:\n\n' + + '• Socket binding failures (dev server won\'t start)\n' + + '• Electron sandbox crashes\n' + + '• npm install failures\n' + + '• Git index corruption\n\n' + + 'Please move your project to the Linux filesystem:\n' + + ' mv /mnt/c/projects/maestro ~/maestro\n' + + ' cd ~/maestro && npm install\n\n' + + 'See: https://docs.runmaestro.ai/installation#wsl2-users-windows-subsystem-for-linux' + ); +} diff --git a/src/renderer/components/FileExplorerPanel.tsx b/src/renderer/components/FileExplorerPanel.tsx index 7d664fd8..eededd73 100644 --- a/src/renderer/components/FileExplorerPanel.tsx +++ b/src/renderer/components/FileExplorerPanel.tsx @@ -650,10 +650,10 @@ function FileExplorerPanelInner(props: FileExplorerPanelProps) { {/* Status bar at bottom */} {session.fileTreeStats && (