Release v1.21.0: Add macos-cleaner skill
- Add macos-cleaner v1.0.0 - Intelligent macOS disk space recovery - Safety-first philosophy with risk categorization (Safe/Caution/Keep) - Smart analysis: caches, app remnants, large files, dev environments - Interactive cleanup with explicit user confirmation - Bundled scripts: analyze_caches, analyze_dev_env, analyze_large_files, find_app_remnants, safe_delete, cleanup_report - Comprehensive references: cleanup_targets, mole_integration, safety_rules - Update marketplace to v1.21.0 - Update all documentation (README.md, README.zh-CN.md, CHANGELOG.md, CLAUDE.md) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
474
macos-cleaner/references/safety_rules.md
Normal file
474
macos-cleaner/references/safety_rules.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# Safety Rules for macOS Cleanup
|
||||
|
||||
Critical safety guidelines to prevent data loss and system damage.
|
||||
|
||||
## Golden Rules
|
||||
|
||||
### Rule 1: Never Delete Without Confirmation
|
||||
|
||||
**ALWAYS** ask user before deleting ANY file or directory.
|
||||
|
||||
**Bad**:
|
||||
```python
|
||||
shutil.rmtree(cache_dir) # Immediately deletes
|
||||
```
|
||||
|
||||
**Good**:
|
||||
```python
|
||||
if confirm_delete(cache_dir, size, description):
|
||||
shutil.rmtree(cache_dir)
|
||||
else:
|
||||
print("Skipped")
|
||||
```
|
||||
|
||||
### Rule 2: Explain Before Deleting
|
||||
|
||||
Users should understand:
|
||||
- **What** is being deleted
|
||||
- **Why** it's safe (or not safe)
|
||||
- **Impact** of deletion
|
||||
- **Recoverability** (can it be restored?)
|
||||
|
||||
### Rule 3: When in Doubt, Don't Delete
|
||||
|
||||
If uncertain about safety: **DON'T DELETE**.
|
||||
|
||||
Ask user to verify instead.
|
||||
|
||||
### Rule 4: Suggest Backups for Large Deletions
|
||||
|
||||
Before deleting >10 GB, recommend Time Machine backup.
|
||||
|
||||
### Rule 5: Use Trash When Possible
|
||||
|
||||
Prefer moving to Trash over permanent deletion:
|
||||
|
||||
```bash
|
||||
# Recoverable
|
||||
osascript -e 'tell app "Finder" to move POSIX file "/path/to/file" to trash'
|
||||
|
||||
# Permanent (use only when confirmed safe)
|
||||
rm -rf /path/to/file
|
||||
```
|
||||
|
||||
## Never Delete These
|
||||
|
||||
### System Directories
|
||||
|
||||
| Path | Why | Impact if Deleted |
|
||||
|------|-----|-------------------|
|
||||
| `/System` | macOS core | System unbootable |
|
||||
| `/Library/Apple` | Apple frameworks | Apps won't launch |
|
||||
| `/private/etc` | System config | System unstable |
|
||||
| `/private/var/db` | System databases | System unstable |
|
||||
| `/usr` | Unix utilities | Commands won't work |
|
||||
| `/bin`, `/sbin` | System binaries | System unusable |
|
||||
|
||||
### User Data
|
||||
|
||||
| Path | Why | Impact if Deleted |
|
||||
|------|-----|-------------------|
|
||||
| `~/Documents` | User documents | Data loss |
|
||||
| `~/Desktop` | User files | Data loss |
|
||||
| `~/Pictures` | Photos | Data loss |
|
||||
| `~/Movies` | Videos | Data loss |
|
||||
| `~/Music` | Music library | Data loss |
|
||||
| `~/Downloads` | May contain important files | Potential data loss |
|
||||
|
||||
### Security & Credentials
|
||||
|
||||
| Path | Why | Impact if Deleted |
|
||||
|------|-----|-------------------|
|
||||
| `~/.ssh` | SSH keys | Cannot access servers |
|
||||
| `~/Library/Keychains` | Passwords, certificates | Cannot access accounts/services |
|
||||
| Any file with "credential", "password", "key" in name | Security data | Cannot authenticate |
|
||||
|
||||
### Active Databases
|
||||
|
||||
| Pattern | Why | Impact if Deleted |
|
||||
|---------|-----|-------------------|
|
||||
| `*.db`, `*.sqlite`, `*.sqlite3` | Application databases | App data loss |
|
||||
| Any database file for running app | Active data | Data corruption |
|
||||
|
||||
### Running Applications
|
||||
|
||||
| Path | Why | Impact if Deleted |
|
||||
|------|-----|-------------------|
|
||||
| `/Applications` | Installed apps | Apps won't launch |
|
||||
| `~/Applications` | User-installed apps | Apps won't launch |
|
||||
| Files in use (check with `lsof`) | Currently open | App crash, data corruption |
|
||||
|
||||
## Require Extra Confirmation
|
||||
|
||||
### Large Deletions
|
||||
|
||||
**Threshold**: >10 GB
|
||||
|
||||
**Action**: Warn user and suggest Time Machine backup
|
||||
|
||||
**Example**:
|
||||
```
|
||||
⚠️ This operation will delete 45 GB of data.
|
||||
|
||||
💡 Recommendation:
|
||||
Create a Time Machine backup first.
|
||||
|
||||
Check last backup:
|
||||
tmutil latestbackup
|
||||
|
||||
Create backup now:
|
||||
tmutil startbackup
|
||||
|
||||
Proceed without backup? [y/N]:
|
||||
```
|
||||
|
||||
### System-Wide Caches
|
||||
|
||||
**Paths**: `/Library/Caches`, `/var/log`
|
||||
|
||||
**Action**: Require manual sudo command (don't execute directly)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
⚠️ This operation requires administrator privileges.
|
||||
|
||||
Please run this command manually:
|
||||
sudo rm -rf /Library/Caches/*
|
||||
|
||||
⚠️ You will be asked for your password.
|
||||
```
|
||||
|
||||
**Reason**:
|
||||
- Requires elevated privileges
|
||||
- User should be aware of system-wide impact
|
||||
- Audit trail (user types password)
|
||||
|
||||
### Docker Volumes
|
||||
|
||||
**Action**: Always list volumes before cleanup
|
||||
|
||||
**Example**:
|
||||
```
|
||||
⚠️ Docker cleanup may remove important data.
|
||||
|
||||
Current volumes:
|
||||
postgres_data (1.2 GB) - May contain database
|
||||
redis_data (500 MB) - May contain cache
|
||||
app_uploads (3 GB) - May contain user files
|
||||
|
||||
Review each volume:
|
||||
docker volume inspect <volume_name>
|
||||
|
||||
Proceed with cleanup? [y/N]:
|
||||
```
|
||||
|
||||
### Application Preferences
|
||||
|
||||
**Path**: `~/Library/Preferences/*.plist`
|
||||
|
||||
**Action**: Warn that app will reset to defaults
|
||||
|
||||
**Example**:
|
||||
```
|
||||
⚠️ Deleting preferences will reset the app to defaults.
|
||||
|
||||
Impact:
|
||||
- All settings will be lost
|
||||
- Custom configurations will be reset
|
||||
- May need to re-enter license keys
|
||||
|
||||
Only delete if:
|
||||
- App is misbehaving (troubleshooting)
|
||||
- App is confirmed uninstalled
|
||||
|
||||
Proceed? [y/N]:
|
||||
```
|
||||
|
||||
## Safety Checks Before Deletion
|
||||
|
||||
### Check 1: Path Exists
|
||||
|
||||
```python
|
||||
if not os.path.exists(path):
|
||||
print(f"❌ Path does not exist: {path}")
|
||||
return False
|
||||
```
|
||||
|
||||
### Check 2: Not a System Path
|
||||
|
||||
```python
|
||||
system_paths = [
|
||||
'/System', '/Library/Apple', '/private/etc',
|
||||
'/usr', '/bin', '/sbin', '/private/var/db'
|
||||
]
|
||||
|
||||
for sys_path in system_paths:
|
||||
if path.startswith(sys_path):
|
||||
print(f"❌ Cannot delete system path: {path}")
|
||||
return False
|
||||
```
|
||||
|
||||
### Check 3: Not User Data
|
||||
|
||||
```python
|
||||
user_data_paths = [
|
||||
'~/Documents', '~/Desktop', '~/Pictures',
|
||||
'~/Movies', '~/Music', '~/.ssh'
|
||||
]
|
||||
|
||||
expanded_path = os.path.expanduser(path)
|
||||
for data_path in user_data_paths:
|
||||
if expanded_path.startswith(os.path.expanduser(data_path)):
|
||||
print(f"⚠️ This is a user data directory: {path}")
|
||||
print(" Are you ABSOLUTELY sure? [type 'DELETE' to confirm]:")
|
||||
response = input().strip()
|
||||
if response != 'DELETE':
|
||||
return False
|
||||
```
|
||||
|
||||
### Check 4: Not in Use
|
||||
|
||||
```python
|
||||
def is_in_use(path):
|
||||
"""Check if file/directory is in use."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['lsof', path],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
# If lsof finds processes using the file, returncode is 0
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False # Assume not in use if check fails
|
||||
|
||||
if is_in_use(path):
|
||||
print(f"⚠️ Warning: {path} is currently in use")
|
||||
print(" Close the application first, then try again.")
|
||||
return False
|
||||
```
|
||||
|
||||
### Check 5: Permissions
|
||||
|
||||
```python
|
||||
def can_delete(path):
|
||||
"""Check if we have permission to delete."""
|
||||
try:
|
||||
# Check parent directory write permission
|
||||
parent = os.path.dirname(path)
|
||||
return os.access(parent, os.W_OK)
|
||||
except:
|
||||
return False
|
||||
|
||||
if not can_delete(path):
|
||||
print(f"❌ No permission to delete: {path}")
|
||||
print(" You may need sudo, but be careful!")
|
||||
return False
|
||||
```
|
||||
|
||||
## Safe Deletion Workflow
|
||||
|
||||
```python
|
||||
def safe_delete(path, size, description):
|
||||
"""
|
||||
Safe deletion workflow with all checks.
|
||||
|
||||
Args:
|
||||
path: Path to delete
|
||||
size: Size in bytes
|
||||
description: Human-readable description
|
||||
|
||||
Returns:
|
||||
(success, message)
|
||||
"""
|
||||
# Safety checks
|
||||
if not os.path.exists(path):
|
||||
return (False, "Path does not exist")
|
||||
|
||||
if is_system_path(path):
|
||||
return (False, "Cannot delete system path")
|
||||
|
||||
if is_user_data(path):
|
||||
if not extra_confirm(path):
|
||||
return (False, "User cancelled")
|
||||
|
||||
if is_in_use(path):
|
||||
return (False, "Path is in use")
|
||||
|
||||
if not can_delete(path):
|
||||
return (False, "No permission")
|
||||
|
||||
# Backup warning for large deletions
|
||||
if size > 10 * 1024 * 1024 * 1024: # 10 GB
|
||||
if not confirm_large_deletion(size):
|
||||
return (False, "User cancelled")
|
||||
|
||||
# Final confirmation
|
||||
if not confirm_delete(path, size, description):
|
||||
return (False, "User cancelled")
|
||||
|
||||
# Execute deletion
|
||||
try:
|
||||
if os.path.isfile(path):
|
||||
os.unlink(path)
|
||||
else:
|
||||
shutil.rmtree(path)
|
||||
return (True, f"Deleted successfully ({format_size(size)} freed)")
|
||||
except Exception as e:
|
||||
return (False, f"Deletion failed: {str(e)}")
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Permission Denied
|
||||
|
||||
```python
|
||||
except PermissionError:
|
||||
print(f"❌ Permission denied: {path}")
|
||||
print(" Try running with sudo (use caution!)")
|
||||
```
|
||||
|
||||
### Operation Not Permitted (SIP)
|
||||
|
||||
```python
|
||||
# macOS System Integrity Protection blocks some deletions
|
||||
except OSError as e:
|
||||
if e.errno == 1: # Operation not permitted
|
||||
print(f"❌ System Integrity Protection prevents deletion: {path}")
|
||||
print(" This is a protected system file.")
|
||||
print(" Do NOT attempt to bypass SIP unless you know what you're doing.")
|
||||
```
|
||||
|
||||
### Path Too Long
|
||||
|
||||
```python
|
||||
except OSError as e:
|
||||
if e.errno == 63: # File name too long
|
||||
print(f"⚠️ Path too long, trying alternative method...")
|
||||
# Try using find + rm
|
||||
```
|
||||
|
||||
## Recovery Options
|
||||
|
||||
### If User Accidentally Confirmed
|
||||
|
||||
**Immediate action**: Check Trash first
|
||||
|
||||
```bash
|
||||
# Files may be in Trash
|
||||
ls -lh ~/.Trash
|
||||
```
|
||||
|
||||
**Next**: Time Machine
|
||||
|
||||
```bash
|
||||
# Open Time Machine to date before deletion
|
||||
tmutil browse
|
||||
```
|
||||
|
||||
**Last resort**: File recovery tools
|
||||
|
||||
- Disk Drill (commercial)
|
||||
- PhotoRec (free)
|
||||
- TestDisk (free)
|
||||
|
||||
**Note**: Success rate depends on:
|
||||
- How recently deleted
|
||||
- How much disk activity since deletion
|
||||
- Whether SSD (TRIM) or HDD
|
||||
|
||||
### Preventing Accidents
|
||||
|
||||
1. **Use Trash instead of rm** when possible
|
||||
2. **Require Time Machine backup** for >10 GB deletions
|
||||
3. **Test on small items first** before batch operations
|
||||
4. **Show dry-run results** before actual deletion
|
||||
|
||||
## Red Flags to Watch For
|
||||
|
||||
### User Requests
|
||||
|
||||
If user asks to:
|
||||
- "Delete everything in ~/Library"
|
||||
- "Clear all caches including system"
|
||||
- "Delete all .log files on the entire system"
|
||||
- "Remove all databases"
|
||||
|
||||
**Response**:
|
||||
```
|
||||
⚠️ This request is too broad and risky.
|
||||
|
||||
Let me help you with a safer approach:
|
||||
1. Run analysis to identify specific targets
|
||||
2. Review each category
|
||||
3. Delete selectively with confirmation
|
||||
|
||||
This prevents accidental data loss.
|
||||
```
|
||||
|
||||
### Script Behavior
|
||||
|
||||
If script is about to:
|
||||
- Delete >100 GB at once
|
||||
- Delete entire directory trees without listing contents
|
||||
- Run `rm -rf /` or similar dangerous commands
|
||||
- Delete from system paths
|
||||
|
||||
**Action**: STOP and ask for confirmation
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
### Before Packaging
|
||||
|
||||
Test safety checks:
|
||||
|
||||
1. ✅ Attempt to delete system path → Should reject
|
||||
2. ✅ Attempt to delete user data → Should require extra confirmation
|
||||
3. ✅ Attempt to delete in-use file → Should warn
|
||||
4. ✅ Attempt to delete without permission → Should fail gracefully
|
||||
5. ✅ Large deletion → Should suggest backup
|
||||
|
||||
### In Production
|
||||
|
||||
Always:
|
||||
- Start with smallest items
|
||||
- Confirm results after each deletion
|
||||
- Monitor disk space before/after
|
||||
- Ask user to verify important apps still work
|
||||
|
||||
## Summary
|
||||
|
||||
### Conservative Approach
|
||||
|
||||
When implementing cleanup:
|
||||
|
||||
1. **Assume danger** until proven safe
|
||||
2. **Explain everything** to user
|
||||
3. **Confirm each step**
|
||||
4. **Suggest backups** for large operations
|
||||
5. **Use Trash** when possible
|
||||
6. **Test thoroughly** before packaging
|
||||
|
||||
### Remember
|
||||
|
||||
> "It's better to leave 1 GB of unnecessary files than to delete 1 MB of important data."
|
||||
|
||||
User trust is fragile. One bad deletion loses it forever.
|
||||
|
||||
### Final Checklist
|
||||
|
||||
Before any deletion:
|
||||
|
||||
- [ ] Path is verified to exist
|
||||
- [ ] Path is not a system path
|
||||
- [ ] Path is not user data (or extra confirmed)
|
||||
- [ ] Path is not in use
|
||||
- [ ] User has been informed of impact
|
||||
- [ ] User has explicitly confirmed
|
||||
- [ ] Backup suggested for large deletions
|
||||
- [ ] Error handling in place
|
||||
- [ ] Recovery options documented
|
||||
|
||||
Only then: proceed with deletion.
|
||||
Reference in New Issue
Block a user