[Windows] bashEditDiff snapshots every Bash call with a full `git status` (fsmonitor forced off) — on by default in bypassPermissions

Status Open
Reported on v2.1.280
Maintainer reply None cached
Activity 1 comment · opened Sep 23, 2026

Environment

  • Claude Code 2.1.280 (Claude Desktop 2.2553.13.0), Windows 11 26200, Git for Windows 2.45.1
  • Sessions run in bypassPermissions, so bashEditDiffEnabled is on by default without being configured

What happens

Around every Bash tool call, the CLI takes working-tree snapshots through a shadow GIT_DIR:

git -c core.hooksPath=NUL -c core.fsmonitor= ... status --porcelain=v2 -z --untracked-files=normal --ignored=no --no-renames --ignore-submodules=all

followed by update-index / write-tree (and commit-tree / diff-tree for the diff). On Windows each git call is two processes (cmd\git.exe launcher + mingw64\bin\git.exe).

Measured

ETW trace (Microsoft-Windows-Kernel-File + Kernel-Process), 20 s, 5 open sessions, 1 of them actively working in a 1,520-file repo:

| | file opens / 20 s | share of Claude-caused opens |
|---|---|---|
| git spawned by the CLI (snapshots) | 11,287 | 45 % |
| everything else Claude (hooks, Bash commands, CLI, Desktop) | 13,956 | 55 % |

  • ~3,700 file opens per snapshot; the single active session triggered a git status every ~5 s (9 in 45 s)
  • Bytes written are negligible — the cost is metadata IOPS and process creation, not throughput
  • It scales with the number of parallel sessions × Bash calls, independent of whether the command changed anything

Why it is more expensive than it needs to be

  1. -c core.fsmonitor= also disables Git's builtin FSMonitor (core.fsmonitor=true), which runs no external command. Blanking only hook-path values would keep the hardening and let large repos use the daemon.
  2. Snapshots also run for read-only commands (ls, cat, grep, git log, git diff, …).
  3. The default depends on the permission mode, not on the repo or platform, so it is effectively always on for bypassPermissions users — and bashEditDiffEnabled is hard to discover.

Suggestions

  • Allow builtin FSMonitor; only blank core.fsmonitor when it points to a hook/command
  • Skip the snapshot for commands already known to be read-only
  • Coalesce snapshots across consecutive Bash calls (reuse the "after" snapshot as the next "before")
  • Document bashEditDiffEnabled and its cost in the settings docs

Workaround

"bashEditDiffEnabled": false in ~/.claude/settings.json.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗