Guide

Mac fan loud while coding? Find the build that is doing it.

The fan is reacting to a process. Here is how to find which one, which project started it, and how to stop it without losing unsaved work.

The fan is reacting to a process. Here is how to find which one, which project started it, and how to stop it without losing unsaved work.

The fan is reacting to a process. Here is how to find which one, which project started it, and how to stop it without losing unsaved work.

Fan noise is a symptom, so find the process

A loud fan means something has been using a lot of CPU for a while. On a developer Mac that is usually a build or a watcher: a Swift compile that never ends, a TypeScript watcher re-checking a whole monorepo, a webpack dev server you forgot in a tab, a Gradle daemon still warm from a project you closed an hour ago.

Guessing does not work because the loudest process is rarely the one in front of you. Measure instead.

Look with Activity Monitor or top

Activity Monitor (Applications > Utilities) sorted by the CPU column is the quickest look. Switch View to All Processes, because helpers like swift-frontend run under Xcode rather than as their own app.

From a terminal, top gives the same picture and refreshes on its own:

top -o cpu -n 8 -s 2

-o cpu sorts by CPU, -n 8 shows eight rows, -s 2 updates every two seconds. A process at 100 percent is using one core; 400 percent is four. The number to watch is not a spike during a build, which is normal, but a process that stays high after you stopped doing anything.

A one-shot list, useful for pasting into a note:

ps -Ao pid,ppid,%cpu,%mem,etime,command -r | head -12

-r sorts by CPU, etime tells you how long the process has been alive. A watcher that has run for six hours at 80 percent is your answer.

About kernel_task

If the top row is kernel_task at several hundred percent, that is not the cause. macOS uses kernel_task to take CPU time away from other processes when the Mac is hot, so a high value means the Mac is already thermally throttling. Look further down the list for the process that heated it up. Sorting by CPU time instead of percent (ps -Ao pid,time,command -r) often makes the real one obvious.

Two other names that show up and mean something else: mds_stores and mdworker are Spotlight indexing, which happens after a big install or a node_modules change and goes away on its own, and WindowServer rises when an app redraws constantly, often a terminal scrolling build output.

Trace it to the project

A row that says node or java is not enough. Get the full command line and the working directory:

ps -o pid,ppid,etime,command -p 48213 lsof -p 48213 -d cwd -Fn | tail -1

The command line names the tool and its arguments (tsc --watch, webpack serve, gradle --daemon). The second command prints the folder it runs in, which is the project. If the folder is somewhere you have not opened today, you found the forgotten one.

Walk up the parent chain when the hot process is a child. swift-frontend is spawned by xcodebuild or Xcode; node running esbuild may belong to vite, which belongs to npm run dev. ps -o ppid= -p <pid> gives the parent, and repeating it gets you to the terminal or editor that started everything.

The usual suspects and what they mean:

  • swift-frontend, clang. A compile or indexing pass. Normal while it lasts; suspicious when it keeps going with Xcode idle, which often points at SourceKit indexing a huge package.

  • tsc --watch, eslint --watch. Re-check the project on every save. Expensive on monorepos, and they never stop on their own.

  • webpack, vite, next dev. Dev servers. Fine in the tab you are using; wasteful in the five you are not.

  • gradle, java, kotlinc. The Gradle daemon stays alive after a build by default and can keep compiling in the background for Android Studio.

  • jest --watch, vitest. Test watchers re-run on changes, including changes made by other watchers.

  • cargo, go. cargo watch and go run loops behave the same way.

Stop it without losing work

Stop watchers and dev servers from the terminal they run in, with Ctrl+C, when you can find that terminal. When you cannot, send the termination signal to the PID you just identified:

kill 48213

Give it a couple of seconds. Build tools catch SIGTERM and exit cleanly. Only if the same PID is still there and still hot, use kill -9 48213. Do not kill the editor or Xcode itself to get rid of a child: quitting Xcode normally stops its build, and closing an integrated terminal stops what runs in it.

For Gradle specifically, ./gradlew --stop in the project ends the daemons the polite way.

Two prevention habits help more than any kill command: close dev servers when you switch projects, and run watchers with a narrower scope (tsc --watch -p packages/app rather than the repo root).

Doing this in Room Service

Room Service samples CPU and memory per process and keeps a Build Watchers list of the build and watch tools that belong to one of your projects: xcodebuild, swift, swift-frontend, clang, tsc, webpack, vite, next, nuxt, rollup, esbuild, parcel, jest, vitest, tailwindcss, gradle, java, kotlinc, npm, yarn, pnpm, bun, node, cargo, go, and deno, each resolved to the project folder it runs in. A tool at 45 percent CPU or more, or 8 percent of memory or more, gets a High CPU or High RAM badge with the figure. If it stays that way for two minutes you get a notification, at most once per half hour.

Each row has Open Project, Open in Terminal, and Quit Process. Quit asks once, sends SIGTERM, checks four times over about a second, and force quits only if the same PID is still running. A bell on the row asks to be told when the build finishes, which is useful for the long but legitimate ones.

Seeing the list is free. Quit Process needs Pro (Process Control). There is no watchers command in the CLI; over MCP, an agent can call list_watchers and, when the “Quit processes and stop watchers” group is on, stop_watcher, which never force quits.

Related

Frequently Asked Questions

Why is my Mac fan loud when I am not building anything?

Is kernel_task using 300 percent CPU the problem?

How do I find which project a node process belongs to?

Should I kill swift-frontend?

What does Room Service count as a build watcher?

Can Room Service stop a watcher automatically?

More guides