Command‑line tool for managing macOS app uninstallations.
- Discover and remove app files (supports match modes)
- Run dry‑runs safely
- Generate uninstall definition manifests
- List and sync definition catalog
- Generate file removal reports
This is a work in progress, current status is beta.
Download and install the latest PKG under releases.
AppPruner should be run as sudo.
- Show help (top‑level):
AppPruner --help- Uninstall by definition name:
AppPruner uninstall --definition-name "companyportal"- Uninstall by manifest file path:
AppPruner uninstall --definition-path /path/to/definition.json- Dry run, substring matching, silent:
AppPruner uninstall --definition-name "companyportal" --match-mode substring --dry-run --silent- List available definitions:
AppPruner list-app-definitions- Search available definitions:
AppPruner search-app-definitions --name "ms"- Sync local catalog with remote:
AppPruner sync-definitions- Generate a new definition manifest:
AppPruner generate-app-definition \
--definition-name "companyportal" \
--app-name "Company Portal" \
--bundle-id "com.microsoft.CompanyPortalMac" \
--alternative-names "Company,MS Company Portal" \
--additional-paths "/Library/Application Support/Microsoft/Intune,~/Library/Preferences/com.microsoft.CompanyPortalMac.plist" \
--match-mode "substring" \
--forget-pkg \
--unload-launch-daemons \
--output-path ./defs- Generate a report of what would be uninstalled:
AppPruner generate-file-report --definition-name "companyportal" --output-path ./AppPruner uses subcommands. The default subcommand is uninstall. If you run AppPruner with no required arguments, it prints help by default.
-
uninstall
- --definition-name (optional if --definition-path is set)
- --definition-path (optional if --definition-name is set)
- --match-mode <exact|prefix|substring|all> (default: all)
- --dry-run
- --remove-user-hive
- --version (select a specific definition/app version if supported)
- --silent
- --wait-time (default: 5)
- --brew-tidy (run
brew cleanuppost uninstall if applicable) - --pre-flight-command (command to run before uninstall starts)
- --post-flight-command (command to run after uninstall completes)
-
list-app-definitions
- Lists all available definitions in the local catalog.
-
generate-app-definition
- --name (definition identifier to create)
- --app-name
- --version (definition version; default: 1)
- --alternative-names <a,b,c>
- --bundle-id
- --search-file-paths <a,b,c> (override default search paths)
- --additional-paths <a,b,c>
- --forget-pkg
- --unload-launch-daemons
- --output-path (default: current directory)
- --brew-name (Homebrew name to look up for the app. If not set app name will be used.)
-
sync-definitions
- Syncs the local catalog with the remote source.
-
generate-file-report
- --definition-name (optional if --definition-path is not set)
- --definition-path (optional if --definition-name is not set)
- --version (select a specific definition version if multiple are available. default: latest)
- --output-path (default: current directory)
Global options
- A shared GlobalOptions group is used; if available, use --debug for verbose logging.
Generated manifests describe how to locate and remove an app. A typical shape:
{
"name": "someapp",
"version": 1,
"updated_at": "2025-10-16T12:34:56Z",
"uninstall": {
"appName": "App",
"bundleId": "com.vendor.App",
"alternativeNames": ["Vendor App", "App by Vendor"],
"searchFilePaths": ["/Applications", "~/Applications"],
"additionalPaths": ["/Library/Application Support/Vendor/App"],
"forgetPkg": true,
"unloadLaunchDaemons": false
}
}- Default subcommand: uninstall
- No required args → prints help and exits successfully.
- Dry runs perform discovery and logging without deleting files.
- Match modes control file discovery breadth: exact, prefix, substring, all.
Apache 2.0