Your Mac locks itself the moment a stranger sits down and you're not there.
An always-on macOS menu-bar app that knows your face — 100% on-device, nothing ever leaves your Mac.
You step away from your Mac. Someone else leans in. The screen locks before they can read a thing. When you sit back down, FaceLock recognizes you and stays out of your way.
- 👤 Knows your face — enroll once; recognition runs entirely on-device with Apple's Vision framework.
- 🛡️ Locks on the rules you choose — away + stranger, any stranger, or walk-away.
- 🫥 Anti-spoof (liveness) — a blink + motion check so a held photo of you won't pass as you.
- 🕵️ Intruder log — captures a snapshot of whoever triggers a lock; review them in a gallery.
- ⏳ Pre-lock countdown — a HUD you can cancel before it locks (no more "it locked while I grabbed coffee").
- 🔔 Lock notifications — get told when and why your screen locked.
- 🧮 Temporal voting + grace period — multi-frame agreement means near-zero false locks.
- 🔋 Light & private — ~4 fps, only face embeddings stored (never images), and zero network code.
Native macOS 26 Liquid Glass — menu popover (left) and settings (right).
Requires macOS 26 (Tahoe), Xcode 16+, and XcodeGen (
brew install xcodegen).
git clone https://github.com/ish-cs/facelock.git
cd facelock
xcodegen generate # build FaceLock.xcodeproj from project.yml
open FaceLock.xcodeproj # press ▶ Run in XcodePrefer the command line?
xcodebuild build -scheme FaceLock -configuration Debug -derivedDataPath build
open build/Build/Products/Debug/FaceLock.app💡 FaceLock has no Dock icon — find the 👁️ in your menu bar (top-right).
| Step | Do this |
|---|---|
| 1️⃣ | Click the 👁️ menu-bar icon → Grant Camera Access (approve the macOS prompt). |
| 2️⃣ | Click Enroll Your Face → look at the camera, slowly turn your head. ~12 samples, a few seconds. |
| 3️⃣ | It flips to Monitoring automatically. You're protected. ✅ |
Want it always on? Settings → Launch at login.
All toggleable in Settings — mix and match.
| Rule | Locks when… | Default |
|---|---|---|
| 🎯 Strict | you're away and a stranger is present | ✅ on |
| 👥 Stranger-always | any stranger appears (even if you're here) — shoulder-surfer guard | ⬜ off |
| 🚶 Walk-away | nobody's there for the walk-away delay | ⬜ off |
Plus a grace period (how long the condition must hold before locking) and an auto-calibrated match sensitivity slider. The menu shows the live recognition distance so you can tune it by eye.
Camera ──frames (~4fps)──▶ FaceMatcher ──result──▶ PolicyEngine ──lock?──▶ Locker
AVFoundation Vision feature-prints rules + grace timer login.framework
(owner vs stranger) (pure, fully tested) (SACLockScreenImmediate)
Four small, single-purpose pieces. The PolicyEngine — the part that actually decides to lock — is pure logic with 19 unit tests covering every rule, the grace timer, and flicker.
Everything runs on your Mac. FaceLock stores only Vision feature-prints (math, not photos) in ~/Library/Application Support/FaceLock/, and contains no networking code whatsoever. Your camera frames never touch disk or the network.
xcodebuild test -scheme FaceLock -destination 'platform=macOS' -only-testing:FaceLockTestsPure-logic tests run headless — no app launch, no camera.
- Recognition uses Vision's general image feature-print (Apple exposes no public face-embedding API). It's solid, not FaceNet-grade —
FaceMatcheris an isolated seam where a CoreML face model can drop in later. Tune the sensitivity slider first. - Liveness is an RGB-camera heuristic (blink + motion): it defeats printed/screen photos, but not a video replay. The FaceTime camera has no depth sensor to do better.
- Requires macOS 26 for the native Liquid Glass UI.
Built with Swift, SwiftUI & Apple Vision. On-device, always.

