PHP and Ruby Developers Have Cache Problems Too: Composer and Bundler
Composer's global cache and Ruby's gem store both grow without bound in the same way npm and pip do. Here's where they hide and what's safe to clear.
Every package manager in every language ecosystem makes the same trade: cache downloaded packages globally so the next install is fast, and never automatically evict anything. Node and Python get most of the attention because they’re the most common; PHP and Ruby developers accumulate the exact same problem, just more quietly.
du -sh ~/Library/Caches/composer
du -sh ~/.gem
du -sh ~/.rbenv/versions
Composer’s global cache
Composer caches every package version it has ever downloaded, keyed by package and version, so it never has to hit Packagist twice for the same thing:
composer config --global cache-dir
# usually ~/Library/Caches/composer on macOS
du -sh ~/Library/Caches/composer/files | sort -hr
This is unambiguously safe to clear — it exists purely to make composer install faster, and
Composer’s own tooling handles the clearing correctly (safer than a raw rm -rf since it also
resets Composer’s internal cache index):
composer clear-cache
Expect your next composer install on any project to take noticeably longer as it re-downloads
everything from Packagist — a one-time cost, same trade-off as every cache in this series.
Ruby’s gems: two different things people mean by “gems”
“Where are my Ruby gems” actually has two possible answers depending on how you installed Ruby, and confusing them is the most common mistake here.
System/Homebrew Ruby with system gems:
du -sh ~/.gem
gem list --local | wc -l # how many gems are actually installed
rbenv or rvm-managed Ruby (the more common modern setup):
du -sh ~/.rbenv/versions/*/lib/ruby/gems
# or for rvm
du -sh ~/.rvm/gems
Under rbenv, every Ruby version you’ve ever installed keeps its own full set of gems —
identical to the Gradle-version and JetBrains-version problem covered elsewhere in this series. If
you installed Ruby 3.0, 3.1, 3.2 and 3.3 over the years and only use 3.3 now, the other three are
carrying their own complete gem sets for nothing:
rbenv versions
# * 3.3.0 (set by /Users/you/.rbenv/version)
# 3.0.0
# 3.1.4
# 3.2.2
rbenv uninstall 3.0.0 # removes the Ruby version and every gem installed under it
Only do this for versions no project on disk actually requires — check for a .ruby-version file
before removing anything:
find ~ -name ".ruby-version" -exec cat {} \; -print 2>/dev/null
Bundler’s cache: per-project, not global
Bundler additionally supports a per-project vendor cache (vendor/bundle or vendor/cache) that
some teams commit to version control for reproducible installs without network access. This is
not the same category as the global caches above — it lives inside your project repository and
may be intentional. Don’t delete vendor/bundle reflexively; check whether it’s tracked in git
first:
git check-ignore vendor/bundle && echo "safe, it's gitignored" || echo "tracked — leave it alone"
Bundler’s actual global cache, separate from any project, lives here and is safe to clear the same way as everything else in this article:
du -sh ~/.bundle/cache
rm -rf ~/.bundle/cache
Summary
| Location | What it is | Safe to delete? |
|---|---|---|
~/Library/Caches/composer | Global Composer package cache | Yes — composer clear-cache |
~/.rbenv/versions/<old> | Full gem set for an unused Ruby version | Yes, if unused — check .ruby-version first |
~/.bundle/cache | Global Bundler cache | Yes |
<project>/vendor/bundle | Per-project vendored gems | Only if gitignored — check first |
The commands above are free and they work. DevCruft, a free Mac app for developers we’re building,
is being designed to catalogue every language ecosystem’s cache on your disk in one scan — Composer,
Ruby, Node, Python, Rust and Go alike — so you’re not running du across a dozen hidden folders by
hand. Join the waitlist to hear when it’s ready.
For the equivalent caches in other ecosystems, see Rust, Go and Python cache cleanup and the Java/Maven/Gradle guide.