From the blog

How to Script macOS Keyboard Shortcuts

When I set up a new computer, the first thing I do (after installing Dropbox and 1Password, of course) is to run a script that installs my favorite command line tools and configures my shell the way I like it. I also go into System Preferences and twiddle various settings. I’ve done it enough times that it doesn’t take me long, but the part that always slows me down is custom keyboard shortcuts.

These are located in the Keyboard preference pane, under the Shortcuts tab, and they allow you to override the keyboard shortcuts for menu commands in any app. My favorite is to map CommandShiftO in the Finder to Show Package Contents, and I have a few more that I couldn’t live without. Unfortunately, setting up all my favorite keyboard shortcuts is tedious, and because I use them by memory, it’s difficult to remember what they all are outside the context in which I use them. So, I set about trying to figure out how to set custom keyboard shortcuts from a shell script, and have them show up in System Preferences as though they were added by hand. Read on to find out what I learned about how to script macOS keyboard shortcuts.

Diving In – Script macOS Keyboard Shortcuts

fseventer screenshot
fseventer shows every change on your hard drive in real time

The most useful tool in my quest was fseventer. This incredible app hooks into the fsevents system introduced in OS X 10.4, and shows a real-time visualization of every file that is changed on your system. Even if you have no practical use for it, it can be eye-opening to see how much stuff is going on at once inside a typical computer.

[Update April 2017: unfortunately, fseventer is now defunct, but a new app has emerged to take its place. If you’re interested in this kind of tool, check out FSMonitor.]

I fired up fseventer, started recording, and then changed a keyboard shortcut in System Preferences. Unsurprisingly, one of the files that changed was the preference file for the app in question. For the Finder, this is ~/Library/Preferences/com.apple.finder.plist. I saved a copy of that file, reverted the change to the keyboard shortcut, and then compared the two files.

From this, I found the NSUserKeyEquivalents element, which contains a dictionary mapping menu items to keyboard shortcuts. Letter and number keys are represented as letters and numbers, as you would expect. However, modifier keys such as ⌘ (command) and ⌥ (option) do not use their normal symbols. Instead, easier-to-type substitute characters are used. If you want to find the symbol for a given modifier key, create a custom keyboard shortcut that uses that key. Then, open the corresponding app’s preference file and look in the NSUserKeyEquivalents dictionary. I’ll give you the starter list of symbols, based on the modifier keys I use. Command, Control, Option, and Shift have convenient short codes, but Tab, the arrow keys, and others require the use of Unicode code points. I’ve given you the code for the Tab key below; finding the codes for other characters is left as an exercise to the reader. (Post any useful ones you find in the comments!)

If you use these symbols in a shell script, I recommend creating named variables so that you can have a hope of reading the code later. Note that the backslash in the Tab key code may need to be escaped if you use it in a shell string. Here is how to use what we have learned so far to set a shortcut of CommandShiftO for Show Package Contents in the Finder:

If you run this code in the Terminal, you will then be able to use your new keyboard shortcut in Finder. Hooray! However, there’s a problem: if you go to System Preferences, you won’t see your new keyboard shortcuts in the “App Shortcuts” section of the Shortcuts tab of the Keyboard preference pane. This puzzled me when I first encountered it, and it took a little more poking around in fseventer to figure out what I was missing.

Getting Custom Shortcuts to Show Up

It turns out that another file is touched when you set a custom keyboard shortcut for an app: ~/Library/Preferences/com.apple.universalaccess.plist. Inside the com.apple.custommenu.apps element, you’ll find an array of the reverse-domain bundle identifiers of the apps that have custom keyboard shortcuts defined in System Preferences. You have to add apps to this file if you want them to show up in the list. But use caution! If you add an app to this list more than once, System Preferences will crash when you try to load the Keyboard pane. In the code below, the addCustomMenuEntryIfNeeded function takes care of this safety check for you.

In the following shell script, I have combined the ideas described in this post into a starting point for you to customize the keyboard shortcuts instantly whenever you are setting up a new Mac. Copy and paste it into a .sh file or your shell rc file, and then have fun making your own dream keyboard shortcut setup script!

One More Thing: Global Shortcuts

You can also set global keyboard shortcuts that work across all applications. These are stored in ~/Library/Preferences/.GlobalPreferences.plist, which you can write to by passing -g  (for “Global”) to the defaults  command.


Interested in joining the Raizlabs team making great software? We’re hiring developers in Boston and SF.


5 Comments

  1. I have fiddled with the .plist files before to get my custom shortcuts to work, and didn’t have any problems with most special keys (cmd, opt, etc…).
    However, I can’t seem to get the tab key to work. Even with the Unicode code.
    Have you had any success with creating a custom shortcut that includes the Tab key?

    I tried it in Script Editor (Mac’s built-in AppleScript Editor) and Pro Tools.

    In Script Editor I can see the Tab symbol next to the menu item, but actually pressing it doesn’t trigger the menu item. Instead it performs a normal tab.

    In Pro Tools I only see the Tab symbol in the App Shortcuts in System Preferences, but not next to the menu items.

    Could you share your experience with using Tab for custom shortcuts?

  2. I had previously made shortcuts with the Tab key, like the Terminal shortcuts to switch tabs that I mention in the blog post. But I just checked, and despite the fact that the shortcuts show up in System Preferences, the menu items in Terminal still show the original keyboard shortcuts, and the ones that use the Control key don’t work any more. I hadn’t noticed the breakage because I don’t actually use tabs in Terminal very often. Sounds like using Tab in shortcuts may have broken; probably worth filing a Radar.

  3. The following command give me an error in my new mac.
    $ defaults read com.apple.universalaccess “com.apple.custommenu.apps”
    Error:
    The domain/defaults pair of (com.apple.universalaccess, com.apple.custommenu.apps) does not exist

    Any idea to solve this???

Leave a Reply

Your email address will not be published. Required fields are marked *