بنقرة واحدة
karabiner
// Configure Karabiner-Elements keyboard remapping using Goku EDN syntax. Use when creating keybindings, layers, simlayers, app-specific shortcuts, or modifying karabiner.edn.
// Configure Karabiner-Elements keyboard remapping using Goku EDN syntax. Use when creating keybindings, layers, simlayers, app-specific shortcuts, or modifying karabiner.edn.
Always search before starting any work across all coding agent session histories (Claude Code, Codex, Cursor, Gemini CLI, Aider, ChatGPT) to find whatever we've discussed before.
Spawn 5 Opus subagents with randomly-generated distinct personas to debate a problem from multiple angles. Use when exploring UX decisions, architecture choices, or any decision that benefits from diverse perspectives arguing creatively.
Query DeepWiki for repository documentation and structure. Use to understand open source projects, find API docs, and explore codebases.
Bundle code context for AI. ALWAYS use --limit 49k unless user explicitly requests otherwise. Use for creating shareable code bundles and preparing context for LLMs.
Build Raycast extensions with React and TypeScript. Use when the user asks to create a Raycast extension, command, or tool.
Create new Agent Skills for Claude Code. Use when user wants to create a skill, add a new capability, document a CLI workflow, or asks how skills work.
| name | karabiner |
| description | Configure Karabiner-Elements keyboard remapping using Goku EDN syntax. Use when creating keybindings, layers, simlayers, app-specific shortcuts, or modifying karabiner.edn. |
Configure macOS keyboard remapping with GokuRakuJoudo - an EDN-based DSL that compiles to Karabiner-Elements JSON.
Karabiner's native JSON is verbose (20,000+ lines). Goku's EDN format is 10-50x more concise:
;; Goku: 1 line
[:caps_lock :escape]
;; Karabiner JSON: ~30 lines
# Install Goku
brew install yqrashawn/goku/goku
# Start as service (watches ~/.config/karabiner.edn)
brew services start goku
# Or run once manually
goku
Config location: ~/.config/karabiner.edn
Logs: ~/Library/Logs/goku.log
{:main [{:des "Rule description"
:rules [[:from :to]
[:from2 :to2]]}]}
All keys use keyword syntax: :a, :1, :f19, :spacebar, :return_or_enter
Find keycodes:
| Symbol | Modifier | Example |
|---|---|---|
!C | Left Command | :!Ca = Cmd+A |
!T | Left Control | :!Ta = Ctrl+A |
!O | Left Option | :!Oa = Opt+A |
!S | Left Shift | :!Sa = Shift+A |
!Q | Right Command | :!Qa |
!W | Right Control | :!Wa |
!E | Right Option | :!Ea |
!R | Right Shift | :!Ra |
!F | Fn | :!Fa |
!P | Caps Lock | :!Pa |
!! | Hyper (Cmd+Ctrl+Opt+Shift) | :!!a |
## | Optional any modifier | :##a |
Combine modifiers: :!CTSa = Cmd+Ctrl+Shift+A
[:from :to] ;; Basic
[:from :to :condition] ;; With condition
[:from :to :condition {:alone :x}] ;; With options
;; Press sequence
[:a [:1 :2 :3]] ;; a -> types 1, 2, 3
;; Simultaneous press (from)
[[:j :k] :escape] ;; j+k together -> escape
[:!!1 "open -a Safari"] ;; Hyper+1 runs shell command
{:applications {:chrome ["^com\\.google\\.Chrome$"]
:code ["com.microsoft.VSCode"]}
:main [{:des "Chrome only"
:rules [[:a :b :chrome]]}]}
{:devices {:hhkb [{:vendor_id 1278 :product_id 51966}]}
:main [{:rules [[:a :b :hhkb]]}]}
{:input-sources {:us {:input_source_id "com.apple.keylayout.US"}}
:main [{:rules [[:a :b :us]]}]}
[:a :b [:chrome :hhkb]] ;; Both conditions
[:a :b [:!chrome]] ;; NOT in Chrome
Fast, simultaneous-key based layers - best for typing speed:
{:simlayers {:w-mode {:key :w}} ;; Hold W activates layer
:main [{:des "w-mode shortcuts"
:rules [:w-mode ;; Apply to this layer
[:e "open -a Finder"] ;; W+E opens Finder
[:r "open -a Safari"] ;; W+R opens Safari
]}]}
Simlayer options:
{:simlayers {:w-mode {:key :w
:modi {:mandatory [:left_control]}}}} ;; Ctrl+W activates
Different behavior on tap vs hold:
{:layers {:caps-mode {:key :caps_lock
:alone {:key :escape}}}} ;; Tap=Esc, Hold=layer
;; Set variable on keydown, clear on keyup
[:w ["w-mode" 1] nil {:afterup ["w-mode" 0] :alone :w}]
;; Use the variable as condition
[:e :!Ce ["w-mode" 1]] ;; W+E -> Cmd+E (only when w-mode=1)
Reusable shell command patterns:
{:templates {:open "open -a '%s'"
:launch "/path/to/script.sh %s"
:alfred "osascript -e 'tell application \"Alfred\" to run trigger \"%s\"'"}
:main [{:rules [[:!!1 [:open "Safari"]] ;; %s replaced with Safari
[:!!2 [:launch "arg1"]]]}]}
{:froms {:delete {:key :delete_or_backspace}
:return {:key :return_or_enter}
:mouse1 {:pkey :button1}}}
{:tos {:spotlight {:key :spacebar :modi :command}
:paste {:key :v :modi :command}
:shift-click {:pkey :button1 :modi :left_shift}}}
{:modifiers {:hyper [:command :shift :control :option]
:meh [:shift :control :option]}}
Fourth position in rules:
[:from :to :condition {
:alone :key ;; to_if_alone
:held :key ;; to_if_held_down
:afterup :key ;; to_after_key_up
:delayed {:invoked :x :canceled :y}
:params {:alone_timeout 200}
}]
{:profiles {:Default {:default true
:sim 250 ;; Simultaneous threshold (ms)
:delay 500 ;; Delayed action time (ms)
:alone 1000 ;; to_if_alone timeout (ms)
:held 500}}} ;; Held threshold (ms)
{:main [{:des "Caps to Escape"
:rules [[:caps_lock :escape]]}]}
{:applications {:chrome ["com.google.Chrome"]}
:main [{:des "Chrome shortcuts"
:rules [[:!Cl :!Ct :chrome]]}]} ;; Cmd+L -> Cmd+T in Chrome
{:simlayers {:nav {:key :spacebar}}
:main [{:des "Navigation layer"
:rules [:nav
[:h :left_arrow]
[:j :down_arrow]
[:k :up_arrow]
[:l :right_arrow]]}]}
{:main [{:des "Caps Lock to Hyper"
:rules [[:caps_lock :!CTOSleft_shift nil {:alone :escape}]]}]}
goku # Compile karabiner.edn once
gokuw # Watch mode (compile on change)
goku -h # Help
# Service management
brew services start goku # Start watch service
brew services stop goku # Stop service
brew services restart goku # Restart after changes
# Check logs
tail -f ~/Library/Logs/goku.log
~/.config/karabiner/karabiner.jsontail ~/Library/Logs/goku.log:des tags:froms/:tos for complex key definitions