Avatar
OsingaOn my interests

On Desktop Productivity

How to use Karabiner-Elements and Keyboard Maestro to get the most out of macOS.

Modified

I spend a lot of time behind my laptop. To try and make the most of it, I enjoy getting to know my tools, with the aim of improving both my comfort and my productivity. A big part of this is done by using shortcuts and automations, which not only makes me move faster with much less arm movement but also takes away a lot of friction. Hopefully future me will benefit from that.

macOS

My laptop of choice is a MacBook, and it runs macOS. Everything in this section uses native features and doesn't require any third-party apps.

Spaces

I tend to have apps and windows open for different projects or modes. For example, I have a Safari window with a bunch of personal tabs, another one with work related tabs, and then also some additional apps for work. Instead of keeping all this on the same desktop, I use spaces. This lets me set up multiple desktops and give each desktop its own focus.

To efficiently use spaces, it's important to efficiently switch between them. As explained in the macOS User Guide linked above, by default this can be done in one of three ways:

  1. Swipe left or right with three or four fingers on a trackpad, or with two fingers on a Magic Mouse.
  2. Press the Control key together with the left or right arrow.
  3. Open Mission Control and select the desktop in the top of the screen.

While functional, none of these are ideal. The first one requires moving a hand off the keyboard, the second one does as well (and even after following my suggestion below to add additional arrow keys it's still awkward), and the third one is just plain cumbersome. Sure, you could set up a hot corner for the latter, but then we're back to moving a hand off the home row.

I suggest a different approach. Go to System Preferences → Keyboard → Shortcuts, and select Mission Control on the left. There, look for the two actions Move left a space and Move right a space and replace the default shortcuts with Command-Shift-1 and Command-Shift-2, respectively. Now you can move smoothly between spaces without relocating your hands, and so far I haven't noticed any conflicts.

Screenshot of "System Preferences → Keyboard → Shortcuts"

Assign Apps to Spaces

Once you're using spaces, you might find that the mapping of one app per space isn't always ideal. For some apps this doesn't matter since they allow multiple open windows (such as Finder or Safari), but for others this isn't possible (such as Mail or Messages). When opening these apps, then, there'll be a sudden jump to the space the app is opened on.

Luckily, this can be fixed. Let's say you have a space for work and a space for personal stuff, and both of them need to have access to the Mail app. Right click on the Mail app icon in the Dock and go to Options → Assign To. The default setting is None, but you can also assign the app to a specific desktop (This Desktop) or—what we're looking for here—to All Desktops.

Now, whenever you open the Mail app, it will open on the space that you're already on.

Screenshot of "Dock → Options → Assign To"

note: For this to show up you'll need to have at least two spaces open.

Hot Corners

Hot corners associate certain actions with the corners of the screen, which are then activated by moving the cursor into that corner.

I'm not a big fan of them, since I find them prone to accidental activations and they require moving a hand off the home row. But, there's one I do find convenient, and that's to set the bottom left corner to Put Display to Sleep. It's less of a necessity now while working from home, but back when I was working at an open floorplan office it was ideal to quickly lock my MacBook. I wouldn't even have to think about it—just flick the cursor into the bottom left corner while getting up or walking away and I was set.

To set this up, go to System Preferences → Desktop & Screen Saver → Hot Corners….

Screenshot of "System Preferences → Desktop & Screen Saver → Hot Corners…"

Dock

This one doesn't necessarily benefit my productivity, but in general I find that it helps my peace of mind to declutter my screen, and a big part of that is the Dock.

First, I have it set to automatically hide and show. This just removes it from the screen entirely until needed, which isn't actually all that often. To do this, go to System Preferences → Dock & Menu Bar and check Automatically hide and show the Dock.

Second, I removed all apps from it that I never or rarely use. It always surprises me to see people with a bunch of default apps in there without bothering to remove them. Either right click on them and then click Remove from Dock or simply drag them off of it.

Third, I added some spacer tiles, which are just empty spaces that can be moved around to create sections within the Dock. To create these:

  1. Launch Terminal.

  2. Enter the following command to create a spacer tile:

    $ defaults write com.apple.dock persistent-apps -array-add '{tile-type="spacer-tile";}'
  3. Enter the following command to restart the Dock:

    $ killall Dock

You can add as many tiles as you like, and just as with regular apps they can be dragged around the Dock and removed to your liking.

Screenshot of "Dock"

Screenshots

macOS has extensive screenshot taking capabilities built in. For a full overview see their support article, but here is a summarized overview:

I particularly like the options to screenshot an area or a window. Also good to know: when you have an area already selected you can press Space to drag the selection around, Option to resize the selection from the center, or Shift to change the selection from just one side while keeping the other as is.

Normally I take screenshots directly to clipboard, but to add markup it needs to be saved to a file. However, if you click on the little screenshot preview in the bottom right of the screen right after taking a screenshot, and then use the markup functionality, you can press Command-Option-C to copy the result to clipboard and prevent it from actually being saved to file. Win-win.

Shortcuts

To round up the macOS section, here are some default shortcuts I use a lot. Some of these might seem simple, but it also means it's a good starting point to really get into the habit of using shortcuts, especially once you start combining them.

Two things I just want to point out:

  1. You can often add Shift to a shortcut to do the reverse of the original shortcut. Examples of this are moving focus between elements going forward (Tab) and backward (Shift-Tab), going to the next (Enter) or previous (Shift-Enter) search result, or switching between tabs or applications (see below).
  2. You can use the menu bar menus to see available actions and their corresponding shortcuts. Lots of apps have shortcuts available, and the best way to start learning them is to just see what's there. You can also press Command-Shift-/ to search within an app's menu items, which will then highlight where the menu item can be found and what its shortcut is (if any).

General

Browser

Karabiner-Elements

The app powering most of my custom shortcuts is Karabiner-Elements. With it, you are able to set up flexible and powerful keyboard modifications.

There are four modifications in particular I recommend, and I find that the easiest way to set these up is to edit the configuration file directly. Go to Karabiner-Elements → Misc and click Open config folder (~/.config/karabiner). Then, with your text editor of choice, open karabiner.json and add the code samples shown in the subsections below under profiles[x].complex_modifications.rules.

Screenshot of "Karabiner-Elements"

Remap Caps Lock to Escape

I rarely use the Caps Lock key. I just don't shout a lot, and I suspect that's the case for many people. Considering it's so rarely used, then, the Caps Lock takes up quite the prominent position on the keyboard.

Now, the Escape key is useful to me. Not in the least because I use Vim, but even in normal day-to-day use there's plenty of moments where quickly dismissing something with it is great, and by remapping the Caps Lock to Escape it's significantly more accessible.

{
  "description": "Change caps_lock to command+control+option+shift (escape when pressed alone)",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "key_code": "caps_lock",
        "modifiers": {
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "left_shift",
          "modifiers": [
            "left_command",
            "left_control",
            "left_option"
          ]
        }
      ],
      "to_if_alone": [
        {
          "key_code": "escape"
        }
      ]
    }
  ]
}
note: This modification on its own can also be done without third-party apps. Go into System Preferences → Keyboard → Modifier Keys… to change the behavior of any of the keyboard's modifier keys, including the Caps Lock. However, this falls short when wanting to do more complex modifications, as I describe in the following subsections.

Remap Caps Lock to Hyper Key

Didn't I just tell you to remap Caps Lock to Escape? Yes, I did. But that was for a single press. With Karabiner-Elements you can set up more complex modifications where you differentiate between a single press (pressing just that one key) and a combined press (pressing multiple keys at the same time).

The Hyper key is the combination of all four modifier keys—Command, Control, Option, and Shift. Performing this keyboard manually would quickly become painful, and therefore it's a combination that's never used. That's great, because it means that we're free to combine it with any other key for custom shortcuts without having to worry about it conflicting with any app or system shortcuts.

This keyboard modification is what enables nearly all of my macros, as described in the Keyboard Maestro section.

note: The configuration for this is included in the previous subsection.

Remap Shift-Caps Lock to Caps Lock

As pure as my intentions are, sometimes I just have to raise my voice from behind the laptop. In such cases it's useful to have an alternative way of activating Caps Lock, considering we have lost the default Caps Lock key. By remapping the combination of Shift and Caps Lock to do this, I keep the new functionality of Caps Lock to act as Escape and the Hyper key while having a way to fall back on the original behavior.

{
  "description": "Use shift+caps_lock as caps_lock",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "key_code": "caps_lock",
        "modifiers": {
          "mandatory": [
            "shift"
          ],
          "optional": [
            "caps_lock"
          ]
        }
      },
      "to": [
        {
          "key_code": "caps_lock"
        }
      ]
    }
  ]
}

Remap fn + h/j/k/l to Arrow Keys

Lastly, this is an easy way improve my navigational abilities. The arrow keys are useful, but they're badly positioned since they require moving a hand off the home row to reach them. By remapping the fn key to work together with the h, j, k, and l keys to act as arrows they're really quick to use.

{
  "description": "Change fn + h/j/k/l to arrow keys",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "key_code": "h",
        "modifiers": {
          "mandatory": [
            "fn"
          ],
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "left_arrow"
        }
      ]
    },
    {
      "type": "basic",
      "from": {
        "key_code": "j",
        "modifiers": {
          "mandatory": [
            "fn"
          ],
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "down_arrow"
        }
      ]
    },
    {
      "type": "basic",
      "from": {
        "key_code": "k",
        "modifiers": {
          "mandatory": [
            "fn"
          ],
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "up_arrow"
        }
      ]
    },
    {
      "type": "basic",
      "from": {
        "key_code": "l",
        "modifiers": {
          "mandatory": [
            "fn"
          ],
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "right_arrow"
        }
      ]
    }
  ]
}
note: The choice for using h, j, k, and l might seem arbitrary, but it means you can navigate with just your right hand all from the home row.

Keyboard Maestro

With the Hyper key set up, a wide range of new possible shortcuts are unlocked. To best make use of this I use Keyboard Maestro, which is built around the concept of macros. A macro is a collection of actions that can be activated through so-called triggers. You describe what you want it to do and specify how you want those actions to activate and Keyboard Maestro will then take care of it.

This probably sounds a bit abstract, but it's also what makes it so flexible and powerful. More than the other suggestions so far, Keyboard Maestro is a personal app in that it's likely to be tailored to each user's needs and workflows. As such, rather than just diving into the "how", I'll also try and explain the "why" behind my setup.

Organization

The app consists of three main panes: one for macro groups, one for macros, and one for the contents of the macro. These macro groups can be used just for organizational purposes, but also to have them share a certain characteristic (such as for palettes).

As my library of macros grew, I found it helped to keep them well organized. I tried a few approaches, but the one I have now is to use three types of macro groups:

Screenshot of "Keyboard Maestro"

Other than that, I also have a → Subroutines group, with the arrow to keep it sorted on top. This contains macros that I don't use directly; instead, they contain generic actions that I execute from other macros. This lets me keep the main logic in one place, so if I ever have to update it I know where to do it and I only have to do it once.

To use these, insert the action called "Execute a Subroutine". You can define and pass along parameters as well, as well as pass data back to the initial macro. See the examples subsection for inspiration on how to use this.

Palettes

Palettes are by far my most used feature of Keyboard Maestro. With it, a small overlay opens up that lists all the macros within the group, including (optionally) their icon and their trigger.

There's a few different ways of having palettes show up, but my favorite is to use Shows a palette for one action when → The hot key … is pressed. With this, pressing the specified hot key will show the palette, and triggering any of its macros will hide it again.

note: Sometimes I open up a palette only to decide I don't want to use any of its macros. Intuitively I'd press Escape to discard it, but that doesn't work—it uses Enter for that instead. As a workaround, I normally add an empty macro with Escape as the trigger. Not ideal, but it makes more sense to me than the default.

As mentioned earlier, the combination of the Hyper key is so impossible it's never used, and it can therefore be freely used for any combination. However, if you start using it for all your shortcuts directly, you'll soon find that you run out of sensible combinations.

So, instead, I use palettes to group macros, and—where possible—use mnemonic shortcuts to trigger them. Once the palette is open you don't necessarily need unique shortcuts anymore, so you can assign each of the macros within the palette a single letter as hot key. With this, it's one more key press compared to directly triggering the macro, but it doesn't pollute your global shortcuts, groups your macros nicely together, and gives you a nice little overlay to see the available macros, in case you need the reminder.

Here are some examples of palettes I use:

Window Management

I previously used a dedicated app for window management, but when I discovered that Keyboard Maestro has this functionality built in I quickly moved over. I'm sure it lacks some features found in dedicated apps, but it's enough for my needs. I use it in two ways:

Typed Strings

Macros can also be triggered by typing a sequence of characters. The only caveat here is that it will also trigger when you're in a text input, so you need to make sure it's not a combination of keys you'd normally use. I prefix most of my typed strings with ; so as to avoid that.

These typed strings are particularly useful for inserting snippets of text. I have a few of these, and to keep them organized I namespace them, meaning I group macros with a similar purpose together under the same prefix. For example, I have ;dt for inserting tomorrow's date and ;dy for inserting yesterday's date. And I have a wide range of typed strings starting with ;f which then insert dummy data (such as ;fs for a Lorem ipsum sentence or ;fe for a fake email address).

Finally, I have a few typed strings for characters I frequently use, such as the arrow I use in this post ("→") that's inserted whenever I type ->, or the multiplication sign ("×") that's inserted whenever I type ;x,

Automations

I have a few macros that are set and forget. They're triggered by things that just happen automatically, so they don't require my input. For example:

Other Examples

Finally, let's dive into some random examples of macros I use and love. As mentioned before, I see Keyboard Maestro as a personal app in that it's likely to be tailored each user's needs and workflows, but I've certainly been inspired myself by seeing others' creativity.

A few of these have been set up as subroutines. In the organization subsection I explain what these are and how to use these.

Making a FaceTime Call

In the palettes subsection I describe my palette for making calls, among which FaceTime calls. The subroutine for this takes a parameter for the contact (like a phone number or an Apple ID) and then takes care of initiating the call.

Screenshot of "Keyboard Maestro -> Subroutines -> FaceTime"

Making a Zoom Call

Similarly to the FaceTime call subroutine, the Zoom call subroutine takes a parameter to then connect to a Zoom call. What's slightly different is that it leaves it more open what to pass along, so that you're able to join a public call (join?confno=123456789), join a passcode-protected call (join?confno=123456789&pwd=abcdef), or start a call (start?confno=123456789).

Screenshot of "Keyboard Maestro -> Subroutines -> Zoom"

Performing OCR

OCR (Optical Character Recognition) lets you pull text from an image. This subroutine only takes care of capturing the image, and then passes along the output to the macro that executed it for further processing. The screencapture command initiates taking a screenshot by dragging the mouse to select an area (-s) and then saves it to the clipboard (-c), and it does this without playing the usual screenshot sound (-x).

Screenshot of "Keyboard Maestro -> Subroutines -> OCR"

Toggling Do Not Disturb

There are a few instances where I need to set the Do Not Disturb state. It's not quite as straightforward as turning it on or off; instead, you need to toggle it. Thankfully, there's a way to check if it is currently active, which can then be used to act accordingly:

Screenshot of "Keyboard Maestro -> Subroutines -> Do Not Disturb"

Create one that checks if the script is 0 to turn it on, and one that checks if the script is 1 to turn it off. The macro taking care of the actual toggling executes a keystroke, which is a shortcut I have set under System Preferences → Keyboard → Shortcuts. There, select "Mission Control" on the left, and configure a shortcut for the action "Turn Do Not Disturb On/Off". I went with Hyper-0, for no particular reason.

Syncing Browser Scroll Positions

When I'm working on a site I sometimes want to try out different designs of the same element. To do this I open two tabs, make my changes in one tab, and then go back and forth between the two tabs to compare. Of course, it helps to then have the two tabs at the exact same scroll position so that there's no jumping around and you can focus entirely on the design changes.

This macro gets the scroll position from the front browser, saves it, and then, when triggered again within 5 seconds, will scroll to that position. If not used within that time it'll delete it, so that it's reset for the next use.

Screenshot of "Keyboard Maestro -> Browsers -> Sync Scroll"

Starting and Stopping Modes

In the palettes subsection I describe my palette for different modes. Most of these modes just open up a few things, but for my work mode I have a system built in that toggles between starting the mode and stopping the mode.

To do this, in the start version I first perform all start-specific actions, then pause for 0.5 seconds so as not to interrupt those start actions, and then disable the start version and enable the stop version. In the stop version I do the same, except that I enable the start version and disable the stop version.

The great thing is that you can then give both versions the same trigger, and since only one of them will ever be enabled it just toggles between the two.

Conclusion

I could go on and on about all my macros, but this seemed like a good selection to give just a taste of what's possible. If you're interested in hearing more about any of this, let me know on Twitter!