See which keys macOS still believes are pressed.
KeyLinger is a small macOS diagnostic utility that queries the current keyboard state instead of reconstructing it from a stream of keydown and keyup events.
That distinction matters. An event listener only knows about events received after it starts. If a remote-desktop session, virtual machine, input utility, or application loses a keyup, opening an event viewer afterwards may be too late. KeyLinger asks macOS what the current session reports right now, so a key that was already stuck can appear on the first poll.
| Event-stream approach | KeyLinger | |
|---|---|---|
| Data source | New key events received after launch | Current key state reported by macOS |
| Key stuck before launch | Usually cannot be inferred | Can be visible immediately |
| Primary purpose | Inspect incoming input events | Diagnose the session's current held-key state |
| History | May retain an event log | Keeps no key history |
Internally, KeyLinger polls:
CGEventSource.keyState(.combinedSessionState, key: keyCode)The default polling rate is 10 Hz and can be set from 2 to 30 Hz. KeyLinger is read-only: it does not synthesize key events or attempt to release a stuck key.
- A modifier, letter, number, or Space remains logically pressed after a remote session.
- An application behaves as though a key is held down, but the source is unclear.
- You want to inspect the current session state without recording what was typed.
- You need to check a suspected stuck key after the problem has already occurred.
The original motivation was diagnosing lost keyup signals in RustDesk sessions; the same state-query approach is useful for any application that appears to have a key stuck down.
- Responsive MacBook/ANSI keyboard map with a clear pressed-key state.
- Key-list view for a compact textual diagnosis.
- Fallback labels for numpad, ISO, JIS, and other keys outside the visual map.
- Normal macOS window layering with visibility across Spaces, plus a persistent menu-bar entry.
- Optional Dock presence with native minimization and reliable click-to-reopen behavior.
- Compact window mode for status-only monitoring.
- Configurable 2–30 Hz polling rate and persistent display preferences.
- English, Simplified Chinese, and Traditional Chinese interface languages.
- Native Apple Silicon and Intel builds.
Download the appropriate DMG from GitHub Releases:
- Apple Silicon: choose the file containing
Apple-Siliconfor M-series Macs. - Intel: choose the file containing
Intel.
Open the DMG and drag KeyLinger.app into Applications.
The current builds use an ad-hoc signature and are not notarized with an Apple Developer ID. On first launch, macOS may block the app. In Finder, Control-click or right-click KeyLinger, choose Open, and confirm the prompt.
- macOS 13 or later.
- Input Monitoring permission is required to reliably read ordinary keys such as letters, numbers, and Space while another application has focus.
- After granting permission, KeyLinger may need to be restarted before background detection becomes available.
KeyLinger shows a permission notice and can open the relevant System Settings page when access is missing.
KeyLinger reads only the set of keys that macOS currently reports as pressed. It does not keep a key-event history, reconstruct typed text, write keyboard data to disk, or upload keyboard data.
The app accesses GitHub only when you manually choose Check for Updates.
Build and open a native app bundle:
./build_app.sh release native
open "dist/KeyLinger.app"Run directly with Swift Package Manager during development:
swift run KeyLingerBuild architecture-specific apps and DMGs:
./build_app.sh release arm64
./scripts/create_dmg.sh arm64
./build_app.sh release x86_64
./scripts/create_dmg.sh x86_64A local universal app can be built with ./build_app.sh release universal. The keyboard-map data can be checked independently with:
swift run KeyLinger --validate-keyboard-layout- KeyLinger reports the logical state of the current macOS session, not the electrical state of the physical keyboard.
- The visual map currently uses a common MacBook/ANSI arrangement. Pressed numpad, ISO, JIS, and other out-of-layout keys appear as fallback labels instead of disappearing.
- Some vendor-specific function keys, Touch Bar actions, and consumer/media keys do not use standard virtual key codes and may not be visible.
- KeyLinger diagnoses a stuck state; it does not forcibly release or modify keys.
KeyLinger is available under the MIT License.