You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HOMEBREW_VERSION: 5.1.14
ORIGIN: https://github.com/Homebrew/brew
HEAD: 10a163ac127624caa80cc5cc5a705e97f3615b0e
Last commit: 5 days ago
Branch: stable
Core tap JSON: 29 May 12:34 UTC
Core cask tap JSON: 29 May 12:34 UTC
HOMEBREW_PREFIX: /opt/homebrew
HOMEBREW_BROWSER: open
HOMEBREW_BUNDLE_USER_CACHE: /Users/jcf/.cache/bundle
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: max
HOMEBREW_DOWNLOAD_CONCURRENCY: 32
HOMEBREW_EDITOR: emacsclient --tty
HOMEBREW_FORBID_PACKAGES_FROM_PATHS: set
HOMEBREW_MAKE_JOBS: 16
HOMEBREW_NO_ENV_HINTS: set
Homebrew Ruby: 4.0.5 => /opt/homebrew/Library/Homebrew/vendor/portable-ruby/4.0.5_1/bin/ruby
CPU: 16-core 64-bit arm_brava
Clang: 21.0.0 build 2100
Git: 2.50.1 => /Applications/Xcode.app/Contents/Developer/usr/bin/git
Curl: 8.7.1 => /usr/bin/curl
macOS: 26.5-arm64
CLT: 26.5.0.0.1777544298
Xcode: 26.5
Metal Toolchain: N/A
Rosetta 2: false
What were you trying to do (and why)?
Maintain a small Brewfile with mas entries for the App Store apps I want Homebrew to install on a fresh setup, alongside formulae, casks, and taps. The Brewfile is generated from a Nix expression by nix-darwin's homebrew module, but the resulting Brewfile is unremarkable — mas "Tailscale", id: 1475387142 and similar lines for a handful of apps.
I expect brew bundle install --cleanup to remove things Homebrew installed but that are no longer in the Brewfile. I do not expect it to remove App Store apps that I installed by clicking "Get" in the App Store app years ago, and which Homebrew has never had any relationship with.
What happened (include all command output)?
Since #22395 (bundle: extend cleanup coverage, merged 2026-05-24), brew bundle cleanup uninstalls every Mac App Store app on the system that is not listed in the Brewfile, regardless of how the app got installed. The cleanup logic in bundle/extensions/mac_app_store.rb has no provenance tracking — it simply shells out to mas list, subtracts the Brewfile's mas entries, and runs mas uninstall on the remainder.
mas list reports every App Store app on the machine, regardless of how it was installed (App Store UI, mas install, Apple Configurator, MDM push). Homebrew cannot distinguish "installed via my Brewfile" from "installed via the App Store UI five years ago" — they look identical. Once the Brewfile has any mas line in it, every other App Store app becomes a cleanup candidate.
On my machine, a single darwin-rebuild switch after brew update self-updated to a post-#22395 version uninstalled these App Store apps with no warning, despite none of them being in the Brewfile and none of them having ever been installed via mas or Homebrew:
Darkroom
Screens 5
Infuse
JSON Peep (Safari extension)
Pixelmator Pro
Noir (Safari extension)
Xcode
These had been installed years ago via the App Store UI. They had nothing to do with Homebrew, were never listed in any Brewfile, and brew had never installed or upgraded them.
#22439 (merged 2026-05-28) patched one subset of the damage by skipping TestFlight apps (which mas list reports with id=0). That fix only addresses TestFlight; the broader case — App Store apps installed via the App Store UI — remains in place by design.
What did you expect to happen?
brew bundle cleanup should only uninstall MAS apps that Homebrew installed via a mas Brewfile entry. Apps installed via the App Store UI, MDM, or any non-Homebrew path should be left alone, exactly as they were prior to #22395.
If maintaining one-to-one parity between a Brewfile and mas list is a feature some users want, it should be opt-in (brew bundle cleanup --mas or --all invoked explicitly), not the default of brew bundle install --cleanup / --zap.
Currently the default makes it unsafe to have anymas line in a Brewfile unless the Brewfile is exhaustive — i.e. unless the user has declared every single App Store app they own. Most users do not maintain exhaustive Brewfiles for their personal Apple ID purchase history. The result is a silent, destructive default that surprised users and could not have been anticipated from the PR description (which does not flag any breaking-change risk for users with existing mas entries).
Three options, in order of decreasing strictness:
Revert MAS cleanup to its pre-bundle: extend cleanup coverage #22395 behaviour. Treat App Store apps as out-of-scope for brew bundle cleanup entirely. This is the safest default and matches the principle that a package manager should not delete software it didn't install.
Gate MAS cleanup behind an explicit opt-in flag that is not implied by --cleanup or --zap. For example, only run MAS cleanup when --mas or --all is passed. Plain brew bundle install --cleanup should not include mas in its scope.
At minimum, if the current default is retained, add a prominent release-note callout for the version that shipped bundle: extend cleanup coverage #22395, and have brew bundle install --cleanup print a one-time warning the first time it identifies MAS apps it would remove that were not installed by mas.
Downstream tools that wrap brew bundle (notably nix-darwin's homebrew module, which sets cleanup = "zap" by user choice and runs brew bundle install --cleanup --zap non-interactively during system activation) silently inherited the new destructive behaviour. Users of those tools had no opportunity to consent to the change.
# Prerequisite: at least one App Store app installed via the App Store UI# that is NOT a TestFlight build (so `mas list` reports a positive id).# e.g. Pages, Numbers, Xcode — anything bought with your Apple ID.
mas list
# 409201541 Pages (14.3)# 497799835 Xcode (26.5)# ...
cat > /tmp/Brewfile <<'EOF'mas "Tailscale", id: 1475387142EOF
brew bundle cleanup --file=/tmp/Brewfile
# Would uninstall Mac App Store apps:# Pages (409201541)# Xcode (497799835)# ...# Run `brew bundle cleanup --force` to make these changes.# Every App Store app the user has, except Tailscale, is now listed# as a cleanup candidate — even though `brew`/`mas` did not install# any of them.
brew doctoroutputVerification
brew updatetwice and am still able to reproduce my issue.brew doctoroutput" above saysYour system is ready to brewor a definitely unrelatedTiermessage.brew install wget. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.brew configoutputWhat were you trying to do (and why)?
Maintain a small Brewfile with
masentries for the App Store apps I want Homebrew to install on a fresh setup, alongside formulae, casks, and taps. The Brewfile is generated from a Nix expression bynix-darwin'shomebrewmodule, but the resulting Brewfile is unremarkable —mas "Tailscale", id: 1475387142and similar lines for a handful of apps.I expect
brew bundle install --cleanupto remove things Homebrew installed but that are no longer in the Brewfile. I do not expect it to remove App Store apps that I installed by clicking "Get" in the App Store app years ago, and which Homebrew has never had any relationship with.What happened (include all command output)?
Since #22395 (
bundle: extend cleanup coverage, merged 2026-05-24),brew bundle cleanupuninstalls every Mac App Store app on the system that is not listed in the Brewfile, regardless of how the app got installed. The cleanup logic inbundle/extensions/mac_app_store.rbhas no provenance tracking — it simply shells out tomas list, subtracts the Brewfile'smasentries, and runsmas uninstallon the remainder.mas listreports every App Store app on the machine, regardless of how it was installed (App Store UI,mas install, Apple Configurator, MDM push). Homebrew cannot distinguish "installed via my Brewfile" from "installed via the App Store UI five years ago" — they look identical. Once the Brewfile has anymasline in it, every other App Store app becomes a cleanup candidate.On my machine, a single
darwin-rebuild switchafterbrew updateself-updated to a post-#22395 version uninstalled these App Store apps with no warning, despite none of them being in the Brewfile and none of them having ever been installed viamasor Homebrew:These had been installed years ago via the App Store UI. They had nothing to do with Homebrew, were never listed in any Brewfile, and
brewhad never installed or upgraded them.#22439 (merged 2026-05-28) patched one subset of the damage by skipping TestFlight apps (which
mas listreports withid=0). That fix only addresses TestFlight; the broader case — App Store apps installed via the App Store UI — remains in place by design.What did you expect to happen?
brew bundle cleanupshould only uninstall MAS apps that Homebrew installed via amasBrewfile entry. Apps installed via the App Store UI, MDM, or any non-Homebrew path should be left alone, exactly as they were prior to #22395.If maintaining one-to-one parity between a Brewfile and
mas listis a feature some users want, it should be opt-in (brew bundle cleanup --masor--allinvoked explicitly), not the default ofbrew bundle install --cleanup/--zap.Currently the default makes it unsafe to have any
masline in a Brewfile unless the Brewfile is exhaustive — i.e. unless the user has declared every single App Store app they own. Most users do not maintain exhaustive Brewfiles for their personal Apple ID purchase history. The result is a silent, destructive default that surprised users and could not have been anticipated from the PR description (which does not flag any breaking-change risk for users with existingmasentries).Three options, in order of decreasing strictness:
brew bundle cleanupentirely. This is the safest default and matches the principle that a package manager should not delete software it didn't install.--cleanupor--zap. For example, only run MAS cleanup when--masor--allis passed. Plainbrew bundle install --cleanupshould not includemasin its scope.brew bundle install --cleanupprint a one-time warning the first time it identifies MAS apps it would remove that were not installed bymas.Downstream tools that wrap
brew bundle(notablynix-darwin'shomebrewmodule, which setscleanup = "zap"by user choice and runsbrew bundle install --cleanup --zapnon-interactively during system activation) silently inherited the new destructive behaviour. Users of those tools had no opportunity to consent to the change.Step-by-step reproduction instructions (by running
brewcommands)