(Mac) I replaced 10 yrs of paying for Keyboard Maestro with a single Lua script

genesishash1 pts0 comments

(Mac) I replaced 10 yrs of paying for Keyboard Maestro with a single Lua script. — kb/hardware

utxo@riseup.net<br>-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEEb7x2<br>kQ4mVYyLr0PhT3n8WmZa<br>9uAFAmiPq2sACgkQT3n8<br>WmZa9uD1bQ/9F2jK4cXe<br>0hHnV6yLwB1sPmR8tqUj<br>3aZoNc7EdYfM5xGvKiQ2<br>=k9xB<br>-----END PGP SIGNATURE-----

(Mac) I replaced 10 yrs of paying for Keyboard Maestro with a single Lua script.

2026-07-06

I've been a Keyboard Maestro user for ten years. Paid for every major upgrade. Built up a Global Macro Group with seventeen macros that my hands depend on: browser history on ⌘J/⌘L, tab switching on ⌘S/⌘D, hard refresh, dev tools, window sizing, a terminal toggle on backtick, forward delete, a text expansion. The kind of setup you stop thinking about because it's part of how you type.

Last week I replaced all of it with one Rebind script. I didn't even write the script. RebindGPT did.

Rebind is a free app that remaps your keyboard with Luau scripts. Think Hammerspoon's scripting with Karabiner's input engine, without the config mess.

The before state

If you've maintained a serious Keyboard Maestro setup, you know what it looks like. Every remap is a macro. Every macro is a stack of click-configured conditions: If any of the following are true: Google Chrome is at the front, Chromium is at the front... execute: Type the ⌘] Keystroke. Otherwise: No Action. Multiply that by every browser you use, then by every shortcut, then again for the apps that need a different keystroke for the same action.

My "browser history forward" macro alone was two condition blocks deep, each enumerating applications one dropdown at a time. Seventeen macros of that. Keyboard Maestro is genuinely good software, but the setup is opaque: you can't diff it, you can't grep it, and you rebuild it dropdown by dropdown on every new machine.

The after state

One Luau file. My entire Global Macro Group, expressed as code I can read:

remap("J", "LeftBrace", function() return cmd() and CHROMISH[front()] end) -- Chrome → ⌘[<br>remap("J", "Left", function() return cmd() and FIREFOXISH[front()] end) -- Firefox → ⌘←<br>remap("L", "RightBrace", function() return cmd() and CHROMISH[front()] end) -- Chrome → ⌘]<br>remap("L", "Right", function() return cmd() and FIREFOXISH[front()] end) -- Firefox → ⌘→That's the entire "browser history" pair, the thing that took four condition blocks across two macros in the old setup. App families are defined once as plain tables and reused throughout:

BROWSERS = set { "Google Chrome", "Chromium", "Brave Browser", "Firefox", "LibreWolf", "Safari" }<br>ARROW_TABS = set { "Google Chrome", "Chromium", "Brave Browser", "Firefox", "LibreWolf", "Safari", "Code", "Visual Studio Code", "Cursor" }<br>BRACKET_TABS = set { "Ghostty", "Terminal", "Hyper", "iTerm2", "iTerm", "MacVim", term }Add a browser to the table, every remap picks it up. Try doing that across seventeen macros of dropdowns.

(Rebind is a free download if you want to poke at it while you read. The full script is at the bottom.)

I didn't write this script

Here's the part that actually surprised me. I described my Keyboard Maestro setup to RebindGPT: the shortcuts, which apps needed which variants, the terminal toggle behavior. It wrote the whole thing, including the subtle stuff I would have gotten wrong on the first pass, like waiting for physical modifiers to clear before injecting a chord that conflicts with them:

-- Emit `chord` after physical modifiers clear — used when the chord conflicts<br>-- with held ⌘/⇧ (macOS applies held modifiers to any injected event).<br>local function injectAfterMods(chord)<br>Run(function()<br>while cmd() or shift() do Sleep(5) end<br>HID.Press(chord)<br>end)<br>endHeld modifiers merging into synthetic events is a real macOS injection pitfall, and the generated script handled it without being asked.

It didn't stop at writing the script, either. When an early version polled System.Window() too aggressively in a timer, I pasted the runtime's warning into the same chat. RebindGPT diagnosed the tick-budget problem and rewrote the hot path: slower timer, expensive check moved behind the keypress that actually needs it.

Coming from AutoHotkey or another tool? You can paste scripts from other tools like AHK, AppleScript, or Hammerspoon into RebindGPT. It converts them into a working Rebind project. I'm in the middle of converting my AHK scripts on Windows the same way.<br>The full script

Everything below is what runs on my machine today. The two configurable values (terminal app and the ⌘P text expansion) surface as UI controls in the Rebind panel, so the script itself stays generic:

The full script (~180 lines)-- rebind: name=taky-km<br>-- rebind: min_sdk=3.2.1<br>-- rebind: description=Keyboard Maestro parity — global, app-conditional chord remaps, app control, and configurable terminal/hash.

-- ═══════════════════════════════════════════════════════════════════════════════<br>-- Config<br>--...

script keyboard maestro rebind browser remap

Related Articles