← Back to PRs

#12804: fix(daemon): use wrapper script for pnpm global installs in service config

by odinho open 2026-02-09 18:16 View on GitHub →
gateway stale
## Summary When installing the gateway service via `openclaw gateway install` from a pnpm global install, the CLI was writing the full pnpm store path into the systemd/launchd service config: ``` ExecStart="/home/user/.local/share/pnpm/5/.pnpm/openclaw@2026.2.6-3_abc123.../node_modules/openclaw/openclaw.mjs" gateway --port 18789 ``` This path contains version-specific directories (including a content hash) that change with every pnpm update. After running `pnpm add -g openclaw@latest`, the old path no longer exists, and the service fails to start. ## Problem PR #1505 attempted to fix this by preferring symlinked paths over realpath-resolved paths. However, this doesn't help pnpm global installs because: 1. The wrapper script at `~/.local/bin/openclaw` runs `exec node /full/pnpm/store/path/openclaw.mjs` 2. `process.argv[1]` is already the full versioned path (no symlink involved) 3. `normalized === resolvedPath`, so the symlink preservation logic doesn't trigger ## Solution 1. **Detect pnpm global store paths** - Check if the path contains `/.pnpm/` combined with `/.local/share/pnpm/` 2. **Prefer the wrapper script** - Look for the CLI wrapper at `~/.local/bin/openclaw` (or platform-specific equivalents) 3. **Fall back gracefully** - If the wrapper isn't found, use the original path The wrapper script is the correct choice because pnpm automatically regenerates it with updated paths during package updates. ## Changes - `src/daemon/program-args.ts`: Add `isPnpmGlobalStorePath()` and `resolvePnpmGlobalWrapperPath()` functions - `src/daemon/runtime-paths.ts`: Add `/.pnpm/` to `VERSION_MANAGER_MARKERS` so doctor can warn about it - `src/daemon/program-args.test.ts`: Add test coverage for pnpm global path detection ## Test plan - [x] All existing tests pass - [x] New tests for pnpm global path detection - [x] Lint passes ## Related - PR #1505 - Original symlink preservation fix (works for local pnpm installs, not global) - Issue #6318 - Windows npm upgrade path fragility (similar problem domain) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR updates daemon service argument resolution to avoid embedding pnpm global store paths (which include version/hash segments) into systemd/launchd configs. It adds pnpm-store path detection, attempts to prefer the pnpm-generated wrapper script for global installs, and expands `VERSION_MANAGER_MARKERS` so doctor can warn on `/.pnpm/` paths. Tests were added to cover wrapper preference and fallback behavior. <h3>Confidence Score: 3/5</h3> - This PR is close, but has a likely runtime crash and a Windows-specific parsing bug to address before merge. - The overall approach is reasonable and covered by new tests, but `fs.constants.X_OK` is used off `node:fs/promises` (likely undefined at runtime), and Windows path parsing for extracting the CLI name is unreliable when the path contains `/` separators; both can break wrapper resolution in real installs. - src/daemon/program-args.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs