Running out of disk space on a Mac is rarely dramatic — it sneaks up on you. Caches accumulate, build artifacts pile up, and before long you're getting low-storage warnings at the worst possible moment. The fix isn't a single deep clean once a year; it's building a reliable automatic mac cleanup schedule that runs in the background and keeps things tidy without requiring your attention. This guide explains exactly how to set that up on macOS Sequoia and Tahoe, whether you're on Apple Silicon or an older Intel Mac.
Why Scheduled Cleanups Beat Reactive Ones
Most people only clean their Mac when something breaks — an app won't open, a download fails, or a Time Machine backup stalls because there's no free space. By then you're already behind. Scheduled cleanups work differently: small, regular passes remove the clutter that would otherwise compound. Caches cleared weekly never balloon into multi-gigabyte logs. Derived data flushed monthly means Xcode stays fast. The cumulative effect is a machine that feels consistently quick rather than one that needs emergency surgery every few months.
There's also a safety argument. Deleting stale files on a schedule — rather than in a panic — gives you time to verify backups are current before anything is removed. You're in control, not the storage alert.
What Actually Accumulates (and Where to Find It)
Before scheduling anything, it helps to know which folders grow fastest. The table below shows the most common offenders on a typical macOS developer or power-user machine, along with realistic size ranges after six to twelve months of normal use.
| Folder / Path | What It Stores | Typical Size After 6–12 Months | Safe to Delete? |
|---|---|---|---|
~/Library/Caches |
Per-user app caches (browser data, app thumbnails, frameworks) | 5–30 GB | Yes — apps rebuild as needed |
/Library/Caches |
System-wide and daemon caches | 1–10 GB | Yes, with care (quit related apps first) |
~/Library/Developer/Xcode/DerivedData |
Xcode build products and indexes | 10–60 GB | Yes — Xcode rebuilds on next open |
~/Library/Developer/Xcode/Archives |
Archived app builds | 5–40 GB | After you've submitted to App Store |
~/.m2/repository |
Maven / Java dependency cache | 2–15 GB | Yes — redownloaded on next build |
~/.cargo/registry |
Rust crate source cache | 1–8 GB | Yes — cargo clean or delete manually |
~/Library/Logs |
Application and crash logs | 100 MB–2 GB | Yes — logs older than 30 days rarely needed |
~/.Trash |
Items moved to Trash but not emptied | Varies widely | Yes, once you confirm you don't need them |
For a deeper look at what's eating your disk, this breakdown of what takes up space on a Mac is a good starting point before you set up any automation.
How to Schedule Automatic Cleanups Using launchd
macOS uses launchd as its native job scheduler — the same system that powers Time Machine, Spotlight indexing, and dozens of background daemons. You can write a small launch agent that runs a shell script on a schedule you define. Here's a step-by-step walkthrough.
Step 1: Write a cleanup shell script
Create a script at a path you control, for example ~/Library/Scripts/mac-cleanup.sh. A basic version might look like this:
#!/bin/zsh
# mac-cleanup.sh — weekly maintenance pass
# Clear user caches older than 7 days
find ~/Library/Caches -maxdepth 1 -mindepth 1 -atime +7 -exec rm -rf {} + 2>/dev/null
# Clear Xcode DerivedData older than 14 days
find ~/Library/Developer/Xcode/DerivedData -maxdepth 1 -mindepth 1 -atime +14 -exec rm -rf {} + 2>/dev/null
# Empty Trash
osascript -e 'tell application "Finder" to empty the trash'
# Log the run
echo "Cleanup ran at $(date)" >> ~/Library/Logs/mac-cleanup.log
Make the script executable: chmod +x ~/Library/Scripts/mac-cleanup.sh
Step 2: Create a launch agent plist
Save the following file to ~/Library/LaunchAgents/com.user.maccleanup.plist. This tells launchd to run your script every Sunday at 2:00 AM.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.maccleanup</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/YOUR_USERNAME/Library/Scripts/mac-cleanup.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>0</integer>
<key>Hour</key>
<integer>2</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/tmp/maccleanup.out</string>
<key>StandardErrorPath</key>
<string>/tmp/maccleanup.err</string>
</dict>
</plist>
Replace YOUR_USERNAME with your actual macOS username (run whoami in Terminal to confirm it).
Step 3: Load the agent
In Terminal, run:
launchctl load ~/Library/LaunchAgents/com.user.maccleanup.plist
To verify it loaded: launchctl list | grep maccleanup. You should see the label in the output. If you ever want to stop it: launchctl unload ~/Library/LaunchAgents/com.user.maccleanup.plist
Using macOS Built-In Storage Recommendations
macOS ships with its own light-touch cleanup features that you may already have but not use consistently. Under Apple menu > System Settings > General > Storage, you'll find:
- Store in iCloud — offloads Desktop and Documents files to iCloud when local space is tight.
- Optimize Storage — removes already-watched Apple TV content and keeps only recent email attachments locally.
- Empty Trash Automatically — deletes items that have been in the Trash for more than 30 days.
- Reduce Clutter — surfaces large and old files you might have forgotten about.
These are good defaults to enable regardless of any scripted automation you set up. They're conservative and non-destructive, so there's no reason to leave them off.
Scheduling Developer Tool Cleanups
Generic cache sweeps miss a lot of the biggest culprits on developer machines. Some tools have their own cleanup commands that are safer than deleting folders directly.
Xcode
Xcode's DerivedData folder at ~/Library/Developer/Xcode/DerivedData is the single largest accumulator for iOS and macOS developers. You can clear it from inside Xcode via Product > Clean Build Folder, or from the command line:
rm -rf ~/Library/Developer/Xcode/DerivedData
Add this to your weekly script. Xcode will regenerate DerivedData the next time you build — there's no data loss, only a slower first compile after the wipe.
Node / npm
Each project's node_modules directory can be several hundred megabytes. The best approach is to remove them from projects you're no longer actively working on. See how to clean up node_modules on Mac for a practical walkthrough, including a one-liner that finds all node_modules directories and reports their sizes before you delete anything.
Homebrew
Homebrew retains old versions of packages after upgrades. Run the following to clean up outdated formulae and their cached downloads:
brew cleanup --prune=30
The --prune=30 flag removes versions and downloads older than 30 days. Add this to your monthly launchd script for a hands-off approach.
Rust / Cargo
Cargo caches downloaded crate sources in ~/.cargo/registry and compiled artifacts in ~/.cargo/registry/cache. The cargo cache crate (install with cargo install cargo-cache) gives you fine-grained control:
cargo cache --autoclean
This removes outdated crate versions while keeping the ones your current projects depend on.
What to Audit Before You Automate
Automation is only as good as the targets you pick. Before scheduling any script, do one manual audit pass so you know roughly how much is in each folder and whether anything there is worth keeping. A tool like Crumb can audit all of these locations at once and show you what's safe to remove before anything is deleted — useful when you're setting up a schedule for the first time and want to establish a baseline.
When setting targets for your script, prefer using -atime (last access time) or -mtime (last modified time) with find rather than deleting entire directories blindly. This way, files that are still in active use stay put.
How Often Should You Run Each Type of Cleanup?
A reasonable cadence for most users looks like this:
- Weekly: Clear
~/Library/Cachessubdirectories older than 7 days, empty the Trash, purge old log files from~/Library/Logs. - Monthly: Clear Xcode DerivedData, run
brew cleanup --prune=30, sweep~/.m2/repositoryfor snapshot artifacts. - Quarterly: Review and remove Xcode Archives you've already shipped, audit
~/.cargo/registry, check for forgotten virtual environments in~/.pyenvor~/.virtualenvs.
If your Mac doubles as a build server or you run heavy CI workloads locally, shorten each interval by half. A machine compiling multiple projects a day accumulates DerivedData and cache files much faster than one used primarily for writing or design.
Verifying Your Schedule Is Working
Once you've loaded your launch agent, it's worth confirming it's actually firing. Check the log file you set up:
cat ~/Library/Logs/mac-cleanup.log
You should see a timestamped entry for each run. If the file is empty or missing after the scheduled time has passed, check the error output at /tmp/maccleanup.err for clues. Common issues include a wrong path to the script, a missing shebang line, or the Mac being asleep when the job was scheduled — for the last case, add a RunAtLoad key set to false and a StartInterval as a fallback, or simply use a time when your Mac is reliably awake.