Windows: agent-created node_modules junctions from git worktrees cause source-file deletion on worktree remove

Status Fixed / completed
Maintainer reply ✓ Yes — bogini
Activity 4 comments · opened May 19, 2026 · closed May 27, 2026
💡 Likely answer: A maintainer (bogini, collaborator) responded on this thread — see the highlighted reply below.

Summary

During a ticket-chain run on Windows, the agent created Windows junctions to share node_modules between feature git worktrees and the main repo. When git worktree remove --force cleaned up the worktrees afterward, it followed the junctions recursively and deleted source files from the main repo's working tree.

All data was recoverable via git restore . (the commits had already been pushed), but the failure mode is silent and surprising.

What happened, step by step

  1. Main repo: C:\repo\securish-bike-parking - an npm-workspaces monorepo with apps/api, apps/web, packages/contracts
  2. Agent created 4 feature worktrees at sibling paths (../wt-bkfk2-57, etc.) from main
  3. Agent created Windows junctions so the worktrees could share the main repo's node_modules (to avoid re-running npm install four times):

``
cmd //c mklink //J "C:\repo\wt-bkfk2-57\node_modules" "C:\repo\securish-bike-parking\node_modules"
``

  1. Agent implemented tickets in the worktrees, committed, merged each branch to main, pushed
  2. Agent removed each worktree:

``
git worktree remove --force /c/repo/wt-bkfk2-57
``

  1. On Windows, git's worktree removal uses recursive directory deletion that follows junctions (analogous to rmdir /S /Q). The chain was:
  • Delete wt-bkfk2-57\node_modules → this is a junction → follows into securish-bike-parking\node_modules
  • Inside securish-bike-parking\node_modules\@bkfk2\api → npm workspace junction → follows into ../../apps/api
  • Result: securish-bike-parking\apps\api\ contents deleted

Why the npm workspace chain exists

npm workspaces on Windows creates junctions (not POSIX symlinks) for workspace packages. So node_modules/@bkfk2/api is a Windows junction pointing to ../../apps/api. Any recursive delete that follows junctions will traverse from node_modules → workspace source directories.

Impact

Source files under apps/api/, most of apps/web/, and packages/contracts/ were wiped from the working tree. Files that the merges had just written back (App.tsx, identity.ts, etc.) were the only survivors. git restore . recovered everything cleanly since the code was in the index.

Guidance requested

The agent chose this junction approach to avoid the cost of four parallel npm install runs. That tradeoff is reasonable in intent, but the Windows junction-following behavior made it catastrophic.

Two things would prevent this:

  1. Agent-side: never create a Windows junction from a feature worktree that points into the main repo's node_modules. Safer alternatives: npm install per worktree (npm cache makes it fast), or copy / reference node_modules with a plain path env var rather than a filesystem junction.
  1. Tooling-side: if Claude Code's worktree-removal path on Windows can detect that a directory being removed contains a junction pointing outside the worktree's own tree, it could warn or refuse rather than silently following the junction into the parent repo.

Environment

  • Windows 11 Pro
  • Git for Windows / MSYS2 Bash
  • npm workspaces monorepo
  • Claude Code agent running the /tch (ticket-chain) skill

View original on GitHub ↗

4 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/36339
  2. https://github.com/anthropics/claude-code/issues/29249
  3. https://github.com/anthropics/claude-code/issues/58885

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

qtec-technology · 4 months ago

Additional repro on Windows + pnpm workspaces (axon, 2026-05-21)

Hit this exact bug today on a pnpm-workspaces monorepo. Posting as
additional repro data — same junction-following mechanism, slightly
different surface.

Environment

  • Windows 11 (NTFS, F: drive on NVMe)
  • pnpm 10.33.0, Node 24.13.1, Git for Windows / MSYS2 Bash
  • Monorepo layout: apps/dashboard/ (Next.js 16) + packages/{config,env,prisma}/
  • Claude Desktop 1.8089.1.0 (Windows)
  • Active git worktrees in <repo>/.claude/worktrees/<adj>-<name>-<hash>/

(the Cowork-tab worktree naming pattern)

What happened

  1. Several Code-tab sessions ran over the past 2-3 weeks, each spawning

its own worktree under .claude/worktrees/

  1. ~10 worktrees had been removed previously (their git worktree list

entries are gone), but their session jsonl folders still exist at
~/.claude/projects/F--source-repos-<repo>--claude-worktrees-*/

  1. Closed and restarted Claude Desktop at ~16:35-16:40 local
  2. UI for one Settings option ("Node selection" / built-in vs system Node)

disappeared after restart (still searchable in settings but no longer
navigable)

  1. At 16:37:42 local (~30 sec after Desktop UI finished restarting),

the root node_modules/ of the active main repo was emptied

  1. Windows Event Log: WER (Windows Error Reporting) service entered

running state at 16:37:16 — 26 seconds before the wipe

Surface vs OP

OP saw apps/api/ source files wiped via
node_modules/@scope/api → workspace junction follow.

In my case only the root node_modules/ contents were wiped —
source files in apps/dashboard/, packages/env/, packages/prisma/
were untouched. The workspace node_modules/ subfolders had already
been mostly empty since pnpm install activity in late April (pnpm's
virtual store keeps real packages in .pnpm/, so workspace
node_modules/ only hold a .modules.yaml and the workspace-internal
symlinks). So the deletion chain seems to have stopped at the root
node_modules/ level.

Trace gap

There is no Bash tool call in any Claude session jsonl (across
~160 sessions for this project) that matches rm -rf node_modules,
rimraf, Remove-Item .* node_modules, or git worktree remove --force
in the 16:25-16:50 window. The destructive operation was triggered
inside Claude Desktop's restart cleanup path, not via the agent's
visible tool calls — confirming OP's tooling-side observation that
worktree removal on Windows needs junction-aware deletion logic.

Impact + recovery

  • Wipe scope: only <repo>/node_modules/ root (~45 MB of symlinks +

.pnpm/ virtual store)

  • No data loss in source tree (everything in git anyway)
  • Recovery: pnpm install --frozen-lockfile -> 44.5 s (pnpm-store cache

was intact, so 749 reused / 763 added)

Suggested addition to OP's mitigation #2

If Claude Desktop's restart cleanup runs git worktree prune /
git worktree remove --force on Windows, the same junction-aware check
should apply there, not only on agent-initiated worktree removal. The
restart-time cleanup hit me without any agent action.

Happy to provide additional repro data (session IDs, exact jsonl
timestamps, folder mtime evidence) if it helps narrow down the
restart-cleanup code path.

bogini collaborator · 4 months ago

Addressed by a merged fix. Please reopen with a fresh repro if you still see this on a current version.

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.