A lightweight macOS menu bar app that warns you before your Mac runs out of RAM and starts killing processes. Native Swift + SwiftUI, ~24 MB of memory, no dependencies, no network access, no analytics, no telemetry. Free and open source under the MIT licence.
curl -fsSL https://raw.githubusercontent.com/Rezasz/crash-guard/main/scripts/install.sh | bashThat clones the repo, builds it, installs Crash Guard.app into /Applications, and
launches it in your menu bar. Run the same command again any time to update.
Prefer to read before you run? Read the script first — it is 90 lines of plain bash — then build by hand:
git clone https://github.com/Rezasz/crash-guard.git
cd crash-guard
./scripts/make-app.sh --installRequirements: macOS 14 (Sonoma) or newer, Apple Silicon, and Xcode or the Command Line
Tools (xcode-select --install). Uninstall: rm -rf "/Applications/Crash Guard.app".
When a Mac locks up or misbehaves under memory load, it is almost never a kernel panic. It
is jetsam — the kernel's memorystatus subsystem killing processes to keep itself
alive. That distinction is the reason this app can exist: a userspace tool cannot prevent a
panic, but it absolutely can warn you before a jetsam event.
Jetsam kills by priority band, not by size. From a real report on the machine this was
built on (JetsamEvent-2026-08-17-045443.ips):
| Process | Resident memory | Priority | Fate |
|---|---|---|---|
| com.apple.Virtualization.Virtual | 4.30 GB | 40 | survived |
| WindowServer | 2.40 GB | 170 | survived |
| python3.13 | 2.29 GB | 180 | survived |
| com.apple.appkit.xpc.openAndSave | 100 MB | 0 | killed |
| DockHelper, sirittsd, Safari.History | ~30 MB | 0 | killed |
2,462 of 2,853 recorded processes were jettisoned — while every large consumer survived. That is why it feels like a system crash rather than a memory warning: Save dialogs stop working, the Dock misbehaves, Safari history dies, Siri breaks, thousands of small helpers die — and the 4.3 GB VM that caused it keeps allocating. macOS's own defence targets the wrong processes. Crash Guard warns you in time to deal with the real consumer.
Subscribes to the kernel's memory pressure signal (DispatchSource.makeMemoryPressureSource)
— the same one the system uses — so warnings arrive well before the "Your system has run out
of application memory" dialog.
Tracks the growth rate of top consumers, not just their current size, and turns the slope into plain English: "python3.13 is growing 600 MB/min — roughly 4 minutes of headroom left."
Terminal emulators (Terminal, iTerm2, Ghostty, Warp, kitty, Alacritty, WezTerm, Hyper, Tabby,
VS Code, Cursor) and coding agents (claude, codex, aider, and your own additions) sit in
a protected tier above the system denylist. Their rows are shielded, Freeze and Quit are
disabled, and when a protected process is the top consumer the app inverts its
recommendation:
Protecting your Claude Code session in Ghostty — free 3.2 GB from Chrome and Docker instead.
This matters more than it sounds. A backgrounded terminal sits in a low priority band, so during a real incident the system is more likely to kill your agent session than the VM that caused the problem.
SIGSTOP halts a runaway process's allocation and CPU burn instantly while preserving all
of its state, so you can save your work and then decide. Every freeze is paired with a
mandatory auto-resume timer (default 60 s) with a live countdown and a Resume now button —
nothing is ever left stopped by accident.
Parses /Library/Logs/DiagnosticReports/JetsamEvent-*.ips — readable without root and
without Full Disk Access — and shows the memory state at the moment of the incident plus a
table of what survived versus what was killed, sorted by size, making the priority-versus-size
problem visible.
- Ollama holding model weights →
ollama stop <model>frees them immediately - Docker Desktop → its memory is a settings slider, not something to kill
- Virtual machines (Parallels, VMware, Apple Virtualization) → pause, never terminate
One click lists everything reclaimable that is neither protected work nor required by macOS, largest first, with per-process quit buttons. The fast path when a long agent run needs headroom right now.
Nothing is ever killed automatically. Per-app rules are opt-in and only ever notify.
A watchdog that burns resources is worse than useless, so the monitoring loop is adaptive: at normal pressure it reads system totals every 5 s and never walks the process table — the per-process walk is the expensive part and only starts at warning pressure or below a configurable available-memory threshold.
Measured on the machine it was built on (Apple Silicon, 16 GB, macOS 26.5.1):
| Metric | Measured |
|---|---|
| Physical footprint | 23.8 MB (peak 33.9 MB) |
| CPU, actively sampling | ~0.3% average — 0.0% on most ticks, 2.2% every fifth second for the full pid walk |
| CPU, idle path | not measured — see limits below |
RSS reads around 70 MB, but that is mostly shared framework pages. Physical footprint is the number jetsam judges — and the same one this app uses to judge everything else.
The entire engine runs without any UI, which is how it is verified:
CrashGuard --report # memory state, top consumers, protection verdicts
CrashGuard --incidents [--verbose] # parsed jetsam incident history
CrashGuard --selftest # verifies freeze/auto-resume against a spawned `sleep`Useful if you want the analysis without the menu bar app, or to script memory checks.
Is this an Activity Monitor alternative? It complements it. Activity Monitor tells you what is using memory right now; Crash Guard watches continuously, predicts when you will run out, protects work you cannot afford to lose, and shows you what happened during past incidents.
Does it need root, Full Disk Access, or a background helper? No. It is unsandboxed and ad-hoc signed, with no privileged helper. Jetsam reports are readable without root or Full Disk Access, and same-user processes need no privileges.
Does it send anything anywhere? No. No network calls, no analytics, no telemetry, no accounts. Read the source.
Will it kill my apps on its own? Never. Every action is one you take from the dropdown, and protected processes require an explicit confirmation that names exactly what you would lose.
Why does the memory-chip icon appear but nothing happens? It only lists processes under memory pressure — at normal pressure it deliberately skips the expensive process walk. Click "Sample now" in the dropdown to force one.
- It cannot prevent a true kernel panic (driver or hardware). It prevents out-of-memory incidents, not crashes in general.
- It cannot beat a single enormous allocation that goes from fine to fatal in one step.
SIGSTOPon a process holding a system lock can stall anything that talks to it. The UI says so at the point of action.- Reading other users' processes needs privileges. v1 covers the current user's processes,
which is where the offenders are. Ancestry lookups fall back to
sysctl KERN_PROC_PID, so a terminal ancestor is still found through root-ownedlogin. - Between full pid walks it tracks the 40 known-largest processes, so a brand-new consumer is picked up within about five seconds rather than instantly — a deliberate trade against CPU.
- The idle-path CPU figure is unmeasured: the test machine never returned to normal pressure during testing. It does three syscalls per 5 s, but that is an argument, not a measurement.
- The graphical UI has not been visually verified in an automated environment; it builds, launches and runs, and the engine is verified through the headless modes.
Sources/CrashGuard/
Monitor/ pressure source, system sampler, process sampler, growth tracker
Incidents/ JetsamEvent .ips parser and model
Actions/ freeze, quit, recipes, protection tiers
Views/ menu bar, dropdown, incident history, settings
Model/ memory model, settings
Util/ formatting, notifications, headless CLI
scripts/
install.sh one-command install
make-app.sh build + bundle + sign (+ --install)
make-icon.swift regenerates Resources/AppIcon.icns
Built with the required APIs directly — host_statistics64, sysctlbyname,
proc_pid_rusage / RUSAGE_INFO_V6 for phys_footprint, proc_listpids,
SMAppService for launch at login — and nothing else.
MIT — see LICENSE. Use it, fork it, ship it.
Issues and pull requests are welcome at github.com/Rezasz/crash-guard.
Questions, bug reports or feedback: reza@kanz.ai
If Crash Guard saved you from losing a long agent run, a star on the repo helps other people find it.
Crash Guard is a mac memory monitor and macOS RAM monitor menu bar app for people searching how to prevent a Mac out-of-memory crash, why macOS kills processes when memory is full, what a jetsam event is, how to read macOS memory pressure, a lightweight Activity Monitor alternative, how to free up RAM on a Mac, why a Mac freezes or beachballs when memory fills up, and how to protect a Claude Code or other coding-agent session from being killed during a low-memory incident.