Resolves locally-installed tool binaries and package-script runners without assuming npm.
Delegating to npx silently assumes an npm-installed tree. On Windows that assumption is fatal under bun: bun install writes node_modules/.bin/<tool>.exe, not the <tool>.cmd that npm’s npx looks for, so npx misses the local install entirely and downloads the tool from the registry instead — which for tsc is the well-known decoy package, not TypeScript. Resolving the shim from node_modules/.bin ourselves sidesteps the whole shim-format question, because every package manager writes one there.
| Function | Description |
|---|
| getPackageManager | Determines which package manager owns the project’s dependency tree. Every signal is collected before any of them is believed, because a repo carrying two lockfiles used to resolve to whichever sat earlier in a fixed list — silently reassigning every package script and every tool invocation to a manager that never installed the tree. The order is: 1. The packageManager field of package.json. It is a deliberate declaration by the repo’s author rather than an artifact left behind by whatever ran last, so it outranks every lockfile — and it is the only signal that helps at all before the first install, when no lockfile exists yet. 2. The sole lockfile, when exactly one manager claims the tree. 3. Among several lockfiles, the manager that launched us (npm_config_user_agent), when it owns one of them — a live signal beats a file that may have been abandoned mid-migration. Otherwise the documented fallback order in LOCKFILES decides. Note this is deliberately NOT “the most recently modified lockfile”: a stray lockfile is typically the newest file, so mtime picks precisely the wrong one. 4. npm_config_user_agent on its own, when there is no lockfile. 5. PackageManager.Npm. Whenever more than one manager claims the tree, the disagreement is reported once per project through warnAboutSeveralClaimants — the resolution stays deterministic, but it stops being silent. |
| getPackageManagerRunCommand | Builds the command parts that run a package script through the manager that owns the tree. |
| resolveToolCommand | Builds the command parts that run a locally-installed tool, with the tool itself already included. Prefers the shim in the nearest node_modules/.bin, walking up through ancestor folders so a hoisted workspace install is still found. Falls back to the owning manager’s exec form when no shim resolves — which is both the previous behavior and the only thing that works under yarn’s Plug’n’Play, where node_modules/.bin does not exist at all. |
| Enum | Description |
|---|
| PackageManager | A package manager that can own a project’s dependency tree. |