A Python CLI tool for automatically cleaning up old macOS screenshots. Keep your Desktop tidy by automatically deleting screenshots older than a specified number of days.
- 🍎 macOS Native: Designed specifically for macOS screenshot patterns
- 🔍 Smart Detection: Automatically finds screenshots by filename pattern
- 🛡️ Safe Operation: Preview mode and confirmation prompts prevent accidental deletion
- 📊 Rich Output: Beautiful tables and colorized console output
- 📝 Logging: Optional file logging for audit trails
- ⚡ Fast: Efficiently scans directories with thousands of files
Install using pip:
pip install screenshot-cleanerOr using uv:
uv tool install screenshot-cleanerInstall from the repository:
git clone <repository-url>
cd screenshot-cleaner
uv syncSee which screenshots would be deleted without actually deleting them:
# Preview screenshots older than 7 days (default)
screenshot-cleaner preview
# Preview with custom age threshold
screenshot-cleaner preview --days=14
# Preview ALL screenshots (no age filter)
screenshot-cleaner preview --days=0
# Preview in a specific directory
screenshot-cleaner preview --path=/path/to/screenshots
# Save log to file
screenshot-cleaner preview --log-file=preview.logDelete old screenshots:
# Clean with confirmation prompt
screenshot-cleaner clean
# Clean without confirmation (use with caution!)
screenshot-cleaner clean --force
# Dry run (preview without deleting)
screenshot-cleaner clean --dry-run
# Custom age threshold
screenshot-cleaner clean --days=30
# Delete ALL screenshots (use with extreme caution!)
screenshot-cleaner clean --days=0 --force
# Custom directory
screenshot-cleaner clean --path=/path/to/screenshots
# With logging
screenshot-cleaner clean --force --log-file=cleanup.logPreview screenshots that would be deleted.
Arguments:
--path: Screenshot directory (default: ~/Desktop)--days: Age threshold in days (default: 7)--log-file: Optional log file path
Delete old screenshots.
Arguments:
--path: Screenshot directory (default: ~/Desktop)--days: Age threshold in days (default: 7)--force: Skip confirmation prompt--dry-run: Preview only, don't delete--log-file: Optional log file path
You can configure macOS to run Screenshot Cleaner automatically using LaunchAgents.
-
Install the tool globally:
uv tool install screenshot-cleaner
-
Find the installation path:
which screenshot-cleaner
-
Create a plist file at
~/Library/LaunchAgents/com.screenshotcleaner.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.screenshotcleaner</string>
<key>ProgramArguments</key>
<array>
<string>/Users/YOUR_USERNAME/.local/bin/screenshot-cleaner</string>
<string>clean</string>
<string>--force</string>
<string>--days</string>
<string>0</string>
</array>
<!-- Run at every reboot -->
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/screenshot-cleaner.log</string>
<key>StandardErrorPath</key>
<string>/tmp/screenshot-cleaner.error.log</string>
</dict>
</plist>-
Update the path in
ProgramArgumentsto match your installation -
Load the LaunchAgent:
launchctl load ~/Library/LaunchAgents/com.screenshotcleaner.plist -
Verify it's loaded:
launchctl list | grep screenshotcleaner
Run at startup:
<key>RunAtLoad</key>
<true/>Run daily at 9 AM:
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>Run every 6 hours:
<key>StartInterval</key>
<integer>21600</integer>To stop automatic execution:
launchctl unload ~/Library/LaunchAgents/com.screenshotcleaner.plist# Clone the repository
git clone <repository-url>
cd screenshot-cleaner
# Install dependencies
uv sync
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=screenshot_cleaner --cov-report=htmlscreenshot_cleaner/
├── __init__.py
├── cli.py # Fire CLI entry point
├── core/
│ ├── __init__.py
│ ├── scanner.py # File discovery and filtering
│ ├── cleanup.py # Deletion operations
│ └── platform.py # OS detection
└── utils/
├── __init__.py
└── logging.py # Logging utilities
tests/
├── core/
│ ├── test_platform.py
│ ├── test_scanner.py
│ └── test_cleanup.py
├── utils/
│ └── test_logging.py
└── test_cli.py
# Run all tests
uv run pytest
# Run specific test file
uv run pytest tests/core/test_scanner.py
# Run with verbose output
uv run pytest -v
# Generate coverage report
uv run pytest --cov=screenshot_cleaner --cov-report=html
open htmlcov/index.htmlThis project uses bump-my-version for automated semantic versioning.
Semantic Versioning:
MAJOR.MINOR.PATCHformat (e.g.,0.1.0)- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
Bumping Versions:
# Patch release (0.1.0 → 0.1.1)
uv run bump-my-version bump patch
# Minor release (0.1.0 → 0.2.0)
uv run bump-my-version bump minor
# Major release (0.1.0 → 1.0.0)
uv run bump-my-version bump majorWhat happens when you bump:
- Version updated in
pyproject.toml - Version updated in
screenshot_cleaner/__init__.py - Git commit created automatically
- Git tag created (e.g.,
v0.2.0)
Before bumping:
- Ensure all changes are committed
- Run tests to verify everything works
- Update CHANGELOG.md with changes
Show current version:
uv run bump-my-version show current_versionDry-run (preview changes):
uv run bump-my-version bump patch --dry-run --verboseAutomated Release Script:
The easiest way to create a release:
# For bug fixes (0.1.0 → 0.1.1)
./scripts/release.sh patch
# For new features (0.1.0 → 0.2.0)
./scripts/release.sh minor
# For breaking changes (0.1.0 → 1.0.0)
./scripts/release.sh majorThe script will:
- Run tests and verify coverage
- Show preview of version bump
- Ask for confirmation
- Bump version and create git tag
- Push changes and tags to remote
Manual Release Process:
- Make your changes and commit them
- Run tests to ensure everything works:
uv run pytest --cov=screenshot_cleaner
- Update CHANGELOG.md with your changes
- Bump the version:
# For bug fixes uv run bump-my-version bump patch # For new features uv run bump-my-version bump minor # For breaking changes uv run bump-my-version bump major
- Push changes and tags:
git push git push --tags
Contributions are welcome! Please read our Contributing Guide for details on:
- Development setup
- Code standards
- Testing guidelines
- Version management
- Pull request process
- Release workflow
- Write tests for new features
- Maintain test coverage above 90%
- Follow existing code style
- Update documentation as needed
- Add type hints to all functions
- Use semantic versioning for releases
- Update CHANGELOG.md with your changes
See CONTRIBUTING.md for complete details.
Screenshot Cleaner is designed specifically for macOS and will not run on other operating systems.
- Verify you're looking in the correct directory (default is ~/Desktop)
- Check that your screenshots match the expected patterns:
- "Screen Shot *.png"
- "Screenshot *.png"
- Try using
--pathto specify a different directory
Ensure you have read/write permissions for the target directory.
MIT License - see LICENSE file for details.
For maintainers: See PUBLISHING.md for instructions on publishing to PyPI.
Quick release:
./scripts/release.sh patch # Creates tag and triggers PyPI publishBuilt with:
- Python Fire - CLI framework
- Rich - Terminal formatting
- uv - Python package manager
Published to PyPI