[BUG] Settings-file watcher enumerates its parent directory, with no bound on parent size

Status Open
Reported on v2.1.224
Maintainer reply None cached
Activity 1 comment · opened Aug 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code 2.1.224, macOS 26.5.2 (Darwin 25.5.0), 18-core Apple Silicon

Summary

Claude Code watches ~/.claude/settings.json by watching the file's parent
directory
. When that file is a symlink whose target lives in a very large
directory, Claude repeatedly opendirs and enumerates the whole directory.

On any Nix system this is the default situation: home-manager materialises
~/.claude/settings.json as a symlink to a top-level /nix/store path, so the
parent directory is the Nix store itself — 366,845 entries on this machine.

Result: an idle Claude session burns 300–500% CPU for the entire duration of
any unrelated Nix build, and starves the build it is reacting to.

Impact

This is not a niche configuration. Every Nix/home-manager user who manages
Claude Code declaratively gets a symlinked settings.json by default, and any
nix build anywhere on the machine triggers it. The two workloads then fight
for cores: the build crawls, and the idle assistant pins the box.

What Should Happen?

Suggested fixes

Any one of these would resolve it:

  • Watch the file path itself rather than scanning the resolved target's parent
  • If a parent-directory watch is required, do not enumerate the directory to

detect the change

  • Bound it defensively: skip directory enumeration above some entry count, and

fall back to polling stat on the single file.

  • Debounce: currently a burst of directory writes yields repeated full

enumerations, roughly one per second, with no coalescing. At the very least don't re-enter a scan while the previous one is still running

The last point matters independently of the symlink case: a full re-enumeration
per change event is expensive for any large config directory.

Error Messages/Logs

Steps to Reproduce

Evidence

Captured with sample(1) and fs_usage(1) against an idle session (no user
input) while nh darwin build . ran in an unrelated directory.

Hot leaf frames — a directory walk, not event delivery:

lstat              29316
__getdirentries64  14675
kevent64            6762   <- comparatively idle

fs_usage, 45s window:

| metric | value |
|---|---|
| accesses to the settings store path | 146 (~3/sec) |
| openat on /nix/store root | 16 |
| lstat on store entries | 741,519 |
| complete passes over 366,845 entries | ~2.0 |

Each open is immediately followed by a getdirentries64 burst on the same fd:

17:01:15.725430  openat            F=20  (R______________)  [-2]//nix/store
17:01:15.726105  getdirentries64   F=20  B=0x1fc0
17:01:15.735722  getdirentries64   F=20  B=0x1fd8
17:01:15.736100  getdirentries64   F=20  B=0x1fc0
...

Entries are visited in unsorted readdir order and include .drv files and
source tarballs, i.e. the whole store directory is enumerated with no filtering.

Reproduction

  1. On macOS, make ~/.claude/settings.json a symlink to a file that sits in a

directory with a very large number of entries:
``
ln -s /nix/store/<hash>-claude-code-settings.json ~/.claude/settings.json
``
(Any large directory reproduces it; the Nix store is simply the obvious case.)

  1. Start Claude Code and leave it idle.
  2. Cause churn in that directory — on Nix, any nix build that fetches paths.
  3. Observe: sample <claude-pid> 10 shows lstat/__getdirentries64 dominant;

sudo fs_usage -w -f filesys <claude-pid> shows repeated openat +
getdirentries64 on the large directory.

Control: replace the symlink with a real file, or point it at a file nested
inside a small directory, and the behaviour disappears completely — /nix/store
syscalls go from 215,483 in a 20s window to 0, with the build still running.

Claude Model

_No response_

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.224 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

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