katbel
macrumors 601
The same trick I have on my devices .. didn’t think of that, thanks!
Simple and clean for now
The same trick I have on my devices .. didn’t think of that, thanks!
Great idea and DO NOT PICK THE TAHOE ONE!!! now trying to get higher macOS and iOS 26 adoption rates isn’t good for Liquid Glass haters.Dumb workaround for now:
Enable Sequoia Public Beta and you won't get a notification.
View attachment 2616852
You will, however, start getting 15.7.6 RC builds offered to you as soon as they put one out. (Could be tomorrow, could be two weeks, but there will be multiple of them before 15.7.6 actually releases.)Dumb workaround for now:
Enable Sequoia Public Beta and you won't get a notification.
View attachment 2616852
Eventually they'll stop updating Sequoia 😀 (except for security updates)You will, however, start getting 15.7.6 RC builds offered to you in a week or two.
The NoBubbleNew profile still works https://forums.macrumors.com/thread...ore-sequoia-for-90-days.2436999/post-33628256Return of the alias in the Dock:
Until such time... (no worries).
plutil -p ~/Library/Preferences/com.apple.dock.plist | grep -i -B 4 -A 1 "com.apple.systempreferences"
/usr/libexec/PlistBuddy -c "Set persistent-apps:1:tile-data:dock-extra bool NO" ~/Library/Preferences/com.apple.dock.plist; killall Dock
They will continue to put out multiple RC builds for each point release. They're still doing it with Sonoma even.Eventually they'll stop updating Sequoia 😀 (except for security updates)
It peaked
#!/bin/bash
# ============================================================================
# macOS Major Upgrade Blocker
# ============================================================================
# Purpose: Block major macOS upgrades while allowing security updates
# Tested on: macOS Sequoia 15.7.3 (Apple Silicon)
#
# This script:
# - Removes major upgrade installers (e.g., macOS 16+)
# - Pins software update catalog to current major version
# - Suppresses update notifications and badges
# - Removes update staging directories
# - Allows manual security updates via: softwareupdate -i -a
#
# Designed to run via LaunchDaemon every 2 hours
# ============================================================================
LOG="/var/log/block-major-upgrades.log"
touch "$LOG" 2>/dev/null
CURRENT_VERSION=$(sw_vers -productVersion | cut -d '.' -f 1)
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG"
}
# --- Log Rotation: Keep last 500 lines ---
if [ -f "$LOG" ] && [ "$(wc -l < "$LOG")" -gt 500 ]; then
tail -500 "$LOG" > "${LOG}.tmp" && mv "${LOG}.tmp" "$LOG"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Log rotated (kept last 500 lines)" >> "$LOG"
fi
log_message "==== Block check started ===="
REMOVED_INSTALLER=false
# --- 1. Remove Major Upgrade Installers ---
# Removes "Install macOS [NextVersion].app" from /Applications
# Only removes installers for versions NEWER than current major version
for installer in /Applications/Install\ macOS*.app; do
if [ -d "$installer" ]; then
# Verify it's a genuine Apple installer
if defaults read "$installer/Contents/Info.plist" CFBundleIdentifier \
2>/dev/null | grep -q "com.apple.InstallAssistant"; then
INSTALLER_VERSION=$(defaults read "$installer/Contents/Info.plist" \
CFBundleShortVersionString 2>/dev/null | cut -d '.' -f 1)
# Version check with error handling
if [ -n "$INSTALLER_VERSION" ] && \
[ "$INSTALLER_VERSION" -gt "$CURRENT_VERSION" ]; then
rm -rf "$installer"
log_message "Removed major upgrade installer: $(basename "$installer")"
REMOVED_INSTALLER=true
fi
fi
fi
done
# --- 2. Disable Automatic Update Checks ---
# System-wide settings to prevent automatic update downloads and installations
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AllowPreReleaseInstallation -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticCheckEnabled -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticDownload -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
CriticalUpdateInstall -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticallyInstallMacOSUpdates -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticallyInstallSystemDataFiles -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
ConfigDataInstall -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
ShowNotifications -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.commerce \
AutoUpdate -bool false 2>/dev/null
# --- 3. User-Specific App Store Settings ---
# Suppress badges and notifications for the current console user
CONSOLE_USER=$(stat -f %Su /dev/console 2>/dev/null)
if [ "$CONSOLE_USER" != "root" ] && [ "$CONSOLE_USER" != "_windowserver" ] && [ -n "$CONSOLE_USER" ]; then
USER_HOME=$(dscl . -read /Users/"$CONSOLE_USER" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
if [ -n "$USER_HOME" ] && [ -d "$USER_HOME" ]; then
# Disable App Store automatic updates
sudo -u "$CONSOLE_USER" defaults write com.apple.commerce \
AutoUpdate -bool false 2>/dev/null
sudo -u "$CONSOLE_USER" defaults write com.apple.commerce \
AutoUpdateRestartRequired -bool false 2>/dev/null
sudo -u "$CONSOLE_USER" defaults write com.apple.appstore \
AutomaticCheckEnabled -bool false 2>/dev/null
# Suppress FollowUp notification badges
sudo -u "$CONSOLE_USER" defaults write \
"$USER_HOME/Library/Preferences/com.apple.systempreferences.plist" \
AttentionPrefBundleIDs -dict-add \
"com.apple.FollowUpSettings.FollowUpSettingsExtension" 0 2>/dev/null
# Remove App Store badge count
sudo -u "$CONSOLE_USER" defaults delete com.apple.appstored BadgeCount 2>/dev/null
# Block Notification Center popups for software updates
sudo -u "$CONSOLE_USER" defaults write \
"$USER_HOME/Library/Preferences/com.apple.ncprefs.plist" \
"_SYSTEM_CENTER_:com.apple.SoftwareUpdateNotification" \
-dict "flags" -int 0 2>/dev/null
# Clean apps array (removes persistent Software Update notification entries)
# This prevents duplicate notification entries from reappearing
sudo -u "$CONSOLE_USER" defaults delete \
"$USER_HOME/Library/Preferences/com.apple.ncprefs.plist" \
apps 2>/dev/null
log_message "Update preferences and badge suppression applied for user: $CONSOLE_USER"
fi
fi
# --- 4. Update Badge Reset ---
# Always remove update notification keys (not only when installer was found)
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
RecommendedUpdates 2>/dev/null
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
LastRecommendedUpdatesAvailable 2>/dev/null
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
LastUpdatesAvailable 2>/dev/null
# --- 5. Catalog Override ---
# Pin software update catalog to current major version (e.g., Sequoia 15.x)
# This prevents macOS 16+ from being offered while allowing 15.x security updates
# Change "index-15" to match your desired major version
CATALOG="https://swscan.apple.com/content/catalogs/others/index-15.sucatalog"
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
CatalogURL "$CATALOG" 2>/dev/null
log_message "Catalog pinned to Sequoia 15.x"
# --- 6. Remove macOS Install Data Staging ---
# Removes the staging directory used for major upgrade preparation
if [ -d "/System/Volumes/Data/macOS Install Data" ]; then
rm -rf "/System/Volumes/Data/macOS Install Data" 2>/dev/null
log_message "Removed macOS Install Data staging"
fi
# --- 7. Remove FollowUp Notifications ---
# Removes additional notification source for software updates
if [ -d "/Library/Application Support/com.apple.followup" ]; then
rm -rf "/Library/Application Support/com.apple.followup" 2>/dev/null
log_message "Removed FollowUp notifications directory"
fi
# --- 8. Selective Installer Cache Cleanup ---
# Only remove installer-related caches, preserve security update caches
if [ "$REMOVED_INSTALLER" = true ]; then
find /Library/Updates \( -name "*Install*" -o -name "*Installer*" \) \
-exec rm -rf {} + 2>/dev/null
log_message "Removed installer cache files"
fi
# --- 9. Restart Dock and NotificationCenter (Outside Work Hours Only) ---
# Clears badges from Dock and Notification Center
# Only restarts during off-hours (before 7 AM or after 10 PM) to avoid disruption
HOUR=$(date +%H)
if [ "$HOUR" -lt 7 ] || [ "$HOUR" -gt 22 ]; then
killall Dock 2>/dev/null
killall NotificationCenter 2>/dev/null
log_message "Restarted Dock and NotificationCenter (badges cleared)"
else
log_message "Badge cleanup completed (Dock restart skipped during work hours)"
fi
log_message "==== Block check completed ===="
exit 0
<?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>Label</key>
<string>com.local.blockmajoros</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/block-major-upgrades.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<!-- Runs every 2 hours (12 times daily) -->
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>1</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>5</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>11</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>13</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>15</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>17</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>19</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>21</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>23</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
<key>StandardOutPath</key>
<string>/var/log/block-major-upgrades.log</string>
<key>StandardErrorPath</key>
<string>/var/log/block-major-upgrades-error.log</string>
</dict>
</plist>
# 1. Create the script
sudo nano /usr/local/bin/block-major-upgrades.sh
# (Paste script content, save with Ctrl+O, Enter, Ctrl+X)
# 2. Make executable
sudo chmod +x /usr/local/bin/block-major-upgrades.sh
# 3. Create LaunchDaemon
sudo nano /Library/LaunchDaemons/com.local.blockmajoros.plist
# (Paste plist content, save)
# 4. Set correct permissions
sudo chmod 644 /Library/LaunchDaemons/com.local.blockmajoros.plist
sudo chown root:wheel /Library/LaunchDaemons/com.local.blockmajoros.plist
# 5. Load the LaunchDaemon
sudo launchctl bootstrap system /Library/LaunchDaemons/com.local.blockmajoros.plist
# 6. Verify it's loaded
sudo launchctl list | grep blockmajoros
# 7. Test run
sudo /usr/local/bin/block-major-upgrades.sh
# 8. Check logs
tail -20 /var/log/block-major-upgrades.log
# Stop and unload LaunchDaemon
sudo launchctl bootout system /Library/LaunchDaemons/com.local.blockmajoros.plist
# Remove catalog override
sudo defaults delete /Library/Preferences/com.apple.SoftwareUpdate CatalogURL
# Re-enable automatic checks
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true
# System will return to normal update behavior
Pins the update catalog to current major version
# --- 5. Catalog Override ---
# Pin software update catalog to current major version (e.g., Sequoia 15.x)
# This prevents macOS 16+ from being offered while allowing 15.x security updates
# Change "index-15" to match your desired major version
CATALOG="https://swscan.apple.com/content/catalogs/others/index-15.sucatalog"
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
CatalogURL "$CATALOG" 2>/dev/null
log_message "Catalog pinned to Sequoia 15.x"
softwareupdate -l returns: "Can’t load data from the Software Update server ((null))."Thanks for catching that! You're absolutely right - the catalog URL returns a 404. I've now removed the catalog override section as it was unnecessary in the first place.But https://swscan.apple.com/content/catalogs/others/index-15.sucatalog does not exist and after setting itsoftwareupdate -lreturns: "Can’t load data from the Software Update server ((null))."
# Remove broken catalog URL (if exists from previous script version)
sudo defaults delete /Library/Preferences/com.apple.SoftwareUpdate CatalogURL
#!/bin/bash
# ============================================================================
# macOS Major Upgrade Blocker
# ============================================================================
# Purpose: Block major macOS upgrades while allowing security updates
# Tested on: macOS Sequoia 15.7.3 (Apple Silicon)
#
# This script:
# - Removes major upgrade installers (e.g., macOS 16+)
# - Pins software update catalog to current major version
# - Suppresses update notifications and badges
# - Removes update staging directories
# - Allows manual security updates via: softwareupdate -i -a
#
# Designed to run via LaunchDaemon every 2 hours
# ============================================================================
LOG="/var/log/block-major-upgrades.log"
touch "$LOG" 2>/dev/null
CURRENT_VERSION=$(sw_vers -productVersion | cut -d '.' -f 1)
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG"
}
# --- Log Rotation: Keep last 500 lines ---
if [ -f "$LOG" ] && [ "$(wc -l < "$LOG")" -gt 500 ]; then
tail -500 "$LOG" > "${LOG}.tmp" && mv "${LOG}.tmp" "$LOG"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Log rotated (kept last 500 lines)" >> "$LOG"
fi
log_message "==== Block check started ===="
REMOVED_INSTALLER=false
# --- 1. Remove Major Upgrade Installers ---
# Removes "Install macOS [NextVersion].app" from /Applications
# Only removes installers for versions NEWER than current major version
for installer in /Applications/Install\ macOS*.app; do
if [ -d "$installer" ]; then
# Verify it's a genuine Apple installer
if defaults read "$installer/Contents/Info.plist" CFBundleIdentifier \
2>/dev/null | grep -q "com.apple.InstallAssistant"; then
INSTALLER_VERSION=$(defaults read "$installer/Contents/Info.plist" \
CFBundleShortVersionString 2>/dev/null | cut -d '.' -f 1)
# Version check with error handling
if [ -n "$INSTALLER_VERSION" ] && \
[ "$INSTALLER_VERSION" -gt "$CURRENT_VERSION" ]; then
rm -rf "$installer"
log_message "Removed major upgrade installer: $(basename "$installer")"
REMOVED_INSTALLER=true
fi
fi
fi
done
# --- 2. Disable Automatic Update Checks ---
# System-wide settings to prevent automatic update downloads and installations
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AllowPreReleaseInstallation -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticCheckEnabled -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticDownload -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
CriticalUpdateInstall -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticallyInstallMacOSUpdates -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
AutomaticallyInstallSystemDataFiles -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
ConfigDataInstall -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.SoftwareUpdate \
ShowNotifications -bool false 2>/dev/null
defaults write /Library/Preferences/com.apple.commerce \
AutoUpdate -bool false 2>/dev/null
# --- 3. User-Specific App Store Settings ---
# Suppress badges and notifications for the current console user
CONSOLE_USER=$(stat -f %Su /dev/console 2>/dev/null)
if [ "$CONSOLE_USER" != "root" ] && [ "$CONSOLE_USER" != "_windowserver" ] && [ -n "$CONSOLE_USER" ]; then
USER_HOME=$(dscl . -read /Users/"$CONSOLE_USER" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
if [ -n "$USER_HOME" ] && [ -d "$USER_HOME" ]; then
# Disable App Store automatic updates
sudo -u "$CONSOLE_USER" defaults write com.apple.commerce \
AutoUpdate -bool false 2>/dev/null
sudo -u "$CONSOLE_USER" defaults write com.apple.commerce \
AutoUpdateRestartRequired -bool false 2>/dev/null
sudo -u "$CONSOLE_USER" defaults write com.apple.appstore \
AutomaticCheckEnabled -bool false 2>/dev/null
# Suppress FollowUp notification badges
sudo -u "$CONSOLE_USER" defaults write \
"$USER_HOME/Library/Preferences/com.apple.systempreferences.plist" \
AttentionPrefBundleIDs -dict-add \
"com.apple.FollowUpSettings.FollowUpSettingsExtension" 0 2>/dev/null
# Remove App Store badge count
sudo -u "$CONSOLE_USER" defaults delete com.apple.appstored BadgeCount 2>/dev/null
# Block Notification Center popups for software updates
sudo -u "$CONSOLE_USER" defaults write \
"$USER_HOME/Library/Preferences/com.apple.ncprefs.plist" \
"_SYSTEM_CENTER_:com.apple.SoftwareUpdateNotification" \
-dict "flags" -int 0 2>/dev/null
# Clean apps array (removes persistent Software Update notification entries)
# This prevents duplicate notification entries from reappearing
sudo -u "$CONSOLE_USER" defaults delete \
"$USER_HOME/Library/Preferences/com.apple.ncprefs.plist" \
apps 2>/dev/null
log_message "Update preferences and badge suppression applied for user: $CONSOLE_USER"
fi
fi
# --- 4. Update Badge Reset ---
# Always remove update notification keys (not only when installer was found)
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
RecommendedUpdates 2>/dev/null
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
LastRecommendedUpdatesAvailable 2>/dev/null
defaults delete /Library/Preferences/com.apple.SoftwareUpdate \
LastUpdatesAvailable 2>/dev/null
# --- 5. Remove macOS Install Data Staging ---
# Removes the staging directory used for major upgrade preparation
if [ -d "/System/Volumes/Data/macOS Install Data" ]; then
rm -rf "/System/Volumes/Data/macOS Install Data" 2>/dev/null
log_message "Removed macOS Install Data staging"
fi
# --- 6. Remove FollowUp Notifications ---
# Removes additional notification source for software updates
if [ -d "/Library/Application Support/com.apple.followup" ]; then
rm -rf "/Library/Application Support/com.apple.followup" 2>/dev/null
log_message "Removed FollowUp notifications directory"
fi
# --- 7. Selective Installer Cache Cleanup ---
# Only remove installer-related caches, preserve security update caches
if [ "$REMOVED_INSTALLER" = true ]; then
find /Library/Updates \( -name "*Install*" -o -name "*Installer*" \) \
-exec rm -rf {} + 2>/dev/null
log_message "Removed installer cache files"
fi
# --- 8. Restart Dock and NotificationCenter (Outside Work Hours Only) ---
# Clears badges from Dock and Notification Center
# Only restarts during off-hours (before 7 AM or after 10 PM) to avoid disruption
HOUR=$(date +%H)
if [ "$HOUR" -lt 7 ] || [ "$HOUR" -gt 22 ]; then
killall Dock 2>/dev/null
killall NotificationCenter 2>/dev/null
log_message "Restarted Dock and NotificationCenter (badges cleared)"
else
log_message "Badge cleanup completed (Dock restart skipped during work hours)"
fi
log_message "==== Block check completed ===="
exit 0
🙂
I'm not using your script, I'm testing another method.🙂
# 7. Test run
sudo /usr/local/bin/block-major-upgrades.sh
Do you see any Update notification after running?
It doesn’t return a number when I run the first code : I substituted the ~ with my user home name,Run
and note the first number followed by => {Code:plutil -p ~/Library/Preferences/com.apple.dock.plist | grep -i -B 4 -A 1 "com.apple.systempreferences"
Then run
Code:/usr/libexec/PlistBuddy -c "Set persistent-apps:1:tile-data:dock-extra bool NO" ~/Library/Preferences/com.apple.dock.plist; killall Dock
where the number after persistent-apps: is the number identified with the first command.
Please post the result of the command so I can understand what’s going on.It doesn’t return a number when I run the first code : I substituted the ~ with my user home name,
should I remove the quotes as well to com.apple.systempreferences ?
It doesn’t return anything , sadly: it goes back to the empty terminal ready to get an inputPlease post the result of the command so I can understand what’s going on.
Here is what it returns on my Mac
plutil -p ~/Library/Preferences/com.apple.dock.plist | grep -i -B 4 -A 1 'com.apple.systempreferences'
12 => {
"GUID" => 1032108749
"tile-data" => {
"book" => {length = 604, bytes = 0x626f6f6b 5c020000 00000510 40000000 ... 04000000 00000000 }
"bundle-identifier" => "com.apple.systempreferences"
"dock-extra" => 1
The number is 12 in the above example.
By the way, it’s easier to use the NoBubbleNew profile 🙂
It won't print anything if System Settings isn't pinned to the Dock (right-click, Options -> Keep in Dock).Please post the result of the command so I can understand what’s going on.
It's possible to install these manually. For Xprotect at least, on older systems you can find the necessary pkg URL in the sucatalog, otherwise for Sequoia I've set up a Little Snitch rule list that I can quickly enable, runIn my opinion, blocking software updates with a firewall is not a good idea because it blocks updates for XProtect and Rosetta.
sudo xprotect version && sudo xprotect check && sudo xprotect update, then disable. The XProtect update goes through before macOS can check for other updates.