Conversation
Adds a new `pnpm clean` command that safely removes node_modules contents from all workspace projects. Uses Node.js fs.rm() which correctly handles NTFS junctions on Windows without following them into their targets, preventing catastrophic data loss. Preserves non-pnpm hidden files (e.g. .cache) and lockfiles by default; use --lockfile/-l to also remove pnpm-lock.yaml files. Also cleans custom virtual-store-dir when configured inside the project root. Closes #10707
…istence before printing - Replace custom isSubdir function with the existing is-subdir package - Only print "Removing" and remove lockfile/virtualStoreDir when they exist - Rethrow non-ENOENT errors instead of swallowing them Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a new pnpm clean command that safely removes node_modules contents from all workspace projects to address catastrophic data loss issues on Windows caused by NTFS junctions when using standard deletion commands like rm -rf or Remove-Item -Recurse. The command uses @zkochan/rimraf which leverages Node.js's fs.rm() to correctly handle junctions without following them into their targets.
Changes:
- Adds
pnpm cleancommand with--lockfileoption to optionally removepnpm-lock.yamlfiles - Implements safe removal that preserves non-pnpm hidden files (e.g.,
.cache) while removing pnpm-specific entries (.pnpm,.bin,.modules.yaml) and regular packages - Handles custom virtual-store-dir configurations when located inside the project root
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm/src/cmd/clean.ts | New command implementation with handler, help text, and helper functions for safe directory removal |
| pnpm/src/cmd/index.ts | Registers the new clean command in the command list |
| pnpm/src/cmd/help.ts | Adds clean command to the advanced commands help section |
| pnpm/test/clean.ts | Comprehensive test suite covering single project, workspace, lockfile handling, and virtual store scenarios |
| pnpm/package.json | Adds is-subdir dependency for path validation |
| pnpm-lock.yaml | Updates lockfile with is-subdir dependency |
| cspell.json | Adds "ntfs" to dictionary for spell checking |
| .changeset/safe-clean-command.md | Documents the new feature for release notes |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…sDirContents - Replace manual fs.access + try/catch with pathExists for cleaner existence checks - Add ENOENT handling to removeModulesDirContents readdir to handle the race where the directory is removed between hasContentsToRemove and readdir Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…emoveLockfile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pnpm clean command for safe node_modules removalpnpm clean command for safe node_modules/lockfile removal
| @@ -0,0 +1,141 @@ | |||
| import { promises as fs } from 'fs' | |||
There was a problem hiding this comment.
Why not import the Promise version of fs directly?
| import { promises as fs } from 'fs' | |
| import fs from 'node:fs/promises' |
There was a problem hiding this comment.
It doesn't make a difference. Currently the way I added it is the way it is used in other places in the repo.
| @@ -0,0 +1,141 @@ | |||
| import { promises as fs } from 'fs' | |||
| import path from 'path' | |||
There was a problem hiding this comment.
Would it generally not be preferred to use the node: prefix for internal modules?
| import path from 'path' | |
| import path from 'node:path' |
There was a problem hiding this comment.
That is not the convention currently used in the repo.
|
See #6816 (comment) I found this new command while maintaining docs translations. I think at least we may need to evaluate the impact by counting the percentage of repos that is using |
|
E.g.: As a Vue Ecoystem maintainer, our main repo vue3 has a clean script: https://github.com/vuejs/core/blob/main/package.json Since Under this point, I would suggest at least change it to |
|
I am not optimistic about the |
|
I think they make a good point; the Perhaps we should consider a more fitting name to avoid any unintended negative effects on some projects. @zkochan |
|
I would suggest keeping all the discussion centralized, there is also a thread on #6816 |
|
@jonkoops Thanks for reminding me, I think I missed it. |
Adds a new
pnpm cleancommand that safely removesnode_modulescontents from all workspace projects. Uses Node.jsfs.rm()which correctly handles NTFS junctions on Windows without following them into their targets, preventing catastrophic data loss. Preserves non-pnpm hidden files (e.g. .cache) and lockfiles by default; use--lockfile/-lto also removepnpm-lock.yamlfiles. Also cleans customvirtual-store-dirwhen configured inside the project root.close #10707
close #6816