Two root causes for the 'imaging extension was built for another version
of Pillow' error users hit after install:
1) cleanup_site_packages ran 'find ... -name "*.py" ! -name "__init__.py"
-delete' with a comment claiming 'keep .pyc only' — but no compileall
step exists. Result: the dist shipped __init__.py + .pyd only, missing
every submodule (Image.py, ImageDraw.py, _version.py, ...). Fresh
installs were broken; in-place upgrades produced a half-old/half-new
site-packages. Removed the deletion entirely.
2) NSIS installer extracted over the previous install without cleaning
python/, app/, scripts/. Upgrades left stale files (old PIL/_version.py
next to new PIL/_imaging.pyd) which raised the Pillow ABI mismatch.
Wipe those subtrees before File /r, preserving config.yaml at the
install root.
- Rewrite tray to run on main thread (pystray owns message loop, uvicorn
in background thread) — fixes unresponsive confirmation dialogs
- Use native Windows MessageBoxW instead of tkinter (embedded Python
has no tkinter)
- Pin numpy <2.0 to fix soundcard's numpy.fromstring (removed in 2.0)
- Strip transitive numpy 2.x wheels in build script
- Installer copies config.example.yaml as config.yaml on fresh install
- Suppress noisy screen_brightness_control warnings
- Use custom icon.ico for installer/uninstaller UI
- LaunchApp opens server then browser after install
- .onInit detects running instance and offers to stop it
- Use WMIC-based process kill targeting embedded Python path
- start-hidden.vbs prefers embedded Python over system Python
- Add pystray dependency to build script
- CLAUDE.md: note to consult CI/CD guide for build changes