update is an agent-first macOS CLI for discovering, previewing, and applying app updates.
It scans installed .app bundles, tracks them locally, checks multiple update providers, emits machine-readable output by default in non-interactive contexts, and makes mutating actions previewable with --dry-run.
- scans installed macOS apps from one or more directories
- checks for updates across:
- Homebrew casks
- Mac App Store
- Sparkle feeds
- GitHub releases
- Electron updater metadata
- optional curated metadata
- previews update and adoption plans before execution
- supports ignore rules and version skips
- exposes config and command metadata through CLI schema commands
- emits
json,ndjson,plain, or human-readable output
- macOS 14+
- Swift 6 toolchain
- Xcode Command Line Tools or Xcode
Optional tools unlock specific providers/executors:
brewfor Homebrew-backed checks, updates, and adoptionmasfor Mac App Store-backed checks and updates
brew tap sammyjoyce/update
brew install updatecurl -fsSL https://raw.githubusercontent.com/sammyjoyce/update/main/scripts/install.sh | bashInstall a specific version:
curl -fsSL https://raw.githubusercontent.com/sammyjoyce/update/main/scripts/install.sh | bash -s -- --version v1.0.0Install to a custom directory:
curl -fsSL https://raw.githubusercontent.com/sammyjoyce/update/main/scripts/install.sh | bash -s -- --bin-dir /usr/local/bingit clone git@github.com:sammyjoyce/update.git
cd update
swift build -c releaseThe compiled binary will be available at:
.build/release/updateupdate scan --format jsonupdate apps list --format jsonupdate apps check 'name:Google Chrome' --provider brew --format jsonupdate apps update 'name:Google Chrome' --provider brew --dry-run --format jsonupdate config show --scope effective --format json
update schema commands --format json
update schema command apps.check --format jsonupdate apps list [selectors...]
update apps get <selector>
update apps check [selectors...]
update apps sources <selector>
update apps update [selectors...] [--all]
update apps adopt [selectors...] [--all]update ignores list
update ignores add [selectors...]
update ignores remove [selectors...]
update skips list
update skips add <selector>
update skips remove [selectors...]update scan run
update doctor run
update config show
update config get <key>
update config set <key> <value>
update config unset <key>
update config reset [key]
update schema commands
update schema command <group.command>
update schema config
update schema errors
update schema examples <group.command>
update completions <shell>The canonical interface is grouped (update apps check, update ignores add, and so on), but the CLI also ships compatibility aliases for convenience:
update list
update check
update sources
update update
update adopt
update ignore
update unignore
update skip
update unskip
update scan
update doctorFor automation and generated scripts, prefer the grouped form.
The CLI supports typed selectors:
id:app_...
bundle:com.google.Chrome
path:/Applications/Google Chrome.app
name:Google Chrome
For durable automation, prefer id: after the first lookup.
update is designed for both humans and automation.
- TTY stdout defaults to human-readable output
- non-TTY single-item output defaults to JSON
- non-TTY collection output defaults to NDJSON
You can force a format explicitly:
update apps list --format json
update apps list --format ndjson
update apps list --format plainField masks are supported on read commands:
update apps list --fields app_id,name,installed_version,update_state --format jsonThe CLI is intentionally conservative.
- use
--dry-runbefore mutating commands - live app updates and adoption require confirmation unless you pass
--yes - non-interactive mutation without confirmation fails instead of guessing
- app bundle replacement refuses privileged paths unless
--allow-sudois set - remote metadata is treated as untrusted text
This repo ships two automation paths:
.github/workflows/ci.yml- builds and tests on pushes and pull requests
.github/workflows/release.yml- builds tagged macOS binaries
- publishes GitHub Release assets
- generates
checksums.txt - updates the Homebrew tap when
HOMEBREW_TAP_TOKENis configured
Release artifacts are packaged as:
update-macos-arm64.tar.gzupdate-macos-x86_64.tar.gzchecksums.txt
update apps sources 'name:Google Chrome' --format jsonupdate ignores add 'name:Google Chrome' --scope updates --reason 'managed elsewhere' --format jsonupdate skips add 'name:Google Chrome' --version 146.0.7680.165 --format jsonupdate completions zsh > _update
update completions bash > update.bash
update completions fish > update.fishswift buildswift testswift run update --help
swift run update doctor run --format json
swift run update apps check 'name:Google Chrome' --provider brew --format json
swift run update apps update 'name:Google Chrome' --provider brew --dry-run --format json.github/workflows/
scripts/
Package.swift
Sources/
update/
UpdateCore/
Tests/
UpdateCoreTests/
Sources/update/contains the CLI entrypoints and command wiringSources/UpdateCore/contains the models, services, coordinators, and provider logicscripts/contains packaging, installer, and tap update scriptsTests/UpdateCoreTests/contains core regression tests
Issues and pull requests are welcome.
If you change the CLI surface, update examples and schema-related behavior together so the human-facing docs and machine-facing contract stay aligned.
- The spec source file under
docs/specs/is intentionally kept out of git. - No license file has been added yet.