From 9dd29218f56d1c95779ff6199e5635234e94658a Mon Sep 17 00:00:00 2001 From: Michal Landsman Date: Wed, 12 Aug 2026 15:13:12 +0200 Subject: [PATCH 1/2] macos: keep spotlight's file results off, and a way to stop the indexer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Spotlight pane's own switches are a results filter and nothing more: with Files and Folders both off, a probe file dropped in ~/projects was still in `mdfind` twenty seconds later. So the two halves are separate here — `defaults.sh` records which rows are off, and a new target stops `mds` from indexing at all. The array name lies. `EnabledPreferenceRules` lists what is turned *off*; `System.files` and `System.folders` appeared in it the moment those two switches went dark, which is how the list was read rather than guessed. Why the indexer half is a whole volume and not ~/projects: nothing else works. `man mdutil`, `man mds`, `man mdimport` and `man mdfind` between them say nothing about exclusions. `.metadata_never_index` in the folder changed nothing. The Privacy list does work, but its plist is behind TCC even for root, so scripting it needs Full Disk Access on the terminal — and is undocumented anyway. The motive is a kernel panic on 2026-08-12: the vnode table filled up while mds reindexed a monorepo behind several coding agents, every mmapped page after that faulted with SIGBUS, launchd took one and the kernel had nowhere to go. --- Makefile | 35 ++++++++++++++++++++++++++++++++++- README.md | 1 + bin/macos/defaults.sh | 28 +++++++++++++++++++++++++++- bin/macos/defaults.test.sh | 4 ++-- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index d13605d..94a3d0e 100644 --- a/Makefile +++ b/Makefile @@ -300,7 +300,7 @@ jetbrains: ## set the JVM options this repo owns in every JetBrains config dir # The panes stow cannot reach, see bin/macos/defaults.sh # -.PHONY: macos macos-touchid +.PHONY: macos macos-touchid macos-spotlight-off macos-spotlight-on macos: ## apply the macOS settings this repo owns (menu bar, Dock, Finder, trackpad, file associations) @[ "$$(uname -s)" = Darwin ] || { echo "macOS only - skipped"; exit 0; }; ./bin/macos/defaults.sh @# Its own script and not a `defaults write` line: the associations live in one @@ -326,6 +326,39 @@ macos-touchid: ## authenticate sudo with Touch ID (root-owned, so its own target cat "$$f"; \ sudo -k; echo "now run any sudo command - it should ask for a fingerprint" +macos-spotlight-off: ## stop indexing files on the data volume (root; see landsman/config#82) + @# There is no per-folder switch, which is the whole reason this is a volume + @# and not ~/projects. `man mdutil`, `man mds`, `man mdimport` and `man + @# mdfind` between them say nothing about exclusions — a volume is the only + @# granularity Apple documents. The two things that look like alternatives + @# were both tried here first: `.metadata_never_index` dropped in the folder + @# changed nothing (a file created after it was in `mdfind` fifteen seconds + @# later), and the Privacy list in System Settings does work but lives in + @# /System/Volumes/Data/.Spotlight-V100/VolumeConfiguration.plist, which TCC + @# hides even from root — PlistBuddy reports "File Doesn't Exist" for a file + @# `sudo mdutil -P` prints happily. Scripting that one needs Full Disk Access + @# handed to whichever terminal runs it, and it is undocumented besides. + @# + @# The cost is Finder's "This Mac" search and anything else that asks + @# Spotlight for a file; app results (Mail, Notes, Messages) come from + @# CoreSpotlight and are expected to survive — check, the first time. + @# What it buys: on 2026-08-12 the vnode table filled up while mds reindexed + @# a monorepo behind several coding agents, every mmapped page after that + @# faulted with SIGBUS, launchd took one and the kernel panicked. + @# + @# Not part of `make macos`, which writes nothing outside $$HOME and asks for + @# no password — same reason macos-touchid is its own target. + @[ "$$(uname -s)" = Darwin ] || { echo "macOS only - skipped"; exit 0; } + sudo mdutil -i off -d /System/Volumes/Data + @echo "reverse with: make macos-spotlight-on" + +macos-spotlight-on: ## index files again (rebuilds what it missed — hours of load) + @# The slow half, and the one to run on purpose rather than to undo a typo: + @# everything that changed while indexing was off is reindexed, which is the + @# load the target above exists to avoid. + @[ "$$(uname -s)" = Darwin ] || { echo "macOS only - skipped"; exit 0; } + sudo mdutil -i on /System/Volumes/Data + ##@ GIT config .PHONY: git git-config-test git-config-format diff --git a/README.md b/README.md index 21da5a0..a3e55a2 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ make git # hook in .gitconfig, set email + commit signing make macos # macOS only: menu bar, Dock, Finder, trackpad, formats, file associations make macos-touchid # macOS only: authenticate sudo with Touch ID (asks for root) +make macos-spotlight-off # macOS only: stop indexing files (asks for root) - see the Makefile make jetbrains # set the IDE heap; then open this repo in the IDE to get the plugins ``` diff --git a/bin/macos/defaults.sh b/bin/macos/defaults.sh index e6d9376..bc71ddc 100755 --- a/bin/macos/defaults.sh +++ b/bin/macos/defaults.sh @@ -143,6 +143,32 @@ wh NSGlobalDomain "com.apple.mouse.tapBehavior" -int 1 w com.apple.AdLib allowApplePersonalizedAdvertising -bool false w com.apple.assistant.support "Dictation Auto Punctuation Enabled" -bool false +# +# Spotlight — what is allowed to show up in results +# +# One array, and its name lies: `EnabledPreferenceRules` lists what is turned +# *off*. Every entry is a row switched off in System Settings > Spotlight, and +# a row left at Apple's default is simply absent. Verified by diffing +# `defaults read` across a flip of the Files and Folders switches — both +# appeared in this array the moment they went dark. +# +# So this is written as one array and not per row: the whole list is the state, +# and `-array` replaces it. Adding a row here means turning it off. +# +# This is a *results* filter and nothing more. `mds` keeps indexing every file +# either way — a probe file dropped in ~/projects with Files and Folders both +# off was still in `mdfind` twenty seconds later. Stopping the indexer is +# `make macos-spotlight-off`, which is a different decision and a separate +# target. +w com.apple.Spotlight EnabledPreferenceRules -array \ + "Custom.relatedContents" \ + "com.apple.iBooksX" "com.apple.calculator" "com.apple.iCal" "com.apple.clock" \ + "com.apple.AddressBook" "com.apple.Dictionary" "com.apple.FaceTime" \ + "com.apple.Numbers" "com.apple.Pages" "com.apple.mobilephone" \ + "com.apple.Photos" "com.apple.podcasts" "com.apple.tips" \ + "net.whatsapp.WhatsApp" \ + "System.files" "System.folders" "System.iphoneApps" + # # Keyboard layouts — Czech and U.S., plus the emoji picker # @@ -184,4 +210,4 @@ killall Dock Finder SystemUIServer ControlCenter 2>/dev/null || true # Apple moves it, the settings are still written and a logout still applies them. /System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u 2>/dev/null || true -echo "$written settings written (menu bar, Dock, Finder, trackpad, formats, privacy) plus the keyboard shortcuts from $(basename "$hotkeys"); Dock, Finder, the menu bar and Control Center restarted, so nothing here waits for a logout" +echo "$written settings written (menu bar, Dock, Finder, trackpad, formats, privacy, Spotlight results) plus the keyboard shortcuts from $(basename "$hotkeys"); Dock, Finder, the menu bar and Control Center restarted, so nothing here waits for a logout" diff --git a/bin/macos/defaults.test.sh b/bin/macos/defaults.test.sh index fb4ce75..401652a 100755 --- a/bin/macos/defaults.test.sh +++ b/bin/macos/defaults.test.sh @@ -44,14 +44,14 @@ fi pairs=$(sed -n "s/^defaults write \([^ ]*\) '\([^']*\)'.*/\1 \2/p" <<<"$out") # A setting written twice is silently the last one — and with 40-odd lines in -# eleven domains, the same key landing in two sections is the way this file rots. +# twelve domains, the same key landing in two sections is the way this file rots. check "no key written twice" '' "$(sort <<<"$pairs" | uniq -d)" check "menu bar keys survive their spaces" '4' \ "$(grep -c "^com.apple.controlcenter NSStatusItem Preferred Position " <<<"$pairs")" # Cheap sanity that the list is still the list, not an empty loop. -check "writes every domain" '11' "$(cut -d' ' -f1 <<<"$pairs" | sort -u | wc -l | tr -d ' ')" +check "writes every domain" '12' "$(cut -d' ' -f1 <<<"$pairs" | sort -u | wc -l | tr -d ' ')" [ "$fails" -eq 0 ] || { echo "$fails failed"; exit 1; } echo "all passed" From 98da3d0cfeb180a70a7434cc34608b5cb7f09078 Mon Sep 17 00:00:00 2001 From: Michal Landsman Date: Wed, 12 Aug 2026 15:28:35 +0200 Subject: [PATCH 2/2] macos: opt out of the search queries Apple collects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Help Apple Improve Search" hands Safari, Siri, Spotlight and Lookup queries to Apple, and the key does not exist until the switch is touched — absent means opted in, which is why it belongs in a file rather than in a memory of having clicked it once. 2 is the opted-out value, taken from what the switch itself wrote rather than from a guess: `defaults read` was diffed across the flip. --- bin/macos/defaults.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bin/macos/defaults.sh b/bin/macos/defaults.sh index bc71ddc..baeddc5 100755 --- a/bin/macos/defaults.sh +++ b/bin/macos/defaults.sh @@ -143,6 +143,13 @@ wh NSGlobalDomain "com.apple.mouse.tapBehavior" -int 1 w com.apple.AdLib allowApplePersonalizedAdvertising -bool false w com.apple.assistant.support "Dictation Auto Punctuation Enabled" -bool false +# "Help Apple Improve Search" in System Settings > Spotlight — the Safari, Siri, +# Spotlight and Lookup queries Apple would otherwise collect. 2 is opted out; +# the key is simply absent until the switch is touched, which is what makes +# opted *in* the default. An integer and not a bool, and this is the value the +# switch itself wrote — it appeared in `defaults read` the moment it went dark. +w com.apple.assistant.support "Search Queries Data Sharing Status" -int 2 + # # Spotlight — what is allowed to show up in results #