A local Windows desktop application that organizes personal photo libraries by face recognition. Point it at your photo folder — it finds every face, lets you name people, and makes every photo of Mom or Grandpa instantly searchable.
All processing runs on your machine. No cloud. No account. No data leaves your drive.
Active development — core features complete. See GitHub Issues for current work.
| Milestone | Status |
|---|---|
| M1 — Foundation (repo, CI/CD, sidecar, DB, scanner, FAISS, Tauri shell, React scaffold) | ✅ Done |
| M2 — Core ML (face detection, clustering, uncertain queue) | ✅ Done |
| M3 — Gallery UI (three-panel layout, naming, merge, corrections) | ✅ Done |
| M4 — Search (multi-person AND, date filter, exact-people mode) | ✅ Done |
| M5 — Corrections (mark wrong, re-evaluation pipeline) | ✅ Done |
| M6 — Ship (onboarding, installer, security hardening) | ✅ Done |
| Code signing (SignPath Foundation) | 🔲 Pending approval |
- Scan folders of any size (tested to 5TB / ~1M photos) in the background — local drives, network shares, and NAS included; add as many folders as you like and manage them anytime from Manage Scan Folders… (see and remove any configured folder — removing one only stops future scanning of it, already-indexed photos and people are never touched)
- Detect and cluster faces automatically — each cluster represents one likely person; FAISS-backed matching stays fast as the library grows
- Name people by clicking a cluster; all their photos are labeled instantly (duplicate names offer a merge)
- Review uncertain faces — anything below the confidence threshold waits in a queue for your confirmation; the app never silently guesses, and prefers suggesting a person you've already named over an anonymous cluster when scores are close, since that's the suggestion you can actually act on. Not a real face worth naming? Mark it "Not relevant" — it moves to a secondary Not Relevant view instead of the main queue, and can be restored for review anytime
- Confirming a match re-checks for more — once you name or confirm a face, a "Looking for more matches…" indicator shows the app actively sweeping the library for other faces that now match, resolving several at once instead of leaving you wondering whether anything happened
- Search by one or more people together, with date ranges and an "exactly these people" mode
- Correct mistakes — mark a face wrong and the whole cluster re-evaluates automatically
- Carry recognition across libraries — export/import named identities as a small file (no photos inside)
- See what it's doing — live activity log with engine and app streams, adjustable verbosity; scan progress reflects every file actually checked (not just newly changed ones), so a rescan of an already-indexed library shows real progress instead of sitting at 0%
- Find blurry photos — a live cutoff slider surfaces them worst-first so you see exactly what each level captures
- Find duplicates — exact copies and the same shot saved at different sizes, each copy listed with its folder, filename, and size; "keep one per group" in one click
- Delete with full detail — the confirmation shows every file's thumbnail, name, folder, and size plus the total space freed; every file is backed up in the app first, local and network folders alike, then goes to the Windows Recycle Bin when possible (a failed Recycle Bin attempt falls back to a safe, already-backed-up removal)
- Rotate sideways photos — finds photos that are upright only in tag-aware viewers (EXIF-only) or where a rotation would let face detection find people it's missing; preview before/after, then rotate the ORIGINAL file in place — the pre-rotation version is always backed up first, the same way everywhere
- Restore backups — every deleted or rotated file has a 7-day app backup, in addition to the Recycle Bin when that applies; restore any of them from one list
- Update notifications — the app checks for new versions automatically (silent unless one is found) and via Help > Check for Updates…; installing runs quietly in the background and skips the old "uninstall previous version?" prompt entirely
- Never touches your files otherwise — scanning and browsing are strictly read-only; the ONLY file-modifying actions are that explicit, confirmed delete and rotate, both always backed up and recoverable; photos removed from disk hide themselves and revive if restored
| Layer | Technology |
|---|---|
| App shell | Tauri 2.x (Rust) |
| Frontend | React 18 + TypeScript + Vite |
| ML backend | Python 3.11 sidecar (FastAPI) |
| Face model | InsightFace buffalo_l (ONNX Runtime, CPU-only) |
| Vector index | FAISS (auto-scales to 1M+ embeddings) |
| Database | SQLite (local, portable, in %APPDATA%\faces-h\) |
| Installer | Single .exe — no Python, Node, or Rust required |
| Code signing | SignPath Foundation (free OSS certificate) |
See docs/ARCHITECTURE.md for the full technical design.
See CLAUDE.md for how to work on this project with Claude Code.
- Windows 10/11
- Python 3.11+
- Node.js 20+
- Rust (stable)
# Python sidecar
python -m venv sidecar/.venv
sidecar/.venv/Scripts/pip install -r sidecar/requirements.txt
python sidecar/main.py --port 51423 --data-dir "%APPDATA%\com.faces-h.app"
# Frontend + Tauri (in a second terminal)
npm install
npm run tauri devcd sidecar && pytest tests/ -q # Python
npm test # Frontend
cargo test --manifest-path src-tauri/Cargo.toml # RustOptional config.json in %APPDATA%\com.faces-h.app\ (all keys optional; defaults shown):
{
"face_model": "insightface_buffalo_l",
"auto_assign_threshold": 0.68,
"uncertain_threshold": 0.50,
"min_face_px": 20,
"min_detection_confidence": 0.5,
"ui_log_level": "info",
"blur_threshold": 60,
"backup_retention_days": 7,
"named_person_preference_margin": 0.04
}Invalid values fall back to defaults with a logged warning. Logs: %APPDATA%\com.faces-h.app\logs\.
- IPC between Tauri and the sidecar is authenticated with a 256-bit per-session token from the OS CSPRNG (generated at startup, never reused)
- Strict Content Security Policy — no external script or font sources
- All third-party GitHub Actions pinned to immutable commit SHAs
- Installer code-signed via SignPath Foundation (pending approval)
- Scanning and browsing never write, move, or delete any photo file; the single file-modifying action is the explicit, user-confirmed "Move to Recycle Bin" delete — never a permanent erase
No data ever leaves your machine. See landing/privacy.html or shifth.com/faces-h/privacy.html.
docs/PRD.md— product requirementsdocs/ARCHITECTURE.md— technical decisions and data modeldocs/DESIGN.md— visual design directiondocs/IMPLEMENTATION_PLAN.md— implementation issues and dependency graph