I’m never quite satisfied with the various methods of creating keyboard shortcuts (hotkeys) on macOS... Here I go again, this time using a small open source utility called skhd - a simple hotkey daemon for macOS.

Danger! Usual disclaimers about downloading and running untrusted code and scripts! If you don‘t know what you are doing, please just don’t!

Pre-requisites

First off, I use my script to re-map MacBook Pro function keys from a few posts back - this is so that I can remap certain keys in the top row of the keyboard to standard function keys:

  • Download the script and make sure it is executable chmod +x keymap.sh
  • Next, run keymap.sh specifying the appropriate command line arguments

For example, I have no use for the spotlight and dictation keys, so I map the 4th and 5th keys to F13 and F14 respectively:

./keymap.sh 4=f13 5=f14

If you followed my previous guide to use a System Preferences keyboard shortcut to take a screenshot, please remove it or reset it to the default, to avoid conflicts!

Next, I need these keys to a trigger global function... enter skhd by koekeishiya (Åsmund Vikane). To compile and install:

  • Get the Xcode command line tools (the easiest method being xcode-select –install).
  • Then, download the code from GitHub and compile skhd:
    git clone https://github.com/koekeishiya/skhd
    cd skhd
    make install
  • Finally, move bin\skhd to a permanent folder - I save programs in ~/Programs, which is also in my PATH.

Configuring skhd

skhd needs a configuration file, ~/.skhdrc. Do review the skhd sample configuration! koekeishiya skhd configuration grammar

The configuration is too powerful (and the examples don’t do it justice)... but I only use two forms:

  • the first form, <hotkey> : <command> triggers the given command when the hotkey is pressed.
  • the second form , checks the active application first:
    • if it is the given application, then run the subsequent command,
    • and finally, if it is anything else (*), then run the subsequent command.

The second form is used with F13 below. In my case, I want F13 to run screencatpure to interactively grab a screenshot of a window to the clipboard, unless the active application is Firefox. In that case, send Cmd+Shift+S to Firefox to trigger Firefox’s in-built screenshot feature. Very cool.

Here is my .skhdrc, which uses skhd -k to emulate a key press:

# Shortcuts to launch / focus on VS code, outlook, firefox, chrome, webex, etc.
cmd + alt + ctrl - v : open /Applications/Visual\ Studio\ Code.app
cmd + alt + ctrl - o : open /Applications/Microsoft\ Outlook.app
cmd + alt + ctrl - p : open /Applications/Microsoft\ PowerPoint.app
cmd + alt + ctrl - f : open /Applications/Firefox.app 
cmd + alt + ctrl - c : open /Applications/Google\ Chrome.app
cmd + alt + ctrl - t : osascript -e 'tell application "Terminal" to activate'
cmd + alt + ctrl - w : osascript -e 'tell application "Webex Meetings" to activate' || open /Applications/Webex.app

# F13 - capture screenshot to clipboard, Cmd+F13 - capture screenshot to file
f13 [
    "firefox" : ~/Programs/skhd -k "cmd + shift - s"
    * : screencapture -coW
]
cmd - f13 : screencapture -oWx ~/Desktop/Screenshots/"$(TZ=UTC date '+%F %H.%M.%S')"@2x.png

# F14 - WebEx mute/unmute
f14 : osascript -e 'tell application "Webex Meetings" to activate' && ~/Programs/skhd -k "cmd + shift - m"

# Cmd+F6 - toggle dark mode (F6 is do not disturb mode)
cmd - 0xB2 : osascript -e 'tell application "System Events" to tell appearance preferences to set dark mode to not dark mode'

# Control+V - if outlook, paste and match style, if other office, paste special
ctrl - v [
    "microsoft outlook" : ~/Programs/skhd -k "cmd + alt + shift - v"
    "microsoft powerpoint" : ~/Programs/skhd -k "cmd + ctrl - v"
    "microsoft word" : ~/Programs/skhd -k "cmd + ctrl - v"
    "microsoft excel" : ~/Programs/skhd -k "cmd + ctrl - v"
]

The last block, Control+V, addresses a pet peeve of mine with Microsoft Office for macOS - with Outlook, I find myself always using “Paste and Match Style” (since Paste will paste HTML formatting if there is, which ruins my mail formatting), but with other Office apps, use “Paste Special” so that I can choose the best format (text, HTML, RTF, etc.). I would of course rather replace Command+V directly, but that’s impossible, since sometimes “Paste Special” and “Paste and Match Style” options are not available, while only “Paste” is.

Surprisingly, there is no --help, so FYI, the important parameters are:

-v Print version number to stdout
-o Output keycode and modifiers of event. Ctrl+C to quit
-r Signal a running instance of skhd to reload its config file
-k Synthesize (generate) a keypress (same syntax as when defining a hotkey)
-t Synthesize (generate) a line of text

Keycodes

To determine the keycode of a key on your keyboard e.g. 0xB2 in hex in the example above:

  • run skhd -o and press the key you want to capture
  • make a note of the keycode (if any)
  • close skhd with Ctrl+C
  • then use the keycode in the configuration file in uppercase - the keycode is case sensitive!

Alas, not all keys can be captured this way, notably the display brightness, media and volume keys.

Also, the way macOS generates keycodes can be a bit weird, e.g. holding Cmd totally changes the keycode instead of just setting a modifier flag.

Starting skhd

I would guess the author provided com.koekeishiya.skhd.plist to start skhd via the macOS Launch Daemon. Per-user settings are stored in ~/Library/LaunchAgents

However, here I’ll just run skhd manually, in the background, and then “disown” it (otherwise zsh/bash cannot exit due to running jobs):

skhd &!

There does not seem to be a way to exit gracefully, so, to stop skhd:

pkill skhd$

Conclusion

So far so good! I’m still figuring out my keystorkes... by leveraging and/or discarding my previous methods, e.g.

Updated 14 Sep 22: Ctrl+V for Microsoft Office, and changed to use 3 modifier keys to launch or focus on applications.