Skip to content

Resolve expanded package scripts against the directory of their manifest - #2209

Merged
webpro merged 1 commit into
webpro-nl:mainfrom
fixfon:fix/2207-expanded-script-cwd
Oct 25, 2026
Merged

webpro merged 1 commit into
webpro-nl:mainfrom
fixfon:fix/2207-expanded-script-cwd

Conversation

@fixfon

@fixfon fixfon commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #2207

When a script inside a source file runs a package script, for example spawnSync('bun', ['run', 'build']) in scripts/dev/dev.mjs with "build": "bun run build:all" and "build:all": "bun scripts/build.mjs" in package.json, knip expanded the package script but kept the directory of the calling file as the working directory. So scripts/build.mjs was looked up in scripts/dev/ and reported as an unresolved import.

The options for scripts found in source files now carry the workspace directory as manifestDir. expandScript uses it as the working directory of the expanded body and clears it, so a nested expansion (for example after yarn's --cwd) is not pushed back to the workspace root. Scripts written literally in a source file still resolve against that file's directory. Because every package manager resolver goes through expandScript, there is no change per resolver.

The new test uses a fixture with the case from the issue, a workspace-local script chain, and a yarn --cwd chain. On main it reports scripts/build.mjs from scripts/dev/dev.mjs and tasks/pack.mjs from packages/app/dev/dev.mjs as unresolved. With the change it passes, and so do get-inputs-from-scripts.test.ts (35 tests together) and pnpm run ci. With the source change removed and the test kept, it fails again.

I also ran the CLI by hand on small fixtures: bun, pnpm and yarn (nested and shorthand) and npm with -- all reported the false unresolved import on main and are clean now. A script that really points to a missing file is still reported. npm run build:all without -- is not expanded at all today, so I left it alone.

@pkg-pr-new

pkg-pr-new Bot commented Oct 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/knip@2209
npm i https://pkg.pr.new/@knip/language-server@2209
npm i https://pkg.pr.new/@knip/mcp@2209

commit: 7271b06

@webpro webpro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @fixfon, this is a tidy fix. Reproduced #2207 with your fixture: with the source change reverted it reports both scripts/build.mjs and tasks/pack.mjs as unresolved, with it the run is clean.

Carrying the manifest directory on the options and consuming it once in expandScript keeps the change out of the individual package manager resolvers, and clearing it after the first hop is what keeps the yarn --cwd chain in the right package. Nice that the fixture covers that case too.

@webpro
webpro merged commit 9d8464d into webpro-nl:main Oct 25, 2026
32 checks passed
@webpro

webpro commented Oct 29, 2026

Copy link
Copy Markdown
Member

πŸš€ This pull request is included in v6.44.0. See Release 6.44.0 for release notes.

Using Knip in a commercial project? Please consider becoming a sponsor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

πŸ› A script expanded from a nested caller resolves its file paths against the caller directory

2 participants