Lockpaw
One hotkey covers your screen. One hotkey uncovers it. Everything keeps running.
No sleep. No display disconnect. No process interruption. The screen glows when your agent needs you.
---
> You could set up Amphetamine, configure Hot Corners, tweak energy settings, and adjust your screen saver. Or you could press ⌘⇧L.
## Features
- ⌨️ **One hotkey** — lock and unlock with ⌘⇧L (customizable)
- 🔒 **Touch ID unlock** — or password fallback, just like your Mac
- 🖥️ **Every screen covered** — all displays, auto-detects new monitors
- 🤖 **Agents keep running** — AI coding tools, builds, downloads, SSH sessions
- 🔔 **Agent alerts** — the locked screen glows when Claude Code, Codex, or Gemini needs you
- 😴 **Prevents sleep** — IOKit assertion keeps your Mac awake while locked
- 📦 **10 MB** — native Swift, no Electron
- 🚫 **No analytics** — no data leaves your Mac, no accounts; the only network call is the signed update check
- 🐕🐈 **Dog or cat mode** — choose the metallic origami dog or cat for the lock screen
- ⚙️ **Native Settings** — lock screen, shortcuts, updates, permissions, and about in one quiet window
## Usage
| Action | How |
|--------|-----|
| Lock | Your hotkey (default `Cmd+Shift+L`) |
| Quick unlock | Same hotkey |
| Fallback unlock | Click *Authenticate with Touch ID* at the bottom of the lock screen |
| Settings | Menu bar → Settings… |
| Change hotkey | Settings → Shortcuts → click to record |
| Change mascot | Settings → Lock Screen → Mascot |
## Agent alerts
Lock your screen and walk away — when your AI agent pauses for permission or finishes,
the locked screen **glows from across the room** and a notification fires. You stay
covered (and private) until *you* unlock. The glow is always silent; turn on a sound in
**Settings → General** if you want one (off by default for shared offices).
**Easiest:** open **Settings → General → Connect your agent** and click your agent —
done. Prefer the terminal? Lockpaw ships a tiny `lockpaw` command-line tool
(`Lockpaw.app/Contents/SharedSupport/lockpaw`); one command wires everything up,
including installing itself into `~/.local/bin` (add `--print` to just see the snippet):
| Agent | Setup | What it hooks |
|-------|-------|---------------|
| **Claude Code** | `lockpaw install-hook claude` | `Notification` + `Stop` hooks in `~/.claude/settings.json` (honors `$CLAUDE_CONFIG_DIR`) |
| **Codex CLI** | `lockpaw install-hook codex` | `notify` in `~/.codex/config.toml` |
| **Gemini CLI** | `lockpaw install-hook gemini` | prints a hook snippet for `~/.gemini/settings.json` |
| **Anything else** | append `; lockpaw ping` to your command | runs after your agent finishes |
The hooks reference `~/.local/bin/lockpaw` by path, so they work no matter what's on
your PATH, and keep working when the app moves or updates. Re-running `install-hook`
upgrades older hook entries in place; existing foreign hooks are never clobbered, and
a `.bak` backup is saved next to any config it touches. `lockpaw install-cli` is still
there if you just want the command on your PATH.
Under the hood, `lockpaw ping` posts a local notification that Lockpaw listens for — it
never launches the app if it isn't already running.
## Install
### Download
Grab the latest signed & notarized DMG from [getlockpaw.com](https://getlockpaw.com) or [GitHub Releases](https://github.com/sorkila/lockpaw/releases).
### Homebrew
```bash
brew tap sorkila/lockpaw
brew install --cask lockpaw
```
### Build from source
```bash
brew install xcodegen
git clone https://github.com/sorkila/lockpaw.git
cd lockpaw
xcodegen generate
xcodebuild -scheme Lockpaw -configuration Release build
```
On first launch, grant **Accessibility** when prompted. The Lockpaw icon appears in your menu bar.
## Design
The lock screen is intentionally minimal. Near-black canvas. Subtle radial glow. One element at a time.
**Calm by default** — the screen opens with your chosen mascot, your message, and a quiet elapsed timer; the pointer slips away after a moment of stillness. The fallback auth button waits quietly at the bottom — always there, never loud. When an agent pings, the screen breathes two slow waves of teal, then keeps a soft "your agent needs you" hint until you return.
**Mascots** — a metallic origami dog or cat rendered in teal and amber, floating in a pool of light. Slow 12-second breathing cycle. On successful unlock, the mascot scales up with a teal bloom and fades away.
**Typography** — system San Francisco throughout. Regular weight message at 55% white. Monospaced timer at 35%. The screen whispers.
**Auth button** — glass material effect with a subtle border. Visible enough to be tappable, quiet enough to stay out of the way.
## Under the hood
**Hotkey** — `CGEvent.tapCreate` with `.listenOnly` on a dedicated background thread. Bypasses the LSUIElement activation issue that affects Carbon hotkeys in menu bar apps. Requires Accessibility permission.
**Input blocking** — separate `CGEventTap` intercepts all keyboard, scroll, and tablet events system-wide while locked. Mouse events pass through to the overlay (SwiftUI buttons need clicks). If macOS disables the tap, it re-enables synchronously in the callback.
**Window level** — `CGShieldingWindowLevel()`, the highest level in the system. Above Spotlight, Notification Center, screen savers, everything.
**Multi-display** — one overlay window per screen, recreated on hot-plug.
**State machine** — `LockState` enum with validated transitions. Every `transitionTo()` call is checked. State is verified again after async authentication returns.
**Sleep prevention** — `IOPMAssertion` keeps the Mac awake while locked.
**Auth** — `LAContext.evaluatePolicy(.deviceOwnerAuthentication)` for Touch ID with password fallback. Rate-limited: 30s cooldown after 3 failed attempts.
**Auto-updates** — Sparkle framework checks for updates automatically. Appcast hosted at getlockpaw.com.
## Security model
Lockpaw is a **visual privacy tool**, not a security boundary.
It guards against the accidental — a colleague, a cat, your own muscle memory while agents run. Not the intentional.
What it does
- Overlay at highest system window level
- Event tap blocks all keyboard/scroll input
- Fast User Switching cancels auth, keeps lock active
- Accessibility revocation detected and handled (force unlock with warning)
- URL scheme rate-limited (100ms debounce)
- Debug escape hatch compile-gated (`#if DEBUG`)
- State machine validates every transition
- Hotkey conflict detection against system shortcuts
What it doesn't do
- Prevent `pkill Lockpaw`
- Block synthetic events (AppleScript, Accessibility API)
- Survive kernel-level access
- Protect against screen recording during overlay fade-in
For real security: `Ctrl+Cmd+Q`.
Found a lock or auth bypass anyway? Please [report it privately](SECURITY.md).
## URL scheme
```
lockpaw://lock Lock the screen
lockpaw://unlock Unlock with Touch ID
lockpaw://unlock-password Unlock with password
lockpaw://toggle Toggle lock state
```
## Architecture
```
Lockpaw/
├─ LockpawApp Entry, MenuBarExtra, AppDelegate, onboarding
├─ Controllers/
│ ├─ LockController State machine, lock/unlock orchestration
│ ├─ Authenticator LAContext · Touch ID · password fallback
│ ├─ InputBlocker CGEventTap · keyboard/scroll blocking
│ ├─ HotkeyManager CGEventTap · global hotkey detection
│ ├─ OverlayWindowManager NSWindow · multi-display · shielding level
│ ├─ SleepPreventer IOKit · idle sleep assertion
│ └─ AgentNotifier UNUserNotificationCenter · agent-ping notifications
├─ Models/
│ ├─ LockState .unlocked → .locking → .locked → .unlocking
│ ├─ HotkeyConfig Centralized hotkey UserDefaults access
│ ├─ PingDecision Pure agent-ping decision (pulse/notify/sound)
│ └─ Mascot Dog/cat lock screen preference
├─ Views/
│ ├─ LockScreenView Dog/cat mascot · agent-ping glow · fallback auth
│ ├─ AmbientScreenView Secondary display gradient animation
│ ├─ MenuBarView Dropdown · lock/unlock/quit
│ ├─ SettingsView Native tabs · hotkey recorder · updates
│ └─ OnboardingView 5-step wizard · hotkey · accessibility · agent alerts
├─ Utilities/
│ ├─ Constants Timing, animations, formatting
│ ├─ Notifications All Notification.Name in one place
│ └─ AccessibilityChecker AXIsProcessTrusted + System Settings
└─ Resources/
└─ Assets App icon, mascot, menu bar icon, colors
LockpawCLI/
└─ main `lockpaw` CLI · ping · install-cli · install-hook
```
## CI
Pushes to `main` and PRs run build + 50 unit tests via GitHub Actions. Shipped DMGs are Developer ID-signed, notarized, and published to [GitHub Releases](https://github.com/sorkila/lockpaw/releases); auto-updates are delivered through Sparkle with EdDSA-signed appcasts.
---
getlockpaw.com