Skip to content

Instantly share code, notes, and snippets.

@phoolish
Last active September 7, 2025 16:59
Show Gist options
  • Save phoolish/e2084fb7da682f1f5d30a7ba97b57f6a to your computer and use it in GitHub Desktop.
Save phoolish/e2084fb7da682f1f5d30a7ba97b57f6a to your computer and use it in GitHub Desktop.

Revisions

  1. phoolish revised this gist Sep 7, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion init.lua
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ Purpose:
    Requirements:
    - Hammerspoon installed and running
    - My shortcut https://www.icloud.com/shortcuts/e87cfa725816453bac39d189e274af89, but any shortcuts app shortcut named "Focus" that accepts:
    - My shortcut https://www.icloud.com/shortcuts/2a4ae272a3104373a230065059500794, but any shortcuts app shortcut named "Focus" that accepts:
    - "on" - enables Do Not Disturb
    - "off" - disables Do Not Disturb
    - "state" - returns current DnD state
  2. phoolish revised this gist Sep 7, 2025. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions init.lua
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ Purpose:
    Requirements:
    - Hammerspoon installed and running
    - Shortcuts app shortcut named "Focus" that accepts:
    - My shortcut https://www.icloud.com/shortcuts/e87cfa725816453bac39d189e274af89, but any shortcuts app shortcut named "Focus" that accepts:
    - "on" - enables Do Not Disturb
    - "off" - disables Do Not Disturb
    - "state" - returns current DnD state
    @@ -21,10 +21,11 @@ Behavior:
    Logging:
    - Warning level by default (quiet operation)
    - Shows startup, successes, and any errors
    - Change log level on line 20 if more verbose output needed
    - Log level available are 'info', 'debug', 'warning', or 'error'
    Author: [Your name]
    Date: [Current date]
    Author: phoolish & Claude AI
    Based on https://mskelton.dev/bytes/managing-focus-with-hammerspoon
    --]]

    local log = hs.logger.new('dnd-automation', 'warning')
  3. phoolish created this gist Sep 7, 2025.
    92 changes: 92 additions & 0 deletions init.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    --[[
    DnD Automation Script for Hammerspoon
    Purpose:
    Automatically enables Do Not Disturb when the screen is locked and disables it
    when unlocked, but only if Hammerspoon was the one that enabled it originally.
    This prevents interfering with manually-set DnD preferences.
    Requirements:
    - Hammerspoon installed and running
    - Shortcuts app shortcut named "Focus" that accepts:
    - "on" - enables Do Not Disturb
    - "off" - disables Do Not Disturb
    - "state" - returns current DnD state
    Behavior:
    - Screen Lock: Check current DnD state, enable if off, track that we enabled it
    - Screen Unlock: Only disable DnD if we previously enabled it automatically
    - Manual DnD: If user manually enables DnD, we won't disable it on unlock
    Logging:
    - Warning level by default (quiet operation)
    - Shows startup, successes, and any errors
    - Change log level on line 20 if more verbose output needed
    Author: [Your name]
    Date: [Current date]
    --]]

    local log = hs.logger.new('dnd-automation', 'warning')

    -- Track if we enabled DnD automatically
    local hammerspoonEnabledDnd = false

    local function focus(state)
    return function()
    local command = "shortcuts run 'Focus' <<<'" .. state .. "'"
    local output, status, type, rc = hs.execute(command, true)

    if not status then
    log.e("Focus shortcut failed for state: " .. state)
    else
    log.i("Focus changed to: " .. state)
    end

    return output, status
    end
    end

    local function getCurrentFocusState()
    local output, status = focus("state")()
    if status and output then
    local trimmed = output:match("^%s*(.-)%s*$") -- Trim whitespace

    -- Check if DnD is currently active
    if trimmed:lower():find("do not disturb") or trimmed:lower():find("dnd") then
    return "on"
    else
    return "off"
    end
    else
    log.e("Failed to get current focus state")
    return "unknown"
    end
    end

    hs.caffeinate.watcher.new(function(eventType)
    if eventType == hs.caffeinate.watcher.screensDidLock then
    local currentState = getCurrentFocusState()

    if currentState ~= "on" then
    focus("on")()
    hammerspoonEnabledDnd = true -- Mark that we enabled it
    else
    hammerspoonEnabledDnd = false -- We didn't enable it
    end

    elseif eventType == hs.caffeinate.watcher.screensDidUnlock then
    local currentState = getCurrentFocusState()

    if currentState == "on" and hammerspoonEnabledDnd then
    focus("off")()
    hammerspoonEnabledDnd = false -- Reset flag
    elseif currentState == "on" and not hammerspoonEnabledDnd then
    log.i("DnD active but was manually enabled, leaving on")
    else
    hammerspoonEnabledDnd = false -- Reset flag just in case
    end
    end
    end):start()

    log.w("DnD automation watcher started")