hammerspoon2-docs
    Preparing search index...

    Namespace notify

    Module for creating and displaying macOS system notifications. macOS notifications require user permission before they will appear. Request it once (typically at startup) via hs.permissions.requestNotifications() and it will be

    hs.permissions.requestNotifications().then(granted => {
    if (granted) hs.notify.show("Hammerspoon", "Notifications are enabled!")
    })
    // Fire and forget
    hs.notify.show("Build complete", "Your project compiled successfully.")

    // With a callback invoked when the user interacts
    hs.notify.show("Build complete", "Click to view the log.", (response) => {
    console.log("User tapped:", response.actionIdentifier)
    })
    const n = hs.notify.create({
    title: "New message",
    subtitle: "From Alice",
    body: "Are you free tonight?",
    sound: true,
    threadIdentifier: "messages-alice",
    actions: [
    { identifier: "REPLY", title: "Reply", textInput: true,
    textInputButtonTitle: "Send", textInputPlaceholder: "Type a reply…" },
    { identifier: "DISMISS", title: "Dismiss", destructive: true }
    ],
    callback: (response) => {
    if (response.actionIdentifier === "REPLY") {
    console.log("Reply text:", response.userText)
    }
    }
    })
    n.send()
    // Later, if needed:
    n.withdraw()
    Property Type Description
    actionIdentifier string "DEFAULT" when the user tapped the notification body; "DISMISS" when dismissed (if .customDismissAction is set); otherwise the action's identifier string
    userText string? Text entered in a textInput action; only present when applicable
    userInfo object The userInfo object originally passed to create(), if any
    notificationId string The notification's unique identifier
    Key Type Default Description
    title string (required) The bold heading line
    subtitle string A second line shown beneath the title
    body string The main message body
    sound boolean | string true true = default sound, false = no sound, string = named .aiff file
    badge number Value to show on the app icon badge
    threadIdentifier string Groups related notifications visually in Notification Center
    userInfo object {} Arbitrary payload passed back to the callback
    interruptionLevel string "active" "passive", "active", or "timeSensitive" — controls Focus/DND behaviour (macOS 12+)
    trigger object When to deliver the notification (see below). Omit for immediate delivery.
    actions array Action buttons (see below)
    callback function Invoked when the user interacts with the notification

    Pass a trigger object in create()'s options to schedule the notification instead of delivering it

    trigger: { type: "timeInterval", interval: 300 }
    

    Calendar* — deliver at a specific date/time. Provide either a JS Date object or individual

    // At a specific moment
    trigger: { type: "calendar", date: new Date("2026-06-01T09:00:00") }

    // At 09:00 on the next day that matches (e.g. next Monday, weekday 2)
    trigger: { type: "calendar", weekday: 2, hour: 9, minute: 0 }

    Supported component keys: year, month, day, hour, minute, second, weekday.

    Key Type Default Description
    identifier string (required) Unique identifier passed to the callback
    title string (required) Button label
    destructive boolean false Renders the title in a destructive (red) style
    foreground boolean false Brings Hammerspoon to the foreground when tapped
    textInput boolean false Converts this action to an inline text-reply button
    textInputButtonTitle string "Send" Label on the reply send button (requires textInput: true)
    textInputPlaceholder string "" Placeholder shown in the text field (requires textInput: true)

    Functions

    create
    removeAllDelivered
    removeAllPending
    show