macOS menu-bar utility for on-screen F1–F12 keys — hardened runtime, HID event simulation, key profiles
  • Swift 92.7%
  • Shell 7.3%
Find a file
2026-03-16 01:08:54 -05:00
.github docs: add .github/copilot-instructions.md 2026-02-27 15:47:06 -06:00
Assets.xcassets Initial commit 2026-02-14 13:11:37 -06:00
Sources feat(ui): integrate all new features into views and app entry point 2026-02-27 15:48:33 -06:00
.gitignore chore: update .gitignore 2026-03-11 00:15:11 -05:00
AppIcon.icns Initial commit 2026-02-14 13:11:37 -06:00
build.sh feat: add dual-architecture release builds (arm64 + x86_64 DMGs) 2026-02-14 20:11:53 -06:00
example.png Added a screenshot 2026-02-14 13:29:35 -06:00
FnKeyboard.entitlements feat(security): add hardened runtime signing and build integrity checks 2026-02-14 20:02:41 -06:00
generate_icon.swift Initial commit 2026-02-14 13:11:37 -06:00
Info.plist chore: bump version to 1.2.0 2026-02-27 15:48:36 -06:00
LICENSE Initial commit 2026-02-14 13:11:37 -06:00
Package.swift Initial commit 2026-02-14 13:11:37 -06:00
README.md docs: add contact information to README 2026-03-16 01:08:54 -05:00

Fn Keyboard

Example

A lightweight macOS menu-bar utility that puts the Mac function keys (F1F12) at your fingertips. Click an on-screen keycap and the real system action fires — brightness, media controls, volume, and more.

macOS Swift License

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

Grab the latest pre-built app from the Releases page — no build tools required:

  1. Download FnKeyboard.app.zip (or the DMG) from the latest release
  2. Unzip and move FnKeyboard.app to /Applications
  3. 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 keyDown and keyUp events, filter for F1F12 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_LIBRARIES code 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.swift against the committed version before execution
  • --timestamp on 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 (not passRetained) to avoid leaking every system keyboard event, and an isMonitoring guard prevents use-after-teardown if the monitor is deallocated while a callback is in-flight.
  • Rate limitingKeySimulator enforces 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

  1. Verify the source — review the code before building, especially KeyPressMonitor.swift and KeySimulator.swift.
  2. Use a signed build — set CODESIGN_IDENTITY when building for distribution to enable signature verification.
  3. Revoke access when not in use — you can disable Input Monitoring for FnKeyboard in System Settings at any time.

Contributing

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/my-idea)
  3. Commit your changes (git commit -m "Add my idea")
  4. Push to the branch (git push origin feature/my-idea)
  5. Open a Pull Request

Please feel free to reach out at DaniilMurashov@icloud.com

License

MIT