Menu Close

DDM OS Reminder (1.2.0)

A swiftDialog-enabled script and LaunchDaemon pair for “set-it-and-forget-it” end-user messaging of Apple’s Declarative Device Management-required macOS updates

DDM OS Reminder (1.0.0) is a swiftDialog and LaunchDaemon pair for "set-it-and-forget-it" end-user messaging of Apple's Declarative Device Management (DDM)-required macOS updates

Overview

While Apple’s Declarative Device Management (DDM) provides Mac Admins a powerful method to enforce macOS updates, its built-in notification tends to be too subtle for most Mac Admins:

While Apple's Declarative Device Management (DDM) provides Mac Admins a powerful method to enforce macOS updates, its built-in notification tends to be too subtle for most Mac Admins

DDM OS Reminder evaluates the most recent EnforcedInstallDate entry in /var/log/install.log, then leverages a swiftDialog-enabled script and LaunchDaemon pair to dynamically deliver a more prominent end-user message of when the user’s Mac needs to be updated to comply with DDM-configured macOS version requirements:

Features

Mac Admins can configure daysBeforeDeadlineBlurscreen to control how many days before the DDM-specified deadline the screen blurs when displaying your customized message

Mac Admins can configure daysBeforeDeadlineBlurscreen to control how many days before the DDM-specified deadline the screen blurs when displaying your customized message:

  • Customizable: Easily customize the swiftDialog message’s title, message, icon, and button text to fit your organization’s needs by editing the provided DDM-OS-Reminder End-user Message.zsh script. (See Step A.)
  • Set-it-and-forget-it: Once installed, the LaunchDaemon executes your customized ddmOSReminder.zsh script, which automatically checks the installed version of macOS against the DDM-enforced macOS version twice daily and displays your customized message if an update is required. (See Step B.)
  • Deadline Awareness: Each time a DDM-enforced macOS version and deadline is updated via your MDM solution, the message will dynamically include an updated countdown to the deadline, creating a sense of urgency for end-users to update their Macs.
  • Tastefully Intrusive: The message is designed to be informative without being overly disruptive — first checking for the user’s Display Sleep Assertions — allowing users to continue their work while being reminded of the need to update.
  • Easy Installation: The script can be easily deployed via any MDM solution, making it simple to roll out across an organization.
  • Logging: The script logs its actions to your specified log file, allowing Mac Admins to monitor its activity and troubleshoot if necessary.

Implementation

A. Customize DDM-OS-Reminder End-user Message.zsh for your organization

The GitHub repository includes a sample DDM-OS-Reminder End-user Message.zsh script which you can use to jump-start your user-facing messaging (and which you’ll later insert into the ddmOSReminder.zsh script, but not deploy to your endpoints; see Step B).

The GitHub repository includes a sample DDM-OS-Reminder End-user Message.zsh script which you can use to jump-start your user-facing messaging.

You’ll want to first update the Organization Variables for your environment:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Organization Variables
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Script Human-readable Name
humanReadableScriptName="DDM OS Reminder End-user Message"

# Organization's Script Name
organizationScriptName="dorm"

# Organization's Days Before Deadline Blur Screen 
daysBeforeDeadlineBlurscreen="3"

Please note that when testing, the script includes logic in the installedOSvsDDMenforcedOS function to display only when a pending update is available and the recommendation is to test on a purposely outdated Mac (and to comment-out the script’s sleep "${sleepSeconds}").

Script output for a pending DDM macOS update
root@Dan ~ # zsh /Users/dan/Downloads/DDM-OS-Reminder\ End-user\ Message.zsh 
dorm (1.0.0): 2025-10-14 14:37:44 - [PRE-FLIGHT]      Created specified scriptLog: /var/log/org.churchofjesuschrist.log
dorm (1.0.0): 2025-10-14 14:37:44 - [PRE-FLIGHT]      

###
# DDM OS Reminder End-user Message (1.0.0)
# https://snelson.us
####

dorm (1.0.0): 2025-10-14 14:37:44 - [PRE-FLIGHT]      Initiating …
dorm (1.0.0): 2025-10-14 14:37:44 - [PRE-FLIGHT]      Complete
dorm (1.0.0): 2025-10-14 14:37:44 - [NOTICE]          Installed OS Version: 15.6.1
dorm (1.0.0): 2025-10-14 14:37:44 - [INFO]            DDM-enforced OS Version: 15.7
dorm (1.0.0): 2025-10-14 14:37:44 - [INFO]            DDM-enforced OS Version Deadline: 2025-10-14
dorm (1.0.0): 2025-10-14 14:37:44 - [NOTICE]          Update Required
dorm (1.0.0): 2025-10-14 14:37:44 - [NOTICE]          Login Trigger Pause: Random 30 to 90 seconds
dorm (1.0.0): 2025-10-14 14:37:44 - [INFO]            Pausing for 78 seconds …
dorm (1.0.0): 2025-10-14 14:39:02 - [NOTICE]          Downloading icon from 'https://ics.services.jamfcloud.com/icon/hash_4555d9dc8fecb4e2678faffa8bdcf43cba110e81950e07a4ce3695ec2d5579ee' …
dorm (1.0.0): 2025-10-14 14:39:03 - [NOTICE]          Display Dialog Window
dorm (1.0.0): 2025-10-14 14:39:15 - [INFO]            Return Code: 0
dorm (1.0.0): 2025-10-14 14:39:15 - [NOTICE]          User clicked Open Software Update
dorm (1.0.0): 2025-10-14 14:39:16 - [QUIT]            Exiting …
dorm (1.0.0): 2025-10-14 14:39:16 - [QUIT]            Shine on, you crazy diamond!
Script output on an up-to-date Mac
root@Dan ~ # zsh /Users/dan/Downloads/DDM-OS-Reminder\ End-user\ Message.zsh 
dorm (1.0.0): 2025-10-14 14:34:25 - [PRE-FLIGHT]      

###
# DDM OS Reminder End-user Message (1.0.0)
# https://snelson.us
####

dorm (1.0.0): 2025-10-14 14:34:25 - [PRE-FLIGHT]      Initiating …
dorm (1.0.0): 2025-10-14 14:34:25 - [PRE-FLIGHT]      Complete
dorm (1.0.0): 2025-10-14 14:34:25 - [NOTICE]          Installed OS Version: 26.0.1
dorm (1.0.0): 2025-10-14 14:34:26 - [INFO]            DDM-enforced OS Version: 26.0.1
dorm (1.0.0): 2025-10-14 14:34:26 - [NOTICE]          Up-to-date
B. Customize ddmOSReminder.zsh for your organization

The GitHub repository includes the ddmOSReminder.zsh script — which is responsible for creating the “set-in-and-forget-it” LaunchDaemon — into which you should insert your customized messaging from Step A, between cat <<'ENDOFSCRIPT' and ENDOFSCRIPT.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# CREATE DDM OS REMINDER SCRIPT
#
#   The following function creates the client-side DDM OS Reminder script, which dynamically
#   generates the end-user message.
#
#   Copy-pasta your organization's customized "DDM-OS-Reminder End-user Message.zsh" script between
#   the "cat <<ENDOFSCRIPT" and "ENDOFSCRIPT" lines below, making sure to leave a full return
#   at the end of the content before the "ENDOFSCRIPT" line.
#
#   NOTE: You'll most likely want to modify the `updateScriptLog` function in the copied script to
#   comment out (or remove) the "| tee -a "${scriptLog}" portion of the line to avoid duplicate
#   entries in the log file.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function createDDMOSReminderScript() {

    notice "Create '${humanReadableScriptName}' script: ${organizationDirectory}/${organizationScriptName}.zsh"

(
cat <<'ENDOFSCRIPT'
# insert
# your
# customized
# DDM-OS-Reminder End-user Message.zsh
# here
#
# Ensure that you leave a full return between the end of your customized messaging script
# and the ENDOFSCRIPT line.
  
ENDOFSCRIPT
) > "${organizationDirectory}/${organizationScriptName}.zsh"

    logComment "${humanReadableScriptName} script created"

    logComment "Setting permissions …"
    chown root:wheel "${organizationDirectory}/${organizationScriptName}.zsh"
    chmod 755 "${organizationDirectory}/${organizationScriptName}.zsh"
    chmod +x "${organizationDirectory}/${organizationScriptName}.zsh"

}

Note: You’ll most likely want to modify the updateScriptLog function in the copied script to comment-out (or delete) the | tee -a "${scriptLog} portion of the line to avoid duplicate entries in the log file.

############################################################################################
#
# Functions
#
############################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
# Client-side Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

function updateScriptLog() {
    echo "${organizationScriptName} ($scriptVersion): $( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" # | tee -a "${scriptLog}"
}

Please remember to also update the Organization Variables for your environment in the ddmOSReminder.zsh script:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Organization Variables
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Organization's Reverse Domain Name Notation (i.e., com.company.division)
reverseDomainNameNotation="org.churchofjesuschrist"

# Script Human-readabale Name
humanReadableScriptName="DDM OS Reminder"

# Organization's Script Name
organizationScriptName="dor"

# Organization's Directory (i.e., where your client-side scripts reside)
organizationDirectory="/Library/Management/org.churchofjesuschrist"

# LaunchDaemon Name & Path
launchDaemonName="${reverseDomainNameNotation}.${organizationScriptName}.plist"
launchDaemonPath="/Library/LaunchDaemons/${launchDaemonName}"
C. Add your customized ddmOSReminder.zsh script to your MDM server

When adding your customized ddmOSReminder.zsh script to your Jamf Pro server, specify the following for Settings > Computer Management > Scripts > Options > Parameter Labels > Parameter 4

  • Parameter 4: Configuration Files to Reset (i.e., None (blank) | All | LaunchDaemon | Script | Uninstall )
Parameter 4: Configuration Files to Reset (i.e., None (blank) | All | LaunchDaemon | Script | Uninstall )

For other MDMs, you can simply “hard-code” the desired setting for the resetConfiguration variable from the following available options:

  • None blank
  • All
  • LaunchDaemon
  • Script
  • Uninstall
# Parameter 4: Configuration Files to Reset (i.e., None (blank) | All | LaunchDaemon | Script | Uninstall )
resetConfiguration="${4:-"All"}"
D. Create a DDM OS Reminder MDM policy

Configure the following when creating the Jamf Pro policy to execute DDM OS Reminder:

  • Options
    • General
      • Trigger: Recurring Check-in
      • Execution Frequency: Once per computer
    • Scripts
      • DDM OS Reminder
  • Scope
    • Targets
      • All Computers
    • Limitations
      • No Limitations
    • Exclusions
      • No Exclusions
F. Add Extension Attributes

While the following Extension Attributes were created for and tested on Jamf Pro, they most likely can be adapted to other MDMs. (For adaptation assistance, help is available on the Mac Admins Slack #ddm-os-reminders channel, or you can open an issue.)

Resources

2025-10-23 02:53:37 dan clicked Remind Me Later
2025-10-23 02:55:28 dan clicked Open Software Update
2025-10-23 03:01:11 dan clicked Remind Me Later
2025-10-23 03:11:32 dan clicked Remind Me Later
2025-10-23 03:48:27 dan clicked KB0054571
2025-10-28 12:00:00
26.1

Support

Community-supplied, best-effort support is available on the Mac Admins Slack (free, registration required) #ddm-os-reminders channel, or you can open an issue.

Posted in Device Management, macOS, Scripts, swiftDialog, Tips & Tricks

Related Posts

3 Comments

  1. fascinating2151fc5403

    this looks great. i went to a jnuc session about using nudge and dmm os updates together, and this looks like it builds that all into 1 single tool.

    • Dan K. Snelson

      DDM OS Reminder can be used in conjunction with “com.apple.configuration.softwareupdate.settings” as it just evaluates the most recent EnforcedInstallDate entry in /var/log/install.log.

Comments are closed.