关于 hammerspoon
Hammerspoon 将 Lua 脚本与 macOS 桌面控制结合,适合希望自动化窗口、应用、快捷键和系统事件的用户。它支持以 Spoons 插件扩展功能。
主要功能
- 01使用 Lua 自动化 macOS
- 02管理窗口与应用
- 03绑定键盘快捷键
- 04通过 Spoons 扩展功能
- 05使用 hs 命令行执行 Lua
适用场景
- 01平铺和调整窗口位置
- 02启动或切换到应用
- 03通过快捷键或命令行重载配置
- 04显示提醒和系统通知
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ plinde/ claude-plugins --skill hammerspoon安装后在 Claude Code 中输入/hammerspoon确认已加载。
详细介绍
Hammerspoon macOS 自动化
Hammerspoon 将 macOS 与 Lua 脚本连接起来,实现强大的桌面自动化。
目录结构
~/.hammerspoon/
├── init.lua # Main entry point (always loaded on startup)
├── Spoons/ # Plugin directory
│ └── *.spoon/ # Individual Spoon packages
│ └── init.lua # Spoon entry point
└── .gitignore
配置基础
init.lua - 入口文件
Hammerspoon 启动时始终会加载 ~/.hammerspoon/init.lua:
-- Enable CLI support (required for hs command)
require("hs.ipc")
-- Load a Spoon
hs.loadSpoon("SpoonName")
-- Configure the Spoon
spoon.SpoonName:bindHotkeys({...})
加载 Spoons
-- Load and auto-init (default)
hs.loadSpoon("MySpoon")
-- Load without global namespace
local mySpoon = hs.loadSpoon("MySpoon", false)
加载后,可以通过 spoon.SpoonName 访问 Spoons。
CLI 用法(hs 命令)
前置条件: 将 require("hs.ipc") 添加到 init.lua,然后手动重新加载一次。
# Reload configuration
hs -c 'hs.reload()'
# Show alert on screen
hs -c 'hs.alert("Hello from CLI")'
# Run any Lua code
hs -c 'print(hs.host.locale.current())'
# Get focused window info
hs -c 'print(hs.window.focusedWindow():title())'
使用 ShiftIt 管理窗口
ShiftIt 是一款热门的窗口平铺 Spoon。
安装
# Download from https://github.com/peterklijn/hammerspoon-shiftit
# Extract to ~/.hammerspoon/Spoons/ShiftIt.spoon/
配置
require("hs.ipc")
hs.loadSpoon("ShiftIt")
spoon.ShiftIt:bindHotkeys({
-- Halves
left = { { 'ctrl', 'cmd' }, 'left' },
right = { { 'ctrl', 'cmd' }, 'right' },
up = { { 'ctrl', 'cmd' }, 'up' },
down = { { 'ctrl', 'cmd' }, 'down' },
-- Quarters
upleft = { { 'ctrl', 'cmd' }, '1' },
upright = { { 'ctrl', 'cmd' }, '2' },
botleft = { { 'ctrl', 'cmd' }, '3' },
botright = { { 'ctrl', 'cmd' }, '4' },
-- Other
maximum = { { 'ctrl', 'cmd' }, 'm' },
toggleFullScreen = { { 'ctrl', 'cmd' }, 'f' },
center = { { 'ctrl', 'cmd' }, 'c' },
nextScreen = { { 'ctrl', 'cmd' }, 'n' },
previousScreen = { { 'ctrl', 'cmd' }, 'p' },
resizeOut = { { 'ctrl', 'cmd' }, '=' },
resizeIn = { { 'ctrl', 'cmd' }, '-' },
})
修饰键
| 按键 | Lua 名称 |
|---|---|
| Command | 'cmd' |
| Control | 'ctrl' |
| Option/Alt | 'alt' |
| Shift | 'shift' |
绑定热键(不使用 Spoons)
-- Simple hotkey
hs.hotkey.bind({'cmd', 'alt'}, 'R', function()
hs.reload()
end)
-- Hotkey with message
hs.hotkey.bind({'cmd', 'shift'}, 'H', function()
hs.alert.show('Hello!')
end)
常用模块
hs.window - 窗口管理
-- Get focused window
local win = hs.window.focusedWindow()
-- Move/resize
win:moveToUnit('[0,0,0.5,1]') -- Left half
win:maximize()
win:centerOnScreen()
-- Get all windows
local allWindows = hs.window.allWindows()
hs.application - 应用控制
-- Launch or focus app
hs.application.launchOrFocus('Safari')
-- Get running app
local app = hs.application.get('Finder')
app:activate()
hs.alert - 屏幕消息
hs.alert.show('Message')
hs.alert.show('Message', nil, nil, 3) -- 3 second duration
hs.notify - 系统通知
hs.notify.new({title='Title', informativeText='Body'}):send()
hs.caffeinate - 睡眠/唤醒
-- Prevent sleep
hs.caffeinate.set('displayIdle', true)
-- Watch for sleep/wake events
hs.caffeinate.watcher.new(function(event)
if event == hs.caffeinate.watcher.systemWillSleep then
print('Going to sleep')
end
end):start()
Spoons
什么是 Spoon?
采用标准结构的独立 Lua 插件:
MySpoon.spoon/
└── init.lua # Required: exports a table with methods
官方 Spoon 仓库
SpoonInstall - 包管理器
hs.loadSpoon("SpoonInstall")
-- Install from official repo
spoon.SpoonInstall:andUse("ReloadConfiguration", {
start = true
})
-- Install from custom repo
spoon.SpoonInstall.repos.Custom = {
url = "https://github.com/user/repo",
desc = "Custom spoons",
branch = "main",
}
spoon.SpoonInstall:andUse("CustomSpoon", { repo = "Custom" })
重新加载配置
手动重新加载
- 点击菜单栏图标 -> “Reload Config”
- 或绑定一个热键:
hs.hotkey.bind({'cmd', 'alt', 'ctrl'}, 'R', function()
hs.reload()
end)
文件变更时自动重新加载
hs.loadSpoon("ReloadConfiguration")
spoon.ReloadConfiguration:start()
或者手动执行:
local configWatcher = hs.pathwatcher.new(os.getenv('HOME') .. '/.hammerspoon/', function(files)
for _, file in pairs(files) do
if file:sub(-4) == '.lua' then
hs.reload()
return
end
end
end):start()
通过 CLI 重新加载
hs -c 'hs.reload()'
注意:需要在 init.lua 中添加 require("hs.ipc")。
故障排除
IPC 无法使用
error: can't access Hammerspoon message port
修复方法: 将 require("hs.ipc") 添加到 init.lua,然后通过菜单栏手动重新加载。
Spoon 无法加载
- 检查路径:
~/.hammerspoon/Spoons/Name.spoon/init.lua - 检查 Spoon 的 init.lua 中是否存在 Lua 语法错误
- 在 Hammerspoon 控制台中检查错误(菜单栏 -> Console)
热键无法使用
- 检查是否与系统快捷键冲突
- 确认修饰键名称为小写字符串
- 在控制台中检查绑定错误
控制台与调试
-- Print to console
print('Debug message')
-- Inspect objects
hs.inspect(someTable)
-- Open console
hs.openConsole()
打开控制台:菜单栏图标 -> Console(或使用已绑定的 Cmd+Alt+C)
最佳实践
- 始终启用 IPC - 添加
require("hs.ipc")以支持 CLI - 使用 Spoons - 不要重复实现窗口管理功能
- 使用版本控制 - 使用 git 跟踪
~/.hammerspoon/ - 保存对象到变量 - 未存储在变量中的对象会被垃圾回收
- 检查控制台 - 出现错误时首先查看这里
参考资料
评论
支持 Markdown