Home - macadmins/nudge GitHub Wiki
Nudge is a lightweight, open-source application that encourages users to update the operating system on their company-issued Mac (in accordance with their organization's IT policies). This encouragement comes in the form of reminders that are displayed front-and-center on the user’s screen, and which reappear more frequently until the Mac is in compliance.
Nudge has already been successfully deployed at hundreds of organizations across public and private sectors, with fleet sizes ranging from less than 100 Macs in a small office to over 10,000 Macs at multiple offices across the globe.
Nudge offers support for multiple languages, custom user deferral settings, and a range of optional features designed to strongly encourage users to update macOS.
Written in Swift 5.10, Nudge is compatible with macOS Monterey 12 and higher (please use Nudge 1.x releases for macOS 11). It is a replacement for the original Nudge-Python project. If you need to enforce macOS updates for earlier versions of macOS, it is recommend to use nudge-python instead.
The SwiftUI version of Nudge offers several distinct advantages:
- An enhanced UI, redesigned with new functionality
- A new UI called
simpleMode
- Support for localization
- Support for Mac computers with Apple silicon
- Customizable buttons and button actions
- Customizable text elements (except for left sidebar)
The following operating system versions have been tested:
- macOS 12.0 ~ 12.7
- macOS 13.0 ~ 13.6.2
- macOS 14.0 ~ 14.5
Before submitting any issues to Nudge, please ensure you using the latest version. You can find the version you are using by running Nudge and clicking on the ?
button at the top left.
Alternatively you can run the -version
argument through the command line
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge -version
1.1.13.81503
To deploy Nudge, your device management infrastructure must include some way to deploy macOS package (.pkg) files. While the Nudge configuration can be deployed to the Mac with a package, it is recommended to build a managed configuration profile (.mobileconfig) and deploy it via MDM.
Nudge consists of the following three components:
- Nudge.app installed to
/Applications/Utilities/Nudge.app
- A LaunchAgent installed to
/Library/LaunchAgents
- A Preference file, either in JSON or mobileconfig format
Rather than trying to install updates via the macOS built-in softwareupdate
binary, Nudge prompts users to install updates via Apple approved/tested methods: System Preferences > Software Update and major application upgrades via the standalone macOS installer (Ex: Install macOS Monterey.app
). Note: in macOS 12.3 and higher, the 'standalone installer' is no longer used, and all updates are driven through the Software Update preference pane.
With the optionally provided LaunchAgent package, Nudge will open every 30 minutes, at the top and bottom of each hour. If you find this behavior too aggressive, you will need to create your own LaunchAgent.
If you install the Nudge package without a configuration, you can attempt to open Nudge through Finder
- but nothing will appear. Nudge will simply write a log entry to the macOS unified log indicating that a required configuration was not found.
Please read on to learn how to engage with Nudge through the command line.
For a full listing of the available command line arguments, please see the wiki.
To open Nudge through the command-line application, open Terminal
and run the following command:
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge
If you have just installed Nudge for the first time, you will likely see the following message returned:
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge
Device fully up-to-date.
In order to trigger Nudge in demo mode, simply pass the -demo-mode
argument
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-demo-mode
This will open Nudge in the English localization and allow you to test the buttons, as well as Light/Dark mode.
If you'd like to trigger simpleMode
in Demo mode, chain the both -demo-mode
and -simple-mode
arguments
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-demo-mode \
-simple-mode
If you'd like to force the icon in Demo mode, chain the both -demo-mode
and -force-screenshot-icon
arguments
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-demo-mode \
-force-screenshot-icon
If you'd like to force simple mode (and don't want to use the built in preferences configuration), simply pass the -simple-mode
argument
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-simple-mode
Nudge has support for both remote JSON and local JSON.
By default, Nudge will look for local JSON located at /Library/Preferences/com.github.macadmins.Nudge.json
.
To use a remote JSON file, simply pass the -json-url
argument.
Note: Spaces must be converted to %20
, just as a standard URL. (This is required both for remote and local assets.)
The following example uses remote JSON included in the Nudge GitHub repository. (You can safely ignore any warnings indicating "There is no application set to open the URL munki://updates
.")
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-json-url \
"https://raw.githubusercontent.com/macadmins/nudge/main/Example%20Assets/com.github.macadmins.Nudge.json"
Note: If the Mac on which you are testing Nudge has a later version of macOS than what is specified in requiredMinimumOSVersion
, you will not observe the Nudge UI, but the Nudge logs will detail the actions taken. For example:
Nudge[9563]: [com.github.macadmins.Nudge:softwareupdate-download] enforceMinorUpdates: true
Nudge[9563]: [com.github.macadmins.Nudge:utilities] Current operating system (11.6) is greater than or equal to required operating system (11.5.2)
Nudge[9563]: [com.github.macadmins.Nudge:user-interface] Device is fully updated
Nudge[9563]: [com.github.macadmins.Nudge:user-interface] Nudge is terminating due to condition met
While the -json-url
argument is mainly designed for web-hosted URLs, you can actually pass it a file://
path if you want to deploy JSON to a location other than /Library/Preferences
or simply want to test your workflow:
- Install the latest Nudge-1.1.9.x.pkg on a local test Mac
- Save the sample JSON to your Downloads folder as
com.github.macadmins.Nudge.json
curl -o ~/Downloads/com.github.macadmins.Nudge.json https://raw.githubusercontent.com/macadmins/nudge/main/Example%20Assets/com.github.macadmins.Nudge.json
- Modify and save with your preferred editor
- Change
requiredInstallationDate
to a date in the future (or in the past) - Change
requiredMinimumOSVersion
to a value greater than (or less than) the output ofsw_vers -productVersion
- Review
actionButtonPath
- Munki: See Munki Links
-
Jamf Pro: See Jamf Self Service for macOS URL Schemes <-- replace "&" in such a string with
&
-
Nudge v1.0.0 behavior: To open System Preferences > Software Update, delete the entire
actionButtonPath
line.
- Change
- Execute the following command in Terminal:
/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge \
-json-url \
"file:///Users/`id -n -u`/Downloads/com.github.macadmins.Nudge.json"
- Press Control + C to break
- Repeat Steps 2 through 4, modifying the values of
requiredInstallationDate
,requiredMinimumOSVersion
, andactionButtonPath
as desired
See also Testing and resetting Nudge.
Using PayloadType com.github.macadmins.Nudge
in a mobileconfig, use the json-url
<key>PayloadContent</key>
<dict>
<key>json-url</key>
<string>https://example.org/nudge.json</string>
</dict>
<key>PayloadType</key>
<string>com.github.macadmins.Nudge</string>
Every release of Nudge comes with an optional LaunchAgent package.
This LaunchAgent will open Nudge every 30 minutes, at the top and bottom of each hour. If you find this behavior too aggressive, you will need to create your own LaunchAgent.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AssociatedBundleIdentifiers</key>
<array>
<string>com.github.macadmins.Nudge</string>
</array>
<key>Label</key>
<string>com.github.macadmins.Nudge</string>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
</array>
<key>ProgramArguments</key>
<array>
<string>/Applications/Utilities/Nudge.app/Contents/MacOS/Nudge</string>
<!-- <string>-json-url</string> -->
<!-- <string>https://raw.githubusercontent.com/macadmins/nudge/main/Nudge/example.json</string> -->
<!-- <string>-demo-mode</string> -->
<!-- <string>-force-screenshot-icon</string> -->
<!-- <string>-simple-mode</string> -->
<!-- <string>-version</string> -->
</array>
<key>RunAtLoad</key>
<true/>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Minute</key>
<integer>30</integer>
</dict>
</array>
</dict>
</plist>
By default, Nudge supports the following locales:
- Chinese
- Danish
- Dutch
- English
- French
- German
- Hindi
- Korean
- Japanese
- Norwegian
- Portuguese
- Russian
- Spanish
- Swedish
If you need additional localizations, you will need the following:
- Localization.strings for locale of the left side of Nudge and the
Additional Machine Details
view - Preferences file
The following example would add support for the French (fr) locale.
Note: There is already a French localization string to fill the rest of the UI
{
"userInterface": {
"updateElements": [
{
"_language": "es",
"actionButtonText": "Actualizar dispositivo",
"informationButtonText": "Más información",
"mainContentHeader": "Su dispositivo se reiniciará durante esta actualización",
"mainContentNote": "Notas importantes",
"mainContentSubHeader": "Las actualizaciones pueden tardar unos 30 minutos en completarse",
"mainContentText": "Se requiere un dispositivo completamente actualizado para garantizar que IT pueda proteger su dispositivo con precisión.\n\nSi no actualiza su dispositivo, es posible que pierda el acceso a algunos elementos necesarios para sus tareas diarias.\n\nPara comenzar la actualización, simplemente haga clic en el botón Actualizar dispositivo y siga los pasos proporcionados.",
"mainHeader": "Tu dispositivo requiere una actualización de seguridad",
"primaryQuitButtonText": "Más tarde",
"secondaryQuitButtonText": "Entiendo",
"subHeader": "Un recordatorio amistoso de su equipo de IT local"
},
{
"_language": "fr",
"actionButtonText": "Mettre à jour l'appareil",
"informationButtonText": "Plus d'informations",
"mainContentHeader": "Votre appareil redémarrera pendant cette mise à jour",
"mainContentNote": "Notes Importantes",
"mainContentSubHeader": "Les mises à jour peuvent prendre environ 30 minutes.",
"mainContentText": "Un appareil entièrement à jour est nécessaire pour garantir que le service informatique puisse le protéger efficacement.\n\n Si vous ne mettez pas à jour votre appareil, vous risquez de perdre l'accès à certains systèmes nécessaires à vos tâches quotidiennes.\n\nPour commencer la mise à jour, cliquez simplement sur le bouton Mettre à Jour le Périphérique et suivez les étapes fournies.",
"mainHeader": "Votre appareil nécessite une mise à jour de sécurité",
"primaryQuitButtonText": "Plus tard",
"secondaryQuitButtonText": "Je comprends",
"subHeader": "Un rappel amical de votre équipe informatique locale"
}
]
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>userInterface</key>
<dict>
<key>updateElements</key>
<array>
<dict>
<key>_language</key>
<string>es</string>
<key>actionButtonText</key>
<string>Actualizar dispositivo</string>
<key>informationButtonText</key>
<string>Más información</string>
<key>mainContentHeader</key>
<string>Su dispositivo se reiniciará durante esta actualización</string>
<key>mainContentNote</key>
<string>Notas importantes</string>
<key>mainContentSubHeader</key>
<string>Las actualizaciones pueden tardar unos 30 minutos en completarse</string>
<key>mainContentText</key>
<string>Se requiere un dispositivo completamente actualizado para garantizar que IT pueda proteger su dispositivo con precisión.
Si no actualiza su dispositivo, es posible que pierda el acceso a algunos elementos necesarios para sus tareas diarias.
Para comenzar la actualización, simplemente haga clic en el botón Actualizar dispositivo y siga los pasos proporcionados.</string>
<key>mainHeader</key>
<string>Tu dispositivo requiere una actualización de seguridad</string>
<key>primaryQuitButtonText</key>
<string>Más tarde</string>
<key>secondaryQuitButtonText</key>
<string>Entiendo</string>
<key>subHeader</key>
<string>Un recordatorio amistoso de su equipo de IT local</string>
</dict>
<dict>
<key>_language</key>
<string>fr</string>
<key>actionButtonText</key>
<string>Mettre à jour l'appareil</string>
<key>informationButtonText</key>
<string>Plus d'informations</string>
<key>mainContentHeader</key>
<string>Votre appareil redémarrera pendant cette mise à jour</string>
<key>mainContentNote</key>
<string>Notes Importantes</string>
<key>mainContentSubHeader</key>
<string>Les mises à jour peuvent prendre environ 30 minutes.</string>
<key>mainContentText</key>
<string>Un appareil entièrement à jour est nécessaire pour garantir que le service informatique puisse protéger votre appareil efficacement.
Si vous ne mettez pas à jour votre appareil, vous risquez de perdre l'accès à certains outils nécessaires à vos tâches quotidiennes.
Pour commencer la mise à jour, cliquez simplement sur le bouton Mettre à jour le périphérique et suivez les étapes fournies.</string>
<key>mainHeader</key>
<string>Votre appareil nécessite une mise à jour de sécurité</string>
<key>primaryQuitButtonText</key>
<string>Plus tard</string>
<key>secondaryQuitButtonText</key>
<string>Je comprends</string>
<key>subHeader</key>
<string>Un rappel amical de votre équipe informatique locale</string>
</dict>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
Nudge offers significant customization, which might be overwhelming. But don't worry, you don't have to customize everything. 😄
For a full listing of the available preferences, please see the wiki. See also Over-configuring Nudge.
In this example, Nudge will do the following:
- Open up in
simpleMode
- Prompt users running any version of macOS Big Sur to upgrade to version
11.6
by 30-Sep-2021 - The
More Info
button will open up to Apple's macOS Big Sur English release notes
{
"userInterface": {
"simpleMode": true
},
"osVersionRequirements": [
{
"aboutUpdateURL": "https://support.apple.com/en-us/HT211896",
"requiredInstallationDate": "2021-09-30T00:00:00Z",
"requiredMinimumOSVersion": "11.6",
"targetedOSVersionsRule": "11"
}
]
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>osVersionRequirements</key>
<array>
<dict>
<key>aboutUpdateURL</key>
<string>https://support.apple.com/en-us/HT211896</string>
<key>requiredInstallationDate</key>
<date>2021-09-30T00:00:00Z</date>
<key>requiredMinimumOSVersion</key>
<string>11.6</string>
<key>targetedOSVersionsRule</key>
<string>11</string>
</dict>
</array>
<key>userInterface</key>
<dict>
<key>simpleMode</key>
<true/>
</dict>
</dict>
</array>
</dict>
</plist>
For full examples please see the Example Assets folder in this repo.
Please the read Getting Started page.
For an authoritative list of the preferences, please see the sidebar for all articles.