HeatLens

A short sample, only when you ask

Why is my Mac running hot?

HeatLens is a free menu-bar app for Apple Silicon Macs. Click once to see what's using your Mac, which project and tool started it, and what you can safely stop. It never stops anything without asking you first.

macOS 14 or later · Apple Silicon · free · signed and notarized

One scan reads

  • Thermal state
  • CPU per process
  • Memory and swap
  • Ports
  • Sleep blockers

Stay with what you're doing

Less guessing. More knowing.

A dev server from yesterday. An agent still thinking. A caffeinate a script forgot. HeatLens ties each busy process to the project and tool behind it, so you can tell work from leftovers at a glance.

  • OpenCode agent~/Projects/jarvis-demo Active work

    Top CPU contributor

    44% of one core across 2 processes. Ranked as work in progress, not junk.

  • next dev~/Projects/portfolio-demo Review

    Long-running dev server

    Up for 38 hours at 1.4% CPU. The card notes you may still have it open in a tab.

  • caffeinatePID 4120 Info

    Holding off sleep

    Since 14:02, from a script in portfolio-demo. Shown as information, not a fault.

How it works

Click, sample, read.

HeatLens lives in the menu bar, has no Dock icon, and does nothing until you ask. One scan is a short, bounded sample. Background watching, alerts and history are optional and off by default.

  1. Click the rings.

    The popover opens at once. It shows when you last scanned and one button. Until you press it, nothing is being measured.

  2. Scan for ten seconds.

    HeatLens measures how much CPU each process used over the sample, as the change between two readings, not the lifetime total. Pick 5, 10 or 15 seconds in Settings, and cancel any time.

  3. Read what it found.

    A one-line status first, then ranked findings. Each has its evidence, a confidence level, what it cannot prove, and the safe actions.

What it shows

Every number names its sample.

Observation and inference are kept apart. Every figure says where it came from, and every label says how sure HeatLens is.

  • Active work, then leftovers.

    Findings are ranked by measured impact right now. A video export at 80% CPU is active work, not junk. A two-day-old idle worker with parent PID 1 is a review candidate, never a verdict.

  • Where a process came from.

    Processes are grouped by parent tree and the tool that started them. The project comes from the working directory or script path, with a confidence level. When it can't tell, it says Unknown project.

  • Thermal and memory state.

    The thermal state macOS itself publishes, busy cores, memory pressure and swap. No temperature reading and no GPU percentage, because no supported API provides a reliable one.

  • Who holds each port.

    After a scan, a Ports section shows which process and which project holds each listening TCP port. Click a row to inspect it, then use the usual actions.

  • Ask your AI agent.

    A read-only MCP server ships inside the app. Settings copies the setup command for Claude Code or Codex. Your agent can scan, list ports or check what's keeping the Mac awake, but it can't stop anything, and reports are redacted.

  • What's keeping it awake.

    When your Mac won't sleep, the results show which process holds it awake, in which project, and since when. Media and downloads do this on purpose, so it's listed as information.

  • From the terminal

    The same read-only tool ships at HeatLens.app/Contents/Helpers/heatlens. Scan or list ports, as text or JSON.

  • A heads-up when it runs hot

    Optional, off by default. On serious thermal pressure, one scan and one notification naming the likely culprit, at most every 30 minutes.

  • Clear a project's leftovers

    One confirmation lists every leftover with a checkbox. Each one is re-checked right before HeatLens signals it.

  • Since last scan

    Scan again to see what changed: CPU 6.1 → 1.4 cores, and which processes are gone.

  • Open it from anywhere

    Turn on ⌃⌥H in Settings and HeatLens opens from any app, without reaching for the menu bar.

  • Menu bar only

    No Dock icon and no window to manage. Launch at login is off until you turn it on.

  • Idle means idle

    Out of the box, no timers and no polling. Measured idle at 0.0% CPU and about 18 MB of memory.

  • Nothing kept

    By default, apart from your settings, nothing is stored after you quit. Keep history is optional, off by default, and local.

  • Copy the results

    Copy the scan as a plain-text report or as JSON, to paste into an issue or a chat.

Knows your stack

Dev servers, agents and the rest.

HeatLens names the tool behind each process tree, so a scan reads like your day, not like a process table.

Dev servers, builds and test runners

  • Next.js
  • Vite
  • Astro
  • Webpack
  • Turbo
  • Vitest
  • Jest
  • tsc --watch
  • Node
  • Bun
  • npm
  • pnpm
  • yarn

Agents and the apps around them

  • Claude Code
  • Codex
  • OpenCode
  • Gemini CLI
  • Docker

Anything else is grouped by its parent tree. When HeatLens can't place a process, it says Unknown project rather than guessing.

Safe by construction

It reads. You decide.

The one thing HeatLens can change on your Mac is to send a single, polite stop signal to a process you own, and only after you have read the confirmation and clicked. Force Quit and stopping a container exist too, behind off-by-default switches, each with its own confirmation.

  • Fully offline

    No network access except an update check when you click it. No account, no telemetry, no analytics, no crash reports.

  • Read-only diagnosis

    It reads the process table and counters macOS exposes to any app. It never opens your files, shell history, environment or agent transcripts, and asks for no permissions.

  • A stop is one SIGTERM, confirmed

    Sent to one PID, after re-checking it is still the same process. No force-quit unless you turn on that off-by-default switch, no bulk kill, and HeatLens tells you what happened.

  • Protected processes get no stop control

    HeatLens only ever offers to stop processes you own. These never get the button:

    • kernel_task
    • WindowServer
    • launchd
    • loginwindow
    • Finder
    • Dock
    • Spotlight
    • root-owned
    • other users'
    • Apple system binaries

Questions

A few things you might be wondering.

Will macOS let me open it?

Yes. Each release is signed with an Apple Developer ID and notarized by Apple, and the notarization ticket is stapled to the disk image, so Gatekeeper opens it without an "unidentified developer" warning. Open the DMG, drag HeatLens to Applications, and launch it. If you want to check for yourself before opening:

spctl -a -t open --context context:primary-signature -vv HeatLens.dmg
Why doesn't it ask for any permissions?

Because it only reads what macOS already lets any app read about running processes: process IDs, parents, start times, executables, CPU and memory counters, and for your own processes the command line and working directory. That is enough to explain most heat and pressure. It does not request Full Disk Access, Accessibility, Screen Recording or an admin password, and it would not learn anything useful from them.

The one exception is optional: if you turn on the thermal alert, macOS asks once whether HeatLens may show notifications.

The flip side is what it can't see: details of root and other users' processes, kernel_task's numbers, the chip temperature, and GPU load. Those places show Not accessible or Unavailable.

Does it run in the background?

Not by default. Out of the box HeatLens has no timers and no polling; it scans when you click Scan now, or once when macOS reports serious heat if you turned on the optional thermal alert. If you turn on Keep watching in the background, it samples every 30 seconds on power and 60 on battery (more often while something is busy, every 120 seconds in Low Power Mode), at a cost of a fraction of a percent of one core; Quit stops it. Measured on the development Mac, the idle app sits at 0.0% CPU with no change in CPU time between samples, and about 18 MB of memory as reported by top. A scan costs about one second of CPU spread over its five to ten seconds. Launch at login is off by default.

Does connecting an AI agent send my data anywhere?

HeatLens itself makes no network connections apart from the update check you click; the MCP server runs on your Mac over standard input and output. But whatever the agent receives, it sends to its own model provider, as with anything else you show it. That's why the reports it gets are redacted: personal paths are replaced, and specific network addresses are left out. You choose whether to connect one, and you can remove it with claude mcp remove heatlens.

What exactly happens when I click Request stop?

A sheet shows the PID, command, project and measured impact, and warns that stopping a dev server or agent can interrupt tests, edits, builds or active sessions. Cancel is the default. If you click Send SIGTERM, HeatLens re-reads the process from the kernel, checks that the PID still has the same start time and still belongs to you, and sends one SIGTERM. It waits a few seconds and tells you whether the process exited, is still running, had already exited, or had been replaced by another process, in which case nothing is sent. It never escalates to SIGKILL; for that, it points you to Activity Monitor. When one project has several leftovers, Stop leftovers lists them in one sheet with a checkbox each, and each selected process goes through the same check and single SIGTERM, one at a time.

Why isn't it sandboxed or on the App Store?

A sandboxed build sees much less: it cannot list all processes, read physical memory footprints, or fall back to ps for system processes. That would make the diagnosis mostly guesswork, so HeatLens ships as a notarized direct download instead. It still runs under the hardened runtime, and the source is on GitHub if you'd rather build it yourself.

How do I uninstall it?

Quit HeatLens from the popover, then drag it from Applications to the Trash. If you had turned on Launch at login, turn it off first in the app's Settings, or remove it under System Settings, General, Login Items. The only other thing it leaves behind is its settings file:

~/Library/Preferences/dev.heatlens.HeatLens.plist

Delete that too and nothing remains.

Does it work on Intel Macs?

Not yet. HeatLens targets macOS 14 or later on Apple Silicon, which is where it has been measured and tested.

Click once. Know why.

One disk image. Drag it to Applications
and click the rings in your menu bar.

macOS 14 or later · Apple Silicon · free