Smooth, animated window snapping on macOS using Raycast + Hammerspoon.
Bring macOS-native-feeling window movements to your desktop with clean animations for:
No jarring jumps. Just smooth, polished transitions.
This extension uses Hammerspoon to apply window animations.
brew install --cask hammerspoon && curl -o ~/.hammerspoon/init.lua https://raw.githubusercontent.com/raycast/extensions/tree/main/extensions/animated-window-manager/main/hammerspoon/init.lua && open -a Hammerspoon
βοΈ This installs Hammerspoon, applies the animated layout config, and opens the app.
Command | Description |
---|---|
Move Window Left (Animated) | Slides focused window to the left half |
Move Window Right (Animated) | Slides focused window to the right half |
Maximize Window (Animated) | Smoothly fills the whole screen |
Reasonable Size (Animated) | Centers window with ~60% width & 70% height |
All animations use native-feeling macOS transitions.
Install Hammerspoon
brew install --cask hammerspoon
Enable CLI access
Make sure the hs
CLI is available:
sudo ln -s ~/.hammerspoon/hs /usr/local/bin/hs
Enable IPC in your ~/.hammerspoon/init.lua
require("hs.ipc") -- Enables CLI execution
Add the layout functions
Paste this into ~/.hammerspoon/init.lua
:
require("hs.ipc")
function moveWindowLeftAnimated()
local win = hs.window.focusedWindow()
if not win then return end
local screen = win:screen()
local frame = screen:frame()
local targetFrame = {
x = frame.x,
y = frame.y,
w = frame.w / 2,
h = frame.h
}
win:move(targetFrame, nil, true, 0.3)
end
function moveWindowRightAnimated()
local win = hs.window.focusedWindow()
if not win then return end
local screen = win:screen()
local frame = screen:frame()
local targetFrame = {
x = frame.x + (frame.w / 2),
y = frame.y,
w = frame.w / 2,
h = frame.h
}
win:move(targetFrame, nil, true, 0.3)
end
function maximizeWindowAnimated()
local win = hs.window.focusedWindow()
if not win then return end
local screen = win:screen()
local frame = screen:frame()
win:move(frame, nil, true, 0.3)
end
function moveWindowReasonableSize()
local win = hs.window.focusedWindow()
if not win then return end
local screen = win:screen()
local frame = screen:frame()
local targetWidth = frame.w * 0.6
local targetHeight = frame.h * 0.7
local targetFrame = {
x = frame.x + ((frame.w - targetWidth) / 2),
y = frame.y + ((frame.h - targetHeight) / 2),
w = targetWidth,
h = targetHeight
}
win:move(targetFrame, nil, true, 0.3)
end
This extension calls your custom Hammerspoon functions like:
hs -c "moveWindowLeftAnimated()"
Hammerspoon then smoothly animates your window into place using native macOS window APIs.
can't access message port
You forgot to enable IPC. Add this to the top of your init.lua
:
require("hs.ipc")
Raycast was focused. We fixed that by automatically closing Raycast before calling hs
using closeMainWindow()
.
This project was built to make macOS window management feel less robotic and more native. Animations make a big difference β and Raycast + Hammerspoon is the perfect lightweight combo.
Open an issue or submit a pull request on GitHub. Happy snapping! β‘οΈ