跨平台鍵盤自訂工具 Kanata

 

https://github.com/jtroo/kanata/

GitHub - jtroo/kanata: Improve keyboard comfort and usability with advanced customization

為什麼選Kanata

多年前購入一把支援巨集的60%鍵盤,體會到把方向鍵移到 home row 帶來的效率提升之後,已經完全回不去普通的方向鍵了。
但是絕大部分鍵盤沒辦法自己改配置,於是改用 AutoHotkey 來實作。

直到最近筆電系統改成Ubuntu,才發現AHK在linux下並沒有好的替代方案。經過一陣子的搜尋之後,覺得 Kanata 算是符合自己的需求:

  1. 跨平台
  2. 開源
  3. 文件詳盡

但設定實在是不太直覺,需要手刻設定檔,完全不考慮沒有軟體開發經驗的人。即使本業就是軟體開發,還是弄了好一陣子才能運作。

看到這邊應該會有人想說「都2025了為什麼不用LLM產生就好?」,嗯…我一開始也是這個想法,結果完全是亂寫一通不能動。太好了人類工程師還是有點價值的。

附註1:此篇文章撰寫時是2025/10,使用的版本是1.9.0,如果後面語法更新了請自行參考官方文件。
附註2:找資料時發現這個名稱會被VTuber天音かなた淹沒,建議加上關鍵字 "keyboard remapper"。雖然看了readme之後發現作者是故意的。

安全性問題

由於這種軟體本質上就是一個 key logger ,會記錄所有鍵盤的輸入,所以請自行考量安全性。

我個人用以下的作法稍微加強安全性:

  • 使用稍微舊一點的版本,不使用自動更新,避免供應練攻擊。
  • 不使用admin權限執行(只有windows可以,liunx有別的作法可以參考官方教學)
  • 在防火牆禁止此程式執行任何網路通訊
  • 輸入敏感內容時把這程式kill掉,輸入完再重新啟動。

設定檔

這邊舉一個最簡單的範例「使用Caps lock當作Fn,Fn+Space=Backspace」,可以再搭配官方教學擴充。

Kanata設定檔的基礎語法是Lisp的S-expression, 所以基本語法是 (s1 s2 s3 ...),使用任意數量空白做為分隔。
單行註解是使用兩個分號: ;;

以下開始。

defcfg: 全領設定。如果沒什麼特殊需求,直接設定 "process-unmapped-keys yes" 就好

(defcfg 
    process-unmapped-keys yes
    log-layer-changes yes  ;; remove this line if you don't need debug logging
)

defsrc: 定義來源按鍵清單,所有希望Katana處理的按鍵都要在這邊列出,否則會被跳過(例外:有設定process-unmapped-keys yes)。下面所有按鍵定義都是按照這邊的「順序」來做對應的,所以請記住順序,順序很重要。
按鍵名稱的定義在 mod.rsstr_to_oscodedefault_mappings 函式中。(真是完全沒在管普通使用者的)

(defsrc
    caps ;; capslock key
    Space ;; space key
)

deflayer: 定義第一個layer,至少要有一個layer來處理預設mapping,名字可以自己取,這邊用layer-default。如果沒有要改預設對應的話,把defsrc的內容複製過來就好。
因為要用caps lock做為觸發動作,我們要在caps前面加上 @ 是用來標示它是alias。Alias在kanata中的定義是 觸發動作的來源

(deflayer layer-default
    @caps
    Space
)

deflayer: 定義第二個layer,來處理自己新增的對應表,名字叫做layer-cap-fn。這邊就把Space改成Backspace了。

(deflayer layer-cap-fn
    caps ;; caps
    Backspace ;; Space
)

defalias: 定義alias會觸發的action,格式是(defalias $alias-name1 $action1 ... )
這邊用的action是(layer-while-held $layer-name),如其名,按住的時候會切換到指定的layer。

(defalias 
    caps (layer-while-held layer-cap-fn)
)

執行

設定都打好之後就可以儲存成檔案讓kanata讀入了:

kanata -c my_config.kbc

如果沒什麼error出現的話,應該就可以正常運作了。

安裝

這東西還要安裝?
因為沒有安裝程式,都是binary,要照自己需求參照文件設定。
kanata沒有內建背景執行模式,直接執行會有console window出來。

Windows

windows上有很多wrapper可以用,或是老招headless conhost:

conhost --headless <executable and arguments>

Linux

因為linux有100種distro就有100種坑,請參考 官方教學 在你的distro上自行摸索。
這邊記錄一下我實際操作的步驟(Kubuntu 24.04 LTS, KDE 5)

non-root執行

首先先看看能不能跑起來:

chmod u+x kanata
./kanata --help

測試OK之後開始。新增一個group叫做uinput,把自己加進去

# If uinput already exists or you have to re-run this process:
sudo groupdel uinput
# If no, add uinput with --system
sudo groupadd --system uinput
sudo usermod -aG input $USER
sudo usermod -aG uinput $USER

檢查一下自己有沒有出現在剛剛加的兩個group裡面,沒有的話,重開機看看

groups $USER

去改udev的規則,給剛剛加的group讀uinput device的權限:

# Create /etc/udev/rules.d/99-input.rules
# add the following line
KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"

存檔,重開機讓各module重新載入。檢查一下是不是都設定好了

ls -l /dev/uinput

輸出應該要類似這樣:

crw-rw---- 1 root (date) uinput /dev/uinput

測試看看能不能無sudo執行:

./kanata -c my_config.kbc

中過的坑:kanata提示權限不足,說要檢查執行它的user有沒有加到uinput裡面,檢查後確定有加,最後找了半天發現是 99-input.rules 裡面的內容打錯字了。

systemd service

移動到systemd user config的dir,沒有的話自己建立一個

~/.config/systemd/user

建立一個 kanata.service,記得裡面kanata路徑要換成自己的

[Unit]
Description=Kanata keyboard remapper

[Service]
Type=simple
ExecStart=/home/%u/bin/kanata/kanata -c /home/%u/bin/kanata/config.kbc
Restart=no

[Install]
WantedBy=default.target

啟動deamon看看:

systemctl --user daemon-reload
systemctl --user enable kanata.service
systemctl --user start kanata.service

有異常可以用status看看發生什麼事:

systemctl --user status kanata.service

處理完再restart:

systemctl --user restart kanata.service

這樣應該重開機之後也會自動載入了。

連結與參考資源

追記

這篇文章在2025/10月初就寫好了但忘記發,看到天音かなた的畢業消息才想到這篇草稿的存在,不知道作者還好不好。

留言