Skip to content

Instantly share code, notes, and snippets.

@pjurczynski
Created January 15, 2026 12:26
Show Gist options
  • Select an option

  • Save pjurczynski/7b09d2f545a161565836f210deb85cf9 to your computer and use it in GitHub Desktop.

Select an option

Save pjurczynski/7b09d2f545a161565836f210deb85cf9 to your computer and use it in GitHub Desktop.
hammerspoon config
-- Hammerspoon: Focus Vivaldi browser, VSCode, Terminal, Finder, Chat, Spotify, and Terminal toggles with AppWindowSwitcher
local hyper = {"ctrl", "alt", "cmd", "shift"}
local lcag = {"ctrl", "alt", "cmd"}
---@type table<string, string>
local appLaunchMap = {
["Vivaldi"] = "Vivaldi",
["Code"] = "Visual Studio Code",
["iTerm"] = "iTerm",
["Terminal"] = "Terminal",
["Finder"] = "Finder",
["Spotify"] = "Spotify",
["Discord"] = "Discord",
["Slack"] = "Slack",
["Signal"] = "Signal",
["Notion"] = "Notion",
["Todoist"] = "Todoist"
}
hs.loadSpoon("AppWindowSwitcher") -- :setLogLevel("debug")
---@param appNames string[]
---@return hs.window|nil
local function findLastMatchingWindow(appNames)
local switcher = spoon.AppWindowSwitcher
local lastMatch = nil
for _, w in pairs(hs.window.orderedWindows()) do
if switcher.match(w, appNames) then
lastMatch = w
end
end
return lastMatch
end
---@param appNames string[]
---@return hs.window|nil
local function findFirstMatchingWindow(appNames)
local switcher = spoon.AppWindowSwitcher
for _, w in pairs(hs.window.orderedWindows()) do
if switcher.match(w, appNames) then
return w
end
end
return nil
end
---@param appNames string[]
local function launchApp(appNames)
for _, appName in pairs(appNames) do
if appLaunchMap[appName] then
hs.application.launchOrFocus(appLaunchMap[appName])
return
end
end
end
---@param appNames string[]
---@return function
local function switchOrLaunch(appNames)
return function()
local focusedWindow = hs.window.focusedWindow()
if not focusedWindow then
return
end
local switcher = spoon.AppWindowSwitcher
local targetWindow = nil
if switcher.match(focusedWindow, appNames) then
targetWindow = findLastMatchingWindow(appNames)
else
targetWindow = findFirstMatchingWindow(appNames)
end
if targetWindow then
targetWindow:raise():focus()
return
end
launchApp(appNames)
end
end
hs.hotkey.bind({"alt"}, "b", switchOrLaunch({"Vivaldi"}))
hs.hotkey.bind({"alt"}, "e", switchOrLaunch({"Code", "Zed"}))
hs.hotkey.bind({"alt"}, "t", switchOrLaunch({"iTerm", "Terminal", "Warp"}))
hs.hotkey.bind({"alt"}, "f", switchOrLaunch({"Finder"}))
hs.hotkey.bind({"alt"}, "m", switchOrLaunch({"Spotify"}))
hs.hotkey.bind({"alt"}, "c", switchOrLaunch({"Discord", "Slack", "Signal"}))
hs.hotkey.bind({"alt"}, "n", switchOrLaunch({"Notion"}))
hs.hotkey.bind({"alt"}, "s", switchOrLaunch({"Todoist"}))
hs.loadSpoon("MiddleClickDragScroll"):start()
hs.loadSpoon("HoldToMinimize"):start()
clipboard_tool = hs.loadSpoon("ClipboardTool")
clipboard_tool.show_copied_alert = false
clipboard_tool:bindHotkeys({
toggle_clipboard = {{"ctrl"}, "v"}
})
clipboard_tool:start()
hs.loadSpoon("WindowHalfsAndThirds"):bindHotkeys({
max_toggle = {lcag, "up"},
left_half = {lcag, "left"},
right_half = {lcag, "right"},
third_left = {lcag, "1"},
third_right = {lcag, "3"},
larger = {lcag, "4"},
smaller = {lcag, "2"}
})
-- GitHubPRMenu Spoon Configuration
hs.loadSpoon("GitHubPRMenu")
spoon.GitHubPRMenu:start()
-- Optional: Customize refresh interval (default: 3600 seconds = 1 hour)
-- spoon.GitHubPRMenu:setRefreshInterval(1800) -- 30 minutes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment