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
Since #17508, autoremove keeps every formula that was built from source because it may take a while to install again. 88 of my 194 formulae were built from source, so unused ones pile up. Three of them (googletest, jansson and libmagic) came from a clamav build I stopped partway through.
It's opt-in because of #17433, and once set it also applies to the automatic runs from brew cleanup and brew uninstall. It only overrides the rule that keeps the formula itself, so build dependencies of the remaining source-built formulae stay. Here that removes 7 formulae (22M) and keeps cmake and ghc, whereas dropping that protection too would remove 25 (2.5G).
Without the variable, an explicit brew autoremove now lists what it's keeping and names the variable, so the empty output no longer looks like a bug. A warning like this was agreed in #13831 but never landed. Automatic runs stay quiet.
#13831 argued against adding more options, but since #17508 there's no other way to have autoremove clean up after source builds.
Have you checked for other open Pull Requests for the same change?
Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
Have you explained why you'd like these changes included, not just what they do?
For bug fixes, have you given step-by-step brew commands to reproduce the bug?
Have you written new tests (excluding integration tests)? Here's an example.
Have you successfully run brew lgtm (style, typechecking and tests) locally?
I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.
Claude Code (Claude Opus 5.5) traced why autoremove kept these formulae, read the #13831 and #17508 history, wrote the change and its specs and verified them. The new specs fail without the change and pass with it. It ran brew autoremove from this branch on my real install, first with --dry-run with and without the variable, then for real with the variable, which removed the 7 formulae above. It also ran brew lgtm, which passes. env_config.rbi was regenerated with tapioca dsl Homebrew::EnvConfig.
- `brew autoremove` keeps every unused formula built from source, so on
machines where most formulae are built from source it finds nothing.
- Add `HOMEBREW_AUTOREMOVE_BUILT_FROM_SOURCE` to remove them anyway.
Build dependencies of the remaining source builds are still kept.
- Warn about the kept formulae when `brew autoremove` is run explicitly,
as agreed in #13831, so the empty output doesn't look like a bug.
HaraldNordgren
changed the title
autoremove: warn about formulae built from source
autoremove: allow removing source-built formulae
Nov 4, 2026
brew autoremove now warns when unused formulae built from source are kept and explains how to include them in removal.
Set HOMEBREW_AUTOREMOVE_BUILT_FROM_SOURCE=1 to remove unused formulae built from source with brew autoremove, brew cleanup and brew uninstall. Build dependencies needed by remaining source-built formulae are retained.
Documentation
Added details about this setting to the environment-variable documentation.
Autoremove candidate selection now supports a configurable policy for formulae built from source. Cleanup can report candidates excluded by that policy. The environment variable, command integration, tests, and documentation cover this behaviour.
Autoremove utility methods accept keep_built_from_source: and pass it through recursive candidate searches. Tests cover formula filtering when the option is false.
Cleanup calculates candidates using the configured source-build policy and can report candidates excluded by that policy. The autoremove command enables the warning. Tests and documentation describe the environment variable.
Merge Risk: Low · up to f64ff
The opt-in can remove build dependencies that users expect to keep. These bounded issues should be fixed or accepted before merging.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title clearly and concisely summarises the main change: allowing autoremove to remove formulae built from source.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Description check
The description directly explains the autoremove changes, the new environment variable, the source-built formula behaviour, and the related tests and commands.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
- The warning lists everything the variable would remove, including
bottled formulae only needed by a formula built from source.
- Pin that so the list stays in step with what gets removed.
The reason will be displayed to describe this comment to others. Learn more.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
⚠️ Outside diff range comments (2)
Minor · Keep build dependencies of source-built formulae that casks require. · autoremove.rb:18-19
Library/Homebrew/utils/autoremove.rb:18-19 Minor · Functional Correctness · Quick win
Keep build dependencies of source-built formulae that casks require.
When HOMEBREW_AUTOREMOVE_BUILT_FROM_SOURCE is set, a source-built formula that a cask requires can still be selected as unused. The recursive pass then removes it from its input, so its build dependencies are no longer protected. The later cask filter keeps that formula. It does not restore protection for its build dependencies. The InstalledDependents check after selection reads runtime dependencies only, so it does not protect build-only edges either.
The installed formula keeps working. A later rebuild from source may fail or require reinstalling the removed build dependency.
Apply the cask check during candidate selection. The protected formula then stays in the input, and its build dependencies stay protected.
- sig { params(formulae: T::Array[Formula], keep_built_from_source: T::Boolean).returns(T::Array[Formula]) }- def unused_formulae_with_no_formula_dependents(formulae, keep_built_from_source: true)+ sig {+ params(formulae: T::Array[Formula], keep_built_from_source: T::Boolean,+ protected_names: T::Set[String]).returns(T::Array[Formula])+ }+ def unused_formulae_with_no_formula_dependents(formulae, keep_built_from_source: true, protected_names: Set.new)
unused_formulae = bottled_formulae_with_no_formula_dependents(formulae, keep_built_from_source:).select do |f|
tab = f.any_installed_keg&.tab
next unless tab
next unless tab.installed_on_request_present?
+ next if protected_names.intersect?(f.possible_names)
tab.installed_on_request == false
end
unless unused_formulae.empty?
- unused_formulae += unused_formulae_with_no_formula_dependents(formulae - unused_formulae,- keep_built_from_source:)+ unused_formulae += unused_formulae_with_no_formula_dependents(formulae - unused_formulae,+ keep_built_from_source:,+ protected_names:)
end
Minor · Qualify the build-dependency guarantee for… · env_config.rb:107-112
Library/Homebrew/env_config.rb:107-112 Minor · Functional Correctness · Quick win
Qualify the build-dependency guarantee for HOMEBREW_NO_CLEANUP_FORMULAE.
The description says that build dependencies of remaining source-built formulae are kept. That does not hold for formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE, or for their installed runtime dependencies. Autoremove removes those formulae from its input before it selects candidates. Their build dependencies then lose that protection, and they can be removed unless another rule keeps them. Reinstalling a removed source-built build dependency can be slow, which the PR is meant to avoid.
Suggested fix
description: "If set, `brew autoremove`, `brew cleanup` and `brew uninstall` will also remove unused " \
"formulae that were built from source. Build dependencies of the remaining formulae that " \
- "were built from source are still kept.",+ "were built from source are still kept. This rule does not keep build dependencies of " \+ "formulae listed in `HOMEBREW_NO_CLEANUP_FORMULAE`, or of their installed runtime " \+ "dependencies. Other rules can still keep them.",
boolean: true,
Regenerate manpages/brew.1 and docs/Manpage.md from the same description text. The docs/Manpage.md body was not inspected, so this change is not shown as a diff for that file.
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 9f04e501-a62c-48f9-af7f-b42f41edd6ee
Commits
Reviewing files that changed from the base of the PR and between 4666d39 and f64ffd9.
Files selected for processing: 1
Library/Homebrew/test/cleanup_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Would rather we reconsider the default rather than adding a new environment variable. Is it "safer" than it was before now, yeh? What cases are now better covered than before?
Thanks!
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On my macOS 12 machine,
brew autoremovecan't clean up anything.brew leavessays nothing needsmakedepend, but autoremove keeps it:Since #17508, autoremove keeps every formula that was built from source because it may take a while to install again. 88 of my 194 formulae were built from source, so unused ones pile up. Three of them (
googletest,janssonandlibmagic) came from aclamavbuild I stopped partway through.Setting
HOMEBREW_AUTOREMOVE_BUILT_FROM_SOURCElets autoremove remove them:It's opt-in because of #17433, and once set it also applies to the automatic runs from
brew cleanupandbrew uninstall. It only overrides the rule that keeps the formula itself, so build dependencies of the remaining source-built formulae stay. Here that removes 7 formulae (22M) and keepscmakeandghc, whereas dropping that protection too would remove 25 (2.5G).Without the variable, an explicit
brew autoremovenow lists what it's keeping and names the variable, so the empty output no longer looks like a bug. A warning like this was agreed in #13831 but never landed. Automatic runs stay quiet.#13831 argued against adding more options, but since #17508 there's no other way to have autoremove clean up after source builds.
brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Claude Code (Claude Opus 5.5) traced why autoremove kept these formulae, read the #13831 and #17508 history, wrote the change and its specs and verified them. The new specs fail without the change and pass with it. It ran
brew autoremovefrom this branch on my real install, first with--dry-runwith and without the variable, then for real with the variable, which removed the 7 formulae above. It also ranbrew lgtm, which passes.env_config.rbiwas regenerated withtapioca dsl Homebrew::EnvConfig.