Automation Keyboard, gesture, and workflow automation on macOS

The automation stack on the Mac Studio uses several tools in layers โ€” each handles what it does best. They overlap intentionally; pick whichever is simplest for a given task.

The Stack
Tool Best for Config location
BetterTouchTool Gestures, window snapping, named triggers, Touch Bar, Stream Deck, floating menus BTT preferences (cloud/local sync)
Keyboard Maestro Complex multi-step macros, app-specific automation, clipboard processing, palettes ~/Library/Application Support/Keyboard Maestro/
Hammerspoon Lua scripting, window management fallback, system-level hotkeys, Spoons ~/.hammerspoon/init.lua
Raycast Quick launcher, snippets, clipboard history, extensions, one-off scripts Raycast preferences
Apple Shortcuts iOS/Mac cross-device automation, Siri integration, share sheet actions iCloud-synced
Division of Labor

BTT owns gesture input โ€” trackpad gestures, mouse button remapping, keyboard sequences, and named triggers that other tools can call. Window snapping zones are set here. The Stream Deck is configured here.

Keyboard Maestro owns complex logic โ€” anything requiring conditionals, variables, loops, or multi-step clipboard manipulation. Palette menus for triggering groups of macros live here.

Hammerspoon is the programmable fallback โ€” when BTT or KM can’t do something (usually low-level window or system manipulation), Lua handles it. HammerFlow manages the hotkey config in TOML.

Raycast handles daily launcher use โ€” switching apps, snippets, clipboard history, quick calculations, and file search. Scripts here are single-purpose utilities.

Shortcuts handles anything that needs to cross devices or appear in the Siri/share sheet context.

Apple Shortcuts

Apple Shortcuts handles automation that needs to cross devices (Mac โ†” iPhone โ†” iPad) or integrate with Siri and the share sheet. iCloud-synced so shortcuts built on iPhone are available on Mac and vice versa.

When to Use Shortcuts

Use Shortcuts (over KM or BTT) when:

  • The automation needs to run on iPhone or iPad
  • It needs a Siri voice trigger
  • It appears in the share sheet (e.g., process selected text/files from any app)
  • It involves Apple-specific services (Health, HomeKit, Focus modes, Messages)
Running Shortcuts from Other Tools

From terminal:

shortcuts run "Shortcut Name"

From Keyboard Maestro: Use the “Execute Shell Script” action with the shortcuts run command.

From Hammerspoon:

hs.task.new("/usr/bin/shortcuts", nil, {"run", "Shortcut Name"}):start()
BetterTouchTool

BTT is the input layer for everything โ€” gestures, window snapping, Touch Bar, Stream Deck, and named triggers that Keyboard Maestro and Hammerspoon can call into.

Location: ~/Applications/BetterTouchTool.app (socket-activated from user Applications folder)

Named Triggers

Named triggers let other apps (Keyboard Maestro, Hammerspoon, scripts) fire BTT actions by name via URL scheme or AppleScript.

Calling a named trigger:

open "btt://trigger_named/?trigger_name=YOUR_TRIGGER_NAME"

From Keyboard Maestro: Use the “Open URL” action with the btt:// URL scheme.

From Hammerspoon:

hs.urlevent.openURL("btt://trigger_named/?trigger_name=YOUR_TRIGGER_NAME")
Window Snapping

Window snapping zones are defined in BTT โ†’ Window Snapping & Moving. Drag a window to a screen edge or corner to snap it to a predefined layout.

Zone Layout
Left edge Left half
Right edge Right half
Top edge Full screen
Top-left corner Top-left quarter
Top-right corner Top-right quarter
Bottom-left corner Bottom-left quarter
Bottom-right corner Bottom-right quarter
Stream Deck

Stream Deck is configured inside BTT (not the Elgato app). Actions are organized into profiles per application context.

  • BTT โ†’ Stream Deck tab โ†’ configure buttons, folders, and dynamic content
  • Use BTT named triggers to call complex multi-tool actions from Stream Deck buttons
Config Backup

BTT config is stored in ~/Library/Application Support/BetterTouchTool/. Back up before updates. Cloud sync is available in BTT settings if enabled.

Export a snapshot: BTT โ†’ Manage Presets โ†’ Export.

Hammerspoon

Hammerspoon is the programmable layer โ€” anything that requires Lua logic, low-level window manipulation, or system events that BTT and KM can’t reach.

Config: ~/.hammerspoon/init.lua โ€” the main entry point. Modular configs split into separate files and required from init.lua.

HammerFlow

HammerFlow manages Hammerspoon hotkey bindings in TOML configuration files, making them readable and maintainable without editing raw Lua.

Config location: ~/.hammerspoon/hammerflow.toml (or similar โ€” check init.lua for exact path)

Format:

[[bindings]]
key = "h"
mods = ["ctrl", "alt"]
action = "some_action"
description = "Do something"
Installed Spoons

Spoons are Hammerspoon plugins stored in ~/.hammerspoon/Spoons/. List installed:

ls ~/.hammerspoon/Spoons/

Common useful Spoons: MiroWindowsManager (window grid), ReloadConfiguration (auto-reload on save), SpoonInstall (install other Spoons).

BTT Integration

Hammerspoon can call BTT named triggers and vice versa:

Hammerspoon โ†’ BTT:

hs.urlevent.openURL("btt://trigger_named/?trigger_name=TRIGGER_NAME")

Reload config:

hs.reload()

Or use the menu bar Hammerspoon icon โ†’ Reload Config.

Debugging

Open the Hammerspoon console from the menu bar icon to see print output and errors. Add print("debug message") anywhere in Lua for tracing.

Watch the console when reloading config โ€” syntax errors appear immediately.

Keyboard Maestro

Keyboard Maestro handles automation that requires logic โ€” conditionals, variables, loops, clipboard manipulation, and multi-step sequences too complex for BTT or Raycast.

Engine: Always running as a background process. Macros fire via hotkeys, typed strings, application triggers, or calls from BTT/Hammerspoon.

Trigger Types
Trigger Use case
Hot Key Direct keyboard shortcut
Typed String Abbreviation expansion (e.g., ;;addr โ†’ full address)
Application Run when an app launches, activates, or quits
Time Schedule โ€” on login, at time, periodically
BTT Named Trigger Called from btt:// URL scheme
Hammerspoon Called via hs.osascript or URL event
Palettes

Palettes are visual popup menus of macros triggered by a hotkey. Use them to group related macros without memorizing individual shortcuts.

Create: New Group โ†’ set “Show as palette when…” โ†’ assign a trigger hotkey.

Variables & Clipboard

KM variables persist across macro runs. Use Set Variable action and reference with %Variable%VariableName%.

The Named Clipboard system stores multiple clipboard items โ€” useful for multi-step copy-paste workflows across windows.

Config Location

Macros are stored in ~/Library/Application Support/Keyboard Maestro/Keyboard Maestro Macros.plist. Sync via iCloud Drive or back up manually before major changes.

Export groups: right-click group โ†’ Export โ†’ saves as .kmmacros file.

Raycast Scripts

Raycast script commands are shell scripts, Python, or Node.js files that run from the Raycast command palette. Good for single-purpose utilities that don’t warrant a full KM macro.

Script Location

Script commands live in a directory registered in Raycast โ†’ Preferences โ†’ Extensions โ†’ Script Commands. Add a directory and Raycast will scan it for scripts with the required comment headers.

Typical location: ~/Scripts/raycast/ or ~/Developer/raycast-scripts/

Script Anatomy

Every script needs a header block:

#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title My Script
# @raycast.mode compact
# @raycast.packageName My Scripts
# @raycast.description Does something useful

echo "Result shown in Raycast"

Modes:

  • compact โ€” result shown inline in Raycast
  • fullOutput โ€” opens a dedicated output window
  • silent โ€” no output shown
Arguments
# @raycast.argument1 { "type": "text", "placeholder": "Enter value" }

echo "You entered: $1"

Raycast prompts for the argument before running.