Skip to content
renner-cPublic

About

Native macOS Liquid Glass HUD for Hammerspoon & CLI — glass toasts, panels, and cheat-sheets via NSGlassEffectView (macOS 26+), with an NSVisualEffectView fallback.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

GlassHUD

Native macOS Liquid Glass HUD for Hammerspoon (and the command line). It renders toasts, titled panels, and a wide cheat-sheet panel using real Apple NSGlassEffectView on macOS 26+ (Tahoe), with a clean NSVisualEffectView frosted fallback on older systems.

platform swift license

The typical use case: replace Hammerspoon's hand-drawn hs.canvas / hs.alert popups with polished, translucent, native glass — without touching your hotkeys or window-management logic. It also works standalone as a CLI (glasshud toast "hello"), so any script or app can throw a native glass HUD on screen.


Features

  • Real Liquid Glass (NSGlassEffectView) on macOS 26+, automatic NSVisualEffectView fallback below. The active backend is reported honestly via glasshud provider — it never claims glass when it isn't.
  • Three styles: toast (small, auto-dismiss), panel (titled, persistent), and help (wide, monospaced cheat-sheet with aligned shortcut columns).
  • Non-activating floating panels — showing a toast never steals focus. They ride across Spaces and appear over fullscreen apps.
  • Identified windows — address HUDs by --id to show, update in place, and hide individually.
  • Adapts to light/dark automatically (semantic AppKit colors, real NSTextField text — no webview).
  • Lightweight background agent (LSUIElement, no Dock icon) with a tiny CLI client. Non-blocking, single-instance, auto-spawns on demand, and optionally autostarts at login via a launchd LaunchAgent.

How it works

your caller (Hammerspoon Lua, a shell script, anything)
   │  glasshud toast/show/update/hide ...
   ▼
glasshud  (CLI client)  ── JSON over a Unix socket ──▶  GlassHUD.app (agent)
                                                          NSPanel + Backdrop
                                                          → NSGlassEffectView
                                                            (or NSVisualEffectView)
  • One Swift binary, two modes: the agent (glasshud --serve) and the client (glasshud <command>). The client auto-spawns the agent if needed and returns immediately, so callers never block.
  • Commands are one-line JSON over ~/.local/state/glasshud/glasshud.sock.
  • Toasts auto-dismiss (~1.6 s default); panels and help persist until hidden.
  • Single instance guaranteed by a flock lock; SIGPIPE ignored so short-lived client probes can't take the agent down.

Requirements

  • macOS 13+ (real glass needs macOS 26+ / Tahoe; older systems get the frosted fallback).
  • Xcode Command Line Tools (swiftc) — full Xcode is not required:
    xcode-select --install
  • Hammerspoon only if you want the Lua integration; the CLI works on its own.

Install

Clone anywhere (the ~/.hammerspoon/GlassHUD location is recommended if you use Hammerspoon), then run the installer:

git clone https://github.com/renner-c/GlassHUD.git ~/.hammerspoon/GlassHUD
cd ~/.hammerspoon/GlassHUD
./install.sh

install.sh builds GlassHUD.app, installs the glasshud CLI shim into ~/.local/bin, installs the Hammerspoon adapter to ~/.hammerspoon/glasshud.lua (pointed at your checkout), and loads the login LaunchAgent.

Add ~/.local/bin to your PATH for the bare glasshud command:

export PATH="$HOME/.local/bin:$PATH"

To rebuild only (no install): ./build.sh.


Command-line usage

glasshud toast "Hello from GlassHUD"
glasshud show   --id note --title "Reminder" --body "Standup at 10am"
glasshud update --id note --title "Reminder" --body "Standup now"
glasshud hide   --id note
glasshud hideAll
glasshud help-panel --body $'Launch\ncmd+enter   terminal'   # wide cheat-sheet
glasshud provider     # print the active backend (glass vs. fallback)
glasshud ping         # exit 0 if the agent is running
glasshud help

Options (glasshud help for the full list):

--id ID            window identity (default "hud"); reused for update/hide
--title T          panel title (bold)
--body B           body text (\n for line breaks)
--style S          toast | panel | help
--duration SECS    auto-dismiss after SECS (<=0 or omitted on panels = persistent)
--mono             force a monospaced body
--click-through    let mouse events pass through
--anchor A         toast | help | center | top | bottom | topRight
--x --y --w --h    explicit placement; x/y are top-left GLOBAL pixels
--screen-x/y/w/h   visible frame of the screen to draw on (top-left coords)
--tint #RRGGBB     tint the glass
--json PATH        read the whole command payload from a JSON file

Hammerspoon integration

The installer drops a glasshud.lua adapter into ~/.hammerspoon/. It calls the binary through hs.task (non-blocking), so your config never stalls.

local glasshud = require("glasshud")

glasshud.toast("hi")                                  -- auto-dismiss glass toast
glasshud.show("note", "Reminder", "Standup at 10am")  -- persistent titled panel
glasshud.update("note", "Reminder", "Standup now")    -- update in place
glasshud.hide("note")
glasshud.helpPanel("help", body)                      -- wide monospaced cheat-sheet
glasshud.hideAll()

To upgrade an existing setup, point your current popup function at the adapter. For example, if your config shows messages through a say()/showPopup() helper, reroute its body to glasshud.toast(...) (or glasshud.render{...} for panels) and keep the same function name and call sites — every trigger and message stays the same, only the rendering changes. Wrapping such edits in -- BEGIN GlassHUD integration / -- END GlassHUD integration markers keeps them easy to find and revert.

The adapter positions HUDs on the focused window's screen and reproduces a "one popup at a time" feel by funneling toasts through a shared window id.


Amethyst layout toasts (optional)

If you use the Amethyst tiling window manager, lua/amethyst_glass.lua replaces Amethyst's built-in layout HUD (the little "Tall / Wide / Row…" popup) with a native glass toast.

Amethyst has no plugin hook, so the module watches Amethyst's own layout keyboard shortcuts with a non-consuming hs.eventtap — the keypress still reaches Amethyst, which performs the real layout change — and shows a glass toast with the layout name. It reads Amethyst's shortcuts and layout order live from its preferences (so rebinding stays in sync) and forces Amethyst's own HUD off (enables-layout-hud), re-applying it whenever Amethyst relaunches, so you get a single toast.

Enable it by requiring the module from your ~/.hammerspoon/init.lua (the installer copies it into ~/.hammerspoon/):

pcall(require, "amethyst_glass")

Then reload Hammerspoon and press your Amethyst layout keys (e.g. ⌥⇧Space to cycle). Notes:

  • The direct select-*-layout shortcuts always show the exact layout name.
  • The cycle shortcut tracks the layout order; it's exact once you've pressed any select shortcut or completed a full cycle (Amethyst exposes no way to read the current layout, so the very first cycle after a reload is best-effort).
  • Requires Hammerspoon's Accessibility permission (which it already needs for window management).

Autostart (launch at login)

install.sh installs a per-user LaunchAgent at ~/Library/LaunchAgents/com.glasshud.agent.plist and loads it immediately:

  • RunAtLoad — starts at every login, in the GUI (Aqua) session, independent of Hammerspoon.
  • KeepAlive (SuccessfulExit = false) — relaunches on a crash, but respects a clean exit (so the single-instance lock and glasshud quit behave, no restart loop).

It's also spawned on demand, so it works even before the first reboot. Manage it:

launchctl print     gui/$(id -u)/com.glasshud.agent      # status
launchctl kickstart -k gui/$(id -u)/com.glasshud.agent   # restart (e.g. after rebuild)
launchctl bootout   gui/$(id -u)/com.glasshud.agent      # stop + unload

Uninstall

./uninstall.sh

Unloads and removes the LaunchAgent, stops the agent, and removes the CLI shim, the Hammerspoon adapter, and runtime state. It leaves the project folder (delete it yourself) and any edits you made to your own init.lua.


OS support & permissions

  • macOS 26+ (Tahoe): real NSGlassEffectView Liquid Glass.
  • macOS 13–25: NSVisualEffectView frosted fallback — same layout and behavior, just the public blur instead of glass.
  • Apple Silicon and Intel (pure AppKit).
  • No private APIs, no SIP changes, no entitlements. The agent draws its own windows and needs no special permissions. (Hammerspoon's own Accessibility permission, for its window management, is unrelated to GlassHUD.)

Project layout

Sources/
  Protocol.swift     # command model, paths, socket addr, logging
  Backdrop.swift     # glass vs. visual-effect provider
  HUDContent.swift   # AppKit text layout (toast / panel / help)
  HUDWindow.swift    # non-activating NSPanel
  HUDController.swift # window registry, positioning, auto-dismiss
  Server.swift       # agent: socket + singleton lock + NSApp
  Client.swift       # CLI parsing + agent spawn + send
  main.swift         # mode dispatch (--serve vs. client)
lua/glasshud.lua       # Hammerspoon adapter (installed to ~/.hammerspoon)
lua/amethyst_glass.lua # optional Amethyst layout-HUD integration
build.sh  install.sh  uninstall.sh  test.sh

Runtime files live in ~/.local/state/glasshud/ (glasshud.sock, glasshud.lock, glasshud.log, launchd.log). The log records each window's frame, visibility, and the active glass backend — handy for debugging.

Run ./test.sh for a manual smoke test of every style.


Tuning the look

  • Sources/HUDWindow.swift → per-style corner radius, window level/shadow.
  • Sources/HUDContent.swift → fonts, sizes, spacing, padding, help-row styling.
  • Sources/Backdrop.swift → glass style (.regular/.clear), tint, and the fallback materials.

Rebuild with ./build.sh, then restart the agent (launchctl kickstart -k gui/$(id -u)/com.glasshud.agent).


License

MIT — see LICENSE.

About

Native macOS Liquid Glass HUD for Hammerspoon & CLI — glass toasts, panels, and cheat-sheets via NSGlassEffectView (macOS 26+), with an NSVisualEffectView fallback.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages