emit-fn-key-on-macos
Emit a real Fn key on macOS (for Typeless push-to-talk, macOS dictation, screenshot shortcuts, emoji picker, Spotlight via.
What this skill does
# Emit a Real Fn Key on macOS
> **Self-Evolving Skill**: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Macos's Fn key (also called the "globe" key on modern MacBooks) is special. It's not a regular modifier — it carries `kCGEventFlagMaskSecondaryFn`, a flag that macOS's input subsystem **discards if set from userland via `CGEventPost`**. Many "remap anything" tools assume Fn behaves like Cmd / Option / Ctrl and try to emit it via `CGEventPost` — and silently fail for dictation, Typeless, macOS's dictation shortcut, Spotlight-via-globe, emoji picker, etc.
The only userland path that emits a Fn the kernel accepts is a **DriverKit VirtualHIDDevice**. Karabiner-Elements ships one. That's why Karabiner is the only FOSS tool for this job in 2026.
## When to Use This Skill
- User wants a macro-pad button, mouse button, or any external key to trigger:
- **Typeless** push-to-talk (`pushToTalk: "Fn"` by default)
- macOS dictation (`Fn Fn` double-tap, or single-Fn in System Settings)
- Emoji picker (`Fn+E`)
- Spotlight-via-globe (`Fn`)
- App-specific Fn combos that don't work when remapped by BTT
- User reports "BTT says the shortcut is firing but nothing happens in Typeless"
- User tries `hidutil property --set` with Fn mappings and sees no effect
- User flashed QMK/ZMK on a board and Fn emission is broken
## Prerequisite Check
```bash
# 1. Karabiner-Elements installed (the only userland tool that can emit real Fn)?
test -d /Applications/Karabiner-Elements.app && echo OK || brew install --cask karabiner-elements
# 2. Karabiner has Input Monitoring + Accessibility?
# System Settings → Privacy & Security → Input Monitoring → Karabiner = ON
# System Settings → Privacy & Security → Accessibility → Karabiner = ON
# 3. On macOS Sequoia+: privileged daemon approved in Login Items?
# System Settings → General → Login Items → Allow in the Background
# → Karabiner-Elements Privileged Daemon = ON
# Without this, Karabiner's DriverKit VirtualHIDDevice won't load and
# your Fn remap will silently do nothing.
```
If Fn already works when pressed on your built-in keyboard but not via a remap, the DriverKit daemon is loaded but the remap rule is wrong — jump to "The One Magic Incantation" below. If even the built-in Fn stops working, re-check prerequisite 3.
## The Core Truth
```
┌───────────────────────────┐ ┌───────────────────────────┐
│ Real Fn (from keyboard) │ │ Fn via CGEventPost(...) │
│ Hardware → DriverKit → │ │ Userland app → Quartz → │
│ HIDEvent with │ │ kCGEventFlagMaskSecon- │
│ NX_DEVICE_CAPABILITY_ │ │ daryFn flag is DROPPED │
│ INPUTKEYBOARD_FUNCTION │ │ before reaching input │
│ flag set │ │ subsystem. │
│ │ │ │
│ ✅ Typeless / dictation │ │ ❌ Typeless / dictation │
│ accept it. │ │ never fire. │
└───────────────────────────┘ └───────────────────────────┘
```
**Karabiner-Elements** registers a DriverKit VirtualHIDDevice. When its remap rule says "emit Fn", it does so through the same kernel path a hardware keyboard uses. The `NX_DEVICE_CAPABILITY_INPUTKEYBOARD_FUNCTION` flag survives and Typeless/dictation accept it.
## The One Magic Incantation
In a Karabiner manipulator's `to` block:
```json
{ "apple_vendor_top_case_key_code": "keyboard_fn" }
```
Not:
- ❌ `{"key_code": "fn"}` — no such key_code, silently ignored
- ❌ `{"modifiers": ["fn"]}` — modifier flag without a key-down, doesn't trigger Fn semantics
- ❌ `{"consumer_key_code": "..."}` — wrong HID usage page
- ❌ `{"key_code": "function"}` — not a Karabiner keyword
The `apple_vendor_top_case_key_code` namespace is Karabiner's mapping for HID Usage Page `0x00FF` (Apple Top Case) with Usage `0x03` (Keyboard Fn). That's the descriptor Apple's own internal keyboard uses.
## Minimal Working Example
Remap the Caps Lock key (on a specific external keyboard only — adjust VID/PID) to emit real Fn:
```json
{
"description": "Caps Lock → Fn (on external keyboard)",
"manipulators": [
{
"type": "basic",
"from": { "key_code": "caps_lock" },
"to": [{ "apple_vendor_top_case_key_code": "keyboard_fn" }],
"conditions": [
{
"type": "device_if",
"identifiers": [{ "vendor_id": 19530, "product_id": 16725 }]
}
]
}
]
}
```
Drop into `~/.config/karabiner/karabiner.json` → profile 0 → `complex_modifications.rules`.
## Verification
```bash
# Open Karabiner-EventViewer
open -a "Karabiner-EventViewer"
# Press your remapped key; the Main tab should show:
# name: fn (not apple_vendor_top_case_key_code)
# ↑ Karabiner normalizes the display back to "fn" but under the hood it's emitting
# the Apple-Top-Case variant that carries the kernel flag.
# Then test the real consumer (e.g., Typeless with pushToTalk: "Fn"):
# Press and hold → mic opens
# Release → mic closes, transcript appears
```
If EventViewer shows the right event but Typeless doesn't fire:
1. Check Typeless has Accessibility permission
2. Confirm `pushToTalk` in Typeless `app-settings.json` is set to `"Fn"` (not `"fn"`, not `"Function"`)
3. Confirm no other tool is also grabbing Fn — BTT with a Fn trigger will steal the event before Typeless sees it
## Tap-vs-Hold: Do NOT Set Fn as a Held-Down Target
Attempted pattern: "tap top button → Return, hold top button → Fn" using Karabiner's `to_if_alone` + `to_if_held_down`.
**This breaks Fn system-wide**. Verified failure 2026-04-21: after loading a rule with `to_if_held_down: [{"apple_vendor_top_case_key_code": "keyboard_fn"}]`, macOS's native Fn key stopped producing Fn even when pressed directly on the built-in keyboard. Full rollback required.
The reason is still unclear — possibly Karabiner's held-down state-machine holds the Fn-flag in a way that conflicts with real hardware Fn events. Until Karabiner upstream fixes it, use a separate button for Fn.
## Why BTT Fails (One-Line Version)
BTT's "Trigger Key Sequence" and "Send Shortcut" actions go through `CGEventPost` with `CGEventCreateKeyboardEvent` + `CGEventSetFlags`. The flag `kCGEventFlagMaskSecondaryFn` is accepted by `CGEventSetFlags` (no error) but dropped by the input event manager before delivery. Apple has never documented this constraint; it's consistent across macOS 13 / 14 / 15.
## Why hidutil Fails
`hidutil property --set '{"UserKeyMapping":[...]}'` operates at the HID report level and can swap keycodes, but it cannot synthesize the Fn _flag_. The flag is set by the keyboard driver (DriverKit or Apple's internal keyboard driver) based on which key was pressed — you can't forge it at the HID report level because it's a per-event computed property, not a persisted one.
## Why QMK on Flashable Boards Can Work (but Jieli-Class Can't)
A QMK board with `NKRO + Apple Fn keycode` on an actual USB HID report descriptor that advertises `Usage Page 0x00FF`, `Usage 0x03` can emit Fn natively. The kernel accepts it because it's a _real_ hardware report.
But **cheap Jieli/Realtek/CH57x pads are not flashable** — their firmware is burned in and exposes a fixed HID descriptor (usually standard keyboard Usage Page `0x07`). No amount of reflashing with QMK/VIA/Vial works because the bootloader won't accept new firmware.
For flashable boards see: <https://github.com/qmk/qmk_firmware> → `APPLE_FN_ENABLE`.
## Deep References
- [`../configure-macro-keyboard/references/03-patterns.md`](../configure-macro-keyboard/references/03-patterns.md) — "Apple vendor Fn encoding" pattern with full rule excerpt
- [`../configure-macro-keyboard/references/04-anti-patterns.md`](../configure-macro-keyboard/references/04-anti-patterns.md) — BTT `CGEventPostRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.