🛡️ Auto-lock your Mac on proximity + panic-hide sensitive apps with one hotkey
A privacy-first macOS security app.
Auto-lock your Mac when you step away from your desk.
- Detects when your iPhone or Apple Watch goes out of Bluetooth range
- Smart hysteresis logic prevents false triggers
- Customizable lock delay (5-30 seconds)
- Works with Bluetooth or WiFi signal strength
- Auto-triggers Panic Mode before locking — apps stay hidden even if the screen is woken without authentication
Blur everything instantly with one keystroke — only your trusted apps stay visible.
- Single hotkey (default:
⌘+Shift+L) blurs all screens immediately and hides non-safelisted apps - Safelist model: apps you trust (Terminal, IDE, browsers, etc.) remain visible and interactive above the blur; everything else vanishes
- Multi-display (v0.3.4): every connected monitor is covered correctly, including external displays with different resolutions or heights
- No-flash switching (v0.3.4): clicking a safelisted app during Panic Mode shows its window instantly — no full-blur frame before the hole appears
- Fullscreen & Chromium support: safelisted apps remain visible whether they are in a normal window, fullscreen Space, or are Chromium-based (Chrome, Edge, Brave, Arc)
- Audio mute (v0.3.3): system audio is silenced on panic and restored to its prior state on release
- Clipboard clear (v0.3.3): anything in the clipboard is wiped on panic — prevents bystanders from pasting copied passwords
- Release with Touch ID for added security
Automatically photographs anyone who fails a panic-release attempt.
- Captures a photo from the front camera on wrong Touch ID or password attempt
- Saved locally to
~/Pictures/Vigil Screen Captures/— never uploaded - Sends a macOS notification so you know even when you're away from the History tab
- Visible in the History log with thumbnail — tap to enlarge
- Toggle on/off in Settings → Panic Mode
Automatically triggers Panic Mode when someone looks over your shoulder.
- Continuous face detection via Vision + AVFoundation — no camera upload, fully local
- Configurable sensitivity and minimum detection duration before triggering
- Auto-release: Panic Mode lifts automatically (no Touch ID required) once the threat clears for a set delay (3–30 s)
- Lock History records shoulder surfing events with a purple badge
- Toggle on/off in Settings → Shoulder Surfing
A full audit log of every lock event.
- Records Proximity Lock triggers, Panic Mode activations, and failed unlock attempts
- View in Settings → History
- Clear at any time
At-a-glance Bluetooth and countdown info next to the menu bar icon.
- Shows live RSSI and lock countdown without opening the popover
- Toggle in Settings → General
Get set up in seconds with a guided welcome checklist.
- Live status for Accessibility, Bluetooth pairing, and app blocklist
- Opens directly from the menu bar popover
- Dismisses automatically once you're ready
Native macOS 26 visual design when available.
- Panic button uses
.glassEffectwith live tint (green/red) - Onboarding footer uses
.buttonStyle(.glassProminent) - Graceful fallback to standard SwiftUI on macOS 15–25
- Local-first: All processing happens on your Mac. No network calls, no telemetry
- iCloud Sync (v0.2.0): Settings, App Safelist, and Lock History sync across your Macs via
NSUbiquitousKeyValueStore— never sent to third parties - Open source: Community audits the code
- Zero dependencies: Pure Apple frameworks only
- Privacy-focused: We don't collect telemetry or analytics
- PrivacyInfo.xcprivacy: Declares all accessed APIs (Bluetooth, Keychain) for notarization compliance
🎬 Demo GIF coming soon (Screen Recording + Gifski)
- Download the latest release from GitHub Releases
- Open
Vigil Screen.dmg - Drag Vigil Screen.app to Applications
- Launch from Applications folder
- Grant permissions (Bluetooth, Accessibility) when prompted
Vigil Screen is notarized by Apple (since v0.3.0) — no Gatekeeper warning on launch.
brew install --cask atomsbaza/tap/vigil-screenTo upgrade later:
brew upgrade --cask vigil-screengit clone https://github.com/atomsbaza/VigilScreen.git
cd VigilScreen
open VigilScreen.xcodeprojRequirements:
- Xcode 16+
- macOS 15 Sequoia or later
- Swift 6.0+
- Open Vigil Screen → Settings
- Go to Proximity Lock tab
- Toggle Enable
- Click Scan for Devices and select your iPhone or Apple Watch
- Tune signal threshold if needed (move farther away to adjust)
- Go to Panic Mode tab
- Review the App Safelist — apps in this list stay visible above the blur (default: Terminal, Xcode, VS Code, Safari, Chrome, Slack, Notion)
- Add trusted apps by clicking + and selecting from running apps, or remove ones you don't need
- Customize keyboard shortcut (default:
⌘+Shift+L) - Toggle Require authentication to release for extra security
Apple Watch double-press also unlocks Panic Mode if you have "Use your Apple Watch to unlock apps and your Mac" enabled in System Settings → Touch ID & Password. Touch ID and password fallback work as well.
Vigil Screen will prompt for Accessibility access on every launch until it's granted — this is required for the global ⌘+Shift+L shortcut to work.
- Click Open Settings in the prompt
- Find Vigil Screen in the Accessibility list and turn it on
- Quit and reopen Vigil Screen — the shortcut will not work until you restart the app after granting permission
Note: macOS requires a restart of the app any time Accessibility permission is newly granted or toggled.
- Proximity Lock: Walk away from your desk with Bluetooth enabled → Mac locks
- Panic Mode: Press
⌘+Shift+L→ selected apps disappear instantly
VigilScreen/
├── App/
│ ├── DockLockApp.swift # @main entry point
│ └── AppDelegate.swift # NSApplicationDelegate + NSWindowDelegate
│
├── MenuBar/
│ ├── MenuBarManager.swift # NSStatusItem + dynamic-height popover
│ ├── MenuBarView.swift # SwiftUI popover UI (welcome gate)
│ └── WelcomeView.swift # First-run onboarding checklist
│
├── Features/
│ ├── PanicMode/
│ │ ├── PanicModeManager.swift # Blur/unhide logic (@MainActor)
│ │ ├── AppBlocklist.swift # Safelist — apps that stay visible during panic
│ │ └── PanicModeView.swift # Settings UI
│ │
│ ├── ProximityLock/
│ │ ├── BluetoothMonitor.swift # CoreBluetooth RSSI scanning + DiscoveredDevice model
│ │ ├── LockTrigger.swift # Hysteresis + lock action
│ │ └── ProximityView.swift # Settings UI
│ │
│ ├── ShoulderSurfing/
│ │ ├── ShoulderSurfingDetector.swift # Vision + AVFoundation face detection
│ │ └── ShoulderSurfingView.swift # Settings UI
│ │
│ └── History/
│ └── LockHistoryView.swift # Lock event audit log UI
│
├── Core/
│ ├── LockEngine.swift # Sends lock screen command
│ ├── SettingsStore.swift # UserDefaults wrapper
│ ├── PermissionManager.swift # Requests OS permissions (@MainActor)
│ ├── IntruderCaptureManager.swift # Front-camera capture on failed auth
│ ├── LockHistoryStore.swift # Persisted audit log of lock events
│ └── CloudSyncStore.swift # iCloud KV sync coordinator (NSUbiquitousKeyValueStore)
│
├── Settings/
│ └── SettingsView.swift # Main settings window
│
└── Resources/
├── VigilScreen.entitlements # App entitlements
└── PrivacyInfo.xcprivacy # Apple privacy manifest (notarization)
Vigil Screen uses the macOS 26 Liquid Glass design language when available, with a clean fallback for macOS 15–25:
| Element | macOS 26 | macOS 15–25 |
|---|---|---|
| Panic button | .glassEffect(.regular.tint(...).interactive()) with exclamationmark.shield.fill icon + ⌘⇧L shortcut hint |
Filled .background (red/green) + rounded clip + ⌘⇧L hint |
| Onboarding CTA | .buttonStyle(.glassProminent) |
.buttonStyle(.borderedProminent) |
All glass effects are gated with #available(macOS 26, *) — the app compiles and runs identically on both targets.
| Component | Choice | Why |
|---|---|---|
| Language | Swift 6.0+ | Strict concurrency enforced across the codebase |
| UI | SwiftUI 6 + AppKit | Native macOS feel, menu bar integration |
| Frameworks | CoreBluetooth, LocalAuthentication, AVFoundation, Vision, CoreGraphics, Security | Pure Apple APIs, zero external dependencies |
| Liquid Glass | macOS 26+ .glassEffect |
Adaptive — falls back gracefully on macOS 15–25 |
| Min Target | macOS 15 Sequoia | Broad compatibility, Ships on all modern Macs |
| Build System | Xcode 16+ | Native Swift 6 strict concurrency support |
Vigil Screen requests only the permissions it needs:
| Permission | Why | Prompt |
|---|---|---|
| Bluetooth | To scan for nearby iPhone/Watch | When enabling Proximity Lock |
| Accessibility | To register global keyboard shortcut | When customizing Panic Mode hotkey |
| Touch ID | To authenticate panic release | When enabling Panic Mode |
| Camera | Intruder Capture (failed-unlock photo) and Shoulder Surfing Detection (face detection, fully on-device) | On first failed auth attempt, or when enabling Shoulder Surfing Detection |
What we DON'T ask for: Microphone, Location, Network
Q: Does Vigil Screen work with multiple Macs? A: Yes — iCloud Sync (added in v0.2.0) automatically syncs Settings, App Safelist, and Lock History across all your Macs.
Q: What if my iPhone is out of battery? A: Proximity Lock won't trigger. Panic Mode still works independently.
Q: Which apps stay visible during Panic Mode? A: Only apps in your Safelist remain visible above the blur (default: Terminal, Xcode, VS Code, Safari, Chrome, Slack, Notion). Everything else is hidden. Add or remove apps in Panic Mode settings.
Q: Is my data safe? A: Completely safe. All processing is local. No cloud, no analytics, no telemetry. It's open source — audit the code yourself.
Q: Does it work on Apple Silicon? A: Yes. Optimized for M1/M2/M3/M4 Macs.
No known issues.
- Settings, Safelist, and History sync via iCloud KV store (v0.2.0) — no third-party servers
- No accounts, no logins
- Bluetooth pairing info in system Keychain (encrypted)
- Intruder photos stored locally only (
~/Pictures/Vigil Screen Captures/) — never synced
- No usage tracking, crash reporting, or analytics
- Full source code on GitHub
- MIT License — fork and audit freely
PrivacyInfo.xcprivacydeclares all accessed APIs (Bluetooth, Keychain)- Required for macOS 15+ notarization
- Confirms:
NSPrivacyTracking: false, zero collected data types
Found a security issue? Report privately to atomsbaza2@gmail.com. See SECURITY.md.
We welcome contributions! See CONTRIBUTING.md.
- 🐛 Report bugs
- 💡 Suggest features
- 📝 Improve docs
- 🔍 Audit security
- 🌍 Translate
- Panic Mode — instant full-screen blur on all screens, safelist keeps trusted apps visible
- Proximity Lock (Bluetooth) — auto-triggers Panic Mode before locking
- Intruder Capture — front-camera photo on failed unlock, saved to
~/Pictures/Vigil Screen Captures/ - Lock History — full audit log of lock events
- Menubar Live Stats — live RSSI + countdown in menu bar
- Local settings, first-run onboarding
- Liquid Glass UI (macOS 26)
- Swift 6 strict concurrency
- Apple Privacy Manifest (PrivacyInfo.xcprivacy)
- iCloud Sync — Settings, App Safelist, and Lock History sync across Macs via
NSUbiquitousKeyValueStore
- Fix: eliminated overlay flash when switching to a safelisted app during Panic Mode — overlay alpha resets instantly on activation, mask rebuilds after a 70 ms settling window, then fades back in over 180 ms
- Shoulder Surfing Detection — continuous face detection via Vision + AVFoundation; triggers Panic Mode automatically when 2+ faces are detected for a configurable duration
- Sensitivity slider and live face count in Settings → Shoulder Surfing tab
- Auto-release: camera stays running during Panic Mode; releases without Touch ID after the threat clears for a set delay (3–30 s)
- Lock History shows shoulder surfing events with a purple badge
- Camera API declared in PrivacyInfo.xcprivacy
- Notarized release — no Gatekeeper warning
- iCloud Key-Value Storage entitlement enabled
- Fix: crash on launch when iCloud sync contained duplicate lock history UUIDs
- Panic Mode now mutes system audio on trigger and restores the prior mute state on release (toggleable in Settings → Panic Mode)
- Panic Mode now clears the clipboard on trigger — prevents bystanders from pasting copied passwords (toggleable in Settings → Panic Mode)
- Fix: multi-display overlay — external monitors now blur correctly on macOS Sequoia
- Fix: blur-to-hole flash eliminated — safelisted apps are always visible through holes during Panic Mode; switching to them is instantaneous with no full-blur frame
- Fix: mask hole coordinates corrected for setups where the primary display and focused display have different heights (wrong
NSScreen.mainheight was used for CG→AppKit y-flip) - Fix: window bounds now sourced exclusively from
CGWindowList— AX was returning inner content views for Chromium/Electron apps, producing undersized holes - Fix: CGEvent tap now survives system-initiated disables (timeout / user input) — no-flash guarantee no longer silently degrades mid-session
- Fix:
CFRunLoopSourceis correctly removed on panic release — eliminates a run loop source leak that accumulated across repeated panic cycles - Fix: newly connected display during active Panic Mode gets safelisted-app holes immediately instead of waiting up to 250 ms
- Performance: GPU blur pipeline pre-warmed at launch; per-app
CALayermask rebuilt on-demand viaCGWindowListonly (~1–3 ms); 250ms loop skips no-op ticks using a rect-signature change check - Performance: preemptive mask rebuild on click now only fires when the clicked window belongs to a safelisted app — non-safelisted clicks (Dock, menu bar) no longer trigger a rebuild
- Custom app modes / profiles (office, café, travel)
- Multiple paired Bluetooth devices (iPhone + Apple Watch)
MIT License — see LICENSE.
Made with ❤️ for developers who care about privacy