Hari Sekhon - Hammerspoon Mac Event-Driven Automation Code
February 3, 2026 · View on GitHub
Summary
Mac event driven automation using Hammerspoon.
Hammerspoon is a system event handler for Mac.
The code is written in Lua.
Includes:
- Auto-switching to Multi-Output for Shazaming when connecting headphones
- Automatically running Speed Test when connecting to a wifi network
Setup
Install Hammerspoon
Install Hammerspoon using Homebrew:
brew install hammerspoon --cask
Add Hammerspoon Code
mkdir -p -v ~/github
git clone https://github.com/HariSekhon/Hammerspoon ~/github/hammerspoon
ln -svFhw ~/github/hammerspoon ~/.hammerspoon
Output:
/Users/hari/.hammerspoon -> /Users/hari/github/hammerspoon
Run Hammerspoon
Finally, start Hammerspoon, you should see its icon in the menu bar.
open -a Hammerspoon
Auto-Start Hammerspoon
Set Hammerspoon to start at login (you can tick this in the Hammerspoon Preferences UI) or just run this:
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Hammerspoon.app", hidden:false}'
Allow Desktop Notifications
Optionally allow pop-up desktop notifications from Hammerspoon so that your code can notify you when it's done something for you (I recommend Banners that automatically disappear without having to click them).
System Settings -> Notifications ->Hammerspoon:
open "x-apple.systempreferences:com.apple.Notifications-Settings.extension?bundleId=org.hammerspoon.Hammerspoon"
Automation Code
Auto-Reload Hammerspoon Upon Any Code Changes
Handled by the self-watcher in auto-reload.lua.
Auto-Switch to Multi-Output to Shazam from TV/Movies while listening on AirPods or Headphones
Automatically switches from AirPods / Headphones connection to Multi-Output Audio Device and Blackhole input to be able to Shazam songs while watching a movie or TV show on AirPods / Headphones.
You will need to install the Blackhole audio driver and set up a Midi Multi-Output Audio device too.
See HariSekhon/Knowledge-Base - Audio page section for more details on this setup.
If you set your Sound output to the in-built Mac Speaker then the code resets the mic to use the standard Mac built-in Mic to keep the input and output aligned in an intuitive way.
If you set your Sound output to any device with Multi-Output or Blackhole in the name then
automatically switches to the Blackhole input for the loop shazamming trick.
Auto-run Speed Test when connecting to a Wifi network
TODO
Quit Transmission if Disk Space Low
Using up all the disk space on macOS can result in a catastrophic bug that requires reinstall and restore from backup, as documented on the HariSekhon/Knowlege-Base - Mac.
If disk space drops below 20GB it detects and quits Transmission bittorent client to avoid filling up the disk and causing a catastropic filesystem failure.
Quit Transmission on Hotspots
Quit Transmission bittorrent client automatically when connecting to a personal hotspot to save your data.
I have accidentally eaten my entire digital nomad mobile e-sim data plan by connecting my laptop to my phone hotspot to try to git push or spotify API something only to find Transmission has immediately used up all my data and I have to buy a new data package.
This is particularly bad if you're at a bus station coding in some random country and they don't have a public wifi on which to buy a new data package.
#DigitNomadProblems
Modular Structure
The top level init.lua is the entry point that imports the rest of the code structured thus:
$ tree -P '*.lua' -I 'test*.lua' --prune
.
├── audio
│ ├── devices.lua
│ ├── switch.lua
│ └── watcher.lua
├── auto-reload.lua
├── init.lua
├── transmission
│ ├── utils.lua
│ ├── watcher-disk-space.lua
│ └── watcher-hotspot.lua
├── utils
│ ├── disk.lua
│ ├── log.lua
│ ├── notify.lua
│ └── watcher-disk-space.lua
└── wifi
└── speedtest.lua
5 directories, 13 files
More Core Repos
Knowledge
DevOps Code
Containerization
CI/CD
Databases - DBA - SQL
DevOps Reloaded
Monitoring
Templates
Desktop
Spotify
The rest of my original source repos are here.
Pre-built Docker images are available on my DockerHub and can be re-generated using the my Dockerfiles repo.