Windows: agent-created node_modules junctions from git worktrees cause source-file deletion on worktree remove
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
- Main repo:
C:\repo\securish-bike-parking- an npm-workspaces monorepo withapps/api,apps/web,packages/contracts - Agent created 4 feature worktrees at sibling paths (
../wt-bkfk2-57, etc.) from main - Agent created Windows junctions so the worktrees could share the main repo's
node_modules(to avoid re-runningnpm installfour times):
````
cmd //c mklink //J "C:\repo\wt-bkfk2-57\node_modules" "C:\repo\securish-bike-parking\node_modules"
- Agent implemented tickets in the worktrees, committed, merged each branch to main, pushed
- Agent removed each worktree:
````
git worktree remove --force /c/repo/wt-bkfk2-57
- 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 intosecurish-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:
- Agent-side: never create a Windows junction from a feature worktree that points into the main repo's
node_modules. Safer alternatives:npm installper worktree (npm cache makes it fast), or copy / reference node_modules with a plain path env var rather than a filesystem junction.
- 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
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗