name: hammerspoon
description: Operate Hammerspoon as a running macOS automation runtime and configurable Lua system. Use when the user mentions Hammerspoon, hs.*, Spoons, init.lua, MJConfigFile, hs.ipc, Lua hotkeys/window management, macOS automation, or wants to inspect, configure, debug, lint, format, test, or live-patch Hammerspoon. Prefer runtime introspection and live official docs/source over stale memory.
license: GPL-3.0-or-later
compatibility: Requires uv. Runtime introspection requires Hammerspoon running with require("hs.ipc") and the hs CLI installed. Docs/source lookup requires network unless cached.
metadata:
author: anntnzrb
allowed-tools: ""
Hammerspoon
Treat Hammerspoon work as two connected systems:
- the running macOS automation runtime
- the persistent Lua config on disk
Prefer truth from the running instance first, then official docs, then upstream source/Spoons, then local config, then ecosystem corroboration.
Entry point
uv run --script <skill-dir>/scripts/cli.py ...
Set <skill-dir> to this skill directory. Do not rely on shell sourcing, executable bits, or shebang dispatch.
Evidence order
- Runtime introspection via CLI (
status,eval,windows,apps,screens,hotkeys,spoons,config) - Live official docs (
docs search,docs module,docs api) - Live upstream source and Spoons (
source search,spoons search,spoons source) - Local config files on disk
- Ecosystem corroboration (Grep.app, GitHub code search) only after official/runtime sources
Avoid cloning Hammerspoon repos unless explicitly needed. Prefer the cached live fetches.
Workflow
- Inspect runtime state or live docs first
- Inspect the relevant config files only as needed
- Pick the right persistence target
- Preview the intended change if a live preview is useful
- Apply the persistent edit
- Apply live when safe (reload config, evaluate Lua)
- Verify both runtime state and file state
- Call out Accessibility permission, MJConfigFile, or restart requirements explicitly
Default pattern: inspect → preview → apply → verify.
Output discipline
- If the user asked for a report, note, patch file, or any other artifact at a specific path, create it before finalizing.
- Do not stop at an acknowledgement, plan, or partial progress update when the task asked for a concrete deliverable.
- After writing the requested artifact, summarize the result briefly.
Runtime introspection
Default to uv run --script <skill-dir>/scripts/cli.py for Hammerspoon IPC. It wraps hs calls with quoting safety and structured output.
Prefer helper subcommands before custom Lua when they fit the task:
status— Hammerspoon runtime health, version, config directorydoctor— status plus Accessibility/MJConfigFile/CLI setup checkseval— execute Lua throughhsand print the resulteval-file— evaluate a Lua file safely without shell quotingreload— triggerhs.reload()windows— list all windows as JSON-safe summariesapps— list running applicationsscreens— list displayshotkeys— list registered hotkeysspoons— list loaded Spoonsconfig— show config directory path
Use raw hs CLI only when:
- debugging the helper itself
- the helper is unavailable
- a truly tiny one-off probe is simpler and there is no quoting risk
For reusable or multiline queries, prefer a temp Lua file plus eval-file.
Live docs lookup
uv run --script <skill-dir>/scripts/cli.py docs search <query>
uv run --script <skill-dir>/scripts/cli.py docs module <hs.module>
uv run --script <skill-dir>/scripts/cli.py docs api <symbol>
uv run --script <skill-dir>/scripts/cli.py docs refresh [--if-needed]
These fetch official Hammerspoon API docs from hammerspoon.org/docs/ and cache them locally. Use --json for structured output with source_url, signature, excerpt, and line references.
Agents should navigate search results by exact symbols, module names, and source URLs.
Live source and Spoons
uv run --script <skill-dir>/scripts/cli.py source search <pattern>
uv run --script <skill-dir>/scripts/cli.py source fetch [--if-needed]
uv run --script <skill-dir>/scripts/cli.py spoon search <query>
uv run --script <skill-dir>/scripts/cli.py spoon source <name>
Source searches query the official Hammerspoon and Spoons GitHub repositories. Fetches are cached and refreshed only when stale or explicitly requested.
Lua quality
uv run --script <skill-dir>/scripts/cli.py lint <path>
uv run --script <skill-dir>/scripts/cli.py fmt --check <path>
uv run --script <skill-dir>/scripts/cli.py fmt --write <path>
uv run --script <skill-dir>/scripts/cli.py test <path>
uv run --script <skill-dir>/scripts/cli.py annotations status
uv run --script <skill-dir>/scripts/cli.py lsp-config print
These discover tools on PATH (luacheck, stylua, busted, lua-language-server). Missing tools return clear error messages with install guidance; they never silently succeed.
lint— runsluacheckwith Hammerspoon globals (hs,spoon).fmt— runsstylua, never formats implicitly.test— runsbustedfor pure Lua tests.annotations— reports whether Hammerspoon EmmyLua annotations appear generated.lsp-config— prints a suggested.luarc.jsonfor Lua language server.
Safe live-change pattern
- Make the intended file change first for persistent behavior.
- Then apply live only to preview or verify the persistent change.
- Prefer precise reloads:
uv run --script <skill-dir>/scripts/cli.py reloaduv run --script <skill-dir>/scripts/cli.py eval-file <temp>.lua
- Call out whether a change requires Accessibility permission grants, an
MJConfigFileupdate, or a full Hammerspoon restart. - If you test an ephemeral tweak before writing it, label it clearly as a preview and persist it before finishing.
Guardrails
- Do not trust memory alone for Hammerspoon APIs; inspect runtime/docs/source.
- Do not assume a specific config layout, Spoond set, hotkey scheme, or config location; inspect first.
- Do not auto-install the
hsCLI or Hammerspoon itself without explicit user request. - Do not reload Hammerspoon after read-only inspection commands.
- Do not mutate the user's
init.luaunless the task explicitly asks for persistent config changes. - Do not format, lint, or fix config files unless the task asks.
- Prefer
uv run --script <skill-dir>/scripts/cli.pyover rawhscalls. - Be explicit about risk when evaluating Lua in a running Hammerspoon.
Resources
scripts/cli.py: public dispatcherscripts/hsctl.py: internal engine for runtime, docs, source, and Lua tooling