flash

Coming from Hammerspoon

Flash is a keyboard-driven macOS app configured in TOML. Its commands, native mappings, and managed plugins cover many everyday Hammerspoon setups without translating arbitrary Lua. Keep Hammerspoon for workflows that need general Lua execution, hardware integrations, or custom windows and web views.

Hammerspoon Flash
hs.hotkey.bind, hs.hotkey.modal [mode.all.mappings] for global shortcuts; NORMAL, INSERT, COMMAND, and TERMINAL mappings for modes; [mode.apps."<bundle-id>".<scope>.mappings] for app-specific bindings
hs.hints, hs.mouse mouse_target, mouse_grid, mouse_pointer, and mouse_button
hs.grid, hs.window window_move slots, proportional frames, and display moves; window_focus directions; window_minimize, window_restore, and native window_fullscreen
hs.application app_open --name=…, app_previous, app_next, and app_quit
hs.window.switcher, hs.chooser :flashlight @windows for cross-app windows; the flashlight also searches apps, tabs, menus, emoji, and plugin catalogs
hs.alert alert_show --message=… and alert_dismiss
hs.eventtap keystrokes send_key and send_keys for explicit key sequences
hs.task A mapping can run an argv array; managed plugins can expose resident commands and data
hs.menubar, hs.canvas The configurable status bar and desktop widgets, with tmux-format templates and plugin data
hs.audiodevice, hs.caffeinate Bundled media commands for volume, playback, and input/output device selection; :caffeinate on, :caffeinate off, and :caffeinate toggle
hs.pasteboard, hs.shortcuts Clipboard history with :clipboard show; Shortcuts catalog with :flashlight @shortcuts

Move a hotkey

This Hammerspoon binding:

hs.hotkey.bind({"cmd", "shift"}, "space", function()
  hs.execute("flash mouse_target")
end)

can live in ~/.config/flash/flash.toml instead:

[mode.all.mappings]
"cmd+shift+space" = ["flash", "mouse_target"]
"alt+h" = ["flash", "window_move", "--position=lefthalf"]
"alt+f" = ["flash", "window_fullscreen"]
"alt+m" = ["flash", "window_minimize"]
"alt+shift+m" = ["flash", "window_restore"]
"alt+l" = ["flash", "window_focus", "--direction=right"]
"alt+c" = ["flash", "caffeinate", "toggle"]

Flash reloads mappings when the file changes. Run flash config_check to validate them and flash doctor if a shortcut does not register. See configuration for modifier syntax, scoped mappings, and running external argv arrays.

Use [mode.apps."<bundle-id>".<scope>.mappings] for bindings that apply in one app, and [[window_rules]] for opt-in placement when a matching window appears.

Move a modal setup

Hammerspoon modal hotkeys enable a set of bindings while a mode is active. Flash’s NORMAL mode does the same for keyboard-driven app control, including unmodified keys and multi-key sequences:

[mode.all.mappings]
"cmd+ctrl+[" = ["flash", "enter_normal_mode"]
"cmd+ctrl+i" = ["flash", "enter_insert_mode"]

[mode.normal.mappings]
"h" = ["flash", "window_move", "--position=lefthalf"]
"l" = ["flash", "window_move", "--position=righthalf"]
"f" = ["flash", "mouse_target"]

NORMAL captures unmapped keys, so give users an explicit way back to INSERT. Flash also supports scoped mappings, counts, and repeatable actions; see normal mode.

Move automation in stages

Hammerspoon can call flash <verb> while you migrate a config. The flash command sends the action to Flash’s resident process. Keep Lua where an action depends on Hammerspoon’s broad module library; expose small external commands through Flash’s argv mappings, or use a managed plugin when it needs lifecycle, live data, or a searchable catalog. Flash does not execute Lua or provide a drop-in hs.* API.

Flash does not add arbitrary event taps, URL callbacks, screen capture, or custom window surfaces to reproduce Hammerspoon modules. Its privacy model and command inventory describe the supported boundaries.