anomalyco / anomalyco/opencode

core: NpmConfig.load ignores dir/.npmrc when an ancestor has package.json/node_modules (common on Windows)

Open
#44,062 0 comments 0 reactions 1 assignee View on GitHub

@rekram1-node is already working on this.

Since Aug 22, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

NpmConfig.load(dir) (packages/core/src/npm-config.ts) can silently ignore the .npmrc in the requested directory on machines where an ancestor directory contains a package.json or node_modules folder. On Windows this is common: the user profile root (C:\Users\<name>) frequently ends up with both from an accidental install, and opencode's own package cache lives under %LOCALAPPDATA%, inside that profile.

What happens
  1. @npmcli/config finds the project prefix by walking up from cwd until it sees a directory containing package.json or node_modules.
  2. For opencode's plugin/package cache dirs (empty on first install), the walk exits the cache and stops at the polluted ancestor.
  3. The requested directory's .npmrc is never read; the ancestor's (or none) is used instead. When the walk stops at the home directory, its .npmrc also collides with the user config and gets dropped entirely ((same as "user" config, ignored)).
  4. NpmConfig.load maps any internal failure to {}, so installs proceed against the default registry with no diagnostic.

Observed on a real machine: probe with cwd = %TEMP%\npmcfg-X containing registry=https://registry.example.test/:

localPrefix: C:\Users\edogu          <- home, not cwd
flat.registry: https://registry.npmjs.org/
sources: ... (same as "user" config, ignored)=project ...

The five existing tests in packages/core/test/npm-config.test.ts fail on this machine and pass in CI only because /tmp ancestors are clean there — i.e. CI cannot see this bug class.

Impact

Plugin/skill dependency installs configured through a project or cache-adjacent .npmrc (private registries, mirrors) silently hit the default registry on affected Windows setups.

Proposed direction

Pin the synthetic CLI prefix to the requested directory (argv: [..., "--prefix=" + dir]). loadLocalPrefix() short-circuits on a cli prefix, making "read dir/.npmrc as project config" deterministic regardless of ancestors. This matches what callers already assume (Npm.install passes path: dir to Arborist explicitly).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.