My MacBook had been getting steadily more sluggish for days: windows lagging when I switched between them, the editor pausing mid-keystroke, builds taking longer than they should. The instinct is to open Activity Monitor, sort by CPU, and look for the culprit. That’s what I did, and it didn’t tell me much.
So I asked Claude Code to take a look from the terminal. The answer wasn’t a runaway process. My Mac was out of memory.
Table of Contents
What the Numbers Actually Said
The machine has 16 GB of RAM and 8 cores. Load averages were around 5 to 6, which is busy but not the problem. The telling figure was swap:
vm.swapusage: total = 11264.00M used = 10896.50M free = 367.50M
Swap is disk that macOS uses as overflow when RAM runs out. It was 10.9 GB used out of 11.3 GB. Once swap is that full, everything slows down, because the system spends its time shuffling memory to and from disk instead of doing the work you asked for.
The machine had also been up for 10 days, so memory apps had long since let go of was still sitting in swap.
You can check your own with two commands:
sysctl vm.swapusage
memory_pressure | grep "free percentage"
Where the Memory Was Going
No single app was the villain. It was the sum of a normal developer day:
| What | Memory | Notes |
|---|---|---|
| VS Code | 2.4 GB | 7 windows open |
| Chrome | 2.0 GB | |
| Microsoft Teams | 1.5 GB | one web view alone was 1.1 GB |
| Docker | 2.8 GB | 4 MySQL containers, allowed to grow to 7.7 GB |
| Claude desktop | 1.25 GB | |
| Spotify | 1.0 GB | |
| Claude Code | 0.7 GB | 4 sessions |
To see this grouped by app rather than as hundreds of helper processes, this one-liner adds up resident memory per process name:
ps -Ao rss,comm | awk 'NR>1{c=$2; sub(/.*//,"",c); m[c]+=$1} END{for(k in m) printf "%7.0f MB %sn", m[k]/1024, k}' | sort -rn | head -15
Fix 1: Stop the Containers You Aren’t Using
This was the quickest win. I had four MySQL containers running, one per project, but I was only working on one of them. The other three were holding about 1.6 GB between them for nothing.
docker stats --no-stream
docker stop <the-ones-you-are-not-using>
Swap dropped from 10.9 GB to 7.2 GB straight away, with about 1 GB of it free again. Starting them back up later is just docker start.
It’s also worth lowering Docker Desktop’s memory limit (Settings → Resources). Mine was allowed to grow to 7.7 GB on a 16 GB machine, which is almost half the RAM for a handful of databases. Around 4 GB is plenty for that.
Fix 2: Make VS Code Lighter Without Giving It Up
Teams is how I talk to my team and Spotify is how I get through the day, so quitting those wasn’t an option. VS Code is where there was real room, and I didn’t want to switch editors to get it.
Closing windows I wasn’t using had already brought VS Code from 2.4 GB down to about 1.2 GB. Each window is its own set of processes, typically 300 to 700 MB once extensions load. Three more changes help.
Only Load Heavy Extensions Where You Need Them
Some extensions run large background processes in every window, whether or not that window has anything for them to do. In my case:
- PlatformIO and C/C++, which I only need for firmware work.
- Python and Pylance, which I only need for the Python projects.
In the Extensions panel, right-click each one and choose Disable. Then open the project that needs it and choose Enable (Workspace). The extension now only loads where it’s used. PlatformIO in particular also starts its own background tooling, so this makes a noticeable difference.
Stop VS Code Watching Generated Folders
VS Code watches files so it can react to changes, and it indexes them for search. In a monorepo, that includes every node_modules, a PHP vendor folder, and build output. Add this to your user settings (Cmd+Shift+P → Preferences: Open User Settings (JSON)):
"files.watcherExclude": {
"**/node_modules/**": true,
"**/vendor/**": true,
"**/out/**": true,
"**/storage/**": true,
"**/.claude/worktrees/**": true
},
"search.exclude": {
"**/node_modules": true,
"**/vendor": true,
"**/out": true
}
The last watcher entry is specific to working with Claude Code: when it runs agents in parallel, it creates git worktrees under .claude/worktrees, and each one is a full copy of the repository for VS Code to watch.
Don’t Reopen Every Window on Launch
If you mostly work through Claude and keep VS Code for editing, one window for the repo you’re in is enough. This stops VS Code restoring every window from last time:
"window.restoreWindows": "none"
Fix 3: Use a Lighter Editor for Peeking
For quickly reading code, rather than working in it, Zed uses a fraction of VS Code’s memory. I’m keeping VS Code as my main editor because it’s what I’m comfortable in, but opening Zed to look something up is a cheap way to avoid another heavy window.
Fix 4: Restart Occasionally
After 10 days, a restart is the quickest way to empty swap completely. Nothing clever, but it works.
The Takeaway
If your Mac feels slow and nothing is maxing out the CPU, check swap before anything else. On a 16 GB developer machine, the usual cause isn’t one bad app. It’s containers you forgot were running, editor windows you forgot were open, and extensions loading everywhere when you need them in one place.

Leave a Reply
You must be logged in to post a comment.