I’ve been using Hammerspoon for a while now to script little macOS automations. One thing it does brilliantly is window management — no need to pay for Magnet or Rectangle.

My config lives in ~/.hammerspoon/, with a lib/settings.lua file that holds my key combos so the bindings stay readable:

hs.settings.set('hotkeyCombo', {'cmd', 'alt', 'ctrl'})
hs.settings.set('fnkeyCombo', {'fn', 'ctrl'})
hs.settings.set('upShiftCombo', {'ctrl', 'shift'})

Now in lib/shortcuts.lua I can wire up window snapping using hs.settings.get('hotkeyCombo') (cmd+alt+ctrl) plus arrow keys —

local hotkey = hs.settings.get('hotkeyCombo')

-- Left half
hs.hotkey.bind(hotkey, "Left", function()
  local win = hs.window.focusedWindow()
  local f = win:screen():frame()
  win:setFrame({ x = f.x, y = f.y, w = f.w / 2, h = f.h })
end)

-- Right half
hs.hotkey.bind(hotkey, "Right", function()
  local win = hs.window.focusedWindow()
  local f = win:screen():frame()
  win:setFrame({ x = f.x + f.w / 2, y = f.y, w = f.w / 2, h = f.h })
end)

-- Maximize
hs.hotkey.bind(hotkey, "Up", function()
  local win = hs.window.focusedWindow()
  win:setFrame(win:screen():frame())
end)

-- Centre at 80%
hs.hotkey.bind(hotkey, "C", function()
  local win = hs.window.focusedWindow()
  local f = win:screen():frame()
  win:setFrame({
    x = f.x + f.w * 0.1,
    y = f.y + f.h * 0.1,
    w = f.w * 0.8,
    h = f.h * 0.8,
  })
end)

Reload Hammerspoon (or hit ⌘R from its console) and you’ve got a custom window manager. Add quarters, thirds, multi-display moves — it’s all just maths on the screen frame!

The nice thing is everything is plain Lua. Reminds me of Rainmeter in Windows.