An interactive Python script that safely manages upgrades for Homebrew, Conda, Python, and npm with logging and rollback capability.
Script Name: safe_update.py - Emphasizing safe, controlled upgrades for your development environment.
Interactive menu with rich UI showing upgrade options and system status
- β Safe Upgrades: Automatically applies patch updates, prompts for minor/major versions
- πΈ Snapshots: Saves pre-upgrade state to
~/upgrade-logs/for rollback - π Detailed Logging: Every command and action is logged with timestamps
- π¨ Rich UI: Beautiful tables and panels (uses
richlibrary if available) - π― Selective Upgrades: Choose which package manager to upgrade
- π§Ή Automatic Cleanup: Cleans up caches after successful upgrades
| Upgrade Type | Behavior | Example |
|---|---|---|
| Patch (x.x.Z) | β Auto-upgrade | 3.12.11 β 3.12.12 |
| Minor (x.Y.x) | npm 10.x β 11.x | |
| Major (X.x.x) | π Requires manual review | Python 3.12 β 3.13 |
The script uses Python's standard library, but for the best experience, install rich:
pip install richpython safe_update.py
# or
./safe_update.py- Upgrade Homebrew - Updates Homebrew and safe packages
- Upgrade Conda - Updates Conda package manager
- Upgrade Python - Updates Python via Conda
- Upgrade npm - Updates global npm packages and npm itself
- Check All - Shows current versions without upgrading
- Upgrade All - Runs all upgrades in sequence
- Exit - Quit the program
- Homebrew formulae and casks
- Safe packages upgraded automatically
- Major/minor version upgrades require confirmation
- Runs
brew cleanupafter upgrades
- Conda package manager itself
- Runs
conda clean --allafter upgrades
- Automatically detects Python source (Conda, Homebrew, or System)
- Conda Python: Upgraded via
conda update python - Homebrew Python: Upgraded via
brew upgrade python@3 - System Python: Not upgraded (macOS system Python should not be modified)
- Other sources (pyenv, asdf, etc.): Not supported
- Major version changes require confirmation
- Displays Python path and source for transparency
- Global npm packages first
- npm itself upgraded last (as recommended)
- Runs
npm cache verifyafter upgrades
All logs and snapshots are saved to ~/upgrade-logs/:
~/upgrade-logs/
βββ upgrade_20250605_143022.log # Detailed execution log
βββ snapshot_20250605_143022.json # Pre-upgrade system state
βββ upgrade_20250605_151533.log
βββ snapshot_20250605_151533.json
{
"homebrew": {
"version": "4.2.10",
"outdated_count": 2,
"outdated_packages": [...]
},
"conda": {
"current": "25.9.1",
"latest": "25.9.1"
},
"python": {
"current": "3.12.12",
"latest": "3.12.12"
},
"npm": {
"current": "11.6.2",
"latest": "11.6.2",
"outdated_count": 0,
"outdated_packages": []
}
}If you need to rollback to a previous version:
- Check the snapshot file:
cat ~/upgrade-logs/snapshot_<timestamp>.json - Manually reinstall the previous version:
# Homebrew
brew install <package>@<version>
# Conda
conda install conda=<version>
# Python
conda install python=<version>
# npm
npm install -g npm@<version>
npm install -g <package>@<version>βββββββββββββββββββββββββββββββββββββββββββββββ
β Welcome β
βββββββββββββββββββββββββββββββββββββββββββββββ
System Upgrade Manager
Log file: ~/upgrade-logs/upgrade_20250605_143022.log
Snapshot: ~/upgrade-logs/snapshot_20250605_143022.json
This tool will help you safely upgrade your system packages.
βββββββββββββββββββββββββββββββββββββββββββββββ
β Main Menu β
βββββββββββββββββββββββββββββββββββββββββββββββ
System Upgrade Manager
1. Upgrade Homebrew
2. Upgrade Conda
3. Upgrade Python
4. Upgrade npm
5. Check All (no upgrades)
6. Upgrade All
0. Exit
Select option [0/1/2/3/4/5/6]: 5
Checking Homebrew...
β All Homebrew packages up to date
Checking Conda...
β Conda 25.9.1 (up to date)
Checking Python...
β Python 3.12.12 (up to date)
Checking npm...
npm: 11.6.2 β Latest: 11.6.2
β All global npm packages up to date
β Snapshot saved to: ~/upgrade-logs/snapshot_20250605_143022.json
- Run option 5 (Check All) first to see what needs updating
- Use option 6 (Upgrade All) for routine maintenance
- Always review logs in
~/upgrade-logs/after major upgrades - Keep snapshots for at least 30 days for rollback capability
- Test your development environment after major upgrades
Install with: pip install rich
The script will work without it but with plain text output.
Make sure you're running safe_update.py (not the old system_upgrade.py name).
If Conda dependencies conflict, try:
conda update -n base -c defaults conda --force-reinstallFix with: sudo chown -R $(whoami) $(brew --prefix)/*
Fix with: sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
- Python 3.7+
- macOS (tested on macOS 15.1+)
- zsh shell
- Homebrew, Conda, and/or npm installed
- Optional:
richlibrary for enhanced UI (pip install -r requirements.txt)
- Package Name Validation: All package names validated before use in shell commands
- Controlled Execution: Uses shell=True only for pipes/redirects with validated inputs
- Input Sanitization: Comprehensive validation using regex patterns
- System Python Protection: Never modifies macOS system Python
- Backup First: Always creates snapshots before making changes
- Comprehensive Logging: All actions logged for audit trail
- Error Handling: Graceful failure handling with proper error messages
- Pinned Requirements:
requirements.txtwith version constraints - Minimal Dependencies: Only
richlibrary for UI (optional) - No Untrusted Input: All commands are hardcoded or validated
Free to use and modify.
