Run a command when unlocking a macOS machine

I needed to start an application each time I unlocked my Mac. But there didn’t seem to be an obvious way to run something every unlock in macOS.

For example, I found that launchd has an on-wake event. Great! But that doesn’t quite work because it also fires on power nap, which is a kind of mini-wake-up in macOS terms. I didn’t want to run the app each time power nap happened, or actually even when a normal wake up happened. I only wanted it when I was actually sitting at and unlocking the machine.

It turns out that Hammerspoon, which I’ve used for a long time to automate various slightly esoteric things1, has a module tucked away for this. hs.caffeinate.watcher had what I needed. I’ll include the code snippet in the lede, and add a bit more detail below.

function runOnUnlock(eventType)
    if (eventType == hs.caffeinate.watcher.screensDidUnlock) then
        -- Carry out your unlock event here, eg:
        hs.execute("/path/to/shell/script.sh", true)
    end
end

local lockWatcher = hs.caffeinate.watcher.new(runOnUnlock)
lockWatcher:start()

The documentation for hs.caffeinate.watcher lists the events it watches for:

  • screensaverDidStart
  • screensaverDidStop
  • screensaverWillStop
  • screensDidLock
  • screensDidSleep
  • screensDidUnlock
  • screensDidWake
  • sessionDidBecomeActive
  • sessionDidResignActive
  • systemDidWake
  • systemWillPowerOff
  • systemWillSleep

Strictly, I should probaly include sessionDidBecomeActive in my list of events, but it’s for fast user switching, and I don’t fast user switch.


  1. Hammerspoon is a wonderful tool to get to know. It has so many uses. My most-used is that I use it to automate window placement using hotkeys. For example, the chain ctrl-space,1 places a window to fill the left half of my screen. ↩︎

← Older
How does SSH's ProxyCommand actually work?
→ Newer
Airpods Pro: final thoughts