One-command macOS updater for Homebrew formulae and casks, Mac App Store apps, global npm packages, Oh My Zsh, pipx packages, uv tools, Rust/cargo, mise, asdf, gcloud components, and optional macOS update checks.
Current version: 3.4.0
The recommended installation path is Homebrew. It avoids the common macOS Gatekeeper friction that happens when unsigned .command files are downloaded through a browser and opened from Finder.
- Homebrew formulae and casks
- Global npm packages
- Mac App Store apps through
mas - Oh My Zsh
- pipx packages and shared pipx libraries
- uv tools and, when possible, uv itself
- Rust toolchains (
rustup) and globally installed crates (cargo install-update) - mise-managed tools (
mise upgrade) - asdf plugins (
asdf plugin update --all) - Google Cloud CLI components (
gcloud components update) - Safe periodic cleanup for Homebrew, npm, and uv caches
- Optional macOS update check through
softwareupdate -l
Every step self-detects its tool and is skipped when the tool is absent, so the same
command works on any Mac. The script does not install package managers for you, except
that --install-homebrew will bootstrap Homebrew on a fresh Mac when you opt in.
- macOS
- Bash available at
/bin/bash(included with macOS) - Optional tools depending on what you want to update:
brew,npm,mas,git,python3/pip3,pipx,uv,rustup/cargo,mise,asdf, andgcloud
Recommended Homebrew install:
brew tap mzored/update-all-mac https://github.com/mzored/update-all-mac
brew install update-all-macThen run:
update-all-macAlternative install from Git:
git clone https://github.com/mzored/update-all-mac.git
cd update-all-mac
chmod +x update-all-mac.command
./update-all-mac.commandAlternative direct script download:
curl -fsSL -o update-all-mac.command https://raw.githubusercontent.com/mzored/update-all-mac/main/update-all-mac.command
chmod +x update-all-mac.command
./update-all-mac.commandAvoid piping the network directly into a shell. Download the file first, review it, then run it.
Earlier versions used a separate Homebrew tap repository. If you installed with the old tap, move to the single-repository tap:
brew uninstall update-all-mac
brew untap mzored/tap
brew tap mzored/update-all-mac https://github.com/mzored/update-all-mac
brew install update-all-macThe source code and Homebrew formula now live in this repository.
If you use GitHub's Download ZIP button or download update-all-mac.command through a browser, macOS may attach a quarantine marker. Because this project ships a shell script rather than a signed and notarized macOS app, double-clicking the downloaded .command file in Finder can show a Gatekeeper warning.
Use Homebrew, git clone, or the Terminal curl -o flow above when possible. If you intentionally downloaded the script through a browser, review it first and then remove the quarantine marker:
xattr -d com.apple.quarantine update-all-mac.commandAfter that, run it from Terminal:
./update-all-mac.commandRun all default update steps:
update-all-macIf you installed from Git or downloaded the script directly, use:
./update-all-mac.commandShow help:
update-all-mac --helpList step IDs:
update-all-mac --list-stepsReport which tools are detected on this Mac (and their versions):
update-all-mac --doctorPreview what would be updated without changing anything:
update-all-mac --dry-runBootstrap a fresh Mac by installing Homebrew if it is missing:
update-all-mac --install-homebrewShow the complete command output instead of compact progress:
update-all-mac --verbosePurge reinstall/download caches in addition to safe cleanup:
update-all-mac --deep-cleanRun only selected steps:
update-all-mac --only homebrew,masSkip selected steps:
update-all-mac --skip npm,pipCheck macOS updates too:
update-all-mac --macosUseful non-interactive run:
UPDATE_ALL_NO_PAUSE=1 update-all-mac --no-color--only <id1,id2> Run only selected steps
--skip <id1,id2> Skip selected steps
--fail-fast Stop after first failure
--strict Exit non-zero on warnings as well as failures
--exit-zero Always exit 0
--no-color Disable ANSI colors in stdout
--macos Add macOS updates check step (softwareupdate -l)
--greedy-casks Include Homebrew casks marked auto_updates/latest
--force-cask-repair Allow forced cask uninstall+install fallback
--mas-accurate Use slower, more accurate mas outdated detection
--parallel Run npm, pipx, and Mac App Store steps concurrently
--dry-run Show what would be updated without changing anything
--install-homebrew Install Homebrew if it is missing (bootstrap a Mac)
--verbose Stream full command output to the terminal
--deep-clean Purge reinstall caches in the Cleanup step
--log-file <path> Override log file path
--lock-dir <path> Override lock directory path
--list-steps Print available step IDs and exit
--doctor Report detected tools/versions and exit
-h, --help Show help and exit
The --parallel flag runs the independent npm, pipx, and Mac App Store steps at the
same time as the heavier Homebrew step, which can shorten total run time. Homebrew, pip,
and uv always run sequentially because they share state. With --parallel, the npm, pipx,
and Mac App Store blocks are printed together after the sequential steps so the log stays
readable, and --fail-fast only stops the sequential steps.
Step IDs:
homebrew Homebrew
npm npm
mas Mac App Store
ohmyzsh Oh My Zsh
pip pip
pipx pipx
uv uv
rust Rust (rustup + cargo)
mise mise
asdf asdf
gcloud gcloud
cleanup Cleanup
macos macOS (only when --macos is used)
--dry-run runs each step's read-only detection and prints what it would update,
without refreshing the Homebrew catalog or changing anything. --doctor prints the
tools detected on the current Mac and their versions, then exits. --install-homebrew
installs Homebrew non-interactively when it is missing (opt-in bootstrap for a new Mac).
The default Cleanup step uses conservative garbage collectors: brew cleanup --scrub,
npm cache verify, and uv cache prune when those commands are available. It removes
old Homebrew versions, failed downloads, and unreferenced cache entries without removing
project-selected Rust, mise, or asdf versions. --deep-clean additionally purges
Homebrew, npm, pip, pipx, and uv reinstall caches, so future installs may need to download
those files again. --dry-run --deep-clean previews this work without deleting anything.
Cleanup is its own selectable step: --only homebrew updates packages but does not clean
caches; use --only homebrew,cleanup when both operations are wanted.
If Homebrew finds a cask directory ending in .upgrading, the script reports the
interrupted upgrade and includes it in the same cask batch as ordinary app updates. This
normally limits Homebrew to one password dialog because Homebrew deliberately resets its
sudo timestamp for each separate process. A separate brew reinstall --cask runs only
if the combined batch cannot recover one or more apps; all such apps are retried together
to limit the fallback to one additional Homebrew request. The terminal and password dialog
identify that fallback before it starts. Homebrew confirmation prompts are disabled for
these unattended operations. After a successful reinstall the script removes that exact
stale .upgrading directory. Forced uninstall remains disabled unless
--force-cask-repair is explicitly used.
Homebrew formulae and casks pinned with brew pin are intentionally skipped. They are
reported in the run log but do not make the Homebrew step fail; all unpinned outdated
packages continue to update normally.
Every CLI option has an environment-friendly path for automation:
UPDATE_ALL_ONLY=homebrew,mas
UPDATE_ALL_SKIP=npm,pip
UPDATE_ALL_EXIT_ZERO=1
UPDATE_ALL_STRICT=1
UPDATE_ALL_FAIL_FAST=1
UPDATE_ALL_NO_COLOR=1
UPDATE_ALL_MACOS=1
UPDATE_ALL_HOMEBREW_GREEDY_CASKS=1
UPDATE_ALL_FORCE_CASK_REPAIR=1
UPDATE_ALL_PIPX_INCLUDE_INJECTED=0
UPDATE_ALL_MAS_ACCURATE=1
UPDATE_ALL_PARALLEL=1
UPDATE_ALL_DRY_RUN=1
UPDATE_ALL_INSTALL_HOMEBREW=1
UPDATE_ALL_VERBOSE=1
UPDATE_ALL_DEEP_CLEAN=1
UPDATE_ALL_LOG_FILE=/path/to/update-all-mac.log
UPDATE_ALL_LOG_MAX_BYTES=1048576
UPDATE_ALL_NET_TIMEOUT=600
UPDATE_ALL_LOCK_DIR=/tmp/update-all-mac.lock
UPDATE_ALL_HEARTBEAT_SECONDS=30
UPDATE_ALL_TEMP_MAX_AGE_MINUTES=1440
UPDATE_ALL_NO_PAUSE=1
UPDATE_ALL_NET_TIMEOUT caps how long the npm step may run (in seconds) when gtimeout
or timeout is available, so a stuck download cannot hang the whole run.
By default, logs are written to:
~/Library/Logs/update-all-mac.log
Each step's full command output is written to the log in real time, so an interrupted
upgrade can be diagnosed from its final completed line. The terminal shows compact
progress and a periodic heartbeat by default; use --verbose for the full stream. When
the log grows past UPDATE_ALL_LOG_MAX_BYTES (1 MiB by default), it is rotated once to
update-all-mac.log.1 before the next run starts.
Current-run temporary files live in one private directory and are removed through a
single exit/signal cleanup path. On the next non-dry run, updater-owned temporary files
older than UPDATE_ALL_TEMP_MAX_AGE_MINUTES are removed by exact filename patterns.
A lock directory prevents concurrent runs:
/tmp/update-all-mac.lock
If a previous run crashed, the script detects stale locks and removes them when safe.
- Review scripts before running them from the internet.
- Some updates can close, replace, or relaunch apps. The script warns when Homebrew cask apps appear to be running.
- Interactive macOS runs configure a temporary
SUDO_ASKPASShelper. If Homebrew needs administrator access, a native password dialog appears and the password is passed directly tosudo; it is never stored by the updater. ExistingSUDO_ASKPASSconfiguration is preserved. - macOS can separately show an App Management notification when Terminal or another host app replaces software in
/Applications. That notice is not another password request; macOS names the host process that launched the updater. --force-cask-repaircan uninstall and reinstall a cask as a recovery fallback. Use it only when you understand the risk.- The macOS step checks for system updates but does not install them.
- A signed and notarized
.appor.pkgwould be required for the cleanest double-click Finder experience. This repository currently distributes a CLI script.
If double-clicking does nothing, run from Terminal to see output:
./update-all-mac.command --no-colorIf macOS blocks a browser-downloaded script, review the file and remove quarantine:
xattr -d com.apple.quarantine update-all-mac.commandIf mas cannot see updates, make sure App Store apps are indexed by Spotlight and that you are signed in to the App Store.
MIT. See LICENSE.