Skip to content

bug: embed auto-install cwd resolves into global npm modules root for global installs, breaking install #1720

Description

@carlos-alm

Found during Titan RECON (v3.15.0)

Severity: Medium
Command: codegraph embed -m minilm
Regression of: #1175 (closed)

Reproduction

  1. Install codegraph globally: npm install -g @optave/codegraph (on a machine where npm's global prefix is Homebrew-managed, e.g. /opt/homebrew).
  2. cd into any target repo, run codegraph build . then codegraph embed -m minilm.

Actual behavior

@huggingface/transformers is not found, so promptInstall() runs. resolveNpmInstallCwd() (src/domain/search/models.ts) computes the install cwd as path.dirname(path.dirname(path.dirname(path.dirname(pkgJsonPath)))) where pkgJsonPath is .../node_modules/@optave/codegraph/package.json. For a global install this resolves to the npm global modules root itself, e.g. /opt/homebrew/lib — the same directory that contains node_modules/npm (npm's own installation).

Running npm install --no-save @huggingface/transformers with cwd: /opt/homebrew/lib fails:

npm error code MODULE_NOT_FOUND
npm error Cannot find module 'node-gyp/bin/node-gyp.js'
npm error Require stack:
npm error - /opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
...

Reproduced directly (no codegraph involved) with:

cd /opt/homebrew/lib && npm install --no-save @huggingface/transformers

— same error. This confirms it's npm's own internal lifecycle-script machinery breaking when asked to install into its own global modules root, not something codegraph can control once it targets that directory.

Confirmed the target project's local node_modules/@huggingface/transformers being already present and resolvable (require.resolve succeeds) makes no difference — the globally-installed codegraph binary never looks there, only at its own resolved install root.

Expected behavior

Auto-install for a globally-installed codegraph should not attempt to write into npm's own global modules root. Options:

  1. Detect the global-install case (e.g. pkgJsonPath sits under the npm global prefix — compare against npm root -g or check if the resolved dir contains node_modules/npm) and skip straight to the "install it manually" instructions instead of attempting an auto-install.
  2. Or, when a global install is detected, prefer installing into a per-user cache/support directory added to NODE_PATH for the transformers dynamic import, rather than colliding with npm's own installation tree.
  3. At minimum, catch this failure mode and give actionable guidance ("codegraph is installed globally; run npm install -g @huggingface/transformers yourself") rather than a generic Auto-install ... failed + ENGINE_UNAVAILABLE.

Root cause

resolveNpmInstallCwd() in src/domain/search/models.ts assumes dirname(pkgJsonPath, 4) is always a normal project root. For a global npm install, that directory is the npm global prefix's lib/ (or equivalent), which already contains npm's own installation and is not a safe target for arbitrary npm install side effects.

Impact

Any user who installs codegraph globally via npm install -g (a documented/common install path) on a machine where the global npm prefix has this npm packaging quirk (observed via Homebrew's Node/npm on macOS) cannot use codegraph embed at all — semantic search and DRY-detection features silently degrade to unavailable, with no way to work around it short of manually fixing the global npm installation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions