English | 日本語
- Global monitoring — Counts all keystrokes regardless of the active application
- Menu bar statistics — Today's count, total count, average keystroke interval
- Show All — Full ranked list of every key with total and today's counts
- Charts — Four interactive views: Top 20 Keys, Daily Totals, Key Categories, Top 10 per Day
- Keystroke Overlay — Real-time floating window showing recent keystrokes (⌘C / ⇧A style)
- Download KeyLens.dmg
- Open the DMG and drag KeyLens.app to
/Applications - Launch the app — grant Accessibility permission when prompted
Note: The app uses an ad-hoc signature and is intended for personal use. Gatekeeper may warn on first launch — right-click the app and choose Open to bypass.
| Item | Requirement |
|---|---|
| macOS | 13 Ventura or later |
| Swift | 5.9 or later (bundled with Xcode 15) |
| Permission | Accessibility (prompted on first launch) |
| Details | |
|---|---|
| Records | Key names (e.g. Space, e) and mouse button names with press counts only |
| Does NOT record | Typed text, sequences, passwords, clipboard content, or cursor position |
| Storage | Local JSON file only — no network transmission |
| Event access | .listenOnly tap — read-only, cannot inject or modify keystrokes |
Full risk summary
| Area | Risk | Mitigation |
|---|---|---|
| Global key monitoring | High (by nature) | .listenOnly + tailAppendEventTap — passive only |
| Data content | Low | Key name + count only; typed text cannot be reconstructed |
| Data file | Medium | Unencrypted; readable by any process running as the same user |
| Network | None | No outbound connections |
| Code signing | Medium | Ad-hoc only; Gatekeeper blocks distribution to other users |
~/Library/Application Support/KeyLens/counts.json
Use Settings… > Open Log Folder to open the directory in Finder. See Architecture for the schema.
./build.sh # Build App Bundle only
./build.sh --run # Build and launch immediately
./build.sh --install # Build, install to /Applications, codesign, reset TCC, launch ← recommended
./build.sh --dmg # Build distributable DMGAlways use
build.sh— runningswift buildalone won't produce a working notification bundle.
What --install does
| Step | What it does |
|---|---|
cp -r KeyLens.app /Applications/ |
Installs to /Applications |
codesign --force --deep --sign - |
Ad-hoc signature (stabilizes Accessibility permission) |
pkill -x KeyLens |
Stops the running process before replacing the binary |
tccutil reset Accessibility <bundle-id> |
Clears the stale TCC entry for the old binary hash |
open /Applications/KeyLens.app |
Launches the new build |
Why TCC reset is needed: macOS stores Accessibility permissions keyed by binary hash. Each swift build produces a new binary, making the old TCC entry stale. Without resetting, AXIsProcessTrusted() returns false even though the toggle appears ON in System Settings.
Logs
tail -f ~/Library/Logs/KeyLens/app.logAn alert is shown on first launch if the permission is missing.
- Click Open System Settings
- Go to Privacy & Security > Accessibility
- Enable KeyLens
- Switch back to any app — monitoring resumes instantly
Recovery mechanism (layered):
| Trigger | Latency |
|---|---|
App becomes active (didBecomeActiveNotification) |
~instant |
| Permission retry timer | every 3 s |
| Health check timer | every 5 s |
For internal design details, see Architecture. For the development roadmap, see Roadmap.
Feedback Welcome! Feel free to open an issue for anything — bug reports, feature requests, or just a simple question. We’d love to hear from you.

