Skip to content

Instantly share code, notes, and snippets.

@IlyaGulya
Created April 18, 2025 19:23
Show Gist options
  • Save IlyaGulya/6992f7daae54444a0fcae63eba148b2e to your computer and use it in GitHub Desktop.
Save IlyaGulya/6992f7daae54444a0fcae63eba148b2e to your computer and use it in GitHub Desktop.
Kitty + Hammerspoon configuration with quake-like terminal style. Dock-aware (in case your dock is on the left).
local spaces = require("hs.spaces")
-- (Optional) helper to read dock position
local function dockOrientation()
local out = hs.execute("defaults read com.apple.dock orientation")
return out:match("^%s*(%S+)")
end
-- get the main window of an app (wait until it's ready)
local function getMainWindow(app)
local win = app:mainWindow()
while not win do
-- removed underscore; Lua wants a plain integer
hs.timer.usleep(10000)
win = app:mainWindow()
end
return win
end
-- move & resize kitty so it starts *after* the dock
local function moveWindow(kitty, space, mainScreen)
local win = getMainWindow(kitty)
if win:isFullScreen() then
hs.eventtap.keyStroke({'fn'}, 'f', 0, kitty)
end
-- safe area minus dock/menu
local scrFrame = mainScreen:frame()
-- customize height ratio (0.4 = 40% of screen)
local heightRatio = 0.3
local newH = math.floor(scrFrame.h * heightRatio)
-- build the smaller frame: full width, 40% height, pinned at top
local winFrame = {
x = scrFrame.x,
y = scrFrame.y,
w = scrFrame.w,
h = newH
}
win:setFrame(winFrame, 0)
spaces.moveWindowToSpace(win, space)
if win:isFullScreen() then
hs.eventtap.keyStroke({'fn'}, 'f', 0, kitty)
end
win:focus()
end
-- hotkey to toggle kitty
hs.hotkey.bind({}, 'f12', function()
local BUNDLE_ID = 'net.kovidgoyal.kitty'
local kitty = hs.application.get(BUNDLE_ID)
if kitty and kitty:isFrontmost() then
kitty:hide()
return
end
local space = spaces.activeSpaceOnScreen()
local mainScreen = hs.screen.mainScreen()
if not kitty then
hs.application.launchOrFocusByBundleID(BUNDLE_ID)
local watcher
watcher = hs.application.watcher.new(function(name, event, app)
if event == hs.application.watcher.launched
and app:bundleID() == BUNDLE_ID
then
moveWindow(app, space, mainScreen)
watcher:stop()
end
end)
watcher:start()
else
moveWindow(kitty, space, mainScreen)
end
end)
-- auto‑reload config on save
hs.loadSpoon("ReloadConfiguration")
spoon.ReloadConfiguration:start()
# make your kitty window borderless
hide_window_decorations titlebar-and-corners
# make kitty app quit entirely instead of leaving null window, which made the script hard to detect kitty window
macos_quit_when_last_window_closed yes
# this one is optional, would quit kitty tab more quickly
confirm_os_window_close 0
# this one is optional, as hammerspoon script would move window in script line 45
remember_window_size yes
# hide kitty from dock and application switcher
macos_hide_from_tasks yes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment