Running npm scripts in VS Code when package.json isn’t in the project root
You open a repository where there’s no package.json at the top level. The front end lives in ui/, a couple of tools in ui/tools/, a backend in another folder. You look for the NPM Scripts view in the Explorer, and it isn't there.
Get Alex’s stories in your inbox
Join Medium for free to get updates from this writer.
That’s the situation in microsoft/vscode#119868, open since March 2021 with 33 👍 and 24 comments. The reporter’s tree:
project-folder
|-- backend1
|-- backend2
|-- static
\-- ui
|-- src
|-- tools
| |-- tool1/package.json
| \-- tool2/package.json
\-- package.jsonTheir finding: the view doesn’t show up until they open one of the three package.json files. Then it lists all three and their scripts. Setting npm.autoDetect to "on" in user and workspace settings didn't change it.
Workarounds that work today
- Open one of the nested
package.jsonfiles. That's what the reporter found, and it makes the view appear. - Run the script in a terminal.
cd ui && npm run devalways works. - Open the nested folder as the workspace. If you mostly work in
ui/, File → Open Folder… on that folder makes it the root, and everything in the view is relative to it. - Define tasks. A
.vscode/tasks.jsonwith"options": { "cwd": "${workspaceFolder}/ui" }gives each script a stable entry under Terminal → Run Task. It's manual work, one entry per script.
Related reports cover the monorepo side: a yarn command being used in a pnpm monorepo (#155555) and an install script appearing in every non-root package (#149924).
Listing nested scripts without a view
I maintain Slashi, a free VS Code extension that lists a project’s scripts in its popup (press Cmd/Ctrl /, then /p ). It doesn't use the NPM Scripts view; it scans the workspace itself:
- It looks for manifest files (
package.json,Makefile,justfile,Cargo.toml,go.modand more) anywhere in the workspace, skippingnode_modules,dist,build,vendorand similar folders. It keeps the first 40 folders it finds. - Each script is labeled with its folder and runs with that folder as the working directory.
- The package manager comes from the
packageManagerfield, then the lockfile in the package's folder, then the one in the workspace root.
To check this against the reporter’s tree, I ran Slashi’s detection function on that exact structure. I added a pnpm-lock.yaml at the root, since the issue doesn't say which package manager they use, and made up scripts for each package:
/ui:dev pnpm: dev — ui cwd=ui → pnpm run dev
/ui:build pnpm: build — ui cwd=ui → pnpm run build
/ui:test pnpm: test — ui cwd=ui → pnpm run test
/tool1:generate pnpm: generate — ui/tools/tool1 cwd=ui/tools/tool1 → pnpm run generate
/tool2:lint pnpm: lint — ui/tools/tool2 cwd=ui/tools/tool2 → pnpm run lintEvery package’s scripts are listed without opening any file, each runs in its own folder, and the root’s pnpm-lock.yaml decides the package manager. This is the function's output (spacing tidied) from a direct call with that tree, not a recording of the editor. The popup builds its list from the same function.
Limits
- It’s not the NPM Scripts view. There’s no tree, no debug button and no
npm.autoDetect. If you want those, use the workarounds above. - The scan is capped at 40 folders. A monorepo with more packages than that gets cut off, so some packages’ scripts won’t be listed.
- Package manager. A
packageManagerfield in the package'spackage.jsonwins, then a lockfile in its folder, then one in the workspace root. If none of those exist, Slashi assumes npm. - The detection is read-only. It never runs your scripts until you pick one.
Takeaway
If the NPM Scripts view is missing, open any nested package.json first. For repositories where you want every script from every package in one searchable list, a launcher that scans the whole workspace is a reasonable fit.
I’m the author of Slashi. It’s free and MIT-licensed: Marketplace · Open VSX · GitHub.







