updater is a macOS CLI/TUI that discovers installed apps, checks for updates across multiple ecosystems, and applies the right update action per app.
- macOS (the one truly non-negotiable requirement)
- Homebrew (recommended)
masfor Mac App Store checks (installed automatically with the Homebrew cask)
Install from Homebrew tap:
brew install --cask lu-zhengda/tap/updater
updater --versionThis is the easiest path and includes mas automatically as a cask dependency.
Upgrade later:
brew upgrade --cask lu-zhengda/tap/updater# 1) Validate environment and dependencies
updater doctor
# 2) Discover installed apps and detected sources
updater scan
# 3) Check available updates
updater check
# 4) Preview update actions without changing anything
updater update --all --dry-run
# 5) Apply updates
updater update --allLaunch the interactive TUI:
updater| Source | How updates are checked | Update behavior |
|---|---|---|
| Sparkle | Appcast feed from app metadata | Direct DMG/ZIP/PKG install when possible, otherwise opens download URL |
| Homebrew cask | brew outdated --cask --greedy --json |
brew upgrade --cask <token> |
| Homebrew formula | brew outdated --formula --json |
brew upgrade <formula> |
| Mac App Store | mas outdated |
mas upgrade <id> or opens App Store updates |
| GitHub Releases | GitHub Releases API | Direct install when possible, otherwise opens release asset URL |
| Electron generic | latest-mac.yml from update server |
Direct install when possible, otherwise opens app |
| Brew-info fallback | brew info --cask --json=v2 |
If brew-installed: brew upgrade --cask; otherwise opens app |
| macOS system | softwareupdate -l |
Opens Software Update settings |
Also detected (for visibility): Setapp, JetBrains Toolbox, and Adobe apps.
Core update workflow:
updater scan
updater check
updater check --share
updater update "1Password"
updater update --all
updater update --all --auto
updater update --all --dry-runScripting/JSON:
updater scan --json
updater check --json
updater outdated --json
updater history --json
updater doctor --json
updater update --all --dry-run --jsonAgent mode:
- All commands support
--json. - When
updaterdetects it is running inside Codex or Claude Code, JSON output is enabled automatically. - Override behavior with
UPDATER_AGENT_MODE=0(force off) orUPDATER_AGENT_MODE=1(force on). updater update --jsonis supported for dry-run planning (--dry-run).
Management:
updater pin "Google Chrome"
updater unpin "Google Chrome"
updater policy "Google Chrome" manual
updater install firefox
updater rollback "Firefox"
updater cleanup --days 90
updater cleanup --days 90 --deleteAutomation:
updater schedule --interval 24
updater schedule --removeConfig file path:
~/.config/updater/config.yaml
Example:
ignored_apps:
- com.apple.Safari
pinned_apps:
- com.google.Chrome
# auto | manual | notify-only
policies:
com.microsoft.VSCode: auto
com.google.Chrome: manual
github_mappings:
com.microsoft.VSCode: "microsoft/vscode"
cask_mappings:
com.readdle.PDFExpert-Mac: "pdf-expert"
github_token: "ghp_..."
max_concurrent: 10
max_backups: 1
interactive_notifications: trueNotes:
GITHUB_TOKENenvironment variable overridesgithub_token.cask_mappingsare only needed when automatic cask token detection is wrong.- Use
updater config exportandupdater config import <file>to move config between machines.
--dry-runprints the exact planned actions without making changes.- Backups are created before install-based updates when app paths are available.
- Failed direct installs attempt automatic rollback from backup.
- Pinned apps are skipped in
update --all. policylets you force per-app behavior (auto,manual,notify-only).
Requires Go 1.25.7+.
git clone https://github.com/lu-zhengda/updater.git
cd updater
make install PREFIX=~/.localIf needed, add to PATH:
export PATH="$HOME/.local/bin:$PATH"If building from source and you want Mac App Store checks, install mas:
brew install masmake build
make test
make cleanMIT