[{"data":1,"prerenderedAt":58},["ShallowReactive",2],{"blog-en-clean-project-build-artifacts":3},{"meta":4,"html":14,"headings":15,"raw":57},{"title":5,"description":6,"topic":7,"date":8,"author":9,"icons":10},"How to Bulk-Clean node_modules, target, and build Folders in Old Projects","Find regenerable dependency and build folders in old projects, clean them in bulk with commands or WashBear, and keep virtualenvs and tracked files safe.","developer-cleanup","2026-10-29","WashBear Team",[11,12,13],"folder-x","code","scrub-brush","\u003Cp>Measure an old project and you will often find a few dozen megabytes of source code next to hundreds of megabytes, or several gigabytes, of \u003Ccode>node_modules\u003C\u002Fcode>, Rust \u003Ccode>target\u003C\u002Fcode>, or Gradle \u003Ccode>build\u003C\u002Fcode> output. With enough projects, these regenerable folders become the largest thing on your disk. This guide helps you decide which folders are safe to delete, shows how to find them in bulk from the command line, and explains how WashBear protects your projects when it cleans them for you.\u003C\u002Fp>\n\u003Ch2 id=\"what-can-be-regenerated\">\u003Ca class=\"heading-anchor\" href=\"#what-can-be-regenerated\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Which folders can be regenerated\u003C\u002Fh2>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Ecosystem\u003C\u002Fth>\u003Cth>Common folders\u003C\u002Fth>\u003Cth>How to restore\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd>Node.js\u003C\u002Ftd>\u003Ctd>\u003Ccode>node_modules\u003C\u002Fcode>, \u003Ccode>.next\u002Fcache\u003C\u002Fcode>, \u003Ccode>.nuxt\u003C\u002Fcode>, \u003Ccode>.turbo\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>npm ci\u003C\u002Fcode>, \u003Ccode>pnpm install\u003C\u002Fcode>, or \u003Ccode>yarn install\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Rust\u003C\u002Ftd>\u003Ctd>\u003Ccode>target\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>cargo build\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Gradle, Android\u003C\u002Ftd>\u003Ctd>\u003Ccode>build\u003C\u002Fcode>, \u003Ccode>.gradle\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Build again\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Maven\u003C\u002Ftd>\u003Ctd>\u003Ccode>target\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Build again\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Swift Package\u003C\u002Ftd>\u003Ctd>\u003Ccode>.build\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>swift build\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>CocoaPods\u003C\u002Ftd>\u003Ctd>\u003Ccode>Pods\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>pod install\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Flutter, Dart\u003C\u002Ftd>\u003Ctd>\u003Ccode>build\u003C\u002Fcode>, \u003Ccode>.dart_tool\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>flutter pub get\u003C\u002Fcode>, then build again\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>Python\u003C\u002Ftd>\u003Ctd>\u003Ccode>__pycache__\u003C\u002Fcode>, \u003Ccode>.pytest_cache\u003C\u002Fcode>, \u003Ccode>.mypy_cache\u003C\u002Fcode>, \u003Ccode>.ruff_cache\u003C\u002Fcode>, \u003Ccode>.tox\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Recreated automatically when tools run\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>PHP\u003C\u002Ftd>\u003Ctd>\u003Ccode>vendor\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>composer install\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>.NET\u003C\u002Ftd>\u003Ctd>\u003Ccode>bin\u003C\u002Fcode>, \u003Ccode>obj\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>dotnet build\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>Restoring exactly what you had depends on a lockfile, such as \u003Ccode>package-lock.json\u003C\u002Fcode>, \u003Ccode>pnpm-lock.yaml\u003C\u002Fcode>, \u003Ccode>yarn.lock\u003C\u002Fcode>, \u003Ccode>Cargo.lock\u003C\u002Fcode>, \u003Ccode>Podfile.lock\u003C\u002Fcode>, or \u003Ccode>composer.lock\u003C\u002Fcode>, so that reinstalling gives you the same versions as before.\u003C\u002Fp>\n\u003Ch2 id=\"risks\">\u003Ca class=\"heading-anchor\" href=\"#risks\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Risks to check first\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Record dependencies before deleting virtual environments\u003C\u002Fstrong>: Python&#39;s \u003Ccode>.venv\u003C\u002Fcode> and \u003Ccode>venv\u003C\u002Fcode> can be rebuilt, but only if \u003Ccode>requirements.txt\u003C\u002Fcode> or a lockfile records the dependencies. If nothing does, export them first with \u003Ccode>pip freeze &gt; requirements.txt\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Some build folders contain hand-written files\u003C\u002Fstrong>: a few projects keep configuration, keys, or hand-written scripts in \u003Ccode>build\u003C\u002Fcode> or \u003Ccode>target\u003C\u002Fcode>, or even commit them to Git. Check for tracked files before deleting.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Old projects may not install again\u003C\u002Fstrong>: packages they depend on may have been unpublished, and old toolchains may no longer install. For old projects you still maintain, confirm they reinstall before deleting anything.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>pnpm projects free less\u003C\u002Fstrong>: a pnpm project&#39;s \u003Ccode>node_modules\u003C\u002Fcode> shares data blocks with the global store, so deleting it may free less space than its size suggests.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"manual-cleanup\">\u003Ca class=\"heading-anchor\" href=\"#manual-cleanup\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Clean up in bulk manually\u003C\u002Fh2>\n\u003Ch3 id=\"find-them\">\u003Ca class=\"heading-anchor\" href=\"#find-them\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Find them first\u003C\u002Fh3>\n\u003Cp>Assuming your projects live in \u003Ccode>~\u002FProjects\u003C\u002Fcode>, the command below lists every \u003Ccode>node_modules\u003C\u002Fcode> and \u003Ccode>target\u003C\u002Fcode> folder with its size. \u003Ccode>-prune\u003C\u002Fcode> stops \u003Ccode>find\u003C\u002Fcode> from descending into those folders, which makes it much faster:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">find ~\u002FProjects -type d \\( -name node_modules -o -name target \\) -prune -print0 \\\n  | xargs -0 du -sh 2&gt;\u002Fdev\u002Fnull | sort -h\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>To focus on projects you have not touched in a long time, add a time condition. A \u003Ccode>node_modules\u003C\u002Fcode> folder&#39;s modification time roughly matches the last dependency install, so treat it as a hint only:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># List node_modules folders with no dependency reinstall in the last 90 days\nfind ~\u002FProjects -type d -name node_modules -prune -mtime +90 -print\n# After checking the list, delete them; rm -rf bypasses the Trash\nfind ~\u002FProjects -type d -name node_modules -prune -mtime +90 -exec rm -rf {} +\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"tool-commands\">\u003Ca class=\"heading-anchor\" href=\"#tool-commands\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Use each tool&#39;s own clean command\u003C\u002Fh3>\n\u003Cp>Inside a single project, prefer the tool&#39;s own command, because it knows which files it generated:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">cargo clean            # remove a Rust project&#39;s target\n.\u002Fgradlew clean        # remove a Gradle project&#39;s build output\nmvn clean              # remove a Maven project&#39;s target\nflutter clean          # remove a Flutter project&#39;s build and .dart_tool\nswift package reset    # remove a Swift package&#39;s .build\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"git-clean\">\u003Ca class=\"heading-anchor\" href=\"#git-clean\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Preview ignored files with Git\u003C\u002Fh3>\n\u003Cp>If a project uses Git, most of what \u003Ccode>.gitignore\u003C\u002Fcode> lists can be regenerated. \u003Ccode>git clean -X\u003C\u002Fcode> deletes only ignored files; preview with \u003Ccode>-n\u003C\u002Fcode> first:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># Preview: list ignored files and folders that would be deleted\ngit clean -ndX\n# Run it only after checking the list\ngit clean -fdX\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"callout callout-warning\">\u003Cp class=\"callout-title\">Warning\u003C\u002Fp>\u003Cp>\u003Ccode>.env\u003C\u002Fcode> files, local configuration, and editor settings are usually in \u003Ccode>.gitignore\u003C\u002Fcode> too. If they appear in the preview, move them out of the way first, or use the \u003Ccode>find\u003C\u002Fcode> commands above to delete specific folders only.\u003C\u002Fp>\n\u003C\u002Fdiv>\u003Ch2 id=\"washbear\">\u003Ca class=\"heading-anchor\" href=\"#washbear\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Clean up in bulk with WashBear\u003C\u002Fh2>\n\u003Cp>WashBear&#39;s \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdeep-clean\">Deep Cleanup\u003C\u002Fa> groups these folders under \u003Cstrong>Project build artifacts\u003C\u002Fstrong>, covering more than thirty tools and frameworks in items such as \u003Cstrong>Node.js build artifacts\u003C\u002Fstrong>, \u003Cstrong>Rust build artifacts\u003C\u002Fstrong>, \u003Cstrong>Python build artifacts\u003C\u002Fstrong>, and \u003Cstrong>Gradle build artifacts\u003C\u002Fstrong>. It recognizes projects by marker files such as \u003Ccode>package.json\u003C\u002Fcode>, \u003Ccode>Cargo.toml\u003C\u002Fcode>, \u003Ccode>pom.xml\u003C\u002Fcode>, and \u003Ccode>Podfile\u003C\u002Fcode>, and lists only the folders the matching tool generates. Expand an item to see each folder&#39;s path, size, file count, and last modification time, and select folders one by one.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Smart recommendation\u003C\u002Fstrong> never preselects this category, and there is no automatic age filter: you decide which projects to clean.\u003C\u002Fp>\n\u003Ch3 id=\"where-it-looks\">\u003Ca class=\"heading-anchor\" href=\"#where-it-looks\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Where WashBear looks for projects\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>\u003Cstrong>Standard Scan\u003C\u002Fstrong>: searches the folders in your home folder, except hidden folders and app data folders such as Library, and keeps only the most recently modified projects, judged by the project folder&#39;s modification time; currently up to 96. If you have many projects, ones you have not touched in a long time may be left out.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Choose Disks\u003C\u002Fstrong>: the system disk is always scanned, and you can also select other disks, such as external drives, to search for projects there, without the limit above. This is the better choice for tidying up old projects.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Desktop, Documents, and Downloads are protected by macOS privacy controls; if you deny access, those locations are skipped. To protect a project, add its folder under \u003Cstrong>By path\u003C\u002Fstrong> in \u003Cstrong>Settings → Scanning &amp; analysis → Scan exclusions\u003C\u002Fstrong>; path exclusions apply to project build artifacts.\u003C\u002Fp>\n\u003Ch3 id=\"protections\">\u003Ca class=\"heading-anchor\" href=\"#protections\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>What is skipped automatically\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>If a build folder contains Git-tracked files, a \u003Ccode>.git\u003C\u002Fcode> folder, or key files such as \u003Ccode>*-keypair.json\u003C\u002Fcode>, WashBear does not clean it, and the result shows \u003Cstrong>Could not be fully read and is excluded\u003C\u002Fstrong>. The same applies when the project is in a Git repository but Git is not available on this Mac.\u003C\u002Fli>\n\u003Cli>Before cleaning, WashBear checks the project and folder again and skips folders that no longer qualify.\u003C\u002Fli>\n\u003Cli>Python&#39;s \u003Ccode>.venv\u003C\u002Fcode> and \u003Ccode>venv\u003C\u002Fcode> are out of scope; \u003Cstrong>Python build artifacts\u003C\u002Fstrong> covers only tool caches such as \u003Ccode>__pycache__\u003C\u002Fcode> and \u003Ccode>.pytest_cache\u003C\u002Fcode>. The \u003Ccode>dist\u003C\u002Fcode> and \u003Ccode>build\u003C\u002Fcode> output folders of Node.js projects are not included either.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Cleanup deletes files directly instead of moving them to the Trash, and the result is recorded in \u003Ca href=\"\u002Fen\u002Fdocs\u002Fgetting-started#history\">Operation History\u003C\u002Fa>. Global npm and pnpm caches are a separate topic covered in \u003Ca href=\"\u002Fen\u002Fblog\u002Fclear-js-package-caches\">how to clear npm, pnpm, and Yarn caches\u003C\u002Fa>; for Xcode&#39;s DerivedData, see \u003Ca href=\"\u002Fen\u002Fblog\u002Fclear-xcode-storage\">clearing Xcode storage\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>To see how much your old projects could give back, \u003Ca href=\"\u002Fen\u002Fdownload\">download WashBear\u003C\u002Fa> and run a scan; scanning alone never deletes anything. The demo below uses sample data, so its items and numbers are only illustrative.\u003C\u002Fp>\n\u003C!--demo:deepClean-->\u003Ch2 id=\"faq\">\u003Ca class=\"heading-anchor\" href=\"#faq\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>FAQ\u003C\u002Fh2>\n\u003Ch3 id=\"faq-restore\">\u003Ca class=\"heading-anchor\" href=\"#faq-restore\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>How do I restore a project after deleting node_modules?\u003C\u002Fh3>\n\u003Cp>Run the install command in the project folder, such as \u003Ccode>npm ci\u003C\u002Fcode>, \u003Ccode>pnpm install\u003C\u002Fcode>, or \u003Ccode>yarn install\u003C\u002Fcode>. With a \u003Ccode>package-lock.json\u003C\u002Fcode>, \u003Ccode>npm ci\u003C\u002Fcode> installs exactly what the lockfile specifies.\u003C\u002Fp>\n\u003Ch3 id=\"faq-source-code\">\u003Ca class=\"heading-anchor\" href=\"#faq-source-code\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Can WashBear delete my source code?\u003C\u002Fh3>\n\u003Cp>No. It deletes only the folders its rules list, those folders must belong to a recognized project, and folders that contain Git-tracked files are skipped.\u003C\u002Fp>\n\u003Ch3 id=\"faq-external-drive\">\u003Ca class=\"heading-anchor\" href=\"#faq-external-drive\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Can I clean projects on an external drive?\u003C\u002Fh3>\n\u003Cp>Yes. Click the arrow next to \u003Cstrong>Start Scan\u003C\u002Fstrong>, choose \u003Cstrong>Choose Disks\u003C\u002Fstrong>, select that drive, and start the scan.\u003C\u002Fp>\n",[16,20,23,26,30,33,36,39,42,45,48,51,54],{"depth":17,"id":18,"text":19},2,"what-can-be-regenerated","Which folders can be regenerated",{"depth":17,"id":21,"text":22},"risks","Risks to check first",{"depth":17,"id":24,"text":25},"manual-cleanup","Clean up in bulk manually",{"depth":27,"id":28,"text":29},3,"find-them","Find them first",{"depth":27,"id":31,"text":32},"tool-commands","Use each tool&#39;s own clean command",{"depth":27,"id":34,"text":35},"git-clean","Preview ignored files with Git",{"depth":17,"id":37,"text":38},"washbear","Clean up in bulk with WashBear",{"depth":27,"id":40,"text":41},"where-it-looks","Where WashBear looks for projects",{"depth":27,"id":43,"text":44},"protections","What is skipped automatically",{"depth":17,"id":46,"text":47},"faq","FAQ",{"depth":27,"id":49,"text":50},"faq-restore","How do I restore a project after deleting node_modules?",{"depth":27,"id":52,"text":53},"faq-source-code","Can WashBear delete my source code?",{"depth":27,"id":55,"text":56},"faq-external-drive","Can I clean projects on an external drive?","\nMeasure an old project and you will often find a few dozen megabytes of source code next to hundreds of megabytes, or several gigabytes, of `node_modules`, Rust `target`, or Gradle `build` output. With enough projects, these regenerable folders become the largest thing on your disk. This guide helps you decide which folders are safe to delete, shows how to find them in bulk from the command line, and explains how WashBear protects your projects when it cleans them for you.\n\n## Which folders can be regenerated {#what-can-be-regenerated}\n\n| Ecosystem | Common folders | How to restore |\n| --- | --- | --- |\n| Node.js | `node_modules`, `.next\u002Fcache`, `.nuxt`, `.turbo` | `npm ci`, `pnpm install`, or `yarn install` |\n| Rust | `target` | `cargo build` |\n| Gradle, Android | `build`, `.gradle` | Build again |\n| Maven | `target` | Build again |\n| Swift Package | `.build` | `swift build` |\n| CocoaPods | `Pods` | `pod install` |\n| Flutter, Dart | `build`, `.dart_tool` | `flutter pub get`, then build again |\n| Python | `__pycache__`, `.pytest_cache`, `.mypy_cache`, `.ruff_cache`, `.tox` | Recreated automatically when tools run |\n| PHP | `vendor` | `composer install` |\n| .NET | `bin`, `obj` | `dotnet build` |\n\nRestoring exactly what you had depends on a lockfile, such as `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `Cargo.lock`, `Podfile.lock`, or `composer.lock`, so that reinstalling gives you the same versions as before.\n\n## Risks to check first {#risks}\n\n- **Record dependencies before deleting virtual environments**: Python's `.venv` and `venv` can be rebuilt, but only if `requirements.txt` or a lockfile records the dependencies. If nothing does, export them first with `pip freeze > requirements.txt`.\n- **Some build folders contain hand-written files**: a few projects keep configuration, keys, or hand-written scripts in `build` or `target`, or even commit them to Git. Check for tracked files before deleting.\n- **Old projects may not install again**: packages they depend on may have been unpublished, and old toolchains may no longer install. For old projects you still maintain, confirm they reinstall before deleting anything.\n- **pnpm projects free less**: a pnpm project's `node_modules` shares data blocks with the global store, so deleting it may free less space than its size suggests.\n\n## Clean up in bulk manually {#manual-cleanup}\n\n### Find them first {#find-them}\n\nAssuming your projects live in `~\u002FProjects`, the command below lists every `node_modules` and `target` folder with its size. `-prune` stops `find` from descending into those folders, which makes it much faster:\n\n```bash\nfind ~\u002FProjects -type d \\( -name node_modules -o -name target \\) -prune -print0 \\\n  | xargs -0 du -sh 2>\u002Fdev\u002Fnull | sort -h\n```\n\nTo focus on projects you have not touched in a long time, add a time condition. A `node_modules` folder's modification time roughly matches the last dependency install, so treat it as a hint only:\n\n```bash\n# List node_modules folders with no dependency reinstall in the last 90 days\nfind ~\u002FProjects -type d -name node_modules -prune -mtime +90 -print\n# After checking the list, delete them; rm -rf bypasses the Trash\nfind ~\u002FProjects -type d -name node_modules -prune -mtime +90 -exec rm -rf {} +\n```\n\n### Use each tool's own clean command {#tool-commands}\n\nInside a single project, prefer the tool's own command, because it knows which files it generated:\n\n```bash\ncargo clean            # remove a Rust project's target\n.\u002Fgradlew clean        # remove a Gradle project's build output\nmvn clean              # remove a Maven project's target\nflutter clean          # remove a Flutter project's build and .dart_tool\nswift package reset    # remove a Swift package's .build\n```\n\n### Preview ignored files with Git {#git-clean}\n\nIf a project uses Git, most of what `.gitignore` lists can be regenerated. `git clean -X` deletes only ignored files; preview with `-n` first:\n\n```bash\n# Preview: list ignored files and folders that would be deleted\ngit clean -ndX\n# Run it only after checking the list\ngit clean -fdX\n```\n\n> [!WARNING]\n> `.env` files, local configuration, and editor settings are usually in `.gitignore` too. If they appear in the preview, move them out of the way first, or use the `find` commands above to delete specific folders only.\n\n## Clean up in bulk with WashBear {#washbear}\n\nWashBear's [Deep Cleanup](\u002Fdocs\u002Fdeep-clean) groups these folders under **Project build artifacts**, covering more than thirty tools and frameworks in items such as **Node.js build artifacts**, **Rust build artifacts**, **Python build artifacts**, and **Gradle build artifacts**. It recognizes projects by marker files such as `package.json`, `Cargo.toml`, `pom.xml`, and `Podfile`, and lists only the folders the matching tool generates. Expand an item to see each folder's path, size, file count, and last modification time, and select folders one by one.\n\n**Smart recommendation** never preselects this category, and there is no automatic age filter: you decide which projects to clean.\n\n### Where WashBear looks for projects {#where-it-looks}\n\n- **Standard Scan**: searches the folders in your home folder, except hidden folders and app data folders such as Library, and keeps only the most recently modified projects, judged by the project folder's modification time; currently up to 96. If you have many projects, ones you have not touched in a long time may be left out.\n- **Choose Disks**: the system disk is always scanned, and you can also select other disks, such as external drives, to search for projects there, without the limit above. This is the better choice for tidying up old projects.\n\nDesktop, Documents, and Downloads are protected by macOS privacy controls; if you deny access, those locations are skipped. To protect a project, add its folder under **By path** in **Settings → Scanning & analysis → Scan exclusions**; path exclusions apply to project build artifacts.\n\n### What is skipped automatically {#protections}\n\n- If a build folder contains Git-tracked files, a `.git` folder, or key files such as `*-keypair.json`, WashBear does not clean it, and the result shows **Could not be fully read and is excluded**. The same applies when the project is in a Git repository but Git is not available on this Mac.\n- Before cleaning, WashBear checks the project and folder again and skips folders that no longer qualify.\n- Python's `.venv` and `venv` are out of scope; **Python build artifacts** covers only tool caches such as `__pycache__` and `.pytest_cache`. The `dist` and `build` output folders of Node.js projects are not included either.\n\nCleanup deletes files directly instead of moving them to the Trash, and the result is recorded in [Operation History](\u002Fdocs\u002Fgetting-started#history). Global npm and pnpm caches are a separate topic covered in [how to clear npm, pnpm, and Yarn caches](\u002Fblog\u002Fclear-js-package-caches); for Xcode's DerivedData, see [clearing Xcode storage](\u002Fblog\u002Fclear-xcode-storage).\n\nTo see how much your old projects could give back, [download WashBear](\u002Fdownload) and run a scan; scanning alone never deletes anything. The demo below uses sample data, so its items and numbers are only illustrative.\n\n::demo deepClean\n\n## FAQ {#faq}\n\n### How do I restore a project after deleting node_modules? {#faq-restore}\n\nRun the install command in the project folder, such as `npm ci`, `pnpm install`, or `yarn install`. With a `package-lock.json`, `npm ci` installs exactly what the lockfile specifies.\n\n### Can WashBear delete my source code? {#faq-source-code}\n\nNo. It deletes only the folders its rules list, those folders must belong to a recognized project, and folders that contain Git-tracked files are skipped.\n\n### Can I clean projects on an external drive? {#faq-external-drive}\n\nYes. Click the arrow next to **Start Scan**, choose **Choose Disks**, select that drive, and start the scan.\n",1793258439426]