跳转到内容

Karabiner-Elements 使用指南 ​

安装、权限授予与「适合谁」写在软件库页面,本篇不重复,默认你已经完成那一篇的第一次使用练习。

为什么需要它 ​

常用的快捷键组合早就被系统和各种应用占满了。想留一组只属于自己脚本或工作流的全局热键,最稳妥的办法不是找一个「看起来还没被占用」的组合,而是造一个几乎不可能被任何应用注册过的修饰键。

四个修饰键(Control、Option、Command、Shift)同时按住的组合极少出现在任何应用的默认快捷键里——应用作者通常不会要求用户同时按住四个修饰键。于是可以把一个位置好、平时几乎用不到的物理键,改造成「按下时相当于同时按住这四个修饰键」的角色,这个角色就叫 Hyper 键:往后你定义的所有个人热键都以「Hyper 键 + 另一个键」的形式存在,几乎不会和任何应用的快捷键冲突。

系统设置里的「键盘 → 键盘快捷键 → 修饰键」只能做一对一替换(比如把 Caps Lock 换成 Control),换不出「一个键等于四个键同时按下」这种多对一的行为,这正是需要 Karabiner 复杂规则的原因。

开始之前 ​

先备份现有配置,改坏了才有退路:

zsh
cp ~/.config/karabiner/karabiner.json ~/.config/karabiner/karabiner.json.backup

Karabiner 自己也会做一层保护:根据官方发布说明,从 12.2.0 版本起,Karabiner-Elements 在每次写入 karabiner.json 之前,如果当天还没有对应的备份文件,会先在 ~/.config/karabiner/automatic_backups/ 下生成一份 karabiner_YYYYMMDD.json。这意味着即便忘了手动备份,通常也能从这个目录里找到改动前的版本,但它只在「当天首次写入」时生成一份,同一天里的多次修改不会逐次留痕,所以动手前手动备份仍然是更可靠的第一道保险。

救援方式:改键改坏了导致打字不顺手,从菜单栏图标选择 Quit Karabiner-Elements 直接退出——按键立即恢复系统原生行为,不需要先去改配置。动手改之前,先确认自己知道菜单栏图标在哪——真的改坏时才能第一时间找到它退出。用外接键盘练习复杂规则时,先确认内置键盘仍然可用,一旦外接键盘的改键出问题,切回内置键盘不受影响。

操作步骤 ​

1. 简单改键与复杂规则的区别 ​

Karabiner 提供两层配置,软件页第一次使用练习里的 Caps Lock→Escape 用的是第一层:

  • Simple Modifications(简单改键):一个键换成另一个键,没有条件、没有单击/长按区分。适合「我就是想让这个键变成那个键」这种一次性诉求。
  • Complex Modifications(复杂规则):以 JSON 规则描述,一个物理键可以在「单击」「按住」「和其他键一起按」等不同场景下触发不同事件,还能按设备、按前台应用等条件生效。造 Hyper 键必须用这一层,因为需要「按住是修饰键组合、单击是另一个键」这种双重身份。

打开方式:Karabiner-Elements 设置里的 Complex Modifications 标签页,点 Add rule 可以从内置规则库选,也可以点 Add your own rule 直接粘贴 JSON。

2. 造 Hyper 键:双重身份靠 to_if_alone 实现 ​

一条复杂规则最外层是 description 加一个 manipulators 数组,下面是把某个键改造成 Hyper 键、同时保留单击功能的骨架(示例选用 Caps Lock 做说明,你可以换成任何自己不常用的键):

json
{
  "description": "Caps Lock as Hyper key, tap for Escape",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "key_code": "caps_lock",
        "modifiers": { "optional": ["any"] }
      },
      "to": [
        {
          "key_code": "left_shift",
          "modifiers": ["left_command", "left_control", "left_option"]
        }
      ],
      "to_if_alone": [{ "key_code": "escape" }]
    }
  ]
}

按官方文档对各字段的定义:

  • to 是「按下 from 键时发送的事件」,这里发的是一个键(left_shift)搭配另外三个修饰键(modifiers 数组),四者一起在键按下时生效——这就是「按住等于四个修饰键同时按下」的来源。
  • to_if_alone 是「单独按下 from 键时发送的事件」,官方文档说明它在 from 键释放的那一刻触发,并且有两个取消条件:按住期间按了其他键(键盘、鼠标按钮或滚轮),或者按住时间超过一个超时阈值(默认 1000 毫秒,可用 parameters 里的 basic.to_if_alone_timeout_milliseconds 调整)。只要这两个条件都没触发,松开时就会补发 to_if_alone 里的事件。

两者合起来的效果就是「双重身份」:按下瞬间已经在发送四个修饰键,如果这期间你按了别的键,组合出的就是你要的热键;如果只是单击后立刻松开(没有按其他键,也没超时),松开时会额外补发 Escape。

3. 按设备生效:外接键盘和内置键盘用不同规则 ​

笔记本内建键盘和外接键盘的按键习惯往往不一样,可能只想在外接键盘上启用 Hyper 键,内建键盘保持原样。这靠 conditions 里的 device_if / device_unless 实现,官方文档给出的例子是把 Caps Lock 改 Escape 限制在 Apple 键盘或内建键盘上:

json
{
  "description": "Change caps_lock to escape on Apple keyboards",
  "manipulators": [
    {
      "type": "basic",
      "from": { "key_code": "caps_lock", "modifiers": { "optional": ["any"] } },
      "to": [{ "key_code": "escape" }],
      "conditions": [
        {
          "type": "device_if",
          "identifiers": [
            { "vendor_id": 1452 },
            { "vendor_id": 76 },
            { "is_built_in_keyboard": true }
          ]
        }
      ]
    }
  ]
}

规则要点:

  • identifiers 数组里的同一个对象内部是「且」的关系(比如 vendor_id 和 is_keyboard 同时写在一个对象里,两者都要满足),数组里不同对象之间是「或」的关系(上面例子是「任一 vendor_id 匹配,或者是内建键盘」)。
  • vendor_id、product_id 是设备的稳定标识,换 USB 口不会变;location_id 则会随 USB 口变化,官方文档特别提醒不要拿它当长期依据。
  • 想反过来「只在这台设备上不生效」,把 device_if 换成 device_unless 即可,字段结构不变。
  • 自己设备的 vendor_id/product_id 从哪查:打开 Karabiner-EventViewer,切到 Devices 标签页,逐个设备读取。

把这段 conditions 加进第 2 步的 Hyper 键规则里,就能做到「只在外接键盘上把 Caps Lock 变成 Hyper 键,内建键盘的 Caps Lock 保持不动」。

4. 规则 JSON 结构逐字段过一遍 ​

把上面两个例子的字段串起来看,一条完整规则的层级是:

text
{
  "description": "...",       // 人类可读的规则说明,会显示在 Settings 界面里
  "manipulators": [
    {
      "type": "basic",        // 目前唯一常用的类型
      "from": { ... },        // 触发条件:哪个键、要不要求配合修饰键
      "to": [ ... ],           // 按下时发送的事件(数组,可以发多个)
      "to_if_alone": [ ... ], // 单独按下时额外发送的事件(可选)
      "conditions": [ ... ]   // 按设备、按前台应用等条件限定规则何时生效(可选)
    }
  ]
}

from 里的 modifiers 分 mandatory(必须按住,且会被规则「吃掉」,不会出现在 to 里)和 optional(可以按也可以不按,且原样保留、不受影响)两种;optional 写 ["any"] 就是「不管额外按了什么修饰键都不影响触发」。这条规则会挂在某个 profile 的 complex_modifications.rules 数组里,一个 profile 可以同时存在多条规则,先匹配的先生效。

5. 用 EventViewer 核对系统实际收到的键码 ​

改键出了问题,光靠「感觉按下去不对」很难定位是哪一层出的错,Karabiner-EventViewer 是官方文档指出的排查手段:从 Launchpad 或 Karabiner-Elements 设置里打开它,输入事件会实时显示出来。

有一点容易踩坑:EventViewer 默认显示的是经过 Karabiner 修改之后的事件,不是硬件原始发出的事件。比如按下 F1 键,硬件本来发出的是 {"key_code":"f1"},但如果系统把它转成了亮度调节,EventViewer 里看到的会是 {"consumer_key_code":"display_brightness_decrement"}——写规则时该用哪个键码,要以这个「最终形态」为准。如果确实需要看硬件的原始事件(比如怀疑某条规则出问题),在 EventViewer 侧栏选择 Capture Raw Input Events,选中目标设备并点 Start capture,这段时间内该设备会暂时绕过 Karabiner 的所有修改,直接显示原始事件。

检查结果 ​

规则保存后(Karabiner 会自动检测配置文件变化并重新加载,不需要重启应用),自己打开 Karabiner-EventViewer 验证:

  • 按住 Hyper 键并配合其他键(比如按住不放的同时按下 A),EventViewer 里应该能看到修饰键的按下事件加上后续那个键;确认自己定义的组合键在这个前提下确实能触发。
  • 单独点一下 Hyper 键(按下立刻松开,中途不碰其他任何键),应该看到最终发出的是 Escape 对应的事件。
  • 如果配了设备条件,换到另一台没有匹配这个条件的键盘上重复上面两步,确认规则没有跟着生效。

三步都符合预期,说明规则按设计工作;哪一步不对,回到对应字段(to、to_if_alone 或 conditions)检查。

常见问题 ​

系统更新后 Karabiner 突然不生效了。 macOS 大版本更新有时会重置输入监控一类的权限授予。回到软件库页面里描述的权限设置,检查 Karabiner 相关组件是否还在允许列表里,被系统自动移除的话重新勾选即可。

多条规则互相打架,只有一条生效。 同一个 profile 里的规则按 complex_modifications.rules 数组的顺序匹配,排在前面的先生效。如果两条规则的 from 有重叠(比如都盯着同一个键的同一个修饰键组合),把想优先生效的那条挪到数组前面,或者给冲突较窄的那条加上更精确的 conditions 缩小生效范围。

改完配置后整个键盘都不听话了,不是只有改的那一条规则失效。 大概率是手写 JSON 时漏了逗号或括号——一处语法错误会让 Karabiner 无法解析整份配置,导致所有规则(包括之前正常工作的)一起失效,而不是新加的那条单独出问题。恢复:用「开始之前」提到的 karabiner.json.backup(或 ~/.config/karabiner/automatic_backups/ 下最近一份自动备份)覆盖回 ~/.config/karabiner/karabiner.json,重新打开 Karabiner-Elements 确认规则数量恢复正常,再重新、逐条地加回改动。

安全提示 ​

Karabiner 依赖「输入监控」权限运行,技术上它能看到你敲下的每一个键。只从官方渠道下载安装包,不要因为图方便导入来路不明的现成规则集——复杂规则里的 to 不仅能发送按键,还能配置 shell_command 直接执行任意 shell 命令,一份看不懂内容的规则文件导入后,实际上就是在自己的机器上运行了别人写的代码。

动手练习 ​

Hyper 键造好之后,先只绑一个热键(比如「Hyper + 某个字母 = 打开一个常用应用」),正常使用两天,确认没有和任何应用的原生快捷键冲突、EventViewer 里单击 Hyper 键仍然稳定输出 Escape,再考虑逐个添加更多组合。一次性绑一整套热键,出问题时很难定位是哪一条规则导致的。

参考资料 ​