The Art of Keyboard Wizardry: Building a 1,000+ Line Karabiner Config

John Lindquist
Instructor

John Lindquist

How I transformed my keyboard into a hyper-productive command center using Karabiner-Elements and Goku

After years of tweaking and refining, my Karabiner-Elements configuration has evolved into an intricate 1,000+ line EDN file that orchestrates every keystroke to do exactly what I need, when I need it. This isn't just simple key remapping; it's a complete reimagining of how I interact with my Mac on a daily basis.

In 2016 I stumbled across the classic “Home Row Computing” post at the exact moment I was relearning to type after shattering my wrist in a long-board accident. That mix of pain and inspiration became the seed for the 1,000-line Karabiner/Goku setup you're reading about today—one that lets me work faster and kinder to my hands.

Lessons From a Broken Wrist

  • Ergo first, fancy later. I adopted split keyboards and low-travel layers before writing a single snippet.
  • Modal beats modifier salad. Holding one key is easier on joints than clawing Ctrl+Opt+Shift.
  • Point-then-press > drag-and-pray. Mouse layers turn pixel-perfect clicks into keyboard muscle memory, reducing both strain and misfires.

Why Home-Row Everything?

Staying on the home row isn't just a nerd flex—it's industrial-grade ergonomics. Keeping wrists neutral and travel distances short is one of the simplest, evidence-backed ways to limit RSI flare-ups, especially after an injury (PubMed, Wired). Home-row computing formalises that idea by making every key combination reachable without stretching. The original Many-But-Finite tutorial did it with AutoHotkey on Windows; I've ported, expanded, and super-charged the concept for macOS.

The Philosophy: Context-Aware Computing

My Karabiner setup is built around a core philosophy: mneumonics + context. Context includes factors like:

  • Which application is active (app-specific behaviors)
  • Whether my hand is on my mouse
  • Whether I'm holding down other modifier keys simultaneously
  • How many fingers are on the trackpad (when in "laptop mode")

This creates a layered, modal interaction system that feels natural once learned, yet provides far more functionality than a standard keyboard. The same physical key can seamlessly perform different actions in different contexts, eliminating waste and maximizing efficiency.

The Foundation: Goku and EDN

Editing Karabiner's raw JSON by hand would be madness at this scale. Instead, I use a tool called Goku to write my configuration in an EDN (Clojure-like) format. Goku watches this EDN file and compiles it down to the complex JSON that Karabiner-Elements expects. This approach brings several benefits:

  • Readable aliases for keys and modifiers instead of cryptic key codes.
  • A template system for reusable shell commands.
  • Logical organization of complex rules (with sections, conditions, etc.).
  • The ability to include comments and documentation inline.

For example, in EDN I can define aliases like a custom Hyper key and use them throughout my config:

:modifiers { :hyper [:command :shift :control :option] ;; Hyper = Cmd+Shift+Ctrl+Opt :cos [:command :shift :option] ;; "cos" = Cmd+Shift+Opt (just an example) }

This is far more manageable than repeating arrays of modifiers in JSON. Goku essentially lets me write a clean config that is then expanded into Karabiner's actual configuration format. The result is a single source-of-truth EDN file that's human-friendly, despite generating thousands of lines of JSON under the hood.

The Architecture: Key Pillars

My configuration's architecture revolves around several key pillars that work in harmony:

1. Application-Specific Behaviors

Each application I use gets its own tailored keyboard behavior profile. When a given app is frontmost, certain keys or combos are remapped to optimize my workflow in that app (while not affecting other apps). For example:

  • Google Chrome – Tapping the left Command key opens a new tab (sending Cmd+T), while holding it still acts as the normal Command modifier. This gives me a one-handed new-tab shortcut on a single key press, without losing the ability to use Command for other shortcuts in Chrome. (Similarly, tapping left Option in Finder might trigger a custom action, etc.)
  • VS Code (and Cursor editor) – Tapping left Command triggers "Go to File" (Cmd+P), giving me quick access to file search, whereas holding it remains the regular Command key for shortcuts. I also map left Control (tap) to open the Command Palette (Cmd+Shift+P) in my code editor. These tap-versus-hold behaviors dramatically speed up common actions.
  • Terminal – I integrate with my terminal/tmux workflow: for instance, pressing Ctrl+R in Terminal is intercepted and translated into a Tmux command that splits the pane (it sends my Tmux prefix Ctrl+B followed by %). This means I can split my terminal window with a single chord, instead of typing two separate commands.

Practically every heavily-used app gets similar treatment. If I'm in Slack, for example, I can use custom combos to navigate channels or go back in history. If I'm in Finder, I have a shortcut that instantly triggers an image compression script on the selected files. The idea is that my keyboard adapts to what I'm doing right now. Pressing the same key in VS Code, Chrome, or Terminal can produce app-specific results that make sense for each context.

2. Mouse & Trackpad: Precision Meets Automation

Over the years, my interaction style has evolved significantly. While I used to rely heavily on trackpad gestures, I now primarily use the right-click on my mouse combined with keyboard keys when at my desk. This shift has made my workflow even more efficient. My setup can still detect how many fingers are touching the trackpad (using Karabiner's Multitouch extension), and it completely changes keyboard behavior based on that finger count. However, when I'm using my MacBook Pro away from my desk, the trackpad acts as a mode switch for my keyboard:

  • 1 Finger on Trackpad – Selection/Navigation Mode: When one finger is resting on the trackpad, certain keys turn into mouse-click tools for easy selection. For example, T (under my left index finger) becomes a left-click, S becomes a right-click, and D becomes a shift-click (for selecting ranges of text or files). I can move the cursor with the trackpad and tap those keys to click or select without ever moving my hand to the mouse. Arrow keys and other keys behave normally in this mode, so I can still navigate with arrows while using T/S/D to select and click. It's like having an extra set of mouse buttons under my fingertips.
  • 2 Fingers on Trackpad – Enhanced Edit/Cut/Copy Mode: With two fingers on the trackpad, I enter a mode for precise cutting and copying. For instance, X will perform a shift+click (to extend selection) then send a Cmd+X (cut) command – effectively "select and cut" in one go. Similarly, pressing C will click and then copy (Cmd+C) the selection, and V will click and then paste. This sounds wild, but in practice it means I can highlight something with a two-finger gesture and cut/copy/paste it with a single keypress, fluidly.
  • 3 Fingers on Trackpad – Media & Screenshot Mode: Placing three fingers on the trackpad toggles a layer for quick media controls and screenshots. For example, S (with three fingers down) takes a screenshot (invoking the macOS screenshot utility), and R starts/stops screen recording. I've mapped a handful of such actions to letter keys in this mode, turning a three-finger gesture + key press into a quick way to capture my screen or control media without hunting for function keys or global shortcuts.

While I don't rely on trackpad gestures as much anymore, the mouse right-click modifier has become my primary mode switch. It's something I should update. When holding right-click, my entire keyboard transforms into a command center of the way we combine trackpad and keyboard usage: if my hand is already on the trackpad, it makes sense that the keyboard might behave differently to complement touch gestures. This synergy between gestures and keys revolutionized my workflow – e.g. I can highlight text or move windows with a gesture and confirm actions with a key press in one smooth motion. Once you get used to it, it feels intuitive and hard to live without.

3. Simlayers: Chord-Based Superpowers

Beyond modifiers and trackpad gestures, I also use simultaneous key presses (chords) — which I call simlayers — to unlock hundreds of additional shortcuts. A "simlayer" is activated by pressing two or more letter keys at the same time (within a tiny timeout). One key essentially acts as a mode trigger for the other. Here are a few of the simlayers I've set up:

  • F Layer (Movement): Pressing F simultaneously with H/J/K/L (which are under my right hand's home row) turns them into arrow keys (left/down/up/right respectively). In other words, F+J sends a Down Arrow, F+K sends Up Arrow, etc. This lets me navigate text or windows using the familiar Vim-style homerow keys, but only when I chord with F (so I don't lose the normal letter typing when I press them sequentially). I also map F+Enter to insert a new line below (an editor shortcut), among other things. F for movement (think "Fly" or arrow flight).
  • J Layer (Deletion): Pressing J with other keys triggers deletion/editing shortcuts. For example, J+S sends a Backspace, J+D sends a Forward Delete, J+F deletes the word ahead (Option+Delete), and J+K might delete an entire line. This chord essentially gives me a dedicated "delete mode" under my left hand (mnemonic: J was originally where "N" is on QWERTY, think N for nuke? It's a stretch, but it works for me!). It's great for quickly cleaning up text without moving my fingers to the actual Backspace or Delete keys.
  • Space Layer (Symbols): Probably my favorite – holding Spacebar and another key produces symbols or symbol combinations. Since Space is hit with the thumb, I can chord it with various letters easily. For example, Space + A types "[", Space + S types "]", Space + D = "(", Space + F = ")". Essentially, I have a whole symbol palette on the home row triggered by the Spacebar. I also set up some combos that output common coding patterns: Space + Hyphen inserts ${} (useful for template literals in code) and puts the cursor between the braces, Space + Quote inserts =\"\" (for quickly adding an empty string attribute and placing cursor inside). The mnemonic here is Space = "insert space for symbols." It lets me type symbols and even small snippets without reaching for Shift+number keys, which is a huge speed win in coding and writing.

Those are just a few examples – I have simlayers for many letters (Q, W, E, F, J, K, ; etc.), each opening up a set of related shortcuts. The key is that they're mnemonically organized. I chose each "trigger" letter to hint at what its layer does (Explorer, Files, Delete, Symbols, etc.), which makes the system much easier to remember. Instead of dozens of arbitrary multi-modifier shortcuts, I essentially have mini modes that group shortcuts by context. Pressing two letter keys at once quickly becomes muscle memory, and it massively multiplies what my keyboard can do without adding any new physical keys.

4. Window Management Integration

Managing windows with the keyboard is another area I've supercharged, thanks to integration with a tiling window manager called Yabai. Yabai runs in the background and exposes commands to move and resize windows, switch workspaces, and more. I've bound many of these actions to convenient key combos via Karabiner:

  • Move windows between displays: I hold down the = key (which I've designated as a "window mode" trigger) and click a window with the mouse to instantly send that window to the next display. No dragging required – the window just jumps to my other monitor.
  • Tiling and resizing: While in this window mode (= held), I can also use letter keys to resize the focused window in small increments. For example, = + J makes the window 10% wider, = + Y makes it 10% narrower. I can nudge windows around or snap them to preset sizes with similar combos. Yabai's tiling means windows often auto-position, but these shortcuts give me fine control when I want it.
  • Spaces (virtual desktops) navigation: I've repurposed my mouse's side buttons for this. If I hold one of my side mouse buttons (Button4 or Button5) and release, it sends me to the previous or next macOS Space (desktop). Essentially, thumb buttons become "switch Space" when tapped. If I hold those buttons instead, Karabiner enters a layer where other keys can trigger more exotic window actions (like creating a new Space, closing the current Space, etc., via Yabai scripts).
  • Creating/destroying spaces: With the right chords I can spawn a new Space or close an empty one on the fly. For instance, = + X in my window mode triggers a script to remove the current desktop Space (if it's empty). Another combo creates a fresh Space and moves the current window there, effectively "teleporting" the app to a new workspace. This is incredibly useful for decluttering or organizing work on the fly.

All these window management shortcuts are powered by Yabai under the hood. Yabai allows complete keyboard control over windows, spaces, and displays through simple shell commands. By binding those commands to keys, I've essentially eliminated most manual window fiddling. I can tile, move, switch, and resize windows without lifting my hands from the keyboard or reaching for the mouse, which keeps me in flow.

(Side note: If you're not familiar with Yabai, it's a popular tiling window manager for macOS that works via a command-line interface and shortcuts. In my setup, Karabiner triggers those CLI commands so quickly it feels native.)

5. Dual-Purpose Keys (Tap vs. Hold)

One of the guiding principles in my config is making keys dual-purpose depending on tap or hold. This means many keys pull double duty: tap them quickly on their own and one thing happens; hold them (or hold as part of a chord) and they serve another role. This trick allows me to squeeze extra functionality out of existing keys without sacrificing their original uses. Some examples:

  • Modifier Keys on Tap: I configure some modifier keys to perform actions if tapped alone, but act normally when held with other keys. As mentioned, tapping my left Command in Chrome opens a new tab, but holding it is just the Command modifier. Similarly, in my code editor, tapping left Control opens the palette, but holding is a regular Control. This pattern extends to others – for instance, tapping the Caps Lock key is interpreted as pressing Escape (useful for Vim or dismissing dialogs), whereas holding Caps Lock engages a custom "Caps layer" (which I use for navigation or triggering Hyper shortcuts). This gives me an "Extra Escape" without losing Caps Lock's position for other modes.
  • Shift Keys = Delete: I took advantage of the fact that tapping Shift by itself normally does nothing (since Shift is only useful in combination). In my config, a quick tap of the left Shift sends a Backspace and a tap of the right Shift sends a Forward Delete. If I actually need to type a capital letter, I'm holding Shift anyway as I press another key, so the hold behavior takes priority and it works normally. But if I just flick my pinky on Shift by itself, boom — it deletes a character. This has turned out to be surprisingly handy, effectively turning the two Shift keys into extra delete keys at the edges of the keyboard.

The general idea is no modifier key sits idle. If there's an opportunity to assign a useful tap behavior that doesn't interfere with the key's hold behavior, I take it. It takes some practice to get used to, but it feels incredibly efficient. Each finger has its own mini shortcut on tap: my left pinky deletes (via Shift), my left thumb enters symbol mode (via Space), etc., all without losing their normal functions when held in combos. Dual-purpose keys are one of the big secrets to keeping this whole setup feeling seamless rather than awkward.

Power User Features and Hidden Gems

Beyond the major pillars above, there are a few extra goodies in my configuration worth mentioning — these really showcase the power and flexibility of Karabiner when paired with a bit of scripting and creativity:

Script Templates for Automation

Karabiner-Elements allows executing shell commands or AppleScripts as a response to key events. I leverage this heavily through Goku's templating system. In my EDN config, I've defined template shortcuts for common shell or AppleScript tasks, such as:

  • Launching or focusing apps: A custom :launch template in my config lets me open applications by name. For example, Launch + F might call a script to focus Finder, Launch + C opens the Cursor editor, Launch + D opens Discord, etc. I just specify the app name in the EDN, and the template expands it to an AppleScript that does open -a "AppName" behind the scenes.
  • Controlling Chrome tabs: I have an :open-chrome and a more advanced :focus-or-open-chrome template. These use AppleScript to check if a Chrome tab with a given URL is already open, and if so, switch to it – otherwise open it in a new tab. This means when I hit certain shortcuts (we'll see examples next), I can instantly bring up exactly the web page or web app I want, without duplicating tabs. It's contextual web navigation at my fingertips.
  • Clipboard and text snippets: There are templates for quickly setting the clipboard to a given text, or typing out a string. For instance, I built a template that reads a text file and types its contents (used for snippet insertion), and another that securely types a password from my keychain (more on that in a bit).

Because these are defined as templates, adding a new one is straightforward and I can reuse them across many key bindings. The use of to.shell_command in Karabiner is incredibly powerful – it essentially lets your keyboard do anything you could script. Want a key combo that runs a particular command-line tool or toggles a setting? It's possible. In my case, I've used it to integrate with everything from window management (Yabai CLI calls) to audio control (AppleScripts for audio apps) to development tooling. The templates just keep things DRY and organized.

URL Quick Access Layer

I spend a lot of time in the browser, so I made a special period (.) simlayer dedicated to quick access of websites. When I press . and another key simultaneously, it will launch or focus a specific website or web app (using the Chrome-focus templates mentioned earlier). Some of my . + key bindings include:

  • . + C → Open ChatGPT in the browser (or bring the tab forward if it's already open).
  • . + G → Open Google's AI (Gemini) search page.
  • . + P → Open Perplexity.ai (another search/AI tool).
  • . + Y → Open YouTube (because cat videos, obviously).
  • . + A → Open Google Analytics Studio (for prompts or analytics dashboards).
  • . + W → Open my Google Calendar in browser.
  • . + J → Open a new JavaScript playground (like js.new).
  • …and so on.

I have a whole host of these mappings for services I use frequently. The beauty is that they reuse those AppleScript templates to avoid duplicate tabs and to focus the app if it's already running. So, for example, hitting . + C will instantly bring up my ChatGPT tab whether it was in the background or completely closed (in which case it opens a new one). It feels almost like using Spotlight, but scoped to the browser and triggered by mnemonic keys.

Development Shortcuts & Snippets

For coding and writing, I created a semicolon (;) layer that gives easy access to common symbols and special characters using mnemonic positions. For example:

  • ; + E types an exclamation mark ! ("E" for "exclamation").
  • ; + A types an @ symbol ("A" for "at").
  • ; + H types a # ("H" for "hash").
  • ; + D types $ ("D" for "dollar"), and so on through % ^ & * for other letters.

This means I don't have to reach for the number row to get those symbols – I can just chord ; with the corresponding home-row letter. It's surprisingly faster and more comfortable. The mnemonic mapping (based on QWERTY positions) makes it easy to remember which is which after a little practice.

In addition, I built a "snippet mode" on the quote key ('). If I hold ' and press certain letters, it will paste or type out predefined snippets of text that I use often. For instance, '+C might insert a console.log() snippet (with the cursor placed appropriately inside the parentheses), '+A might expand to an async keyword, '+N could drop in a snippet for a common CSS class template, and so forth. One particularly useful trick: I integrated macOS's secure credential storage for certain snippets – so '+E might fetch my work email from the keychain and type it out, or '+1 could auto-type a password or API token. This way I can input frequently-used credentials or text blocks with a simple chord, without exposing them in plaintext in my config.

Finally, one of my favorite little layers is the emoji picker I set up. By pressing Z (the letter Z) and another key, I have a whole set of emojis I can instantly insert into any text field. For example, Z+L types out the "❤️" emoji, Z+J inserts "😂", Z+F inserts "🔥", Z+O inserts the ever-important "💩", etc. I mapped a bunch of my most-used emoji to intuitive letters (like L for love heart, F for fire, J for joy/laughter, O for poop… you get the idea). This might seem frivolous, but if you communicate a lot in text, being able to drop in emoji reactions without opening an emoji picker menu is surprisingly convenient. And of course, I also have one key in that mode reserved to open the full emoji picker (Z+E triggers the standard Mac emoji picker, just in case I need an emoji I didn't hard-map).

These little custom layers (snippets, emoji, symbols, etc.) are the hidden gems of my setup – they save me small amounts of time and friction that add up enormously over the course of a day. When you can generate boilerplate, insert symbols, or express yourself with emoji via quick chords, the keyboard starts to feel less like a barrier and more like an extension of your thought process.

The Learning Curve Reality

I won't lie — this setup has a steep learning curve. It represents years of incremental adjustments and additions to my workflow. If you tried to adopt it all at once, you'd probably feel overwhelmed and frustrated. But here's the thing: you're not supposed to implement it all at once. The key is to start small and let the configuration grow with your needs and muscle memory. Each layer or trick I added solved a specific pain point or frequent task in my workflow, and I only added one at a time, giving myself days or weeks to get used to each change.

Start small:

  1. Begin with basic app-specific tweaks – Pick one or two apps you use constantly and remap one or two keys to ease a common action (like the Chrome and VS Code examples of tapping Command to do something useful). Get comfortable with those first.
  2. Add one simlayer – A great starting point is the Spacebar symbol layer for brackets and parentheses, or maybe a simple one like F for arrows. This immediately adds value, but it's also easy to remember (since you'll feel the thumb or finger chord as a reminder). Use it until it's second nature.
  3. Gradually integrate trackpad gestures – Perhaps start with just the one-finger selection mode. Train yourself to rest a finger on the trackpad while selecting text with T/S/D keys. Once that clicks (pun intended), introduce the two-finger cut/copy layer, etc. You'll be stacking modes without even realizing it.
  4. Build out your most-used applications – Over time, identify the top dozen shortcuts you use or wish existed in each app, and encode them into your config. Maybe your design software could use a chord for "next artboard", or your email client for "archive email". By focusing on what irks you most or what you do most often, each addition provides a noticeable payoff.

The important part is iterative learning. Because everything is contextual and layered, you can add new behaviors without completely uprooting your existing habits. Your muscle memory for normal typing largely remains unaffected; you're just layering new abilities on top, one by one. It definitely takes dedication to master, but if you enjoy this kind of customization (and I suspect you do, if you've read this far!), the journey is part of the fun.

The Payoff

After living with this setup for so long, I can confidently say I cannot imagine working any other way. My keyboard has become an extension of my mind – or perhaps more accurately, I've molded it to mirror how my mind works. Common actions become reflexes. I think about what I want to do, and my fingers already have a way to do it without me reaching for the mouse, menu, or remembering a long shortcut sequence. The productivity boost is hard to quantify, but it's very real. More importantly, it makes working on my computer feel fluid and even enjoyable, rather than a constant friction of "ugh, where is that command again."

Crucially, this setup is personal. It's tuned to my workflow, my applications, and my preferences. Your ultimate setup will likely look different, and that's okay. The principles, however, can apply to anyone: layers, modes, context-awareness, and mindful key reuse. By starting small and continuously iterating, you can gradually transform your keyboard into a tool that truly works for you, not just a generic input device.

Key Takeaways

  1. Start Simple: Don't try to implement everything at once. Begin with one or two changes that solve your biggest pain points and build from there.
  2. Use Mnemonics: Design your shortcuts and layers around mnemonic letters or positions (e.g. E for Explorer, F for arrow movements). This makes them easier to remember and more intuitive to use.
  3. Embrace Context: Let the same key do different things in different contexts (different apps, or when combined with trackpad gestures, etc.). This multiplicative approach gives you far more functionality without adding new keys.
  4. Document Everything: Keep your config organized with comments and logical sections. Six months from now, you'll forget why that one key is behaving oddly unless you wrote it down! Good documentation in your config is a lifesaver as it grows.
  5. Iterate Constantly: Treat your config as a living document. Tweak it, refine it, and let it evolve with your workflow. If something's not working or you find a better idea, change it. There's no "perfect" setup, only what's perfect for you at this moment.

The Code

If you're interested in the nitty-gritty, you can find my complete configuration here:karabiner.edn gist. The karabiner.edn file there is extensively commented and organized for readability. Browsing through it might give you additional ideas of what's possible.

Pro tip: One of my best recommendations for learning Goku/EDN syntax is to use GitHub's code search to find other people's karabiner.edn files. Search for "karabiner.edn" on GitHub and you'll discover hundreds of real-world examples showing different approaches and clever tricks. It's an invaluable resource when you're trying to figure out how to implement a specific feature.

Remember: the best keyboard setup is the one you will actually use. It doesn't have to be as elaborate as mine to make a huge difference. Start with solving your most frequent repetitive tasks or annoyances, and gradually add layers of customization. Your future self will thank you for every keystroke saved, every context switch avoided, and every workflow made just a bit smoother.


This post represents years of iteration and refinement in keyboard customization and I still tweak it daily! Your mileage may vary, but hopefully these principles of contextual, layered input inspire you to tailor your own setup. The key is to start simple and let it grow naturally, even a few smart remappings can dramatically improve your daily productivity.

Share with a coworker