Skip to main content

A macOS CLI that audits media folders, fixes extensions, and imports into Apple Photos

Project description

Smart Media Manager (ALPHA)

[!WARNING] ⚠ Alpha Software - Do Not Use in Production

This project is currently in alpha stage and under active development. It may contain bugs, incomplete features, or unexpected behavior. Do not use this tool on your only copy of important media files. Always maintain backups before running this software.

Status: Alpha (pre-release) — breaking changes and data loss risks are possible.

A macOS-first CLI that audits folders of photos and videos, fixes mismatched extensions, stages compatible media, and imports everything into Apple Photos without manual clicking.

HighlightsRequirementsInstallationUsageDevelopmentTesting


Smart Media Manager normalizes filenames, validates files via multiple signature detectors, auto-installs transcode dependencies, and keeps a skip log so nothing silently disappears.

✦ Highlights

  • Deterministic detection pipeline — Powered by libmagic, PureMagic, PyFSig, binwalk, and ffprobe consensus voting plus RAW refinement
  • Fail-fast conversions — Direct source→target conversion with automatic cleanup on failure (v0.4.0: backup system removed for simplicity)
  • Extension preservation — File extensions are never changed unless the detected format differs (v0.4.0: fixes .mp4 → .mov renaming bug)
  • Dependency bootstrapper — Installs Homebrew formulas (ffmpeg, libheif, imagemagick, etc.) and RAW codecs only when the current camera family needs them
  • Apple Photos automation — Batched AppleScript commands with rate-limiting and retry logic, metadata preservation using exiftool
  • Comprehensive statistics — Color-coded summary with detailed metrics for scanned, converted, imported, and skipped files
  • Interactive retry — Prompt to retry failed imports without re-running the entire pipeline
  • Transparent skip logging — Corrupt files, archives, vector artwork, and unsupported assets are called out with remediation guidance
  • Progress tracking — Real-time progress bars with ETA for each pipeline stage
  • Corrupt video detection — Validates video files before staging to avoid wasted time
  • Smart conversions — PNG preferred for images (faster, smaller), remuxing for compatible codecs

▣ Requirements

Requirement Details
Operating System macOS 12 (Monterey) or newer with stock Photos app
⚠ Does not work on Windows or Linux
Package Manager Homebrew (auto-installs dependencies)
Python 3.12+ (managed by uv)
Disk Space Sufficient for staging folders and logs

⚙ Configuration Notes

Skipping dependency bootstrap

If you prefer to manage Homebrew/pip packages yourself, pass --skip-bootstrap (or set SMART_MEDIA_MANAGER_SKIP_BOOTSTRAP=1). The CLI will trust your environment and skip auto-installs, but will fail if required tools are missing.

No automatic fallbacks

When Apple Photos refuses a file, the CLI logs it to smm_skipped_files_<timestamp>.log and moves on. It never attempts emergency conversions that could explode disk usage.

⬇ Installation

Recommended: Install as a tool

Install globally with uv tool (creates smart-media-manager executable on your PATH):

uv tool install smart-media-manager --python 3.12

Note: The --python 3.12 flag is required because rawpy (used for RAW image processing) only has wheels for Python 3.9-3.13. Without this flag, systems with Python 3.14+ as default will fail to resolve dependencies.

This is the recommended method. The executable will be available system-wide as smart-media-manager.

To install a specific version:

uv tool install smart-media-manager==0.5.44a1 --python 3.12

Alternative: Install as a package

Install into a project or virtual environment:

# Add to project dependencies
uv add smart-media-manager

# Or install in current venv
uv pip install smart-media-manager

When installed as a package, run with: uv run smart-media-manager or activate the venv first.


▶ Usage

Quick start

Import all media from the current directory:

smart-media-manager

Common examples

Scan a specific folder recursively:

smart-media-manager ~/Pictures/Inbox --recursive

Scan and delete staging folder after successful import:

smart-media-manager ~/Downloads/Photos --recursive --delete

Import a single file:

smart-media-manager ~/Downloads/photo.jpg

Import into a specific album (non-interactive):

smart-media-manager ~/Pictures/Vacation --recursive --album "Summer 2024" -y

Command-line options

Option Description
PATH Directory to scan (default: current directory) or path to a single file
--recursive Recursively scan subdirectories
--follow-symlinks Follow symbolic links when scanning
--delete Delete staging folder after successful import
--album NAME Photos album name to import into (default: 'Smart Media Manager')
--copy Copy files to staging instead of moving (originals untouched)
--skip-duplicate-check Skip duplicate checking during import (faster but may import duplicates)
--skip-bootstrap Skip automatic dependency installation
--skip-convert Skip format conversion/transcoding (files must already be compatible)
--skip-compatibility-check Skip all compatibility validation (may cause import errors)
--max-image-pixels VALUE Set Pillow image pixel limit; use none to disable (default)
-y, --yes, --assume-yes Skip confirmation prompt (useful for automation)
--version Show version and exit

What happens during a run

  1. Scanning — Discovers all files with real-time progress
  2. Detection — Identifies media types using consensus voting
  3. Staging — Moves files to FOUND_MEDIA_FILES_<timestamp> folder
  4. Conversion — Processes incompatible formats (PNG, HEVC, etc.)
  5. Import — Sends batches to Apple Photos via AppleScript
  6. Statistics — Displays color-coded summary with success rates
  7. Retry prompt — Option to retry failed imports (if any)

Output and logging

Output Location Description
Console Terminal Progress bars, warnings, statistics summary
Run log .smm_logs/smm_run_<timestamp>.log Detailed INFO-level logs
Skip log smm_skipped_files_<timestamp>.log Failed/skipped files with reasons
Staging FOUND_MEDIA_FILES_<timestamp>/ Processed media (kept unless --delete)

Interactive features

After import completes, if any files failed:

  • Statistics summary — Detailed breakdown with color coding
  • Retry prompt — Option to retry just the failed imports
  • Updated results — Final statistics after retry

During Photos import, if a dialog blocks:

  • Dialog detection — Detects when Photos is waiting for user interaction
  • Retry prompt — Close the dialog and press Enter to continue, or type 'abort' to cancel

Graceful interruption

Press Ctrl+C at any time to cleanly interrupt the process:

  • Logs are saved to the run log file
  • Skip log is preserved if it has entries
  • Staging folder is preserved for manual recovery
  • Exit code 130 (standard SIGINT) is returned

⚙ Development

Quick setup

# Clone and enter
git clone https://github.com/Emasoft/Smart-Media-Manager.git
cd Smart-Media-Manager

# Install dependencies (runtime + dev tools) and enable hooks
uv sync
git config core.hooksPath githooks

# Install editable version (optional)
uv tool install --editable . --python 3.12

# Run tests
uv run pytest

Development workflow

  1. Make changes to the codebase
  2. Run tests with uv run pytest
  3. Format code with uv run ruff format --line-length=320 smart_media_manager/ tests/
  4. Check linting with uv run ruff check smart_media_manager/ tests/

Version management

Bump version (dev only):

# Bump to next alpha version
uv version --bump minor --bump alpha

# Verify version
smart-media-manager --version

⊕ Testing

Run the test suite:

uv run pytest

Tests use lightweight sample media and monkeypatched detectors, so most scenarios run without Apple Photos.


▣ Privacy & Data Hygiene

[!CAUTION] Sensitive Data Warning

  • Skip logs (smm_skipped_files_<timestamp>.log) may contain partial paths — redact before sharing
  • Staging directories (FOUND_MEDIA_FILES_*) are large and gitignored — delete after confirming imports
  • Always scan for secrets before opening PRs or releases

▤ Release Checklist

  1. Update CHANGELOG.md
  2. Bump version: uv version --bump minor --bump alpha
  3. Run tests: uv run pytest
  4. Scan for secrets: uv tool run gitleaks detect --no-banner
  5. Build: uv build
  6. Inspect dist/ contents
  7. Tag and push: git tag vX.Y.ZaN then git push origin vX.Y.ZaN
  8. Publish: uv publish (PyPI)
  9. GitHub release: created automatically on tag push via workflow

▦ License

MIT License - see LICENSE file for details.

▧ Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

▨ Changelog

See CHANGELOG.md for version history.


▩ Local Documentation

The docs_dev/ folder is gitignored and protected by hooks. It's automatically backed up to .git/local_backups/docs_dev.tar.gz during git operations.

Enable hooks once per clone:

git config core.hooksPath githooks

Manual backup/restore:

./scripts/protect_docs_dev.sh backup   # Create backup
./scripts/protect_docs_dev.sh restore  # Restore from backup

▤ Licensing & Dependencies

Smart Media Manager is MIT licensed. Runtime dependencies:

Component License Notes
filetype 1.2.0 MIT https://pypi.org/project/filetype/
puremagic 1.30 MIT Keep copyright notice
isbinary 1.0.1 BSD-3-Clause Include attribution if redistributed
python-magic 0.4.27 MIT Wraps system libmagic
pyfsig 1.1.1 MIT Signature detection
pillow 12.0.0 HPND/MIT-CMU Retain license when redistributing
rawpy 0.25.1 MIT RAW image processing via LibRaw

External tools via Homebrew (binwalk, ffmpeg, imagemagick, exiftool, etc.) ship under their own licenses.


▦ Support

Open an issue or discussion in the repository for bugs, feature requests, or compatibility updates.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smart_media_manager-0.5.44a1.tar.gz (181.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smart_media_manager-0.5.44a1-py3-none-any.whl (118.7 kB view details)

Uploaded Python 3

File details

Details for the file smart_media_manager-0.5.44a1.tar.gz.

File metadata

  • Download URL: smart_media_manager-0.5.44a1.tar.gz
  • Upload date:
  • Size: 181.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for smart_media_manager-0.5.44a1.tar.gz
Algorithm Hash digest
SHA256 d44f4dd3329167ce7c6c6ab335d42ac3dd4a2c54b881d03656495dbd8df75e20
MD5 fa51b5c8d962acb76838efafc174ad97
BLAKE2b-256 055edbc87fa632be25e8cd055b70d6cb8183a6360e32310e33dd7d32a1b805bd

See more details on using hashes here.

File details

Details for the file smart_media_manager-0.5.44a1-py3-none-any.whl.

File metadata

  • Download URL: smart_media_manager-0.5.44a1-py3-none-any.whl
  • Upload date:
  • Size: 118.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for smart_media_manager-0.5.44a1-py3-none-any.whl
Algorithm Hash digest
SHA256 e94b7e7820227ce6ef45914008e11c022775cf72f46c06c6e100c1d21ae0e5c1
MD5 6b2968250d261feb3f186f100acdfba5
BLAKE2b-256 2680db020c3d036f613582094614374d4c56f01aa98968fc17d9fc61842b9ec4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page