Maven .m2 Repository Taking Up Too Much Disk Space on Mac?

How ~/.m2/repository, sbt caches, and Ivy quietly consume 5-30GB -- and how to clean them safely

If you develop Java, Scala, or Kotlin on macOS, you've likely never thought about the ~/.m2/repository directory. That's by design -- Maven downloads dependencies silently and stores them forever. After a year or two of active JVM development, this directory alone can consume 5-30GB of your SSD.

Add sbt's Ivy cache, Coursier cache, and build output directories, and JVM development can easily eat 40-60GB of disk space across all your projects. This guide covers how to find, audit, and safely clean every JVM build tool cache on macOS.

5-20GB
~/.m2/repository
3-10GB
~/.sbt + ~/.ivy2
2-8GB
~/.cache/coursier
5-30GB
target/ directories

Where Maven Stores Everything on macOS

Maven's local repository is a directory tree mirroring the Maven Central coordinates (groupId/artifactId/version). Every dependency you've ever used gets cached here permanently:

LocationWhat's InsideTypical Size
~/.m2/repositoryAll downloaded JARs, POMs, sources, javadocs5-20GB
~/.m2/repository/.cacheMaven resolver metadata cache100-500MB
~/.m2/wrapperMaven wrapper distributions200-800MB
~/.m2/settings.xmlConfiguration (keep this!)Tiny
project/target/Build outputs per project500MB-3GB each

Quick Audit: How Much Space Are You Losing?

Run this to get the full picture of JVM cache usage on your Mac:

# Maven local repository
du -sh ~/.m2/repository 2>/dev/null

# Maven wrapper distributions
du -sh ~/.m2/wrapper/dists 2>/dev/null

# sbt caches
du -sh ~/.sbt 2>/dev/null
du -sh ~/.ivy2 2>/dev/null

# Coursier cache (used by sbt, scala-cli, cs)
du -sh ~/.cache/coursier 2>/dev/null
du -sh ~/Library/Caches/Coursier 2>/dev/null

# Scala/Metals/Bloop caches
du -sh ~/.bloop 2>/dev/null
du -sh ~/.cache/metals 2>/dev/null

# Kotlin daemon & caches
du -sh ~/.kotlin/daemon 2>/dev/null

# Find ALL target/ dirs across projects
find ~/Projects -name "target" -type d -maxdepth 4 -exec du -sh {} + 2>/dev/null | sort -rh | head -20

# TOTAL snapshot of all JVM caches
echo "=== JVM Build Tool Disk Usage ==="
for dir in ~/.m2 ~/.sbt ~/.ivy2 ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.kotlin; do
    [ -d "$dir" ] && echo "$(du -sh "$dir" 2>/dev/null)"
done
Tip: The target/ directories across all your Maven and sbt projects often dwarf the shared cache. A single Spring Boot project can produce a 500MB+ target/ directory.

Cleaning Maven's Local Repository

1. Remove Old SNAPSHOT Versions

SNAPSHOT dependencies are development versions that change frequently. Old snapshots are never cleaned automatically:

# Find all SNAPSHOT directories
find ~/.m2/repository -type d -name "*SNAPSHOT*" -exec du -sh {} + 2>/dev/null | sort -rh

# Remove all SNAPSHOTs (safe -- they'll re-download)
find ~/.m2/repository -type d -name "*SNAPSHOT*" -exec rm -rf {} + 2>/dev/null

# Remove SNAPSHOT JARs older than 60 days
find ~/.m2/repository -path "*SNAPSHOT*" -name "*.jar" -mtime +60 -delete

2. Remove Old Versions of Dependencies

When dependencies get updated, the old version stays in .m2 forever. You can clean versions you haven't used recently:

# Find JARs not accessed in 90+ days
find ~/.m2/repository -name "*.jar" -atime +90 -exec du -sh {} + 2>/dev/null | sort -rh | head -30

# Remove dependency files not accessed in 6 months
find ~/.m2/repository -name "*.jar" -atime +180 -delete
find ~/.m2/repository -name "*.pom" -atime +180 -delete

# Clean up empty directories afterward
find ~/.m2/repository -type d -empty -delete
Warning: Access time tracking must be enabled on your filesystem for -atime to work reliably on macOS. If unsure, use -mtime (modification time) instead.

3. Maven Dependency Purge Plugin

Maven has a built-in plugin for cleaning the local repository intelligently:

# Purge all SNAPSHOTs from local repo
mvn dependency:purge-local-repository -DsnapshotsOnly=true

# Re-resolve and download fresh copies
mvn dependency:purge-local-repository -DreResolve=true

# Purge specific groups
mvn dependency:purge-local-repository \
    -DmanualInclude=com.example:my-lib

# List what would be purged (dry run)
mvn dependency:purge-local-repository -DactTransitively=false -Dverbose=true

4. Clean Maven Wrapper Distributions

# Check wrapper distributions
du -sh ~/.m2/wrapper/dists/*

# Remove all but keep settings.xml
rm -rf ~/.m2/wrapper/dists/*

# Remove metadata cache
rm -rf ~/.m2/repository/.cache

Cleaning sbt Caches (Scala Developers)

sbt uses Ivy for dependency resolution (sbt 0.x/1.x) and Coursier (sbt 1.3+). Both download dependencies independently of Maven:

LocationWhat's InsideSafe to Delete?
~/.sbtsbt boot, plugins, global settingsCaches yes, settings no
~/.ivy2/cacheIvy-resolved dependency JARsYes (re-downloads)
~/.ivy2/localLocally published artifactsMaybe (check first)
~/.cache/coursierCoursier dependency cacheYes (re-downloads)
~/Library/Caches/CoursierCoursier macOS cacheYes (re-downloads)
~/.bloopBloop build server cacheYes (regenerates)
~/.cache/metalsMetals LSP cache (IntelliJ/VSCode)Yes (re-indexes)
# Clean sbt boot & plugin caches
rm -rf ~/.sbt/boot
rm -rf ~/.sbt/1.0/plugins/target
rm -rf ~/.sbt/1.0/target

# Clean Ivy cache
rm -rf ~/.ivy2/cache
rm -rf ~/.ivy2/local   # Only if you don't publishLocal

# Clean Coursier cache
rm -rf ~/.cache/coursier/v1
rm -rf ~/Library/Caches/Coursier/v1

# Clean Bloop & Metals
rm -rf ~/.bloop
rm -rf ~/.cache/metals

# Using coursier CLI
cs cleanup   # if cs is installed

Cleaning Kotlin & Build Server Caches

# Kotlin daemon files
du -sh ~/.kotlin/daemon 2>/dev/null
rm -rf ~/.kotlin/daemon

# Kotlin/Native cache
du -sh ~/.konan 2>/dev/null
rm -rf ~/.konan/cache
rm -rf ~/.konan/dependencies

# IntelliJ caches (from JVM development)
du -sh ~/Library/Caches/JetBrains/ 2>/dev/null

# IntelliJ local history & index
du -sh ~/Library/Caches/JetBrains/IntelliJIdea*/caches 2>/dev/null
Tip: Kotlin/Native's ~/.konan directory can reach 2-5GB on its own. It stores prebuilt binaries for all target platforms even if you only target one.

Bulk Cleaning target/ Directories

Every Maven and sbt project creates a target/ directory for compiled classes, packaged JARs, and intermediate build outputs. These add up fast:

# Find all JVM target/ directories, sorted by size
find ~/Projects -name "target" -type d \
    \( -path "*/src/*" -prune -o -print \) \
    -exec du -sh {} + 2>/dev/null | sort -rh | head -20

# Delete target/ in projects not touched in 30+ days
find ~/Projects -name "target" -type d -maxdepth 4 -mtime +30 \
    -exec echo "Removing: {}" \; -exec rm -rf {} + 2>/dev/null

# Maven multi-module: clean all sub-modules
cd ~/Projects/my-project && mvn clean

# sbt equivalent
cd ~/Projects/my-scala-project && sbt clean

Using ClearDisk to Monitor JVM Caches

ClearDisk -- Free, Open-Source Cache Monitor for macOS

Instead of running audit commands manually, ClearDisk sits in your menu bar and monitors all JVM caches alongside other developer tool caches:

View on GitHub -- MIT License, Swift/SwiftUI, macOS 14+

Install: brew tap bysiber/cleardisk && brew install --cask cleardisk

Automated Monthly Cleanup Script

Save this as ~/.local/bin/jvm-cache-cleanup.sh and run it monthly:

#!/bin/bash
# JVM Build Tool Cache Cleanup Script for macOS
# Safely cleans Maven, sbt, Coursier, and build outputs

set -euo pipefail

echo "=== JVM Cache Audit ==="

# Pre-cleanup sizes
echo "--- Current Sizes ---"
for dir in ~/.m2/repository ~/.sbt ~/.ivy2 ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.konan ~/.kotlin; do
    [ -d "$dir" ] && echo "$(du -sh "$dir" 2>/dev/null)"
done

TOTAL_BEFORE=$(du -shc ~/.m2/repository ~/.sbt ~/.ivy2 ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.konan ~/.kotlin 2>/dev/null | tail -1 | cut -f1)
echo "Total before: $TOTAL_BEFORE"

# 1. Remove SNAPSHOTs older than 30 days
echo -e "\n--- Cleaning old SNAPSHOTs ---"
find ~/.m2/repository -path "*SNAPSHOT*" -name "*.jar" -mtime +30 -delete 2>/dev/null
find ~/.m2/repository -type d -name "*SNAPSHOT*" -empty -delete 2>/dev/null

# 2. Remove Maven metadata cache
rm -rf ~/.m2/repository/.cache 2>/dev/null

# 3. Clean Ivy cache (sbt re-downloads via Coursier)
rm -rf ~/.ivy2/cache 2>/dev/null

# 4. Clean Coursier cache entries older than 60 days
find ~/.cache/coursier -type f -mtime +60 -delete 2>/dev/null
find ~/Library/Caches/Coursier -type f -mtime +60 -delete 2>/dev/null

# 5. Clean Bloop & Metals
rm -rf ~/.bloop 2>/dev/null
rm -rf ~/.cache/metals 2>/dev/null

# 6. Clean Kotlin daemon
rm -rf ~/.kotlin/daemon 2>/dev/null

# 7. Clean stale target/ directories (30+ days old)
echo -e "\n--- Cleaning stale target/ dirs ---"
find ~/Projects -name "target" -type d -maxdepth 4 -mtime +30 \
    -exec echo "  Removed: {}" \; -exec rm -rf {} + 2>/dev/null

# Post-cleanup sizes
echo -e "\n--- After Cleanup ---"
for dir in ~/.m2/repository ~/.sbt ~/.ivy2 ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.konan ~/.kotlin; do
    [ -d "$dir" ] && echo "$(du -sh "$dir" 2>/dev/null)"
done

TOTAL_AFTER=$(du -shc ~/.m2/repository ~/.sbt ~/.ivy2 ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.konan ~/.kotlin 2>/dev/null | tail -1 | cut -f1)
echo -e "\nTotal after: $TOTAL_AFTER (was: $TOTAL_BEFORE)"
echo "Done! JVM caches cleaned."

How Maven .m2 Grows Over Time

Maven's local repository grows because:

A typical Spring Boot project can add 300-500MB to .m2 from dependencies alone. After working on 10+ projects over a year, 10GB+ is common.

The Cross-Tool Duplication Problem

The worst part of JVM build tool caches is duplication. If you use multiple build tools, the same JARs get cached multiple times:

DependencyMaven LocationGradle LocationCoursier Location
guava-32.1.jar~/.m2/repository/com/google/guava/~/.gradle/caches/modules-2/~/.cache/coursier/v1/
jackson-core-2.15.jar~/.m2/repository/com/fasterxml/~/.gradle/caches/modules-2/~/.cache/coursier/v1/
slf4j-api-2.0.jar~/.m2/repository/org/slf4j/~/.gradle/caches/modules-2/~/.cache/coursier/v1/

Each popular library gets stored 2-3 times across different cache directories. There's no deduplication between Maven, Gradle, and Coursier.

Note: Gradle can use mavenLocal() to read from ~/.m2/repository, but it still copies artifacts to its own cache. This doesn't save space -- it doubles it.

IntelliJ IDEA Cache Cleanup

If you use IntelliJ for JVM development, its caches compound the problem:

# IntelliJ caches
du -sh ~/Library/Caches/JetBrains/IntelliJIdea* 2>/dev/null
du -sh ~/Library/Caches/JetBrains/IdeaIC* 2>/dev/null

# IntelliJ local index (can be huge)
du -sh ~/Library/Caches/JetBrains/IntelliJIdea*/caches 2>/dev/null

# IntelliJ system (logs, plugins)
du -sh ~/Library/Application\ Support/JetBrains/ 2>/dev/null

# Safe to clean: invalidate caches from within IntelliJ
# File -> Invalidate Caches -> Invalidate and Restart

# Or manually remove old version caches
# (keep only the latest version directory)
ls -la ~/Library/Caches/JetBrains/
Tip: IntelliJ keeps caches for every version you've ever installed. After upgrading, old version caches remain. Check for directories like IntelliJIdea2023.3 when you're running 2025.x.

Quick Reference Cheatsheet

# === MAVEN ===
du -sh ~/.m2/repository                # check size
rm -rf ~/.m2/repository/.cache         # metadata cache
mvn dependency:purge-local-repository  # smart purge
find ~/.m2 -name "*SNAPSHOT*" -type d -exec rm -rf {} + # old snapshots

# === SBT ===
rm -rf ~/.ivy2/cache                   # Ivy cache
rm -rf ~/.sbt/boot                     # sbt boot files
rm -rf ~/.cache/coursier/v1            # Coursier cache
rm -rf ~/Library/Caches/Coursier/v1    # macOS Coursier

# === KOTLIN ===
rm -rf ~/.kotlin/daemon                # daemon files
rm -rf ~/.konan/cache                  # K/N cache

# === BUILD SERVERS ===
rm -rf ~/.bloop                        # Bloop cache
rm -rf ~/.cache/metals                 # Metals cache

# === BUILD OUTPUTS ===
find ~/Projects -name "target" -type d -maxdepth 4 -exec du -sh {} + 2>/dev/null | sort -rh

# === NUCLEAR (ALL JVM CACHES) ===
rm -rf ~/.m2/repository ~/.ivy2/cache ~/.cache/coursier ~/Library/Caches/Coursier ~/.bloop ~/.cache/metals ~/.kotlin/daemon ~/.konan/cache

Frequently Asked Questions

How much space can I recover from Maven caches?

Typically 5-20GB from ~/.m2/repository alone. If you add sbt/Coursier/Kotlin caches and target/ directories, total recovery can reach 30-50GB for active JVM developers.

Is it safe to delete ~/.m2/repository?

Yes. It only contains downloaded dependencies. Maven re-downloads everything on the next build. Your first build will be slower, but nothing breaks permanently. Keep ~/.m2/settings.xml intact -- it holds your configuration.

Will cleaning .m2 affect Gradle?

Only if your Gradle builds use mavenLocal(). Gradle has its own cache at ~/.gradle/caches/. See our Gradle Cleanup Guide for that.

How do I prevent .m2 from growing so large?

Unfortunately, Maven has no built-in cache eviction. The best approach is periodic cleanup -- monthly for SNAPSHOTs, quarterly for the full repository. The dependency:purge-local-repository plugin helps but only works within a single project context.

What's the difference between .ivy2 and .cache/coursier?

Ivy is the older resolution engine used by sbt 1.2 and below. Coursier is the modern replacement used by sbt 1.3+. If you've upgraded sbt, the .ivy2 cache is likely stale and can be safely deleted.

Does ClearDisk handle all these caches?

ClearDisk monitors the common JVM cache locations (~/.m2, ~/.gradle, target/ directories) along with 15+ other developer tool caches. It's a free, open-source macOS menu bar app. Get it on GitHub.