Created
April 18, 2025 19:23
-
-
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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