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, or record your own.
- Touch ID unlock. Rest a finger on the sensor, nothing to click first. Password fallback like your Mac.
- Every screen covered. All displays, including ones you plug in while locked.
- Agents keep running. AI coding tools, builds, downloads and SSH sessions carry on underneath.
- Agent alerts. The locked screen glows when Claude Code, Codex, Gemini, Cursor, Copilot or Aider needs you, and the notification says which agent and why.
- Lid closed, still running. Optional. Close the MacBook lid while locked and your agents keep going, no external display needed. It uses one small helper you approve once, and sleep comes back when you unlock, when the Mac runs hot, or at 20% battery.
- Pings on your phone. Optional. Forward agent pings to ntfy, Pushover or any webhook, such as Home Assistant.
- Shortcuts and Spotlight. Lock Screen and Is Lockpaw Locked? actions. There's no unlock action, on purpose.
- Your wallpaper, Aerials included. Optionally shows each display's macOS wallpaper behind the lock screen; Aerials keep moving while plugged in.
- Fade to black. Optionally dims the lock screen to pure black after a while (good for OLED) without sleeping the display.
- Small and native. About 14 MB of Swift. No Electron.
- No analytics. No accounts, and the only network call is the signed update check, plus anything you switch on yourself.
- Dog, cat, or your own. Pick the origami dog or cat, drop in your own image, or show no mascot at all.
Usage
| Action | How |
|--------|-----|
| Lock | Your hotkey (default Cmd+Shift+L) |
| Quick unlock | Same hotkey, or rest a finger on Touch ID |
| Fallback unlock | Click Use Password at the bottom of the lock screen and type your Mac password |
| Settings | Menu bar → Settings… |
| Change hotkey | Settings → General → Shortcut, click to record |
| Change mascot, use your own image, or turn it off | Settings → Lock Screen → Mascot |
| Hide the menu bar icon | Settings → General → Show in menu bar (open Lockpaw from Applications to bring it back) |
| Keep agents running with the lid closed | Settings → General → Keep running with the lid closed |
| Send pings to your phone | Settings → Agents → Send pings off this Mac → Send to |
| Claude's phone pushes only while you're away | Settings → Agents → Claude phone pushes only while away → Set Up |
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 → Agents if you want one (off by default for shared offices).
The lock screen says who is waiting, one quiet line per session: Claude Code 2m, Codex 12m. Each has a dot that's amber while it needs you, teal once it's done, and red on an error. Project names stay off the lock screen, since anyone walking past can read it; turn them on in Settings → Agents. The notification always names the project: Claude Code needs permission in my-app. The glow is teal when your agents are done and amber while any of them is blocked on you or stopped on an error (a red dot marks the error); a later "done" never repaints a waiting glow teal.
Easiest: open Settings → Agents → Connect an agent and click your agent. A check marks the ones already connected.
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 + StopFailure hooks in ~/.claude/settings.json (honors $CLAUDE_CONFIG_DIR); Notification is matched to the types that need you, so auth_success and the like stay quiet |
| Codex CLI | lockpaw install-hook codex | notify in ~/.codex/config.toml for finished, plus a PermissionRequest hook in ~/.codex/hooks.json for waiting. Trust it once via /hooks in Codex (honors $CODEX_HOME). If another tool already uses notify, it keeps running, right after Lockpaw |
| Gemini CLI | lockpaw install-hook gemini | Notification + AfterAgent hooks in ~/.gemini/settings.json |
| Cursor | lockpaw install-hook cursor | stop hook in ~/.cursor/hooks.json (--done) |
| Copilot CLI | lockpaw install-hook copilot | agentStop + notification hooks in ~/.copilot/hooks/lockpaw.json (honors $COPILOT_HOME) |
| Aider | lockpaw install-hook aider | notifications-command in ~/.aider.conf.yml |
| Anything else | append ; lockpaw ping --agent my-tool --done to your command | runs after your agent finishes (--waiting / --error for the other two) |
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.
Claude phone pushes only while you're away
Claude Code's Remote Control can push to
your phone. It skips the push while a marker file exists, if you set
CLAUDE_CLIENT_PRESENCE_FILE (Claude Code
2.1.181 or later). Lockpaw keeps that file for you.
- The file is
~/Library/Application Support/Lockpaw/present. It is empty. - It exists while your Mac is unlocked and awake. Lockpaw removes it when you lock
- It comes back when you unlock.
lockpaw install-hook claude --presence. Both add this to ~/.claude/settings.json
(or $CLAUDE_CONFIG_DIR) next to the Claude hook, with a .bak backup:
"env": { "CLAUDE_CLIENT_PRESENCE_FILE": "/Users/you/Library/Application Support/Lockpaw/present" }
A value you set yourself is never overwritten. Copy Setup puts the line on the clipboard if you'd rather add it by hand. New Claude Code sessions pick it up.
One edge: if Lockpaw crashes while unlocked, the file stays and pushes stay quiet. The next launch fixes it, and it removes the file at once if the screen is locked.
Install
Download
Grab the latest signed & notarized DMG from getlockpaw.com or GitHub Releases.
Homebrew
brew tap sorkila/lockpaw
brew install --cask lockpaw
Build from source
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.
Lockpaw is free and stays free. If it earns its place, you can support Lockpaw: $9 is a fine thank-you, $19 if it saves your afternoons.
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. When an agent pings, the screen breathes two slow waves of light (teal when it's done, amber when it's waiting on you), then keeps a soft glow and a quiet line per agent under the timer 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. Or bring your own: a custom image gets a soft feathered edge so it sits in the same pool of light (transparent backgrounds look best).
Typography. System San Francisco throughout. Regular weight message at 55% white. Monospaced timer at 35%. The screen whispers.
Auth button. Glass material with a subtle border, easy to find without drawing the eye.
Under the hood
Hotkey. CGEvent.tapCreate on a dedicated background thread. Bypasses the LSUIElement activation issue that affects Carbon hotkeys in menu bar apps. The tap consumes the matched keystroke so it never reaches the app in front. Requires Accessibility permission.
Input blocking. A separate CGEventTap intercepts keyboard, scroll, tablet and trackpad-gesture events system-wide while locked, including the Dock's own gesture stream, so a three-finger swipe can't slide another Space in. 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. With the lid closed that isn't enough, so the optional LockpawHelper LaunchDaemon (registered with SMAppService) sets pmset disablesleep while locked and clears it on unlock, at boot, and a minute after the app goes away. Its XPC interface is that one switch, and both ends check each other's code signature. See SECURITY.md.
Auth. While locked, a biometrics-only LAContext is already armed behind the overlay, so the first finger press unlocks with nothing to click. The fallback is a password field on the lock screen itself, checked against your login password through Open Directory and rate-limited to a 30s cooldown after 3 failed attempts. The cover never comes down for it, and while the field is open Lockpaw runs in kiosk mode, so app switching and Force Quit stay blocked even though macOS hides typed keys from the input tap. A rejected finger on the armed sensor costs no attempt: it may be a palm or a bag strap, and Touch ID enforces its own lockout in hardware.
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 accidents: a colleague, a cat, your own muscle memory while agents run. It won't stop someone who means to get in.
What it does
- Overlay at highest system window level
- Event tap blocks all keyboard, scroll and trackpad-gesture input
- Quit is refused while locked
- 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
Ctrl+Cmd+Q.
Found a lock or auth bypass anyway? Please report it privately.
URL scheme
lockpaw://lock Lock the screen
lockpaw://unlock Show the password field (Touch ID is always live)
lockpaw://unlock-password Show the password field
lockpaw://toggle Toggle lock state
Architecture
Lockpaw/
├─ LockpawApp Entry, MenuBarExtra, AppDelegate, onboarding
├─ Controllers/
│ ├─ LockController State machine, lock/unlock orchestration
│ ├─ Authenticator LAContext · armed Touch ID · password check
│ ├─ InputBlocker CGEventTap · keyboard/scroll blocking
│ ├─ HotkeyManager CGEventTap · global hotkey detection
│ ├─ OverlayWindowManager NSWindow · multi-display · shielding level
│ ├─ SleepPreventer IOKit · idle sleep assertion
│ ├─ LidSleepController Lid-closed mode · SMAppService helper · XPC · power cutouts
│ ├─ WebhookRelayController Optional ping relay · ntfy / Pushover / webhook · Keychain
│ └─ AgentNotifier UNUserNotificationCenter · agent-ping notifications
├─ Models/
│ ├─ LockState .unlocked → .locking → .locked → .unlocking
│ ├─ HotkeyConfig Centralized hotkey UserDefaults access
│ ├─ PingDecision Pure agent-ping decision (pulse/notify/sound)
│ ├─ PassiveAuthPolicy Pure armed-Touch-ID rules (arm/re-arm/stand down)
│ ├─ AgentPing Typed ping: hook payload → agent · project · kind (shared with the CLI)
│ ├─ LockdownPolicy Pure gesture lockdown (Space swipes)
│ ├─ LidSleepPolicy Pure lid-closed rules (thermal, battery) + macOS lock handling
│ ├─ WebhookRelay Pure relay request builder + per-session throttle
│ ├─ SupporterLicence Polar key check · supporter state
│ ├─ Mascot Dog/cat/custom/none lock screen preference (+ supporter mascots, seasonal skins)
│ └─ TerminationPolicy Quit is refused while guarded (+ LockStatus mirror)
├─ Views/
│ ├─ LockScreenView Mascot (dog/cat/custom) · agent-ping glow · fallback auth
│ ├─ AmbientScreenView Secondary display gradient animation
│ ├─ MenuBarView Dropdown · lock/unlock/quit
│ ├─ Settings Native toolbar tabs (General, Lock Screen, Agents, About) · 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
LockpawHelper/ Lid-closed mode's root LaunchDaemon (opt-in) · one XPC call: sleep on/off
CI
Pushes to main and PRs run the build and the full unit test suite via GitHub Actions. Shipped DMGs are Developer ID-signed, notarized, and published to GitHub Releases; auto-updates are delivered through Sparkle with EdDSA-signed appcasts.
Support
Everything in Lockpaw is free and MIT-licensed, and everything that ships stays free. No feature is ever moved behind a payment.
If Lockpaw earns its place on your Mac, you can become a supporter (once, $9 or $19 suggested, or pay what you want) or sponsor me on GitHub. Supporters get a few thank-yous: four extra mascots, seasonal skins for the Dog and Cat, and no more asks: Lockpaw asks once, in a small card after it has done its job, and after that at most once a year in the menu bar. Contributors get a supporter licence on the house.
Pairs with
Tintpad is the other half of the loop: one hotkey opens your terminal at the right repo with Claude Code, Codex, or any agent already running. Tintpad starts your agents. Lockpaw covers for you while they run. Also free, also MIT.