
canaryd
A quiet health monitor for your Mac.
It detects heat and stalled apps, then recovers them without taking your focus.
Install · Usage · How it works · Development
Canaryd is a local macOS watchdog. It uses exact Apple Silicon temperature data, macOS responsiveness state, and a reversible clipboard probe to find problems that a simple process check can miss.
- Watch heat. Detect CPU or GPU temperatures at or above 70°C and show the processes that correlate with the load.
- Recover stalled apps. Confirm that a GUI app is not responding before a controlled restart.
- Verify CleanClip. Check that CleanClip records new clipboard items, not only that its process exists.
- Stay quiet. Use background restarts and Notification Center. Do not open a foreground alert or take input focus.
- Keep data local. Store state, events, and logs on the Mac.
Status at a glance
Run canaryd status to see health, recent recovery events, pending app hangs,
and thermal pressure.
The screenshot contains example values. Process names, temperatures, and events come from your Mac.
Install
Install with an AI agent
Give this prompt to Codex, Claude Code, Cursor, or another coding agent:
Read https://raw.githubusercontent.com/ThaddeusJiang/canaryd/main/SKILL.md and follow its instructions to install or update Canaryd on this Mac.Requirements
- macOS on Apple Silicon or Intel
- Erlang/OTP and Elixir 1.15 or later
- Xcode Command Line Tools for the built-in notification helper
macmon 0.8.0for exact CPU and GPU temperatures on Apple Silicon
Install the system tools:
xcode-select -p >/dev/null || xcode-select --install
brew install elixir macmon
brew pin macmon
macmon --version
The last command must print macmon 0.8.0. Canaryd rejects another version
until its JSON schema is verified.
Install the current source
Use this method for the features documented in this repository:
git clone https://github.com/ThaddeusJiang/canaryd.git
cd canaryd
mix deps.get
mix escript.build
mix escript.install --force ./canaryd
Install the published release
Install the fixed Hex release:
mix escript.install hex canaryd 0.1.0
Add the Mix escript directory to PATH if the shell cannot find canaryd:
export PATH="$HOME/.mix/escripts:$PATH"
Add that line to the shell profile to keep the setting.
First run
canaryd status
The first command installs two launchd agents:
| Agent | Interval | Work |
|---|---|---|
| Thermal check | 1 minute | Read temperature and find high-CPU processes |
| Full health check | 5 minutes | Check the system, GUI apps, and CleanClip |
Every command verifies these agents. If an agent is missing, Canaryd creates it again. You do not need to manage plist files.
Usage
| Command | Purpose |
|---|---|
canaryd status | Show the current health snapshot and recent events |
canaryd check | Run one full health check now |
canaryd thermal-check | Run one thermal and high-CPU process check now |
canaryd history [target] | Show events for cleanclip, system, thermal, or apps |
canaryd install | Reinstall and load both launchd agents |
canaryd uninstall | Remove both launchd agents and the notification helper |
Examples:
canaryd check
canaryd history thermal
canaryd history apps
How it works
Canaryd applies a confirmation and cooldown policy before it changes another app.
| Signal | Detection | Response |
|---|---|---|
| CPU or GPU heat | Three macmon samples; keep the highest average | Notify on the first hot round; offer an action after the same safe app leads two rounds |
| GUI app hang | Read the state that macOS uses in Force Quit | Confirm twice, then restart a supported third-party app |
| CleanClip process | Check the process with pgrep | Restart it in the background when it is missing |
| CleanClip function | Write a reversible clipboard marker and verify a new history entry | Restore the clipboard, then restart CleanClip after a failed probe |
| System pressure | Read thermal throttling, load, and memory pressure | Warn after three consecutive full checks |
Safety rules
- Canaryd never treats battery temperature as CPU or GPU temperature.
- A user clipboard change always takes priority over probe restoration.
- A third-party GUI app must fail two consecutive checks before restart.
- Apple apps, system daemons, and unsafe helper processes do not get automatic actions.
- Each app has a one-hour restart or prompt cooldown.
- Automatic termination can discard unsaved data in a stalled app.
When the Mac is idle for more than 30 minutes, Canaryd skips the CleanClip functional probe. It still checks the system and GUI responsiveness.
Detailed recovery policy
### Thermal pressure Canaryd keeps the highest CPU and GPU average from a three-sample window. A CPU or GPU temperature of at least 70°C causes thermal pressure. Battery temperature stays separate and does not represent chip temperature. The first hot round sends a warning that stays in Notification Center until the user dismisses it. The warning has a 15-minute cooldown for each leading process. Canaryd lists up to five processes that use at least 20% CPU. CPU use is correlation evidence. It is not exact heat attribution. After the same safe third-party app leads two rounds, the notification offers Close and Restart. Dismissal or timeout means Ignore. Canaryd does not activate the app or take mouse focus. Apple apps, system services, nested helper apps, and processes without a safe app bundle never get these actions. Each app has a one-hour prompt cooldown. ### GUI app recovery Canaryd uses the same responsiveness state that macOS shows in Force Quit. A third-party app must be not responding in two consecutive rounds. Canaryd then stops and opens the app in the background. Each app has a one-hour restart cooldown. The Force Quit state has no public macOS API. Canaryd resolves the interface at runtime. If a future macOS release removes it, the scan becomes unavailable and Canaryd does not stop an app. `CursorUIViewService` is an explicitly supported Apple text-input service. After two failed rounds, Canaryd sends a 120-second notification with Close and Restart actions. Dismissal or timeout means Ignore. Close or Restart can force-stop the current instance. macOS starts a new instance through launchd or an XPC client when it is needed. The notification has a one-hour cooldown. ### CleanClip recovery The functional probe saves every pasteboard item and data type. It restores the snapshot only when no newer pasteboard write occurred. A user copy during the probe always wins. A probe failure causes a quiet restart with a one-hour cooldown. Three consecutive failures during the cooldown set the target to `blocked` and send a notification. Canaryd records recovery automatically.Local data
Canaryd stores all runtime data in:
~/Library/Application Support/canaryd/
├── state.dets
├── events.dets
├── stdout.log
└── stderr.logstate.dets contains the latest state-machine snapshot. events.dets contains
the event history for app, thermal, system, and probe actions. The log files
contain launchd output.
Uninstall
Remove the launchd agents and the notification helper:
canaryd uninstall
To remove the saved state and logs too:
rm -r "$HOME/Library/Application Support/canaryd"
Development
git clone https://github.com/ThaddeusJiang/canaryd.git
cd canaryd
mix deps.get
mix test
mix escript.build
The project uses pure Elixir/OTP, DETS storage, launchd, and a small Swift notification helper.