Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time

Examples

Examples for users to check as quick reference and source of inspiration. Most docs are comments (starting with ;;) in the code blocks.

minimal configuration

Below is the minimal configuration. It does nothing. Make sure you have a profile named “Default” in karabiner.json.

{}

swap key

fromto
;:
shift + ;;
command + ;command + ;
option + ;option + ;
control + ;control + ;
{:main [{:des   "swap ; :"
         :rules [[:semicolon :!Ssemicolon]
                 [:!Ssemicolon :semicolon]]}]}

You can find all keycodes here or using the Karabiner-EventViewer.app.

modifier keys

{:main [{:des   "demo modifier keys"
         :rules [
                 ;; shift 1 to 1
                 ;; !S here means shift
                 [:!S1 :1]
                 ;; 1 to !
                 [:1 :!S1]
                 ;; control shift 1 to 12
                 ;; !TS means control shift
                 [:!TS1 [:1 :2]]]}]}

;; C T O S stands for left_command left_control left_option left_shift
;; Q W E R stands for right_command right_control right_option right_shift

;;;; hyper
;; !! stands for left_command + left_control + left_option + left_shift
;; :!!1 left_command + left_control + left_option + left_shift + 1

right_command to f16

fromto
right_commandf16
left_command + right_commandleft_command + f16
option + right_commandoption + f16
shift + right_commandshift + f16
control + right_commandcontrol + f16
{:main [{:des   "right_command to f16"
         :rules [[:##right_command :f16]]}]}

Note: Other modifier keys work because of the ”##” prefix. If you replace ## with #C (C for left_command), only

> left_command + right_command -> left_command + f16 will work.

Others combinations would simply act like

> control + right_command -> control + right_command

caps_lock to ESC when pressed alone, to ctrl as modifier

{:main [{:des   "caps_lock to esc when pressed alone, to ctrl as modifier"
         :rules [[:##caps_lock :left_control nil {:alone :escape}]]}]}

press j and l simultaneously to f16

{:main [{:des   "press j and l simultaneously to f16"
         :rules [[[:j :l] :f16]]}]}

using a regular key as a modifier key

simlayer, templates example

{:templates {:open "open \"%s\""}
 :layers    {}
 :simlayers {;; make w key a simlayer key
             ;; layers works too, but only recommended for none typing keys
             ;; like . , tab
             ;; or keys like z, which used less often
             :launch-mode {:key :w}}
 :main      [{:des   "launch mode"
              :rules [:launch-mode
                      [:k [:open "/Applications/Emacs.app"]]
                      [:l [:open "/Applications/Google Chrome.app"]]]}]}

same as below config, all conditions (layer, simlayer, application, input-source, device) works this way.

{:templates {:open "open \"%s\""}
 :layers    {}
 :simlayers {:launch-mode {:key :w}}
 :main      [{:des   "launch mode"
              :rules [[:k [:open "/Applications/Emacs.app"] :launch-mode]
                      [:l [:open "/Applications/Google Chrome.app"] :launch-mode]]}]}

layer example

{:templates {:open   "open \"%s\""
             :alfred "osascript -e 'tell application \"Alfred 3\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"}
 :layers    {:alfred-layer {:key :z}}
 :simlayers {:launch-mode {:key :w}}
 :main      [{:des   "launch mode"
              :rules [:launch-mode
                      [:k [:open "/Applications/Emacs.app"]]
                      [:l [:open "/Applications/Google Chrome.app"]]]}

             {:des   "alfred mode"
              :rules [:alfred-mode
                      [:h [:alf "search repos" "me.lachlan.githubjump"]]
                      [:x [:alf "killProcess" "com.ngreenstein.alfred-process-killer"]]]}]}

below config works as well

{:templates {:open   "open \"%s\""
             :alfred "osascript -e 'tell application \"Alfred 3\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"}
 :layers    {:alfred-layer {:key :z}}
 :simlayers {:launch-mode {:key :w}}
 :main      [{:des   "character key as modifier key rules"
              :rules [:launch-mode
                      [:k [:open "/Applications/Emacs.app"]]
                      [:l [:open "/Applications/Google Chrome.app"]]
                      :alfred-mode ;; all conditions works this way
                      [:h [:alf "search repos" "me.lachlan.githubjump"]]
                      [:x [:alf "killProcess" "com.ngreenstein.alfred-process-killer"]]]}]}

use left_control+w as simlayer key

{:templates {:open   "open \"%s\""
             :alfred "osascript -e 'tell application \"Alfred 3\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"}
 :layers    {:alfred-layer {:key :z}}
 :simlayers {:launch-mode {:key :w
                           ;; can omit the vector if only one modifier is used
                           ;; :modi {:mandatory :left_control}

                           ;; more examples
                           ;; :modi {:optional :any}
                           ;; :modi {:optional [:left_shift :left_command]
                           ;;        :mandatory :left_control}
                           :modi {:mandatory [:left_control]}}}
 :main      [{:des   "character key as modifier key rules"
              :rules [:launch-mode
                      ;; lctrl down and w+k run shell script "open /Applications/Emacs.app"
                      [:k [:open "/Applications/Emacs.app"]]
                      [:l [:open "/Applications/Google Chrome.app"]]
                      :alfred-mode ;; all conditions works this way
                      [:h [:alf "search repos" "me.lachlan.githubjump"]]
                      [:x [:alf "killProcess" "com.ngreenstein.alfred-process-killer"]]]}]}

custom variable

{:main [{:des   "alfred"
         :rules [;; set f16 as the trigger key of alfred
                 ;; press h + l will trigger alfred and set "in-alfred" to 1
                 [[:h :j] [:f16 ["in-alfred" 1]]]

                 :in-alfred ;; when "in-alfred" is 1

                 ;; press enter will select one alfred result and set "in-alfred" to 0
                 [:##return_or_enter [:return_or_enter ["in-alfred" 0]]]

                 ;; press esc will exit alfred and set "in-alfred" to 0
                 [:##escape [:escape ["in-alfred" 0]]]

                 ;; press ctrl + j will invoke down_arrow
                 [:!Tj :down_arrow]

                 ;; press ctrl + k will invoke up_arrow
                 [:!Tk :up_arrow]

                 ;; press ctrl + l will invoke return_or_enter and set "in-alfred" to 0
                 [:!Tl [:return_or_enter ["in-alfred 0"]]]]}]}

double-tap right shift twice to enter double shift mode

{:des   "Press right_shift twice to enter double shift mode, press right_shift once to leave it"
                       :rules [[:right_shift ["double-right-shift-mode" 1] ["shift-pressed-once" 1]]
                               [:right_shift [:right_shift ["shift-pressed-once" 1]] ["double-right-shift-mode" 0] {:delayed {:invoked ["shift-pressed-once" 0] :canceled ["shift-pressed-once" 0]}}]
                               :double-right-shift-mode
                               [:right_shift ["double-right-shift-mode" 0]]
                               [:a "say 'know we are in double shift mode'"]]}

use the multitouch feature

{:des "ctrl+y to command+v (trackpad example)"
 :rules
 [;; ctrl+y to command+v
  [:!Ty :!Cv]
  ;; ctrl+y to command+v when one finger on trackpad
  [:!Ty :!Cv :multitouch_extension_finger_count_total]
  ;; ctrl+y to command+v when one finger on trackpad
  [:!Ty :!Cv ["multitouch_extension_finger_count_total" 1]]
  ;; ctrl+y to command+v when two finger on trackpad
  [:!Ty :!Cv ["multitouch_extension_finger_count_total" 2]]
  ;; ctrl+y to command+v when three finger on the upper half of trackpad
  [:!Ty :!Cv ["multitouch_extension_finger_count_upper_half_area" 3]]]}

This syntax don’t support specify negative multitouch conditions. For example:

Don't map a to b when there are three fingers on the trackpad.

device, input-method, application conditions

{:layers        {:z-mode {:key :z}}
 :devices       {;; define devices
                 ;; vendor_id and product_id can be found in Karabiner EventViewer gui
                 :hhkb [{:vendor_id 2131 :product_id 256}]}
 :applications  {;; define applications
                 :Browsers [;; these strings are regex to match applications bundle_identifiers
                            ;; you can find bundle_identifiers in the Info.plist file of an applications
                            ;; eg. in /Applications/Mail.app/Contents/Info.plist
                            ;; search for "CFBundleIdentifier"
                            ;; you can also find bundle_identifiers using command line:
                            ;; osascript -e 'id of app "Google Chrome"'
                            "^org\\.mozilla\\.firefox$"
                            "^org\\.mozilla\\.firefoxdeveloperedition$"
                            "^com\\.google\\.Chrome$"
                            "^org\\.chromium\\.Chromium$"
                            "^com\\.google\\.Chrome\\.canary$"
                            "^com\\.apple\\.Safari$"]}
 :input-sources {;; define input-source, these data can be founhd in Karabiner EventViewer gui
                 :us {:input_mode_id   ""
                      :input_source_id "com.apple.keylayout.US"
                      :language        "en"}}

 ;; can config like this
 :main [{:des   "contions demo"
         :rules [;; multiple conditions
                          ;;;; when
                 ;; the input-method is :us
                 ;; the activated application is one of app in :Browsers
                 ;; the key is triggered by :hhkb
                 ;; may l key to command + optional + l
                 [:condi :us :hhkb :Browsers :z-mode]
                 [:l :!COi]]}]
 ;; or
 :main [{:des   "contions demo"
         :rules [[:l :!COi [:us :hhkb :Browsers :z-mode]]]}]

 ;; or
 :main [{:des   "contions demo"
         :rules [[:condi :us :hhkb]
                 [:l :!COi [:Browsers :z-mode]]]}]}

profiles

Skip this section if you don’t use profiles.

Since karabiner cli now supports set variables, profiles are mainly used for multiple users using the same machine or between different usages like gaming profiles and working profiles. Goku doesn’t support that well for now.

However, you can define your multiple profiles. Only one profile can be set as the default profile (:default true).

Then you can use profile keyword :Default as conditions or layers keyword. You need to specify each rule to a profile, or they will be considered in the default profile.

If you want to have an empty profile for gaming, you can create one in the karabiner GUI (no need to change anything in Goku).

{:profiles {:Default {;; "default true means" rules default goes into this rule if no profiles specified
                      :default true
                      ;; simultaneous key press threshold
                      ;; simlayer is implemented with to_if_alone and simultaneous key press feature
                      :sim     250
                      ;; to_delayed_action_delay_milliseconds
                      ;; checkout karabiner's documentation
                      ;; https://pqrs.org/osx/karabiner/json.html
                      ;; basically it means time after which the key press is count delayed
                      :delay   500
                      ;; https://pqrs.org/osx/karabiner/json.html#to-if-alone
                      ;; to_if_alone_timeout_milliseconds
                      ;; affects to_if_alone behavior
                      ;; simlayer is implemented with to_if_alone and simultaneous key press feature
                      :alone   1000
                      ;; to_if_held_down_threshold_milliseconds
                      ;; check the doc, I don't know what does this mean.
                      ;; maybe press this many milliseconds counts a "held" ?
                      :held    500}}}

same key in different mode, from @nikitavoloboev’s config

You can use karabiner command-line interface to set variables when you open specifc type of files in your editor. See ISSUE #79.

{:profiles
 {:Default {:default true
            :sim     50
            :delay   80
            :alone   120
            :held    70}}
 :simlayers {:js-mode {:key :period :condi ["in-js" 1]} ;;  karabiner_cli --set-variables {"in-js": 1}
             :go-mode {:key :period :condi ["in-go" 1]} ;;  karabiner_cli --set-variables {"in-go": 1}
             :py-mode {:key :period :condi ["in-python" 1]} ;;  karabiner_cli --set-variables {"in-python": 1}
             :elixir-mode {:key :period :condi ["in-elixir" 1]} ;;  karabiner_cli --set-variables {"in-elixir": 1}
             :rust-mode {:key :period :condi ["in-rust" 1]}} ;;  karabiner_cli --set-variables {"in-rust": 1}
 :main [{:des "jsdot"
         :rules [:js-mode
                 [:a [:c :o :n :s :o :l :e :period :l :o :g :!S9 :!S0 :left_arrow]] ; -> console.log()
                 [:v [:j :a :v :a :s :c :r :i :p :t :spacebar]]]} ; -> javascript
        {:des "godot"
         :rules[:go-mode
                [:a [:f :m :t :period :!Sp :r :i :n :t :l :n :!S9 :!S0 :left_arrow]] ; -> fmt.Println()
                [:v [:g :o :l :a :n :g :spacebar]]]} ; -> golang
        {:des "pydot"
         :rules[:py-mode
                [:a [:p :r :i :n :t :!S9 :!S0 :left_arrow]] ; -> print()
                [:v [:p :y :t :h :o :n :spacebar]]]} ; -> python
        {:des "elixdot"
         :rules[:elixir-mode
                [:a [:!Si :!So :period :p :u :t :s :!S9 :!S0 :left_arrow]] ; -> IO.puts()
                [:v [:e :l :i :x :i :r :spacebar]]]} ; -> elixir
        {:des "rustdot"
         :rules[:rust-mode
                [:a [:p :r :i :n :t :l :n :!S1 :!S9 :!S0 :left_arrow]] ; -> println!()
                [:v [:r :u :s :t :spacebar]]]}]} ; -> rust

disable all pointing buttons

{:des "disable all pointing buttons"
 :rules [[{:any :pointing_button} :vk_none]]}

command-q twice to quit application

{:des   "Quit application by pressing command-q twice"
 :rules [[
          ;; <from> second cmd-q (when variable "command-q" is 1)
          :!C#Pq
          ;; <to>, 3 to action
          ;; 1. call cmd-q
          ;; 2. set variable "command-q" to 0
          ;; 3. cleanup the :cmdq notification (omit the thrid item to cleanup notification)
          [:!Cq ["command-q" 0] [:noti :cmdq]]
          ;; <condition> when variable "command-q" is 1
          ["command-q" 1]]


         [
          ;; <from> first cmd-q (when variable "command-q" is 0)
          :!C#Pq

          ;; <to>, 2 to action
          ;; 1. show notification with :id :cmdq, :text "Press Again to QUIT"
          ;; 2. set variable "command-q" to 1 (for the second press)
          [[:noti :cmdq "Press Again to QUIT"] ["command-q" 1]]

          ;; <condition> nil means no required condition
          nil

          ;; <additional-option>
          {
           ;; to_delayed_action documentation
           ;; https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/to-delayed-action/
           :delayed {
                     ;; run 2 actions when no other key presses after basic.to_delayed_action_delay_milliseconds
                     ;; 1. set variable "command-q" to 0
                     ;; 2. cleanup notification :id :cmdq
                     :invoked  [["command-q" 0] [:noti :cmdq]]

                     ;; run 2 actions when another key presses within basic.to_delayed_action_delay_milliseconds
                     ;; 1. set variable "command-q" to 0
                     ;; 2. cleanup notification :id :cmdq
                     :canceled [["command-q" 0] [:noti :cmdq]]}}]]}