App Switching using Browser-Style Keyboard Shortcuts

December 18, 2021
Focus through Lens

I use the ⌘ + 1,2,3… keyboard shortcuts in Safari/Chrome frequently to quickly activate specific tabs.

After I set up the Hyper Key on my Mac, I wanted to replicate this style of shortcut for Mac apps. Binding Hyper + 1,2,3… to my most used apps makes switching to a particular app faster and more direct.

As usual, I use Hammerspoon to set this up.

Configuring your Application List

I started by manually setting up a list of apps, but was frustrated that I had to manually update the list whenever I changed apps or ordering. However, it turns out you can read the apps in your Dock directly from a property list:

function getDockPersistentApps()
  local results = { }
    local dockPlist ="HOME") .. "/Library/Preferences/")    
    local persistentApps = dockPlist['persistent-apps']
    for k, v in pairs(persistentApps) do
      local bundleId = v['tile-data']['bundle-identifier']
      local appName = v['tile-data']['file-label']
      results[#results+1] = { bundleId=bundleId, appName=appName }

    return results

At the end, you have a Lua table with the bundle ids and app names of every app in the “persistent” part of your Dock.

Creating the Keyboard Shortcuts

Once you have the list of apps and bundle names (which always match your Dock’s apps1), the Hammerspoon keybinding code is straightforward.

for count, app in pairs( getDockPersistentApps() ) do
    keyModal:bind({}, string(count), nil, 
        function() hs.application.launchOrFocus(app.appName) end) 

That’s all there is to it. My current shortcuts:

Key App
_Hyper_+1 Spark (Email)
_Hyper_+2 Fantastical (Calendar)
_Hyper_+3 Safari
_Hyper_+4 Bear
_Hyper_+5 Messages
_Hyper_+6 Xcode

This is one of my favorite and most used additions to my Mac.

Photo by Alex Perez on Unsplash

  1. You can add a file watcher to this file and have your config automatically reload whenever the Dock is changed, or just reload Hammerspoon fully when you make a Dock change. I do the latter currently. ↩︎