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

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:

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
daysBeforeDeadlineBlurscreento 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.zshscript. (See Step A.) - Set-it-and-forget-it: Once installed, the LaunchDaemon executes your customized
ddmOSReminder.zshscript, 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).

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
installedOSvsDDMenforcedOSfunction 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’ssleep "${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 )

For other MDMs, you can simply “hard-code” the desired setting for the resetConfiguration variable from the following available options:
- None
blank AllLaunchDaemonScriptUninstall
# 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
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
- JamfEA-DDM-OS-Reminder-User-Clicks.zsh: Reports the user’s button clicks for the DDM OS Reminder message.
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
- JamfEA-Pending_OS_Update_Date.zsh: Reports the date of a pending DDM-enforced macOS update.
2025-10-28 12:00:00
- JamfEA-Pending_OS_Update_Version.zsh: Reports the version of a pending DDM-enforced macOS update.
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.


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.
I like the look of this. How does it handle if we use deferrals instead of a hard deadline?
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.