Fn Keyboard
March 16, 2026 · View on GitHub

A lightweight macOS menu-bar utility that puts the Mac function keys (F1–F12) at your fingertips. Click an on-screen keycap and the real system action fires — brightness, media controls, volume, and more.
Features
- Menu-bar only — lives in the status bar with a keyboard icon, no Dock clutter
- Beautiful popover — all 12 function keys grouped like a real Mac keyboard
- SF Symbols — each key shows the matching system icon and label
- Animations — hover highlight and spring-press feedback
- Dark / Light mode — colors automatically adapt to your system appearance
- Real key simulation — tapping a keycap triggers the actual system function via HID / CGEvent
- Physical key monitoring — detects which F-keys are physically held down (requires Accessibility permission)
- Security hardened — hardened runtime, code signing, rate limiting, and memory-safe event handling
Requirements
| Requirement | Minimum |
|---|---|
| macOS | 13.0 Ventura |
| Xcode CLI Tools | xcode-select --install |
Installation
Download (recommended)
Grab the latest pre-built app from the Releases page — no build tools required:
- Download FnKeyboard.app.zip (or the DMG) from the latest release
- Unzip and move FnKeyboard.app to
/Applications - Open the app — grant Input Monitoring when prompted
Build from source
git clone https://github.com/<your-username>/FnKeyboard.git
cd FnKeyboard
chmod +x build.sh
./build.sh
open build/arm64/FnKeyboard.app # or build/x86_64/ on Intel
Create release DMGs (both architectures)
./build.sh --release
# → release/FnKeyboard-macos-arm64.dmg (Apple Silicon)
# → release/FnKeyboard-macos-x86_64.dmg (Intel)
For distribution builds, sign with a Developer ID:
CODESIGN_IDENTITY="Developer ID Application: Your Name" ./build.sh --release
Create a single-architecture DMG
./build.sh --dmg
# → build/FnKeyboard.dmg (current architecture only)
Permissions
On first launch, macOS will prompt you for Input Monitoring (Accessibility). This is required so the app can detect physical key presses and simulate system actions.
System Settings → Privacy & Security → Input Monitoring — enable FnKeyboard.
Project Structure
FnKeyboard/
├── Sources/
│ ├── FnKeyboardApp.swift # @main entry — NSStatusItem + NSPopover
│ ├── FunctionKey.swift # Data model & static key definitions
│ ├── FunctionKeyView.swift # Individual keycap SwiftUI component
│ ├── KeyboardView.swift # Main popover layout (header, keys, footer)
│ ├── KeyPressMonitor.swift # CGEvent tap for physical key detection
│ └── KeySimulator.swift # HID / CGEvent key simulation
├── Assets.xcassets/ # App icon asset catalog
├── FnKeyboard.entitlements # Hardened Runtime entitlements (no exceptions)
├── Info.plist # App metadata (LSUIElement = true)
├── Package.swift # Swift Package Manager manifest
├── build.sh # Build + codesign + DMG (single or dual-arch)
├── generate_icon.swift # Standalone script to generate AppIcon.icns
└── LICENSE
Usage
| Action | How |
|---|---|
| Open | Click the ⌨️ icon in the menu bar |
| Trigger a key | Click any keycap in the popover |
| Dismiss | Click anywhere outside the popover |
| Quit | Click the ⌨️ icon → Quit button |
Security
FnKeyboard requires powerful system permissions to function. Please read the following so you understand the trade-offs.
Permissions & Privilege
| Permission | Why it's needed | What it grants |
|---|---|---|
| Input Monitoring (Accessibility) | Detect physical F-key presses via a CGEvent tap | Read access to all keyboard events system-wide |
| Accessibility — Event Injection | Simulate brightness, media, and volume controls | Ability to post arbitrary HID and CGEvent key events |
macOS bundles both capabilities into a single Accessibility permission — they cannot be requested separately.
No App Sandbox
The app runs unsandboxed because the CGEvent tap and HID event APIs are not available inside the App Sandbox. This means the process has unrestricted access to the filesystem, network, and other user-level resources.
What the App Does — and Does NOT Do
- Does: Intercept
keyDownandkeyUpevents, filter for F1–F12 key codes only, and discard everything else immediately. - Does NOT: Log, store, transmit, or retain any keystroke data. No network connections are made. No data leaves the process.
Hardened Runtime
The app is code-signed with Hardened Runtime and zero entitlement exceptions, which protects against:
DYLD_INSERT_LIBRARIEScode injection- Unsigned executable memory (JIT)
- Debugger attachment by non-root processes
Build Integrity
The build script (build.sh) includes:
- SHA-256 verification of
generate_icon.swiftagainst the committed version before execution --timestampon distribution code signatures for notarization support- A warning when falling back to ad-hoc signing (not suitable for distribution)
Runtime Protections
- Event tap memory safety — the CGEvent tap callback uses
passUnretained(notpassRetained) to avoid leaking every system keyboard event, and anisMonitoringguard prevents use-after-teardown if the monitor is deallocated while a callback is in-flight. - Rate limiting —
KeySimulatorenforces a minimum 150 ms interval between simulated presses per key, preventing event flooding from rapid automated clicks. - Tap debouncing — the UI debounces on-screen key taps (200 ms) as a second layer of defense against rapid input.
Recommendations for Users
- Verify the source — review the code before building, especially KeyPressMonitor.swift and KeySimulator.swift.
- Use a signed build — set
CODESIGN_IDENTITYwhen building for distribution to enable signature verification. - Revoke access when not in use — you can disable Input Monitoring for FnKeyboard in System Settings at any time.
Contributing
- Fork the repo
- Create a feature branch (
git checkout -b feature/my-idea) - Commit your changes (
git commit -m "Add my idea") - Push to the branch (
git push origin feature/my-idea) - Open a Pull Request
Please feel free to reach out at DaniilMurashov@icloud.com