Homebrew cleanup leaves old kegs in Cellar after brew upgrade
0 reputation · 15 Oct 2025, 03:37 UTC
0 reputation · 15 Oct 2025, 03:37 UTC
Disk usage keeps rising after brew upgrade because each formula version occupies its own versioned Cellar directory and the previous keg remains until cleanup runs. The supported removal path is brew cleanup, which deletes old kegs and download caches, yet retains any keg currently linked into the prefix or lying in the dependency closure of another installed keg.
The staleness window is configurable through environment variables such as HOMEBREW_CLEANUP_MAX_AGE_DAYS and HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS, but these thresholds are version-sensitive and must be confirmed locally. A dry run with brew cleanup -n lists candidates under the current policy, though it does not guarantee a later real cleanup will select the same set if the installed set or environment changes.
The unresolved decision is rollback versus reclamation. Homebrew has no supported downgrade command, so removing an old keg means reinstall is the only way back, yet cleanup cannot infer rollback intent. brew pin protects a formula from upgrade and cleanup, but unpinned old kegs receive no such protection; a keg merely downloadable via brew install is still treated as disposable.
What criteria does brew cleanup use to decide an unlinked keg is safe to delete when the formula has no installed dependents? Does the periodic full cleanup window override the max-age threshold in a way that removes kegs sooner than expected? Which inspection commands reliably distinguish a keg protected by dependency closure from one that is simply disposable?
brew cleanup actually deletesAn unlinked keg is removed when three conditions hold: it is not the version currently linked into the Homebrew prefix, the formula is not pinned, and no installed formula lists it as a dependency. The dependency closure is the decisive protection. A keg that could be reinstalled later is still disposable if nothing installed depends on it.
The periodic full cleanup window controlled by HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS can perform a more aggressive pass that removes eligible old kegs and caches without waiting for HOMEBREW_CLEANUP_MAX_AGE_DAYS. In practice, this means a keg may disappear sooner than the max-age setting suggests. Treat the exact defaults and interaction as version-sensitive; confirm them locally rather than assuming a fixed number of days.
brew uses --installed <formula> Empty output means no installed formula protects that keg.brew list --versions <formula> and inspect the symlink at $(brew --prefix)/opt/<formula>.brew cleanup -n This lists the exact kegs and caches that would be removed under the current policy. It is not a guarantee for a later run if the installed set or environment changes.brew config and brew doctor.Homebrew has no supported downgrade command. Once an old keg is deleted, reinstalling that exact version is the only recovery path. brew pin <formula> protects a formula from both upgrade and cleanup; unpinned old kegs receive no such protection.
If cleanup still removes kegs you expected to keep, share the output of brew cleanup -n and brew config. That detail changes the recommendation: either pin the formula, adjust the cleanup environment variables, or accept the reclamation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.