emit-fn-key-on-macos について
macOSでKarabiner-ElementsとDriverKit VirtualHIDDeviceを使い、キーの再マッピングから実際のFnイベントを出すためのスキルです。外部ボタンをFn操作に割り当てる手順、検証方法、前提条件、失敗する方法を説明します。
主な機能
- 01Karabiner-ElementsでFnを出力する設定
- 02Apple Top Caseキーコードの使用
- 03Karabiner-EventViewerでイベントを確認
- 04権限とTypeless設定の確認
- 05記録済みのFnマッピング失敗を回避
活用シーン
- 01外部ボタンをTypelessのプッシュトゥトークに割り当て
- 02macOSの音声入力や絵文字ピッカーを起動
- 03アプリが反応しないFnマッピングの診断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill emit-fn-key-on-macosインストール後、Claude Code で/emit-fn-key-on-macosを入力して読み込まれたか確認します。
同梱ファイルCLAUDE.mdreferences/failed-approaches.md
詳細
macOS で実際の Fn キーイベントを送信する
自己進化型スキル:このスキルは使用を通じて改善されます。手順に誤りがある、パラメーターが変わった、回避策が必要だった場合は、後回しにせず、すぐにこのファイルを修正してください。実際に再現できる問題がある場合にのみ更新してください。
Macos の Fn キー(最近の MacBook では「グローブ」キーとも呼ばれます)は特殊です。通常の修飾キーではなく、kCGEventFlagMaskSecondaryFn を伴います。このフラグは、ユーザー空間から CGEventPost 経由で設定すると、macOS の入力サブシステムによって破棄されます。多くの「何でもリマップ」ツールは、Fn が Cmd/Option/Ctrl と同じように動作すると想定し、CGEventPost 経由で送信しようとしますが、音声入力、Typeless、macOS の音声入力ショートカット、グローブキー経由の Spotlight、絵文字ピッカーなどでは、何も起きないまま失敗します。
カーネルが受け入れる Fn をユーザー空間から送信する唯一の方法は、DriverKit VirtualHIDDevice です。Karabiner-Elements はこれを搭載しています。そのため、2026 年時点でこの用途に使える FOSS ツールは Karabiner だけです。
このスキルを使う場面
- ユーザーが、マクロパッドのボタン、マウスボタン、その他の外部キーで次の機能を実行したい場合:
- Typeless のプッシュ・トゥ・トーク(デフォルトでは
pushToTalk: "Fn") - macOS の音声入力(
Fn Fnのダブルタップ、または「システム設定」での単一 Fn) - 絵文字ピッカー(
Fn+E) - グローブキー経由の Spotlight(
Fn) - BTT でリマップすると動作しない、アプリ固有の Fn コンボ
- Typeless のプッシュ・トゥ・トーク(デフォルトでは
- ユーザーから「BTT ではショートカットが実行されたと表示されるのに、Typeless では何も起きない」と報告があった場合
- ユーザーが Fn のマッピングに
hidutil property --setを試しても効果がない場合 - ユーザーがキーボードに QMK/ZMK を書き込んだ後、Fn の送信が動作しない場合
前提条件の確認
# 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.
内蔵キーボードで Fn を押すと動作するのに、リマップ経由では動作しない場合は、DriverKit デーモンは読み込まれていますが、リマップルールに誤りがあります。以下の「唯一の魔法の呪文」に進んでください。内蔵キーボードの Fn まで動作しなくなった場合は、前提条件 3 を再確認してください。
重要な事実
┌───────────────────────────┐ ┌───────────────────────────┐
│ 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 は DriverKit VirtualHIDDevice を登録します。リマップルールで「Fn を送信」と指定すると、ハードウェアキーボードと同じカーネル経路を通じて送信します。NX_DEVICE_CAPABILITY_INPUTKEYBOARD_FUNCTION フラグはそのまま保持されるため、Typeless/音声入力で受け付けられます。
唯一の魔法の呪文
Karabiner の manipulator の to ブロックには、次のように記述します。
{ "apple_vendor_top_case_key_code": "keyboard_fn" }
次のようには記述しません。
- ❌
{"key_code": "fn"}— そのような key_code は存在せず、何も起きないまま無視されます - ❌
{"modifiers": ["fn"]}— キーを押すイベントを伴わない修飾フラグなので、Fn の動作は発生しません - ❌
{"consumer_key_code": "..."}— HID 使用ページが異なります - ❌
{"key_code": "function"}— Karabiner のキーワードではありません
apple_vendor_top_case_key_code 名前空間は、HID Usage Page 0x00FF(Apple Top Case)の Usage 0x03(Keyboard Fn)に対する Karabiner のマッピングです。これは Apple 純正の内蔵キーボードが使う記述子です。
最小限の動作例
Caps Lock キー(特定の外付けキーボードのみを対象にします。VID/PID を調整してください)を、実際の Fn を送信するようにリマップします。
{
"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 }]
}
]
}
]
}
~/.config/karabiner/karabiner.json の profile 0 → complex_modifications.rules に追加します。
動作確認
# 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
EventViewer に正しいイベントが表示されるのに Typeless が反応しない場合:
- Typeless にアクセシビリティ権限があることを確認してください
- Typeless の
app-settings.jsonでpushToTalkが"Fn"に設定されていることを確認してください("fn"でも"Function"でもありません) - Fn を別のツールが取得していないことを確認してください。Fn をトリガーに設定した BTT があると、Typeless がイベントを受け取る前に横取りします
タップと長押し:Fn を押しっぱなしにする対象として設定しないでください
試したパターン:「上部のボタンをタップ → Return、長押し → Fn」を、Karabiner の to_if_alone と to_if_held_down で実現する方法です。
これを行うと、システム全体で Fn が動作しなくなります。2026-04-21 に失敗を確認しました。to_if_held_down: [{"apple_vendor_top_case_key_code": "keyboard_fn"}] を含むルールを読み込んだ後、内蔵キーボードで直接押しても、macOS の標準 Fn キーが Fn を生成しなくなりました。完全なロールバックが必要でした。
原因はまだ不明です。Karabiner の長押し状態機械が、実際のハードウェア Fn イベントと競合する形で Fn フラグを保持している可能性があります。Karabiner の上流で修正されるまでは、Fn には別のボタンを使ってください。
BTT が失敗する理由(1 行で)
BTT の「Trigger Key Sequence」と「Send Shortcut」アクションは、CGEventCreateKeyboardEvent と CGEventSetFlags を使って CGEventPost を呼び出します。フラグ kCGEventFlagMaskSecondaryFn は CGEventSetFlags に受け付けられます(エラーは発生しません)が、配信前に入力イベントマネージャーによって破棄されます。Apple はこの制約をこれまで一度も文書化していませんが、macOS 13/14/15 で一貫して確認されています。
hidutil が失敗する理由
hidutil property --set '{"UserKeyMapping":[...]}' は HID レポートレベルで動作し、キーコードを入れ替えることはできますが、Fn フラグ を合成することはできません。このフラグは、押されたキーに基づいてキーボードドライバー(DriverKit または Apple の内部キーボードドライバー)が設定します。HID レポートレベルでは偽装できません。これは永続化されるプロパティではなく、イベントごとに計算されるプロパティだからです。
QMK を使える書き換え可能なボードで動作する理由(Jieli クラスでは動作しない理由)
Usage Page 0x00FF、Usage 0x03 を通知する実際の USB HID レポートディスクリプターで NKRO + Apple Fn keycode を設定した QMK ボードは、Fn をネイティブに送信できます。これは 実際の ハードウェアレポートであるため、カーネルに受け付けられます。
しかし、安価な Jieli/Realtek/CH57x パッドは書き換えできません。ファームウェアが焼き付けられており、固定の HID ディスクリプター(通常は標準キーボードの Usage Page 0x07)を公開します。ブートローダーが新しいファームウェアを受け付けないため、QMK/VIA/Vial で何度書き換えても動作しません。
書き換え可能なボードについては、こちらをご覧ください:https://github.com/qmk/qmk_firmware → APPLE_FN_ENABLE。
詳細な参考資料
../configure-macro-keyboard/references/03-patterns.md— 完全なルール抜粋を含む「Apple vendor Fn encoding」パターン../configure-macro-keyboard/references/04-anti-patterns.md— BTT のCGEventPostの失敗、Fn のタップと長押しの失敗、Jieli での QMK/VIA の失敗./references/failed-approaches.md— この特定のタスクに関する失敗事例の概要
関連スキル
configure-macro-keyboard— このスキルを 1 つの手順として使う、最初から最後までのセットアップワークフロー(より大きな Karabiner ルール内で、外部マクロパッドのボタンを Fn に割り当てます)diagnose-hid-keycodes— ハードウェアが送信するキーコードがまだ分からない場合は、まずこちらを使用してください。その後でここに戻り、Fn に再マッピングしてください。
実行後の振り返り
このスキルの完了後、タスクを終える前に振り返ってください。
- 現在地を確認します。 — 編集前に、この SKILL.md が正規のファイルであることを確認します。
- 何が失敗しましたか? — 失敗の原因となった指示を修正します。
- 予想以上にうまくいったことは何ですか? — 推奨プラクティスに加えます。
- 何が変わりましたか? — 実情がドキュメントと異なる場合は、ベンダー ID、キーコード、または FOSS ツールのバージョンを更新します。
- 記録します。 — トリガー、修正、根拠を含む進化ログの項目(または
04-anti-patterns.mdの行)を追加します。
先送りしないでください。次回の実行では、あなたが残した状態を引き継ぎます。