Photo by Fernando Arcos from Pexels

Solve Shortcut Hell in MacOS — Building a Hyper Key

If you like shortcuts and try to use them in every application, you will run into it eventually: Shortcut Hell. Two (or more) applications wanting to use the same shortcut and no way to change them.

Well, what if I told you there’s a way to create a completely new layer on your keyboard? What if I told you this way no application will ever be able to steal your shortcuts? All you need to sacrifice is one tiny button on your keyboard. Best of all: you get to choose which button you sacrifice.

Introducing: the Hyper key!

The Hyper key is a custom sibling of Shift, Option, Control and Command. It acts as a new modifier to all the other keys on your keyboard. Hammerspoon enables this behaviour by defining a completely new “modal” key, over which you have complete control. While it is most natural to enable and disable this mode in tandem with a key-press and -release, you can actually enable it whenever you like.

Hammerspoon does require a little help to get this done. That help comes from Karabiner, a tool for reassigning keys on your keyboards. Karabiner can do a whole lot more, but right now this is all I use it for (and for remapping Windows-keyboards to proper Mac-layout 😇).

Setting up Karabiner

You can begin by downloading Karabiner-Elements from its website. Once installed, start it and make sure it starts when you login. Then, you can start remapping keys in the Simple modifications tab, view your currently connected devices in the Devices tab (and later also disconnected devices, since Karabiner remembers them).

To start setting up the Hyper key, create a new item on the Simple modifications tab and remap the to for all devices. Of course this is where you can choose which key should be your Hyper key.

Remapping a key to F18 for the Hyper key

Why F18 you ask? Well, it’s a key that’s (probably) not on your keyboard and yet MacOS supports function keys up to 20. That means anything above F12 is free to use for these things. F18 is just the value that was used in an example I once found, which led to this setup. It kinda stuck.

Setting up Hammerspoon

Hammerspoon is an interface between a Lua scripting engine and various MacOS APIs. For more information on its capabilities and ways to install it, please see my previous post about it.

If you are not familiar with Hammerspoon and/or Lua, I suggest you put the coming code snippets in a file and import it from a file . This will allow you to follow the post below exactly and keep your clean so you can more easily add other features to it later.

Now that is causing keypress/-release events for , we can use Hammerspoon to tap into the MacOS keyboard event system and create our own layer of keys.

The feature we will use for this is called . It allows us to create a keyboard mode, which we can programmatically turn on and off. To turn it on and off, we use the events from the key we remapped in Karabiner.

How Hammerspoon’s modal works to create a new keyboard modifier state

Let’s see what this would look like in the Lua script (put it in (or if you’re impatient, download it here):

local This = {}-- Hyper mode needs to be bound to a key. Here we are binding
-- it to F17, because this is yet another key that's unused.
-- Why not F18? We will use key-events from F18 to turn hyper
-- mode on and off. Using F17 as both the modal and source of key
-- events will result in a very jittery Hyper mode.
This.hyperMode = hs.hotkey.modal.new({}, 'F17')-- Enter Hyper Mode when Hyper-key is pressed
function enterHyperMode()
This.hyperMode:enter()
end
-- Leave Hyper Mode when Hyper-key is pressed
function exitHyperMode()
This.hyperMode:exit()
end

This is the base of the Hyper mode. The new that is created, which can be turned on and off using the and functions. Now we still need to bind to some keyboard events to actually enable the Hyper key.

-- Binds the enter/exit functions of the Hyper modal to all
-- combinations of modifiers
function This.install(hotKey)
hs.hotkey.bind({}, hotKey, enterHyperMode, exitHyperMode)
hs.hotkey.bind({"shift"}, hotKey, enterHyperMode, exitHyperMode)
hs.hotkey.bind({"ctrl"}, hotKey, enterHyperMode, exitHyperMode)
hs.hotkey.bind({"ctrl", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"cmd"}, hotKey, enterHyperMode, exitHyperMode)
hs.hotkey.bind({"cmd", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"cmd", "ctrl"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"cmd", "ctrl", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt"}, hotKey, enterHyperMode, exitHyperMode)
hs.hotkey.bind({"alt", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "ctrl"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "ctrl", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "cmd"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "cmd", "shift"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "cmd", "ctrl"}, hotKey, enterHyperMode,
exitHyperMode)
hs.hotkey.bind({"alt", "cmd", "shift", "ctrl"}, hotKey,
enterHyperMode, exitHyperMode)
end
return This

The function will bind to all of the events of the key passed in through the parameter. It binds both a key press and a key release function, to turn the Hyper-mode on and off.

Now we have the basics and we can use this to bind arbitrary Lua-functions to keys combined with our Hyper-key. Here is an example file which imports the Hyper mode and binds a few keys:

-- Load and install the Hyper key extension. Binding to F18
local hyper = require('hyper')
hyper.install('F18')
-- Quick Reloading of Hammerspoon
hyper.bindKey('r', hs.reload)
-- Global Application Keyboard Shortcuts
hyper.bindKey('p', function()
am.switchToAndFromApp("com.spotify.client")
end)
hyper.bindShiftKey('p', function()
hs.spotify.displayCurrentTrack()
end)
hyper.bindKey(']', function()
am.switchToAndFromApp("com.googlecode.iterm2")
end)

These are just a few examples of what you can do. The is part of another extension, which I will be sharing shortly in a follow-up post. If you’re ready to get to know Hammerspoon, browse the docs and find something fun to do.

Congratulations, you have unlocked your very own Hyper-key. Thanks for reading and please come back again soon for some inspiration to use it (for serious stuff and fun 😇).

— JH

Mac O’Clock

The best stories for Apple owners and enthusiasts

Jan-Hendrik Kuperus

Written by

Hi! I’m the Founder and Director of Yoink. I love writing code, tweaking it, beautifying it. I'm an all-round coder and a Professional Amateur Baker 😁🎂

Mac O’Clock

The best stories for Apple owners and enthusiasts

Jan-Hendrik Kuperus

Written by

Hi! I’m the Founder and Director of Yoink. I love writing code, tweaking it, beautifying it. I'm an all-round coder and a Professional Amateur Baker 😁🎂

Mac O’Clock

The best stories for Apple owners and enthusiasts

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store