Skip to content

Instantly share code, notes, and snippets.

@johnlindquist
Created May 27, 2026 18:03
Show Gist options
  • Select an option

  • Save johnlindquist/f6ecdcf1dcc8ec4fac5ad90eb768acaf to your computer and use it in GitHub Desktop.

Select an option

Save johnlindquist/f6ecdcf1dcc8ec4fac5ad90eb768acaf to your computer and use it in GitHub Desktop.
GokuRakuJoudo: Write Your Karabiner Config in EDN — tutorial + full config by @johnlindquist

GokuRakuJoudo: Write Your Karabiner Config in EDN

GokuRakuJoudo (Goku) lets you write your Karabiner-Elements keyboard config in a concise EDN format instead of editing Karabiner's 20,000+ line JSON by hand.

This gist walks through setup, explains every major concept, and includes my full 1,500-line karabiner.edn as a working real-world example.


Install

# Install Goku
brew install yqrashawn/goku/goku

# Start the watcher (rebuilds karabiner.json on every save)
brew services start goku

# Or run once manually
goku

Requirements:

  • macOS with Karabiner-Elements installed
  • A Karabiner profile named "Default" (Goku writes rules into this profile)

Your config lives at ~/.config/karabiner.edn. Every time you save it, gokuw (the watcher) regenerates the complex_modifications section of your karabiner.json.


Core Concepts

1. Rule Structure

Rules live inside :main and follow this pattern:

[:from :to :conditions {:options}]

Only :from and :to are required:

{:main [{:des "My rules"
         :rules [[:caps_lock :escape]           ; Caps Lock → Escape
                 [:a [:1 :2 :3]]                ; a → type "123"
                 [:b "open -a Safari"]]}]}       ; b → run shell command

2. Modifier Shorthand

Goku uses a compact prefix notation instead of spelling out modifiers:

Prefix Modifier
!C ⌘ Command (left)
!S ⇧ Shift (left)
!O ⌥ Option (left)
!T ⌃ Control (left)
!Q ⌘ Command (right)
!R ⇧ Shift (right)
!E ⌥ Option (right)
!W ⌃ Control (right)
!F fn
## Optional any modifier

Combine them freely:

[:!Ca :1]           ; Cmd+A → 1
[:!CSa :1]          ; Cmd+Shift+A → 1
[:!COSa :1]         ; Cmd+Opt+Shift+A → 1
[:##caps_lock :escape]  ; Caps Lock → Escape (pass through any held modifiers)

3. Simlayers (Simultaneous Layers)

This is Goku's killer feature. Press a key simultaneously with another to activate a layer. Tap the key alone and it types normally.

{:simlayers {:s-mode {:key :s}}    ; Define: S is a layer trigger

 :main [{:des "s-mode navigation"
         :rules [:s-mode            ; Condition prefix for all rules below
                 [:h :left_arrow]   ; S+H → Left
                 [:j :down_arrow]   ; S+J → Down
                 [:k :up_arrow]     ; S+K → Up
                 [:l :right_arrow]  ; S+L → Right
                 ]}]}

How it works:

  • Press S + H together (within threshold) → Left Arrow
  • Press S alone → types s normally
  • The layer key still works for normal typing — you don't lose any keys

4. Layers (Hold-Based)

Traditional hold-to-activate layers. The key does one thing when tapped, another when held:

{:layers {:tab-mode {:key :tab}}   ; Hold Tab for layer, tap for normal Tab

 :main [{:des "tab mode"
         :rules [:tab-mode
                 [:s :capture_screenshot]
                 [:r :record_screen]]}]}

You can customize tap behavior with :alone:

{:layers {:escape-mode {:key :escape
                         :alone [{:key :escape}        ; Tap → Escape
                                 {:set ["my-mode" 0]}] ; Also reset a variable
                         }}}

5. Templates

Templates eliminate repetition for shell commands using %s placeholders:

{:templates {:open "open \"%s\""
             :launch "open -a \"%s\""
             :km "osascript -e 'tell application \"Keyboard Maestro Engine\" to do script \"%s\"'"
             :script "/bin/bash ~/.config/scripts/%s.sh"}

 :main [{:des "app launchers"
         :rules [:launch-mode
                 [:s [:launch "Slack"]]
                 [:c [:launch "Chrome"]]
                 [:f [:open "~/Downloads"]]
                 [:r [:script "restart_yabai"]]]}]}

6. Custom Modifier Aliases

Name common modifier combos:

{:modifiers {:hyper [:command :shift :control :option]
             :co    [:command :option]
             :cs    [:command :shift]}

 :main [{:des "hyper shortcuts"
         :rules [[:1 {:key :1 :modi :hyper}]]}]}  ; 1 → Hyper+1

7. From/To Aliases

Name common keys or actions to keep rules readable:

{:froms {:delete {:key :delete_or_backspace}
         :return {:key :return_or_enter}}

 :tos {:spotlight {:key :f13}
       :go_back   {:key :hyphen :modi :control}
       :go_home   {:key :up_arrow :modi :command}}

 :main [{:des "navigation"
         :rules [[:delete :go_home]
                 [:return :spotlight]]}]}

8. Application Conditions

Scope rules to specific apps:

{:applications {:chrome  ["com.google.Chrome"]
                :code    ["com.microsoft.VSCode" "dev.zed.Zed"]
                :slack   ["com.tinyspeck.slackmacgap"]}

 :main [{:des "Chrome shortcuts"
         :rules [:chrome                      ; Condition: Chrome only
                 [:left_command :left_command
                  nil {:alone :!Ct}]]}        ; Tap Cmd → New Tab

        {:des "Code shortcuts"
         :rules [:code
                 [:left_command :left_command
                  nil {:alone :go_to_file}]]}]} ; Tap Cmd → Go To File

Find bundle IDs: osascript -e 'id of app "Google Chrome"'

9. Simultaneous Keys (No Layer)

Press two keys at the same time for an action:

[:[:j :k] :escape]    ; J+K pressed together → Escape

10. Dual-Purpose Keys

One action when tapped, another when held:

; Caps Lock: tap → Escape, hold → activate escape-mode layer
[:caps_lock ["escape-mode" 1] nil {:alone :escape
                                    :afterup ["escape-mode" 0]}]

; Left Command: tap → Go To File, hold → Command
[:left_command :left_command nil {:alone :go_to_file}]

11. Variables (State)

Set and check variables to create complex behaviors:

; Set a variable
[:w ["my-layer" 1]]

; Use a variable as a condition
[:h :left_arrow ["my-layer" 1]]

; Reset in :afterup
[:w ["my-layer" 1] nil {:afterup ["my-layer" 0]
                         :alone :w}]

12. Mouse Button Mapping

Map mouse buttons and create mouse-triggered layers:

{:froms {:right_click {:pkey :button2}}

 :main [{:des "mouse layers"
         :rules [; Hold Button4 for layer, tap for Space Left
                 [{:pkey :button4} ["button4-mode" 1]
                  nil {:alone [:space_left]
                       :afterup ["button4-mode" 0]}]
                 ; Right Click + Left Click → Shift+Click
                 :button4-mode
                 [{:pkey :button1} {:pkey :button1 :modi :left_shift}]]}]}

13. Condition Shorthand with :condi

Switch conditions mid-block without nesting:

{:des "Code shortcuts"
 :rules [:code                        ; All rules below are Code-only
         [:left_command :left_command nil {:alone :go_to_file}]

         [:condi :code :escape-mode]  ; Switch to: Code AND escape-mode
         [:g :focus_git]
         [:f :find_in_project]

         [:condi :code :nav-mode]     ; Switch to: Code AND nav-mode
         [:a :open_prev_editor]
         [:t :open_next_editor]]}

14. Multitouch Trackpad Conditions

Trigger different actions based on how many fingers are on the trackpad:

{:main [{:des "1-finger trackpad"
         :rules [[:f :button1 ["multitouch_extension_finger_count_total" 1]]
                 [:d {:pkey :button1 :modi :left_shift}
                     ["multitouch_extension_finger_count_total" 1]]]}]}

Requires the Karabiner MultitouchExtension.


My Config

See karabiner.edn in this gist for a complete, working config featuring:

  • 30+ simlayers covering navigation, editing, app launching, symbols, emojis, window management, and more
  • Colemak layout remapping (QWERTY input → Colemak output via Karabiner)
  • App-specific rules for Chrome, VS Code/Cursor/Zed, Slack, Terminal, Ableton Live, Final Cut Pro, and more
  • Mouse button layers (Button4/Button5 hold for layers, Right Click hold for layer)
  • Trackpad finger-count rules (different actions for 1/2/3/4 fingers)
  • Window management via Yabai scripts (move/resize/focus windows across displays and spaces)
  • Template system for shell commands, AppleScript, Keyboard Maestro macros, and more
  • Dual-purpose keys: Caps Lock (tap Escape / hold for layer), Left Command (tap Go To File / hold for Cmd), Tab (tap Tab / hold for layer)

Layer Cheatsheet

Layer Trigger Purpose
escape-mode Hold Escape/Caps App focus, view switching, space management
movement-mode F + key Arrow keys (hjkl), line start/end
shift-mode D + key Shift+Arrow, text selection
opt-mode A + key Option+Arrow (word jump), AceJump
shift-opt-mode S + key Shift+Option+Arrow (word select)
command-mode C + key Cmd+Arrow, go home/end
command-shift-mode V + key Cmd+Shift+Arrow
delete-mode J + key Backspace, forward delete, word/line delete
nav-mode K + key Editor tabs, go back/forward
cursor-mode G + key Multi-cursor, find match, AceJump
spacebar-mode Space + key Symbols: [](){}${} =>
semicolon-mode ; + key Special chars: !@#$%^&*
snippet-mode ' + key Code snippets: console.log(), await, async
emoji-mode Z + key Paste emojis: 🔥😂🤔👍❤️
launch-mode U + key / F24 Launch apps: Slack, Chrome, Zed, Finder
period-mode . + key Focus or open Chrome tabs (URLs)
comma-mode , + key Always open new Chrome tab (URLs)
go-mode T + key IDE go-to: references, symbol, definition
peek-mode R + key IDE peek: definition, implementations, refs
kit-mode N + key Open projects in editor
media-mode M + key Play/pause, next track
equal-mode Hold = Window management (Yabai)
home-mode Hold Home Window layout, display management
tab-mode Hold Tab Screenshots, media, app launch
quick-mode Q + key Utilities, timestamp, Goku reload
close-mode W + key Close all/others in IDE
finder-mode E + key Open folders
close-bracket-mode Hold ] Window tiling (mwm)

Quick Start with My Config

# 1. Install Goku and Karabiner-Elements
brew install yqrashawn/goku/goku
brew install --cask karabiner-elements

# 2. Copy my config
cp karabiner.edn ~/.config/karabiner.edn

# 3. Customize paths and app references to match your system

# 4. Run Goku
goku

# 5. Start the watcher
brew services start goku

What to Customize

  1. Remove Colemak: Delete the "Colemak Remapping" section at the bottom if you use QWERTY, and change all :-X aliases to regular :X keys throughout
  2. Templates: Update file paths in :templates to match your system
  3. App bundle IDs: Update :applications for your installed apps
  4. Scripts: The window management templates reference ~/.config/scripts/ — replace with your own scripts or remove
  5. Keyboard Maestro: km() calls require Keyboard Maestro — replace with open -a or shell commands
  6. URLs in period-mode/comma-mode: Replace with your own frequently visited sites
  7. Project paths in kit-mode: Replace with your own project directories

Tips

  • Start with one simlayer. Add s-mode for navigation, use it for a week, then expand.
  • Use goku (one-shot) to test changes before enabling the watcher.
  • Check logs at ~/Library/Logs/goku.log if rules aren't working.
  • Use Karabiner EventViewer to find key codes and bundle IDs.
  • Simlayer threshold (:simlayer-threshold) controls how fast you need to chord — lower it if layers activate during normal typing.
  • ## is critical for modifier passthrough. Without it, [:right_command :f16] only fires on bare Right Command.

Resources

{;; --- GLOBAL SETTINGS ---
:default true ; Apply rules by default
:alone 500 ; Timeout (ms) for 'alone' state detection
:delay 200 ; Delay (ms) for sequence keys
:held 500 ; Timeout (ms) for 'held' state detection
:simlayer-threshold 140 ; Timeout (ms) for simultaneous key press detection (simlayers)
;; --- CUSTOM MODIFIER ALIASES ---
:modifiers {:super-hyper [:command :shift :control :option :fn] ; All modifiers including Fn
:hyper [:command :shift :control :option] ; Cmd+Shift+Ctrl+Opt
:cos [:command :shift :option] ; Cmd+Shift+Opt
:cst [:command :shift :control] ; Cmd+Shift+Ctrl
:co [:command :option] ; Cmd+Opt
:cs [:command :shift] ; Cmd+Shift
:ct [:command :control] ; Cmd+Ctrl
:cto [:command :control :option] ; Cmd+Ctrl+Opt
:to [:control :option] ; Ctrl+Opt
:ts [:control :shift] ; Ctrl+Shift
:os [:option :shift]
:tos [:command :shift :option]} ; Opt+Shift
;; --- INPUT KEY ALIASES (:froms) ---
:froms {;; Standard Aliases
:delete {:key :delete_or_backspace}
:return {:key :return_or_enter}
:tilde {:key :grave_accent_and_tilde}
;; Colemak Layout Aliases (use :-X where X is the Colemak letter)
;; Quick Reference: QWERTY -> Colemak
;; E->F, R->P, T->G, Y->J, U->L, I->U, O->Y, P->;
;; S->R, D->S, F->T, G->D, J->N, K->E, L->I, ;->O, N->K
:-q {:key :q}
:-w {:key :w}
:-f {:key :e} ; Colemak 'F' is QWERTY 'E'
:-p {:key :r} ; Colemak 'P' is QWERTY 'R'
:-g {:key :t} ; Colemak 'G' is QWERTY 'T'
:-j {:key :y} ; Colemak 'J' is QWERTY 'Y'
:-l {:key :u} ; Colemak 'L' is QWERTY 'U'
:-u {:key :i} ; Colemak 'U' is QWERTY 'I'
:-y {:key :o} ; Colemak 'Y' is QWERTY 'O'
:-semicolon {:key :p} ; Colemak ';' is QWERTY 'P'
:-a {:key :a}
:-r {:key :s} ; Colemak 'R' is QWERTY 'S'
:-s {:key :d} ; Colemak 'S' is QWERTY 'D'
:-t {:key :f} ; Colemak 'T' is QWERTY 'F'
:-d {:key :g} ; Colemak 'D' is QWERTY 'G'
:-h {:key :h}
:-n {:key :j} ; Colemak 'N' is QWERTY 'J'
:-e {:key :k} ; Colemak 'E' is QWERTY 'K'
:-i {:key :l} ; Colemak 'I' is QWERTY 'L'
:-o {:key :semicolon} ; Colemak 'O' is QWERTY ';'
:-z {:key :z}
:-x {:key :x}
:-c {:key :c}
:-v {:key :v}
:-b {:key :b}
:-k {:key :n} ; Colemak 'K' is QWERTY 'N'
:-m {:key :m}
;; Mouse Buttons
:left_click {:pkey :button1}
:right_click {:pkey :button2}} ; Added for clarity based on usage later
;; --- OUTPUT ACTION ALIASES (:tos) ---
:tos {;; Mode Reset - single source of truth for all mode resets
:reset-all-modes [{:set ["caps-lock-mode" 0]}
{:set ["fn-mode" 0]}
{:set ["opt-mode" 0]}
{:set ["shift-opt-mode" 0]}
{:set ["movement-mode" 0]}
{:set ["cursor-mode" 0]}
{:set ["delete-mode" 0]}
{:set ["nav-mode" 0]}
{:set ["snippet-mode" 0]}
{:set ["kit-mode" 0]}
{:set ["button2-mode" 0]}
{:set ["button4-mode" 0]}
{:set ["button5-mode" 0]}
{:set ["escape-mode" 0]}
{:set ["home-mode" 0]}]
;; Basic Keys
:delete {:key :delete_or_backspace}
:return {:key :return_or_enter}
:tilde {:key :grave_accent_and_tilde}
;; macOS & App Launchers
:spotlight {:key :f13} ; Often used as a custom spotlight trigger
:chatgpt {:key :0 :modi :hyper} ; Open chatgpt overlay
:alfred {:key :spacebar :modi :option} ; Opt+Space
:emoji_picker {:key :spacebar :modi :ct} ; Ctrl+Cmd+Space
:open_1password {:key :f1 :modi :hyper} ; Cmd+\
:autofill_1password {:key :f2 :modi :hyper} ; Command+Ctrl+Opt+\
;; Screenshots & Recording
:restore_screenshot {:key :7 :modi :cs} ; Cmd+Shift+4 (macOS default region capture)
:capture_screenshot {:key :4 :modi :cs} ; Cmd+Shift+4 (macOS default region capture)
:record_screen {:key :6 :modi :cs} ; Custom shortcut? (macOS default is Cmd+Shift+5)
:take_screenshot {:key :6 :modi :cs} ; Alias for record_screen?
;; Mouse Actions
:shift_click {:pkey :button1 :modi :left_shift}
;; General Editing & Navigation
:go_back {:key :hyphen :modi :control} ; Ctrl+- (Common in IDEs)
:go_forward {:key :hyphen :modi :ts} ; Ctrl+Shift+- (Common in IDEs)
:go_home {:key :up_arrow :modi :command} ; Cmd+Up
:go_end {:key :down_arrow :modi :command} ; Cmd+Down
:expand_selection {:key :right_arrow :modi :cst} ; Ctrl+Shift+Cmd+Right (IDE specific?)
:shrink_selection {:key :left_arrow :modi :cst} ; Ctrl+Shift+Cmd+Left (IDE specific?)
:insert_line_below {:key :return_or_enter :modi :command} ; Cmd+Enter
:insert_line_above {:key :return_or_enter :modi :cs} ; Cmd+Shift+Enter
:delete_line {:key :k :modi :cs} ; Custom: Cmd+Shift+K
:wrap_emmet {:key :p :modi :hyper} ; Custom: Hyper+P
;; IDE/Editor Specific Actions (VSCode-like?)
:fix_with_ai {:key :d :modi :cs} ; Cmd+Shift+P
:command_palette {:key :p :modi :cs} ; Cmd+Shift+P
:cursor_find_match {:key :d :modi :command} ; Cmd+D
:cursor_select_all {:key :l :modi :cs} ; Cmd+Shift+L
:cursor_above {:key :up_arrow :modi :co} ; Cmd+Opt+Up
:cursor_below {:key :down_arrow :modi :co} ; Cmd+Opt+Down
:acejump {:key :j :modi :cos} ; Custom: Cmd+Opt+Shift+J
:acejump_line {:key :l :modi :cos} ; Custom: Cmd+Opt+Shift+L
:acejump_selection {:key :s :modi :cos} ; Custom: Cmd+Opt+Shift+S
:acejump_multi {:key :m :modi :cos} ; Custom: Cmd+Opt+Shift+M
:close_all [{:key :r :modi :command} {:key :w}] ; Custom Sequence? Cmd+R then W?
:close_others [{:key :t :modi :co}] ; Cmd+Opt+T (VSCode default)
:developer_tools [{:key :i :modi :co}] ; Cmd+Opt+I (Browser Dev Tools)
:find_in_project {:key :f :modi :cs} ; Cmd+Shift+F
:replace_in_project {:key :h :modi :cs} ; Cmd+Shift+H
:focus_git {:key :g :modi :ts} ; Ctrl+Shift+G (VSCode Source Control)
:focus_editor {:key :e :modi :hyper} ; Custom: Hyper+E
:focus_editor_left {:key :i :modi :hyper} ; Custom: Hyper+I
:focus_editor_right {:key :n :modi :hyper} ; Custom: Hyper+N
:focus_explorer {:key :e :modi :cs} ; Cmd+Shift+E (VSCode Explorer)
:focus_terminal {:key :grave_accent_and_tilde :modi :control} ; Custom: Hyper+T
:toggle-pane-zoom-cmux {:key :return_or_enter :modi :cs} ; Cmd+Shift+Enter (cmux Toggle Pane Zoom)
:start_debugger {:key :f5}
:restart_debugger {:key :f5 :modi :cs} ; Cmd+Shift+F5
:go_to_references {:key :f12 :modi :shift} ; Shift+F12
:go_to_symbol {:key :o :modi :cs} ; Cmd+Shift+O
:go_to_symbol_in_workspace {:key :o :modi :cos} ; Cmd+Opt+Shift+O ? (Cmd+T in VSCode)
:go_to_hints {:key :spacebar :modi :cs} ; Cmd+Shift+Space (Parameter Hints)
:search_everywhere {:key :p :modi :co} ; Cmd+Opt+P ? (Go To File is Cmd+P)
:go_to_implementations {:key :f12 :modi :command} ; Cmd+F12
:go_to_definition {:key :f12}
:go_to_line {:key :g :modi :control} ; Ctrl+G
:go_to_prev_problem {:key :f8 :modi :os} ; Opt+Shift+F8
:go_to_next_problem {:key :f8 :modi :option} ; Opt+F8
:new_terminal {:key :grave_accent_and_tilde :modi :ts} ; Ctrl+Shift+` (VSCode)
:open_next_editor {:key :right_arrow :modi :co} ; Cmd+Opt+Right (Often Next Tab)
:open_prev_editor {:key :left_arrow :modi :co} ; Cmd+Opt+Left (Often Prev Tab)
:focus_next_editor_group {:key :f16 :modi :option} ; Custom: Opt+F16
:focus_prev_editor_group {:key :f16 :modi :os} ; Custom: Opt+Shift+F16
:peek_definition {:key :f12 :modi :option} ; Opt+F12
:peek_implementations {:key :f12 :modi :cs} ; Cmd+Shift+F12
:peek_declaration {:key :f19 :modi :control} ; Custom: Ctrl+F19
:peek_references {:key :f19 :modi :command} ; Custom: Cmd+F19
:peek_type {:key :f19 :modi :shift} ; Custom: Shift+F19
:replace {:key :f :modi :co} ; Cmd+Opt+F (Replace in file)
:rename {:key :f2} ; Standard Rename
:fold {:key :open_bracket :modi :co} ; Cmd+Opt+[
:unfold {:key :close_bracket :modi :co} ; Cmd+Opt+]
:toggle_fold [{:key :r :modi :command} {:key :l :modi :command}] ; Custom Sequence: Cmd+R then Cmd+L ?
:split_window {:key :backslash :modi :command} ; Cmd+\ (VSCode Split Editor)
:toggle_sidebar {:key :b :modi :command} ; Cmd+B (VSCode Toggle Sidebar)
:go_to_file {:key :p :modi :command} ; Cmd+P (VSCode Go To File)
;; Symbols
:open_brace {:key :open_bracket :modi :shift} ; {
:close_brace {:key :close_bracket :modi :shift} ; }
:open_paren {:key :9 :modi :shift} ; (
:close_paren {:key :0 :modi :shift} ; )
:less_than {:key :comma :modi :shift} ; <
:greater_than {:key :period :modi :shift} ; >
;; Chrome Specific
:chrome_tab_switcher {:key :a :modi :cs} ; Custom: Cmd+Shift+A (Built-in is Ctrl+Tab / Ctrl+Shift+Tab)
:open_dev_tools {:key :i :modi :co} ; Cmd+Opt+I
:chrome_full_screen {:key :f :modi :ct} ; Ctrl+Cmd+F
:focus_omnibar {:key :l :modi :command} ; Cmd+L
:chrome_go_back {:key :open_bracket :modi :command} ; Cmd+[
:chrome_go_forward {:key :close_bracket :modi :command} ; Cmd+]
;; Ableton Live Specific
:add_midi_clip {:key :m :modi :cs} ; Cmd+Shift+M
:add_midi_track {:key :t :modi :cs} ; Cmd+Shift+T
:loop_selection {:key :l :modi :command} ; Cmd+L
:toggle_clip_device_view {:key :tab :modi :shift} ; Shift+Tab
:narrow_grid {:key :1 :modi :command} ; Cmd+1
:widen_grid {:key :2 :modi :command} ; Cmd+2
:snap_to_grid {:key :4 :modi :command} ; Cmd+4
:split_clip {:key :e :modi :command} ; Cmd+E
;; Window Management / Display Layouts (Likely custom scripts/apps)
:display_layout_1 {:key :1 :modi :hyper} ; Custom: Hyper+1
:display_layout_2 {:key :2 :modi :hyper} ; Custom: Hyper+2
;; Terminal / Tmux
:tmux {:key :b :modi :control} ; Standard Tmux prefix Ctrl+B
:tmux_new_pane {:key :5 :modi :shift} ; Standard Tmux split vertical % (Shift+5)
:terminal_previous_tab {:key :open_bracket :modi :cs} ; Cmd+Shift+[ (Standard macOS)
:terminal_next_tab {:key :close_bracket :modi :cs} ; Cmd+Shift+] (Standard macOS)
;; Slack Specific
:slack_previous {:key :open_bracket :modi :command} ; Cmd+[ (History Back)
:slack_next {:key :close_bracket :modi :command} ; Cmd+] (History Forward)
;; Utilities
:superkey {:key :0 :modi :hyper} ; Custom trigger: Hyper+0
:toggle_screen_brush {:key :tab :modi :option} ; Custom: Opt+Tab (Annotation tool?)
:autocomplete {:key :spacebar :modi :control}} ; Ctrl+Space (macOS standard suggestion)
;; --- SCRIPT TEMPLATES ---
;; Templates for generating shell commands using osascript, security, kenv, etc.
:templates {;; Common path shortcuts (DRY principle)
:script "/bin/bash /Users/johnlindquist/.config/scripts/%s.sh"
:cursor "/usr/local/bin/cursor %s"
:zed "/usr/local/bin/zed %s"
;; Layer indicator (shows notification when layer activates)
:notify "osascript -e 'display notification \"%s\" with title \"Layer\"'"
:beep "osascript -e 'beep'"
:beep2 "osascript -e 'beep 2'"
:new-note "osascript -e 'tell application id \"m.runningwithcrayons.Alfred\" to run trigger \"new-note\" in workflow \"com.johnlindquist.new-note\" with argument \"\"'"
:new-blog "osascript -e 'tell application id \"com.runningwithcrayons.Alfred\" to run trigger \"new-blog\" in workflow \"com.johnlindquist.new-blog\" with argument \"\"'"
:alfred "osascript -e 'tell application \"Alfred 4\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"
:code-project "~/.kenv/bin/code-project \"%s\""
:delay "osascript -e 'delay \"%s\"'"
:km "osascript -e 'tell application \"Keyboard Maestro Engine\" to do script \"%s\"'"
:type "osascript -e 'tell application \"System Events\" to keystroke \"%s\"'"
:type-secret "osascript -e '
set out to do shell script \"security find-generic-password -a $USER -s %s -w\"
tell application \"System Events\" to keystroke out
'"
:kit "~/.kit/kar \"%s\""
:focus "~/.kit/kar focus \"%s\""
:launch "/Users/johnlindquist/.local/bin/launch-focus \"%s\""
:wezterm "/Users/johnlindquist/.config/scripts/wezterm_run.sh \"%s\""
:wez-trigger "/Users/johnlindquist/.config/scripts/wezterm_trigger.sh \"%s\""
:open-chrome "osascript -e 'tell application \"Google Chrome\"\nactivate\nopen location \"%s\"\nend tell'"
;; Inside your :templates map in karabiner.edn
:focus-or-open-chrome "/usr/bin/osascript /Users/johnlindquist/.config/focus-tab.scpt \"%s\""
:open-new-tab "/usr/bin/osascript /Users/johnlindquist/.config/open-tab.scpt \"%s\""
:open "open \"%s\""
:open-github-cmux "/bin/bash /Users/johnlindquist/.config/scripts/open_github_cmux_cwd.sh"
:open-a "open -a '%s'"
:restream "osascript -e 'tell application \"Restream Chat\" to activate'"
:zsh "zsh ~/.zfunc/'%s'"
:print "osascript -e '
set the clipboard to do shell script \"echo $PLEASE\"
tell application \"System Events\"
keystroke \"v\" using command down
end tell
'"
:modify "~/.simple/bin/modify --%s"
:pad "~/.simple/bin/pad"
:test "osascript -e 'say \"poop\"'"
:compress-finder-image "/Users/johnlindquist/scripts/scripts/compress-finder-image.ts"
:copy-transcribe-low "open -g -a 'Audio Hijack' ~/transcripts/copy-transcribe-low.ahcommand"
:paste-transcribe-low "open -g -a 'Audio Hijack' ~/transcripts/paste-transcribe-low.ahcommand"
:copy-transcribe-high "open -g -a 'Audio Hijack' ~/transcripts/copy-transcribe-high.ahcommand"
:paste-transcribe-high "open -g -a 'Audio Hijack' ~/transcripts/paste-transcribe-high.ahcommand"
:transcribe "open -g -a 'Audio Hijack' ~/transcripts/transcribe.ahcommand"
:paste "osascript -e '
set the clipboard to \"%s\"
tell application \"System Events\"
keystroke \"v\" using command down
end tell
'"
:paste-enter "osascript -e '
set the clipboard to \"%s\"
tell application \"System Events\"
keystroke \"v\" using command down
end tell
delay 0.1
tell application \"System Events\"
keystroke return
end tell
'"
:delay-key "osascript -e '
delay 0.1
tell application \"System Events\"
keystroke \"%s\"
end tell
'"
:read-paste-enter "osascript -e '
set theFile to POSIX file \"%s\"
set fileContents to read theFile as «class utf8»
set the clipboard to fileContents
tell application \"System Events\"
keystroke \"v\" using command down
end tell
delay 0.1
tell application \"System Events\"
keystroke return
end tell
'"
:datamuse "osascript -e '
tell application id \"com.runningwithcrayons.Alfred\" to run trigger \"datamuse\" in workflow \"com.johnlindquist.datamuse\" with argument \"%s\"
'"
:detach_tab "/bin/bash /Users/johnlindquist/.config/scripts/detach_chrome_tab.sh"
:open_new_space_and_focus "/bin/bash /Users/johnlindquist/.config/scripts/open_new_space_and_focus.sh"
:space_right "/bin/bash /Users/johnlindquist/.config/scripts/space_right.sh"
:space_right_by_display "/bin/bash /Users/johnlindquist/.config/scripts/space_right_by_display.sh"
:space_left "/bin/bash /Users/johnlindquist/.config/scripts/space_left.sh"
:space_left_by_display "/Users/johnlindquist/.config/scripts/space_left_by_display.sh"
:space_right_wrap "/Users/johnlindquist/.config/scripts/space_right_wrap.sh"
:space_left_wrap "/Users/johnlindquist/.config/scripts/space_left_wrap.sh"
:move_window_right "/bin/bash /Users/johnlindquist/.config/scripts/move_window_right.sh"
:move_window_left "/bin/bash /Users/johnlindquist/.config/scripts/move_window_left.sh"
:move_window_right_half "/bin/bash /Users/johnlindquist/.config/scripts/move_window_right_half.sh"
:move_window_left_half "/bin/bash /Users/johnlindquist/.config/scripts/move_window_left_half.sh"
:move_window_center_full "/bin/bash /Users/johnlindquist/.config/scripts/move_window_center_full.sh"
:move_window_center_66 "/bin/bash /Users/johnlindquist/.config/scripts/move_window_center_66.sh"
:move_window_to_next_empty_space "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_next_empty_space.sh"
:move_window_to_previous_empty_space "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_previous_empty_space.sh"
:move_window_to_display_1 "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_display_1.sh"
:move_window_to_display_2 "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_display_2.sh"
:move_window_to_display_3 "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_display_3.sh"
:move_window_to_display_4 "/bin/bash /Users/johnlindquist/.config/scripts/move_window_to_display_4.sh"
:remove_current_space "/bin/bash /Users/johnlindquist/.config/scripts/remove_current_space.sh"
:remove_empty_spaces_improved "/bin/bash /Users/johnlindquist/.config/scripts/remove_empty_spaces_improved_improved.sh"
:move_to_next_display "/bin/bash /Users/johnlindquist/.config/scripts/move_to_next_display.sh"
:move_to_previous_display "/bin/bash /Users/johnlindquist/.config/scripts/move_to_previous_display.sh"
:move_window_east "/bin/bash /Users/johnlindquist/.config/scripts/move_window_east.sh"
:move_window_west "/bin/bash /Users/johnlindquist/.config/scripts/move_window_west.sh"
:window_resize_to_next_tenth_wider "/bin/bash /Users/johnlindquist/.config/scripts/window_resize_to_next_tenth_wider.sh"
:window_resize_to_next_tenth_narrower "/bin/bash /Users/johnlindquist/.config/scripts/window_resize_to_next_tenth_narrower.sh"
:restart_yabai "/opt/homebrew/bin/yabai --restart-service || /opt/homebrew/bin/yabai --start-service -c /Users/johnlindquist/.config/yabairc"
:stop_yabai "/opt/homebrew/bin/yabai --stop-service"
:focus_next_window_same_app "/bin/bash /Users/johnlindquist/.config/scripts/focus_next_window_same_app.sh"
:focus_previous_window_same_app "/bin/bash /Users/johnlindquist/.config/scripts/focus_previous_window_same_app.sh"
:focus_west "/bin/bash /Users/johnlindquist/.config/scripts/focus_direction.sh west"
:focus_east "/bin/bash /Users/johnlindquist/.config/scripts/focus_direction.sh east"
:focus_north "/bin/bash /Users/johnlindquist/.config/scripts/focus_direction.sh north"
:focus_south "/bin/bash /Users/johnlindquist/.config/scripts/focus_direction.sh south"
:fix_floats "/bin/bash /Users/johnlindquist/.config/scripts/fix_floats.sh"
:wait "osascript -e 'delay %s'"
:chatgpt_voice "shortcuts run gpt-voice"
:raycast "open -g \"raycast://extensions/%s\""
:ai-command "open -g \"raycast://ai-commands/%s\""
;;
}
;;
;; --- APPLICATION IDENTIFIERS ---
;; Used for application-specific rules (`:condi`)
:applications {:ableton ["com.ableton.live"]
:chrome ["com.google.Chrome", "company.thebrowser.dia"]
:cursor ["com.todesktop.230313mzl4w4u92", "dev.zed.Zed"]
:zed ["dev.zed.Zed"]
:finder ["com.apple.finder"]
:terminal ["com.apple.Terminal", "com.googlecode.WezTerm"] ; Added WezTerm example
:code ["com.microsoft.VSCode", "com.todesktop.230313mzl4w4u92", "com.todesktop.23052492jqa5xjo", "com.exafunction.windsurf", "com.visualstudio.code.insiders", "dev.warp.Warp-Stable", "dev.zed.Zed"] ; Added Insiders, Warp example
:fcp ["com.apple.FinalCut"]
:miro ["com.electron.realtimeboard"]
:screenflow ["net.telestream.screenflow10"]
:screenstudio ["com.timpler.screenstudio"]
:slack ["com.tinyspeck.slackmacgap"]
:wezterm ["com.github.wez.wezterm"]
:cmux ["com.cmuxterm.app"]
:windows ["com.microsoft.rdc.macos", "com.parallels.desktop.appstore"]} ; RDP, Parallels
;; :webstorm ["com.jetbrains.Webstorm"] ; Example if needed
;; --- STANDARD LAYERS (Tap/Hold) ---
;; Layers activated by holding a key, with different behavior on tap.
:layers {;; :caps_lock-mode {:key :escape :alone {:key :escape}} ; Tap Caps for Esc, Hold for layer
:close-bracket-mode {:key :close_bracket} ; Hold ']' for layer
;; Escape Mode: Tap Esc normally, Hold Esc to activate layer AND reset other modes
:escape-mode {:key :escape
:params {:basic.to_if_alone_timeout_milliseconds 200
:basic.to_if_held_down_threshold_milliseconds 200}
:alone [{:key :escape}
{:set ["caps-lock-mode" 0]}
{:set ["fn-mode" 0]}
{:set ["opt-mode" 0]}
{:set ["shift-opt-mode" 0]}
{:set ["movement-mode" 0]}
{:set ["cursor-mode" 0]}
{:set ["delete-mode" 0]}
{:set ["nav-mode" 0]}
{:set ["snippet-mode" 0]}
{:set ["kit-mode" 0]}
{:set ["button2-mode" 0]}
{:set ["button4-mode" 0]}
{:set ["button5-mode" 0]}
{:set ["escape-mode" 0]}
{:set ["home-mode" 0]}]}
;; {:set ["submit-dictation-mode" 0]}
;;
:f23-mode {:key :f23 :alone {:key :vk_none}} ; Use F23 as a layer trigger
:launch-mode {:key :f24 :alone {:key :spacebar :modi :left_option}} ; Hold F24 for layer, Tap for Alfred
:non-mode {:key :non_us_backslash :alone {:key :non_us_backslash}} ; European backslash key layer
:num-mode {:key :keypad_num_lock :alone {:key :vk_none}} ; Num Lock layer
:shift-mode {:key :shift} ; Simple shift layer (less common, usually handled by OS)
:tab-mode {:key :tab} ; Hold Tab for layer
:home-mode {:key :home} ; Hold Home for layer
:tilde-mode {:key :grave_accent_and_tilde :alone {:key :grave_accent_and_tilde}} ; Hold Tilde for layer, Tap for Tilde
;; :fn-mode {:key :fn :alone {:key :home}} ; Hold Fn for layer, Tap for Home
:equal-mode {:key :equal_sign} ; Hold '=' for layer
:hyphen-mode {:key :hyphen}} ; Hold '-' for layer
;; --- SIMLAYERS (Simultaneous Key Presses) ---
;; Layers activated by pressing multiple keys *simultaneously*.
:simlayers {;; Top Row Simlayers
:zero-mode {:key :0} ; Press 0 + another key
:quick-mode {:key :q} ; Press Q + another key
:close-mode {:key :w} ; Press W + another key (for closing things)
:finder-mode {:key :e} ; Press E + another key ('F' in Colemak, for Finder actions)
:peek-mode {:key :r} ; Press R + another key ('P' in Colemak, for Peek actions)
:go-mode {:key :t} ; Press T + another key ('G' in Colemak, for Go actions)
:presentation-mode {:key :p} ; Press P + another key (';' in Colemak, for presentations)
;; Home Row Simlayers (with trackpad avoidance)
;; :condi ensures the layer only activates if NOT touching the trackpad
:opt-mode {:key :a :condi ["multitouch_extension_finger_count_total" 0]} ; A + key (Option layer)
:shift-opt-mode {:key :s :condi ["multitouch_extension_finger_count_total" 0]} ; S + key ('R' Colemak, Shift+Option layer)
:shift-mode {:key :d :condi ["multitouch_extension_finger_count_total" 0]} ; D + key ('S' Colemak, Shift layer)
:movement-mode {:key :f :condi ["multitouch_extension_finger_count_total" 0]} ; F + key ('T' Colemak, Arrow movement layer)
:cursor-mode {:key :g :condi ["multitouch_extension_finger_count_total" 0]} ; G + key ('D' Colemak, Cursor actions layer)
:delete-mode {:key :j} ; J + key ('N' Colemak, Deletion layer)
:nav-mode {:key :k} ; K + key ('E' Colemak, Navigation layer)
:period-mode {:key :period} ; . + key (URL opening and focusing layer)
:comma-mode {:key :comma} ; , + key (URL opening layer)
:semicolon-mode {:key :semicolon} ; ; + key ('O' Colemak, Special character layer)
:launch-mode {:key :u} ; U + key ('L' Colemak, App launching layer) - Note: also defined in :layers with F24 trigger
:snippet-mode {:key :quote} ; ' + key ('O' Colemak? Seems incorrect, ' is ' on Qwerty, P on Colemak - Check Colemak mapping) - Snippet layer
:emoji-mode {:key :z} ; Z + key (Emoji layer)
;; Bottom Row Simlayers
:command-mode {:key :c} ; C + key (Command layer)
:ctrl-opt-mode {:key :x}; X + key (Control Option layer)
:cmd-opt-mode {:key :b}; X + key (Control Option layer)
:command-shift-mode {:key :v} ; V + key (Command Shift layer)
:kit-mode {:key :n} ; N + key ('K' Colemak, Script Kit layer)
:media-mode {:key :m} ; M + key (Media keys layer)
:slash-mode {:key :slash} ; / + key (Seems unused?)
;; Special Key Simlayers
:spacebar-mode {:key :spacebar} ; Space + key (Symbol layer)
:password-mode {:key :quote :condi :shift-mode}} ; Shift + ' + key (Password entry layer) - Check conditions
;; --- DEVICE IDENTIFIERS ---
:devices {;; Map device names to their vendor/product IDs for device-specific rules
:moonlander [{:product_id 6505 :vendor_id 12951}]
:kinesis [{:product_id 259 :vendor_id 10730}]
:kinesisb [{:product_id 65535 :vendor_id 1452}] ; Built-in? Check IDs
:kinesisv [{:product_id 258 :vendor_id 1452}] ; Built-in? Check IDs
:apple [{:device_id 864 :vendor_id 10730}]} ; Example - check your specific Apple keyboard ID
;; :macbook [{:product_id 832 :vendor_id 1452}] ; Example MacBook keyboard
;; --- MAIN RULE DEFINITIONS ---
:main [{:des "Global Modifier Rules"
:rules [;; Global modifier rules
;; [:fn ["equal-mode" 1] nil {:alone {:key :home} :afterup {:set ["equal-mode" 0]}}]
;; fn key cannot be remapped on MacBook built-in keyboard (hardware limitation)
;; [:fn :home]
[{:key :caps_lock :modi :command} :return_or_enter]
[:caps_lock ["escape-mode" 1] nil {:alone {:key :escape} :afterup {:set ["escape-mode" 0]}}]
;; [:fn :equal_sign]
[:left_option :left_option nil {:alone {:key :semicolon :modi :left_command}
:afterup :reset-all-modes}]]}
{:des "Raycast Options"
:rules [
;; Need to figure out "froms" when adding modifiers
;; [{:key :s :modi :option} [:raycast "johnlindquist/ai-writing/rewrite"]]
;; [{:key :h :modi :option} [:raycast "raycast/raycast-ai/ai-chat?context=%7B%22preset%22:%226375022D-2B06-4DB4-A82E-8B0C96459304%22%7D"]]
;; [{:key :a :modi :option} [:raycast "raycast/raycast-ai/ai-chat"]]
;; [{:key :w :modi :option} [:raycast "johnlindquist/wezterm-panes/list-panes"]]
;; [{:key :e :modi :option} [:raycast "file-search/search-files"]]
;; [{:key :d :modi :option} [:raycast "johnlindquist/recent-zed-projects/index"]]
;; [{:key :m :modi :option} [:raycast "johnlindquist/copy-page-as-markdown/copy-page-as-markdown"]]
;; [{:key :f :modi :option} [:raycast "Codely/google-chrome/search-tab"]]
;; [{:key :c :modi :option} [:raycast "raycast/clipboard-history/clipboard-history"]]
]
}
{:des "Global Ctrl+F-keys → fn+F-keys (media/hardware controls)"
:rules [[:!Tf1 {:key :f1 :modi :fn}] ; brightness down
[:!Tf2 {:key :f2 :modi :fn}] ; brightness up
[:!Tf3 {:key :f3 :modi :fn}] ; mission control
[:!Tf4 {:key :f4 :modi :fn}] ; spotlight
[:!Tf5 {:key :f5 :modi :fn}] ; dictation
[:!Tf6 {:key :f6 :modi :fn}] ; do not disturb
[:!Tf7 {:key :f7 :modi :fn}] ; media back
[:!Tf8 {:key :f8 :modi :fn}] ; play/pause
[:!Tf9 {:key :f9 :modi :fn}] ; media forward
[:!Tf10 {:key :f10 :modi :fn}] ; mute
[:!Tf11 {:key :f11 :modi :fn}] ; volume down
[:!Tf12 {:key :f12 :modi :fn}]]} ; volume up
{:des "Global Button2-Mode"
:rules [:button2-mode
[{:pkey :button1} [{:pkey :button1 :modi :left_shift}] :!screenflow]
;; [:home :return_or_enter]
;; [:-s [{:pkey :button1 :modi :left_shift}]]
[:spacebar :return_or_enter]
;;
]}
;; --- Device Specific Rules ---
{:des "Windows RDP/Parallels Remapping"
:rules [:windows ; Apply only when :windows apps are frontmost
;; Swap Cmd and Ctrl for Windows compatibility
[:##left_command :left_control]
[:##left_control :left_command]
;; Example app-specific override within windows context
[:condi :windows :escape-mode]]}
;; [:-f {:key :f :modi :ts}] ; Ctrl+Shift+F in escape-mode only under windows
{:des "Apple Keyboard Specific Tweaks"
:rules [;; :apple ; Apply only to the specified :apple device
;; Example remappings for a specific Apple keyboard
;; [:slash :left_command :!windows {:alone :slash}] ; Slash -> Cmd (except in windows), Tap Slash
;; [:##period :left_control :!windows {:alone :period}] ; Period -> Opt (except in windows), Tap Period
[:!Oslash [:period :slash]]]} ; Opt+Slash -> ". /" sequence
;; [:m :left_control :!windows {:alone :m}] ; M -> Ctrl (except in windows), Tap M
;; Comma activates escape-mode temporarily while held
;; [:comma {:set ["escape-mode" 1]} nil {:afterup {:set ["escape-mode" 0]} :alone :comma}]
;; Shift keys become Delete/FwdDelete when tapped alone
;; [:##left_shift :left_shift nil {:alone :delete}]
;; [:##right_shift :right_shift nil {:alone :delete_forward}]
;; Fn key modifications (example commented out)
;; [:fn :super_hyper nil {:alone :key :spacebar :modi :left_option}] ; Fn tap -> Alfred, Hold -> SuperHyper
;; [[:fn :left_control] {:key :return_or_enter :modi :cs}] ; Fn+Ctrl -> Cmd+Shift+Enter
; Note: Kinesis/Moonlander specific rules commented out in original, add back if needed
{:des "Global Alfred Trigger"
:rules [;; Map PageUp tap to Alfred (can be adapted to other keys like Left Shift)
[:page_up :page_up nil {:alone :alfred}]]}
;; [:left_shift :left_shift nil {:alone :alfred}] ; Example using Left Shift tap
;; --- Mouse & Trackpad Rules ---
{:des "Basic Mouse Button Actions"
:rules [; Right Click + A/B (Example - seems incomplete?)
;; Simulate Cmd+Key shortcuts with Left Click + Key
;; [{:sim [{:pkey :button1} {:key :a}]} :!Ca] ; LeftClick+A -> Cmd+A (Select All)
;; [{:sim [{:pkey :button1} {:key :c}]} :!Cc] ; LeftClick+C -> Cmd+C (Copy)
;; [{:sim [{:pkey :button1} {:key :v}]} :!Cv] ; LeftClick+V -> Cmd+V (Paste)
;; [{:sim [{:pkey :button1} {:key :x}]} :!Cx] ; LeftClick+X -> Cmd+X (Cut)
;; [{:sim [{:pkey :button1} {:key :z}]} :!Cz] ; LeftClick+Z -> Cmd+Z (Undo)
;; Mouse Chord Actions
[[{:pkey :button1} {:pkey :button2}] :mission_control :!screenflow] ; Left+Right Click -> Mission Control (except in Screenflow)
;; Simultaneous mouse‑button chord
;; Mouse Button Layers (Hold button to activate layer)
[{:pkey :button4} ["button4-mode" 1] nil {:alone [:space_left_by_display] :afterup ["button4-mode" 0]}] ; Hold Btn4 for layer, Tap -> Ctrl+Left
[{:pkey :button5} ["button5-mode" 1] nil {:alone [:space_right_by_display] :afterup ["button5-mode" 0]}] ; Hold Btn5 for layer, Tap -> Ctrl+Right
[{:pkey :button2} ["button2-mode" 1] nil {:alone :button2 :afterup ["button2-mode" 0]}]]} ; Hold RightClick for layer, Tap -> RightClick
;; {:des "Button2 Mode (Right Click Hold)"
;; :rules [:button2-mode
;; ;; Remap keys while Right Click is held
;; [:a [{:pkey :button1} :!Ca]] ; RClick+A -> LeftClick then Cmd+A
;; [:s :shift_click] ; RClick+S -> Shift+LeftClick
;; [:d [{:pkey :button1} :!Cd]] ; RClick+D -> LeftClick then Cmd+D
;; [:c [{:pkey :button1} :!Cc]] ; RClick+C -> LeftClick then Cmd+C
;; [:x [{:pkey :button1} :!Cx]] ; RClick+X -> LeftClick then Cmd+X
;; [:v [{:pkey :button1} :!Cv]] ; RClick+V -> LeftClick then Cmd+V
;; ;; Remap Left Click while Right Click is held
;; ;; In Screenflow: Shift+Click then Cmd+Delete
;; [{:pkey :button1} [{:pkey :button1 :modi :left_shift} :!Cdelete_or_backspace] :screenflow]
;; ;; Default (commented out in original): [{:pkey :button1} {:pkey :button1 :modi :left_shift}] Shift+Click
;; ]}
{:des "Button4 Mode (Button4 Hold)"
:rules [:button4-mode
;; Remap Left Click while Button4 is held
[{:pkey :button1} :shift_click]]} ; Btn4+LeftClick -> Shift+LeftClick
{:des "Button5 Mode (Button5 Hold)"
:rules [:button5-mode
;; Remap Left Click while Button5 is held
[{:pkey :button1} :shift_click]]} ; Btn5+LeftClick -> Shift+LeftClick
;; --- Trackpad Rules (Grouped by Finger Count - Method 2: Individual Conditions) ---
{:des "Trackpad: 1 Finger Actions"
:rules [;; Apply these rules only when exactly 1 finger is on the trackpad
[:-t :button1 ["multitouch_extension_finger_count_total" 1]] ; T (F Colemak) -> Left Click
[:w :!Cw ["multitouch_extension_finger_count_total" 1]] ; W -> Cmd+W (Close)
[:-f :!Cright_arrow ["multitouch_extension_finger_count_total" 1]] ; F (E Colemak) -> Cmd+Right (Forward?)
[:-b :!Cleft_arrow ["multitouch_extension_finger_count_total" 1]] ; B -> Cmd+Left (Back?)
[:r :!Cl ["multitouch_extension_finger_count_total" 1]] ; R (P Colemak) -> Cmd+L (Focus Location Bar?)
[:a {:pkey :button1 :modi :left_option} ["multitouch_extension_finger_count_total" 1]] ; A -> Opt+Click
[:s :button2 ["multitouch_extension_finger_count_total" 1]] ; S (R Colemak) -> Right Click
[:d {:pkey :button1 :modi :left_shift} ["multitouch_extension_finger_count_total" 1]] ; D (S Colemak) -> Shift+Click
[:g {:pkey :button1 :modi :left_command} ["multitouch_extension_finger_count_total" 1]] ; G (D Colemak) -> Cmd+Click
[:z :!Cz ["multitouch_extension_finger_count_total" 1]] ; Z -> Cmd+Z (Undo)
[:x :!Cx ["multitouch_extension_finger_count_total" 1]] ; X -> Cmd+X (Cut)
[:c :!Cc ["multitouch_extension_finger_count_total" 1]] ; C -> Cmd+C (Copy) <--- Check this
[:v :!Cv ["multitouch_extension_finger_count_total" 1]] ; V -> Cmd+V (Paste)
[:delete [:button1 :delete] ["multitouch_extension_finger_count_total" 1]] ; Delete -> LeftClick + Delete
[:hyphen [{:pkey :button1} :delete_line] ["multitouch_extension_finger_count_total" 1]]]} ; Hyphen -> LeftClick + Delete Line (Custom Action)
{:des "Trackpad: 2 Fingers Actions"
:rules [;; Apply these rules only when exactly 2 fingers are on the trackpad
[:x [{:pkey :button1 :modi :shift} :!Cx] ["multitouch_extension_finger_count_total" 2]] ; X -> Shift+Click then Cmd+X
[:c [:button1 :!Cc] ["multitouch_extension_finger_count_total" 2]] ; C -> LeftClick then Cmd+C <--- Check this
[:v [:button1 :!Cv] ["multitouch_extension_finger_count_total" 2]] ; V -> LeftClick then Cmd+V
;; REMOVED/COMMENTED: [:left_command :return_or_enter ["multitouch_extension_finger_count_total" 2]]
[:delete [{:pkey :button1 :modi :shift} :delete] ["multitouch_extension_finger_count_total" 2]]]} ; Delete -> Shift+Click then Delete
{:des "Trackpad: 3 Fingers Actions"
:rules [;; Apply these rules only when exactly 3 fingers are on the trackpad
[:-a :restore_screenshot ["multitouch_extension_finger_count_total" 3]] ; S (R Colemak) -> Capture Screenshot
[:-s :capture_screenshot ["multitouch_extension_finger_count_total" 3]] ; S (R Colemak) -> Capture Screenshot
[:-r :record_screen ["multitouch_extension_finger_count_total" 3]]]} ; R (P Colemak) -> Record Screen
{:des "Trackpad: 4 Fingers Actions"
:rules [;; Apply these rules only when exactly 4 fingers are on the trackpad
[:##f :return_or_enter ["multitouch_extension_finger_count_total" 4]]]} ; F -> Enter (## means optional mods)
;; --- Application Specific Rules ---
{:des "Ableton Live"
:rules [:ableton ; Apply only when Ableton is frontmost
;; Trackpad Avoidance (0 fingers)
[:condi :ableton ["multitouch_extension_finger_count_total" 0]]
[:tilde :!COb] ; Tilde -> Cmd+Opt+B (Toggle Browser)
[[:spacebar :s] :f9] ; Space+S -> F9 (Record)
[[:spacebar :a] [:open_bracket :open_bracket]] ; Space+A -> '[[' sequence?
;; Trackpad Interaction (1 finger)
[:condi :ableton ["multitouch_extension_finger_count_total" 1]]
[:tab :!Stab] ; Tab -> Shift+Tab (Toggle Clip/Device View)
[:left_option [:!Ce :!Cj]] ; Left Opt -> Cmd+E (Split), Cmd+J (Consolidate) ?
[:-b [:shift_click :add_midi_clip]] ; B -> Shift+Click then Add MIDI Clip
[:-q [:q :q]] ; Q -> QQ ?
[:-w :!COl] ; W -> Cmd+Opt+L (Toggle Loop)
[:-d [:button1 :button1]] ; D (S Colemak) -> Double Click
[:-g :!C4] ; G (T Colemak) -> Cmd+4 (Toggle Grid Snap)
[:hyphen :!C1] ; - -> Cmd+1 (Narrow Grid)
[:equal_sign :!C2] ; = -> Cmd+2 (Widen Grid)
[:-f :!Stab] ; F (E Colemak) -> Shift+Tab
[:-p :!COp] ; P (R Colemak) -> Cmd+Opt+P (Toggle Plugin Windows)
[:left_shift [:button1 :delete_or_backspace]] ; Left Shift -> Click + Backspace
[:delete_or_backspace [:button1 :delete_or_backspace]] ; Delete -> Click + Backspace
[:1 :narrow_grid] ; 1 -> Narrow Grid
[:2 :widen_grid] ; 2 -> Widen Grid
;; Trackpad Interaction (2 fingers)
[:condi :ableton ["multitouch_extension_finger_count_total" 2]]
[:-a :!COb] ; A -> Cmd+Opt+B
[:-r :loop_selection] ; R (S Colemak) -> Loop Selection (Cmd+L)
[:-s :split_clip] ; S (D Colemak) -> Split Clip (Cmd+E)
[:-t :loop_selection] ; T (F Colemak) -> Loop Selection (Cmd+L)
;; Trackpad Interaction (3 fingers)
[:condi :ableton ["multitouch_extension_finger_count_total" 3]]
[:-t :add_midi_track]]} ; T (F Colemak) -> Add MIDI Track
{:des "Google Chrome"
:rules [:chrome ; Apply only when Chrome is frontmost
;; Tap Left Cmd for Ctrl+T (New Tab), Hold for Cmd
[:left_command :left_command nil {:alone [:!Ct]}]
;; [:left_option :left_option nil {:alone ["open simple://scripts/list-chrome-tabs"]}] ; Tap Left Opt for custom script
;; [:right_option :focus_omnibar] ; Tap Right Opt for Cmd+L
;; [:left_control :left_option nil {:alone [:!CSt]}] ; Tap Ctrl for Cmd+Shift+T (Reopen Tab), Hold for Opt
;; Trackpad Interaction (2 fingers)
[:condi :chrome ["multitouch_extension_finger_count_total" 2]]
[:-d :open_dev_tools] ; D (S Colemak) -> Open Dev Tools
[:-a :!COleft_arrow] ; A -> Cmd+Opt+Left (Prev Tab)
[:-t :!COright_arrow] ; T (F Colemak) -> Cmd+Opt+Right (Next Tab)
;; Escape Mode in Chrome
[:condi :chrome :escape-mode]
[:-f :chrome_full_screen] ; Esc+F -> Toggle Full Screen
;; Opt Mode (A-Simlayer) in Chrome
[:condi :chrome :opt-mode]
[:-o :chrome_tab_switcher] ; A+O (semicolon Colemak) -> Tab Switcher (Cmd+Shift+A)
[:condi :chrome :button2-mode]
[:-w [{:pkey :button1} :!Cw]]
[:-a [{:pkey :button1} [:delay-key "e"]]]]}
{:des "WezTerm"
:rules [:wezterm ; Apply only when WezTerm is frontmost
[:left_command :left_command nil {:alone :go_to_file}]
[:left_control :left_control nil {:alone :command_palette}]]}
{:des "VS Code / Cursor"
:rules [:code ; Apply only when :code apps are frontmost
;; Tap Left Cmd for Go To File (Cmd+P), Hold for Cmd
[:left_command :left_command nil {:alone :go_to_file}]
;; Tap Left Ctrl for Command Palette (Cmd+Shift+P), Hold for Ctrl
[:left_control :left_control nil {:alone :command_palette}]
;; Tap Right Ctrl for Command Palette (Cmd+Shift+P), Hold for Ctrl
[:right_control :right_control nil {:alone :command_palette}]
;; [:home :start_debugger] ; Tap Home for F5
;; [:end :restart_debugger] ; Tap End for Cmd+Shift+F5
;; Escape Mode in Code (View/Focus Switching)
[:condi :code :escape-mode]
[:-g :focus_git] ; Esc+G (T Colemak) -> Focus Git View (Ctrl+Shift+G)
[:-a :focus_editor] ; Esc+A -> Focus Editor (Hyper+E)
[:-e :focus_editor] ; Esc+E (K Colemak) -> Focus Editor (Hyper+E)
[:-t :focus_terminal] ; Esc+T -> Focus Terminal (Hyper+T)
;; [:-h :focus_editor_left] ; Esc+H -> Focus Left Editor (Hyper+I)
[:-i {:key :i :modi :cos}] ; Esc+I (L Colemak) -> Cmd+Opt+Shift+I ?
[:-x :focus_explorer] ; Esc+X -> Focus Explorer (Cmd+Shift+E)
[:-f :find_in_project] ; Esc+F (E Colemak) -> Find in Project (Cmd+Shift+F)
[:-r :replace_in_project] ; Esc+R (P Colemak) -> Replace in Project (Cmd+Shift+H)
[:-z [:!Ck :z]] ; Esc+Z -> Cmd+K Z (Toggle Zen Mode)
[:delete_or_backspace :toggle_sidebar] ; Esc+Delete -> Toggle Sidebar (Cmd+B)
;; [:delete_forward :!COb] ; Esc+FwdDelete -> Cmd+Opt+B (Toggle Bottom Panel?)
;; Trackpad Interaction (1 finger) in Code
[:condi :code ["multitouch_extension_finger_count_total" 1]]
;; Tap Left Cmd for Start Debugger (F5), Hold for Cmd
[:left_command :left_command nil {:alone :start_debugger}]
;; [:left_option :left_option nil {:alone :restart_debugger}] ; Tap Left Opt for Restart Debugger
;; Trackpad Interaction (2 fingers) in Code
[:condi :code ["multitouch_extension_finger_count_total" 2]]
[:-t [:button1 :f2]]]} ; T (F Colemak) -> Left Click then F2 (Rename)
{:des "Terminal / iTerm"
:rules [:terminal ; Apply only when :terminal apps are frontmost
;; Tmux: Ctrl+R -> Prefix + % (New Vertical Pane)
[:!Cr [:tmux :tmux_new_pane]]
;; Nav Mode (K-Simlayer) in Terminal
[:condi :terminal :nav-mode]
[:-a :terminal_previous_tab] ; K+A -> Previous Tab (Cmd+Shift+[)
[:-t :terminal_next_tab]]} ; K+T (F Colemak) -> Next Tab (Cmd+Shift+])
{:des "Slack"
:rules [:slack ; Apply only when Slack is frontmost
;; Tap Left Cmd for Ctrl+T (Find Conversation?), Hold for Cmd
[:left_command :left_command nil {:alone :!Ct}]
;; Nav Mode (K-Simlayer) in Slack
[:condi :slack :nav-mode]
[:-a :slack_previous] ; K+A -> Previous History (Cmd+[)
[:-t :slack_next]]} ; K+T (F Colemak) -> Next History (Cmd+])
{:des "Final Cut Pro"
:rules [:fcp ; Apply only when FCP is frontmost
;; Button3 Hold -> Hold H (Hand tool), Tap -> A (Select tool)
[{:pkey :button3} [:h {:pkey :button1}] nil {:afterup {:key :a}}]
;; Trackpad Interaction
[:condi :fcp :multitouch_extension_finger_count_total]
;; Delete -> Click + Backspace
[:delete_or_backspace [:button1 :delete_or_backspace]]]}
{:des "Miro"
:rules [:miro ; Apply only when Miro is frontmost
;; Trackpad Interaction (1 finger)
[:condi :miro ["multitouch_extension_finger_count_total" 1]]
;; Delete -> Esc + Click + Backspace
[:delete_or_backspace [:escape :button1 :delete_or_backspace]]
;; A -> Esc + N (Text tool) + Click
[:a [:escape :n :button1]]
;; Trackpad Interaction (2 fingers)
[:condi :miro ["multitouch_extension_finger_count_total" 2]]
;; F -> Esc + N (Text tool) + Click
[:f [:escape :n :button1]]
;; C -> Cmd+C (Copy) + Click + Cmd+V (Paste)
[:c [:!Cc :button1 :!Cv]]]}
{:des "Finder"
:rules [:finder
[:condi :finder :button2-mode]
;; [:-r [{:pkey :button1} ["/Users/johnlindquist/scripts/scripts/compress-finder-image.ts"]]] ;;cmd+shift+r
[:-r [{:pkey :button1} [:compress-finder-image]]] ;;cmd+shift+r
[:delete_or_backspace [{:pkey :button1} {:key :delete_or_backspace :modi :left_command}]]]} ;;cmd+shift+r
{:des "Cursor"
:rules [:cursor ; Apply only when Cursor is frontmost
;; Trackpad Interaction (1 finger)
[:condi :cursor :button2-mode]
;; [{:pkey :button1} [{:pkey :button1} {:key :f3 :modi :hyper}]] ;;ctrl+shift+alt+cmd+f3
[:-a [{:pkey :button1} {:key :f11 :modi :hyper}]] ;;ctrl+shift+alt+cmd+f3
[:-f [{:pkey :button1} {:key :f3 :modi :hyper}]] ;;ctrl+shift+alt+cmd+f3
[:-s [{:pkey :button1} {:key :f8 :modi :hyper}]] ;;ctrl+shift+alt+cmd+f3
[:-r [{:pkey :button1} {:key :f12 :modi :left_shift}]] ;;ctrl+shift+alt+cmd+f3
[:-x [{:pkey :button1} {:key :d :modi :cs}]] ;;cmd+shift+d
[:delete_or_backspace [{:pkey :button1} {:key :delete_or_backspace :modi :left_command}]]]} ;;ctrl+shift+alt+cmd+f3
{:des "ScreenFlow"
:rules [:screenflow ; Apply only when ScreenFlow is frontmost
;; Button3 Hold -> Hold H (Hand tool), Tap -> A (Select tool)
[{:pkey :button3} [:h {:pkey :button1}] nil {:afterup {:key :a}}]
;; Tap Left Cmd -> Shift+Click + Cmd+Delete, Hold for Cmd
[:left_command :left_command nil {:alone [{:pkey :button1 :modi :left_shift} :!Cdelete_or_backspace]}]
;; Trackpad Interaction
[:condi :screenflow :multitouch_extension_finger_count_total]
[:spacebar :spacebar] ; Space -> Play/Pause
;; D -> Shift+Click + Cmd+Delete
[:d [{:pkey :button1 :modi :left_shift} :!Cdelete_or_backspace]]
;; A -> Cmd+Opt+; (Add Video Action)
[:a :!COsemicolon]
;; Button2 Mode (Right Click Hold) in Screenflow
[:condi :screenflow :button2-mode]
;; Left Click -> Shift+Click + Cmd+Delete
[{:pkey :button1} [{:pkey :button1 :modi :left_shift} :!Cdelete_or_backspace]]]}
{:des "Screen Studio"
:rules [:screenstudio ; Apply only when ScreenStudio is frontmost
;; X -> C X sequence? (Maybe Cut?)
[:x [:c :x]]]}
;; --- Layer Rules (Tap/Hold Triggers) ---
;; {:des "Caps Lock Mode (Tap Esc, Hold Layer)"
;; :rules [:caps_lock-mode
;; ;; Remap keys while Caps Lock is held
;; [:##caps_lock :##escape] ; Allow Caps Lock + Esc -> Esc
;; [:a :caps_lock] ; Caps+A -> Actual Caps Lock toggle
;; [:spacebar [:spacebar :equal_sign :spacebar]] ; Caps+Space -> " = "
;; [:-g :focus_git] ; Caps+G (T Colemak) -> Focus Git
;; [:-n :hyphen] ; Caps+N (J Colemak) -> Hyphen
;; [:-e {:key :hyphen :modi :left_shift}]]} ; Caps+E (K Colemak) -> Underscore
{:des "Escape Mode (Hold Esc)"
:rules [:escape-mode
;; Application specific rules are defined within app blocks (:code, :chrome, etc.)
;; General rules for Escape Mode
[:-w {:key :w :modi :hyper}] ; Esc+W -> window
[:-f [:toggle-pane-zoom-cmux] :cmux] ; Esc+F -> Toggle Pane Zoom (cmux only)
[:-f {:key :f :modi :hyper}] ; c+F -> Focus
[:-s :spotlight] ; Esc+S (D Colemak) -> Spotlight
[:-c :chatgpt]
;; [:-t :mission_control] ; Esc+T (F Colemak) -> Mission Control
;; Number row -> Cmd+Opt+Number (Switch Spaces/Desktops?)
[:1 :!CO1]
[:2 :!CO2]
[:3 :!CO3]
[:4 :!CO4]
[:5 :!CO5]
[:6 :!CO6]
[:7 :!CO7]
[:0 :!CO0]
[{:pkey :button1} [{:pkey :button1} [:read-paste-enter "/Users/johnlindquist/.config/snippets/continue.txt"]]]
[:-o {:key :escape :modi :left_command}] ; C+E (K Colemak) -> Go to Home (Cmd+Up)
[:-i {:key :k :modi :co}]]} ; C+E (K Colemak) -> Go to Home (Cmd+Up)
;;
{:des "Fn Mode (Hold Fn, Tap Home)"
:rules [:fn-mode
;; Remap keys while Fn is held (like traditional Fn layer)
;; Homerow arrows with Shift
[:##d :left_shift] ; Fn+D (S Colemak) -> Shift
[:##h :!Fleft_arrow] ; Fn+H -> Fn+Left Arrow
[:##j :!Fdown_arrow] ; Fn+J (Y Colemak) -> Fn+Down Arrow
[:##k :!Fup_arrow] ; Fn+K (E Colemak) -> Fn+Up Arrow
[:##l :!Fright_arrow]; Fn+L (U Colemak) -> Fn+Right Arrow
;; Space/Cmd remapping
[:##spacebar {:key :return_or_enter}] ; Fn+Space -> Enter
[:##left_command {:key :return_or_enter :modi :cs}] ; Fn+Cmd -> Cmd+Shift+Enter
;; Bottom row remapping
[:##z {:key :i :modi :command}] ; Fn+Z -> Cmd+I ?
[:##c {:key :l :modi :command}] ; Fn+C -> Cmd+L ?
[:##x {:key :i :modi :cos}]]} ; Fn+X -> Cmd+Opt+Shift+I ?
{:des "Hyphen Mode (Hold Hyphen)"
:rules [:slash-mode
;; Git/Code related snippets while holding Hyphen
[:-n :!CTOSf] ; Hyphen+N (J Colemak) -> Ctrl+Cmd+Opt+Shift+F ?
[:-s [:read-paste-enter "/Users/johnlindquist/.config/snippets/commit-push-pr.txt"]]
[:-g [:read-paste-enter "/Users/johnlindquist/.config/snippets/git-diff-then-commit.txt"]]
[:-d [:read-paste-enter "/Users/johnlindquist/.config/snippets/developer-instructions.txt"]]
[:-t [:read-paste-enter "/Users/johnlindquist/.config/snippets/think-and-fix.txt"]]
[:-w [:read-paste-enter "/Users/johnlindquist/.config/snippets/commit-push-watch.txt"]]
;; [:-p [:read-paste-enter "/Users/johnlindquist/.config/snippets/planner.txt"]]
[:-e [:read-paste-enter "/Users/johnlindquist/.config/snippets/execute.txt"]]
;; [:-i [:read-paste-enter "/Users/johnlindquist/.config/snippets/execute-test.txt"]]
[:-c [:read-paste-enter "/Users/johnlindquist/.config/snippets/continue.txt"]]
[:-p [:read-paste-enter "/Users/johnlindquist/.config/snippets/project.txt"]]
[:-b [:read-paste-enter "/Users/johnlindquist/.config/snippets/break-down-problem.txt"]]
[:-i [:read-paste-enter "/Users/johnlindquist/.config/snippets/improve.txt"]]]}
{:des "Equal Mode (Hold Equal)"
:rules [:equal-mode
;; Mouse/Arrow interactions while holding Equal
;; [{:pkey :button1} [{:pkey :button1} :x :delete_forward]] ; Equal+LClick -> LClick + X + FwdDelete ?
;; [{:pkey :button2} [{:pkey :button1} :delete_forward :spacebar]] ; Equal+RClick -> LClick + FwdDelete + Space ?
[{:pkey :button1} [:move_to_next_display]] ; Equal+LClick -> Move to next display
[{:pkey :button3} [:move_window_to_next_empty_space]] ; Equal+RClick -> Move to previous display
;; [{:pkey :button6} :!Tright_arrow] ; Equal+Btn5 -> Ctrl+Right COMMENTED OUT
;; [{:pkey :button6} ["/Users/johnlindquist/.config/scripts/space_right.sh"]] ; Equal+Btn6 -> jump/make space right
;; [{:pkey :button4} :!Tleft_arrow] ; Equal+Btn4 -> Ctrl+Left COMMENTED OUT
;; [{:pkey :button4} ["/Users/johnlindquist/.config/scripts/space_left.sh"]] ; Equal+Btn4 -> jump/make space left
;; [:-h :!Tleft_arrow] ; Equal+H -> Ctrl+Left COMMENTED OUT
[:-j [:window_resize_to_next_tenth_wider]]
[:-l [:move_window_west]]
[:-u [:move_window_east]]
[:-y [:window_resize_to_next_tenth_narrower]]
[:-h [:space_left]] ; Equal+H -> jump/make space left
[:-n [:move_window_to_previous_empty_space]] ; Equal+J -> move left
[:-e [:move_window_to_next_empty_space]] ; Equal+K -> move right
;; [:-x [:remove_current_space]]
[:-x [:remove_empty_spaces_improved]]
[:-m [:mission_control]]
[:-d [:move_to_next_display]]
[:-r [:restart_yabai]]
[:-s [:stop_yabai]]
[:-t [:focus_next_window_same_app]]
[{:key :f :modi :left_shift} [:focus_previous_window_same_app]]
[:1 [:move_window_to_display_1]]
[:2 [:move_window_to_display_2]]
[:3 [:move_window_to_display_3]]
[:4 [:move_window_to_display_4]]
;; [:-i :!Tright_arrow] ; Equal+I (L Colemak) -> Ctrl+Right COMMENTED OUT
[:-i [:space_right]] ; Equal+I -> jump/make space right
[:-c :!CSc] ; Equal+C -> Cmd+Shift+C
[:home {:key :home :modi :hyper}]]} ; Equal+Home -> Hyper+Home
{:des "Tab Mode (Hold Tab)"
:rules [:tab-mode
;; Actions while holding Tab
[:-z :restore_screenshot] ; Tab+A (P Colemak) -> Restore Screenshot
[:-r :record_screen] ; Tab+R (P Colemak) -> Record Screen
[:-s :capture_screenshot] ; Tab+S (R Colemak) -> Capture Screenshot
[:-i :!SOi] ; Tab+I (L Colemak) -> Shift+Opt+I ?
[:-q :vk_consumer_next] ; M+F (E Colemak) -> Next Track
[:-p :vk_consumer_play]
[:-t [:launch "Google Tasks"]]
[:-k [:launch "Google Keep"]]
[:-m [:launch "/Users/johnlindquist/Applications/Chrome Apps.localized/Messages.app"]]
;;
]} ; M+P (R Colemak) -> Play/Pause
;; {:des "Submit Dictation Mode"
;; :rules [:submit-dictation-mode
;; [:home [{:key :home :modi :shift} ["submit-dictation-mode" 0]]]
;; ;;
;; ]}
{:des "Home Mode (Hold Home)"
:rules [:home-mode
;; Actions while holding Home I have to go.
;; Colemak Top Row -> F1-F10 with :hyper
;; [:-q {:key :f1 :modi :hyper}]
[:grave_accent_and_tilde [:space_left]]
[:-q [:focus_west]]
[:-w {:key :f2 :modi :hyper}]
[:-f {:key :f3 :modi :hyper}]
;; [:-p {:key :f4 :modi :hyper}]
[:-p [:focus_east]]
[:-g [:space_right]]
[:-j {:key :f6 :modi :hyper}]
[:-l {:key :f7 :modi :hyper}]
[:-u {:key :f8 :modi :hyper}]
[:-y {:key :f9 :modi :hyper}]
[:semicolon {:key :f10 :modi :hyper}]
;; Colemak Middle Row -> F11-F20 with :hyper
;; [:-a {:key :f11 :modi :hyper}]
[:hyphen [:move_window_to_previous_empty_space]]
[:-a [:move_window_left_half]]
;; [:-r {:key :f12 :modi :hyper}]
[:-r [:move_window_center_66]]
;; [:-s {:key :8 :modi :hyper}]
[:-s [:move_window_center_full]]
;; [:-t {:key :9 :modi :hyper}]
[:-t [:move_window_right_half]]
[:-d [:move_window_to_next_empty_space]]
[:-h [:move_to_previous_display]]
[:-n [:move_window_center_66]]
[:-e [:move_window_center_full]]
[:-i [:move_window_right_half]]
;; [:-h [:focus_west]]
;; [:-n [:focus_south]]
;; [:-e [:focus_north]]
;; [:-i [:focus_east]]
[:-n {:key :f17 :modi :hyper}]
[:-e {:key :f18 :modi :hyper}]
[:-i {:key :f19 :modi :hyper}]
[:-o {:key :f20 :modi :hyper}]
;; Colemak Bottom Row -> F1-F10 with [:super :hyper]
[:-z {:key :f1 :modi :super-hyper}]
[:-x {:key :f2 :modi :super-hyper}]
[:-c {:key :f3 :modi :super-hyper}]
[:-v {:key :f4 :modi :super-hyper}]
[:-b {:key :f5 :modi :super-hyper}]
[:-k {:key :f6 :modi :super-hyper}]
[:-m {:key :f7 :modi :super-hyper}]
[:comma {:key :f8 :modi :super-hyper}]
[:period {:key :f9 :modi :super-hyper}]
[:slash {:key :f10 :modi :super-hyper}]
[:return_or_enter [:fix_with_ai]]
[:1 [:move_window_to_display_1]]
[:2 [:move_window_to_display_2]]
[:3 [:move_window_to_display_3]]
[:4 [:move_window_to_display_4]]
[:left_shift {:key :f11 :modi :left_shift}]]}
;;
;; {:des "Close Bracket Mode (Hold ])"
;; :rules [:button2-mode
;; ;; Window Management via 'mwm' script while holding ']'
;; [:2 ["/opt/homebrew/bin/mwm move-left"]] ; ]+2 -> Move Left
;; [:3 ["/opt/homebrew/bin/mwm center"]] ; ]+3 -> Center
;; [:4 ["/opt/homebrew/bin/mwm move-right"]] ; ]+4 -> Move Right
;; [:-q ["/opt/homebrew/bin/mwm maximize-height"]] ; ]+4 -> Maximize Height
;; [:-a ["/opt/homebrew/bin/mwm maximize"]] ; ]+A -> Maximize
;; [:-w ["/opt/homebrew/bin/mwm left width-34% height-100%"]] ; ]+W -> Left 1/3 Column
;; [:-f ["/opt/homebrew/bin/mwm center width-34% height-100%"]] ; ]+F (E Colemak) -> Top Half
;; [:-p ["/opt/homebrew/bin/mwm right width-34% height-100%"]] ; ]+P (Semicolon Colemak) -> Right 1/3 Column
;; [:-r ["/opt/homebrew/bin/mwm left width-50% height-100%"]] ; ]+R (S Colemak) -> Left Half
;; [:-s ["/opt/homebrew/bin/mwm center width-75% height-75%"]] ; ]+S (D Colemak) -> Center 75%
;; [:-t ["/opt/homebrew/bin/mwm right width-50% height-100%"]] ; ]+T (F Colemak) -> Right Half
;; [:-z ["/opt/homebrew/bin/mwm left width-66% height-100%"]] ; ]+Z -> Left 2/3 Column
;; [:-x ["/opt/homebrew/bin/mwm snap-left"]] ; ]+X -> Bottom Half
;; ;; [:-c ["/opt/homebrew/bin/mwm right width-66% height-100%"]] ; ]+C -> Right 2/3 Column
;; [:-v ["/opt/homebrew/bin/mwm snap-right"]] ; ]+C -> Right 2/3 Column
;; [:spacebar ["/opt/homebrew/bin/mwm display-next"] :condi :!screenflow] ; ]+Space -> Move to Next Display
;; ;; cmd+tab
;; [:-c :!Ctab]
;; [:-g :!Cgrave_accent_and_tilde]
;; [:-b ["/bin/bash /Users/johnlindquist/.config/scripts/pin_left.sh"]]
;; ;; control+`
;; ;; [:left_option :!Ctilde]
;; ]}
{:des "Close Bracket Mode (Hold ])"
:rules [:close-bracket-mode
;; Window Management via 'mwm' script while holding ']'
[:2 ["/opt/homebrew/bin/mwm move-left"]] ; ]+2 -> Move Left
[:3 ["/opt/homebrew/bin/mwm center"]] ; ]+3 -> Center
[:4 ["/opt/homebrew/bin/mwm move-right"]] ; ]+4 -> Move Right
[:-q ["/opt/homebrew/bin/mwm maximize-height"]] ; ]+4 -> Maximize Height
[:-a ["/opt/homebrew/bin/mwm maximize"]] ; ]+A -> Maximize
[:-w ["/opt/homebrew/bin/mwm left width-34% height-100%"]] ; ]+W -> Left 1/3 Column
[:-f ["/opt/homebrew/bin/mwm center width-34% height-100%"]] ; ]+F (E Colemak) -> Top Half
[:-p ["/opt/homebrew/bin/mwm right width-34% height-100%"]] ; ]+P (Semicolon Colemak) -> Right 1/3 Column
[:-r ["/opt/homebrew/bin/mwm left width-50% height-100%"]] ; ]+R (S Colemak) -> Left Half
[:-s ["/opt/homebrew/bin/mwm center width-75% height-75%"]] ; ]+S (D Colemak) -> Center 75%
[:-t ["/opt/homebrew/bin/mwm right width-50% height-100%"]] ; ]+T (F Colemak) -> Right Half
[:-z ["/opt/homebrew/bin/mwm left width-66% height-100%"]] ; ]+Z -> Left 2/3 Column
[:-x ["/opt/homebrew/bin/mwm snap-left"]] ; ]+X -> Bottom Half
[:-c ["/opt/homebrew/bin/mwm right width-66% height-100%"]] ; ]+C -> Right 2/3 Column
[:-v ["/opt/homebrew/bin/mwm snap-right"]] ; ]+C -> Right 2/3 Column
[:spacebar ["/opt/homebrew/bin/mwm display-next"]]]} ; ]+Space -> Move to Next Display
{:des "F23 Mode (Hold F23)"
:rules [:f23-mode
[:-i :!SOi]]} ; F23+I (L Colemak) -> Shift+Opt+I ?
;; --- Simlayer Rules (Simultaneous Presses) ---
{:des "quick Mode (Q + Key)"
:rules [:quick-mode
;; Utility scripts triggered by Q + Key
[:g ["/Users/johnlindquist/scripts/scripts/goku-notify.ts"]] ; Q+G -> Reload Karabiner via Goku
[:d ["date +\"%Y-%m-%d %H:%M:%S\" | tee >(pbcopy) | /opt/homebrew/bin/terminal-notifier -sound default -message"]] ; Q+D -> Copy/Notify current timestamp
;; Cmd+Opt modified arrow keys via Q + Key (same as B layer)
[:##h :!COleft_arrow] ; Q+H -> Cmd+Opt+Left
[:##j :!COdown_arrow] ; Q+J -> Cmd+Opt+Down
[:##k :!COup_arrow] ; Q+K -> Cmd+Opt+Up
[:##l :!COright_arrow]]}
{:des "Zero Mode (0 + Key)"
:rules [:zero-mode
;; Display Layout Switching via Hyper Key shortcuts
[:1 :display_layout_1] ; 0+1 -> Hyper+1
[:2 :display_layout_2] ; 0+2 -> Hyper+2
[:3 :!CSTO3] ; 0+3 -> Ctrl+Shift+Cmd+Opt+3 ?
[:4 :!CSTO4]]} ; 0+4 -> Ctrl+Shift+Cmd+Opt+4 ?
{:des "Close Mode (W + Key)"
:rules [:close-mode
;; Closing actions in Code triggered by W + Key
[:condi :code :close-mode]
[:-a :close_all] ; W+A -> Close All (Cmd+R, W sequence?)
[:-o :close_others]]} ; W+O (Semicolon Colemak) -> Close Others (Cmd+Opt+T)
;; Add :condi :chrome if needed for browser
{:des "Finder Mode (E + Key / F Colemak)"
:rules [:finder-mode
;; Open common folders or run scripts via E + Key
[:-a "open /Applications"] ; E+A -> Open Applications
[:-d "open ~/Downloads"] ; E+D (S Colemak) -> Open Downloads
[:-h "open ~"] ; E+H -> Open Home Directory
[:-j ["~/.kit/kar fenced-js"]] ; E+J (Y Colemak) -> Fenced JS script
[:-b [:tilde :tilde :tilde :b :a :s :h :return_or_enter :return_or_enter :tilde :tilde :tilde :up_arrow]]]} ; E+B -> Fenced Bash snippet
{:des "Peek Mode (R + Key / P Colemak)"
:rules [:peek-mode
;; VSCode Peek actions triggered by R + Key
[:-h :peek_definition] ; R+H -> Peek Definition (Opt+F12)
[:-e :peek_implementations]; R+E (K Colemak) -> Peek Implementations (Cmd+Shift+F12)
[:-n :peek_references] ; R+N (J Colemak) -> Peek References (Cmd+F19)
[:-i :peek_declaration] ; R+I (L Colemak) -> Peek Declaration (Ctrl+F19)
[:-o :peek_type]]} ; R+O (Semicolon Colemak) -> Peek Type (Shift+F19)
{:des "Go Mode (T + Key / G Colemak)"
:rules [:go-mode
;; VSCode Go To actions triggered by T + Key
[:-r :go_to_references]; T+R (S Colemak) -> Go To References (Shift+F12)
[:-w :go_to_symbol_in_workspace]; T+W -> Go To Symbol in Workspace
[:-s :go_to_symbol]; T+S (D Colemak) -> Go To Symbol (Cmd+Shift+O)
[:-h :go_to_hints]; T+H -> Go To Hints (Cmd+Shift+Space)
[:-i :go_to_implementations]; T+I (L Colemak) -> Go To Implementations (Cmd+F12)
[:-n :go_to_symbol]; T+N (J Colemak) -> Go To Symbol (Cmd+Shift+O)
[:-o :go_to_definition]; T+O (Semicolon Colemak) -> Go To Definition (F12)
[:-l :go_to_line]; T+L (U Colemak) -> Go To Line (Ctrl+G)
[:comma :go_to_prev_problem]; T+, -> Prev Problem (Opt+Shift+F8)
[:period :go_to_next_problem]]}; T+. -> Next Problem (Opt+F8)
{:des "Opt Mode (A + Key / Option Layer, No Trackpad)"
:rules [:opt-mode
;; Option-modified keys and AceJump triggers via A + Key
;; Arrow keys with Option
[:##h :!Oleft_arrow] ; A+H -> Opt+Left
[:##j :!Odown_arrow] ; A+J (Y Colemak) -> Opt+Down
[:##k :!Oup_arrow] ; A+K (E Colemak) -> Opt+Up
[:##l :!Oright_arrow]; A+L (U Colemak) -> Opt+Right
;; AceJump Triggers
[:semicolon :acejump] ; A+; -> AceJump (Cmd+Opt+Shift+J)
[:-b [:acejump :open_brace]] ; A+B -> AceJump then '{'
[:spacebar :acejump] ; A+Space -> AceJump
[:escape :acejump_line] ; A+Esc -> AceJump Line (Cmd+Opt+Shift+L)
[:-l :acejump_line] ; A+L (U Colemak) -> AceJump Line
[:tab [:acejump_line :acejump_selection]] ; A+Tab -> AceJump Line then Select
[:-u [:acejump_line :acejump_selection]] ; A+U (I Colemak) -> AceJump Line then Select
[:-m :acejump_multi] ; A+M -> AceJump Multi (Cmd+Opt+Shift+M)
[:left_shift :acejump_selection] ; A+LShift -> AceJump Select
;; Other
[:-s [:superkey :home]] ; A+S (D Colemak) -> AceJump Select (Cmd+Opt+Shift+S)
[:-t [:superkey]] ; A+T (F Colemak) -> Superkey (Hyper+0)
[:left_shift :!CSO0] ; A+LShift -> Cmd+Shift+Opt+0 ?
[:-p {:key :1 :modi :hyper}] ; A+P -> Superkey+PageUp
[:-o {:key :escape :modi :left_command}]]}
{:des "Shift+Opt Mode (S + Key / R Colemak Layer, No Trackpad)"
:rules [:shift-opt-mode
;; Shift+Option modified arrow keys via S + Key
[:##h :!OSleft_arrow] ; S+H -> Shift+Opt+Left
[:##j :!OSdown_arrow] ; S+J (Y Colemak) -> Shift+Opt+Down
[:##k :!OSup_arrow] ; S+K (E Colemak) -> Shift+Opt+Up
[:##l :!OSright_arrow]; S+L (U Colemak) -> Shift+Opt+Right
;; Mouse buttons
[:##spacebar {:pkey :button1 :modi :left_command}] ; S+Space -> Cmd+Click
[:##left_shift :##button2]]} ; S+LShift -> Right Click
;; Chrome Navigation (Commented out - handled elsewhere?)
;; [:condi :chrome]
;; [:-n :chrome_go_back] ; S+N (J Colemak) -> Chrome Back
;; [:-e :chrome_go_forward] ; S+E (K Colemak) -> Chrome Forward
{:des "Shift Mode (D + Key / S Colemak Layer, No Trackpad)"
:rules [:shift-mode
;; Shift modified keys via D + Key
;; Arrow keys with Shift
[:##h :!Sleft_arrow] ; D+H -> Shift+Left
[:##j :!Sdown_arrow] ; D+J (Y Colemak) -> Shift+Down
[:##k :!Sup_arrow] ; D+K (E Colemak) -> Shift+Up
[:##l :!Sright_arrow]; D+L (U Colemak) -> Shift+Right
;; Selection and Line Insertion
[:left_shift :shrink_selection] ; D+LShift -> Shrink Selection
[:return_or_enter :insert_line_above] ; D+Enter -> Insert Line Above
[:semicolon :expand_selection] ; D+; -> Expand Selection
[:quote :shrink_selection] ; D+' -> Shrink Selection
;; Page Up/Down with Shift
[:##m :!Spage_down] ; D+M -> Shift+PageDown
[:##comma :!Spage_up] ; D+, -> Shift+PageUp
;; Home/End Equivalents
[:##y :!Shome :windows] ; D+Y (O Colemak) -> Shift+Home (Windows only)
[:##o :!Send :windows] ; D+O (Semicolon Colemak) -> Shift+End (Windows only)
[:##y :!CSleft_arrow] ; D+Y -> Cmd+Shift+Left (Select to Line Start)
[:##o :!CSright_arrow] ; D+O -> Cmd+Shift+Right (Select to Line End)
[:escape ["pkill -f 'Script Kit'"]]]}
{:des "Movement Mode (F + Key / T Colemak Layer, No Trackpad)"
:rules [:movement-mode
;; Basic arrow key movement via F + Key
[:##h :left_arrow] ; F+H -> Left
[:##j :down_arrow] ; F+J (Y Colemak) -> Down
[:##k :up_arrow] ; F+K (E Colemak) -> Up
[:##l :right_arrow]; F+L (U Colemak) -> Right
;; Autocomplete / Line Insertion
[:semicolon :autocomplete] ; F+; -> Autocomplete (Ctrl+Space)
[:return_or_enter :insert_line_below] ; F+Enter -> Insert Line Below
;; Home/End Equivalents
[:##y [:!Shome :escape] :windows] ; F+Y (O Colemak) -> Shift+Home, Esc (Windows only)
[:##o :end :windows] ; F+O (Semicolon Colemak) -> End (Windows only)
[:##y :!Cleft_arrow] ; F+Y -> Cmd+Left (Line Start)
[:##o :!Cright_arrow]]} ; F+O -> Cmd+Right (Line End)
{:des "Cursor Mode (G + Key / D Colemak Layer, No Trackpad)"
:rules [:cursor-mode
;; Cursor actions (multi-cursor, AceJump) via G + Key
[:h :cursor_find_match] ; G+H -> Find Match (Cmd+D)
[:j :cursor_below] ; G+J (Y Colemak) -> Cursor Below (Cmd+Opt+Down)
[:k :cursor_above] ; G+K (E Colemak) -> Cursor Above (Cmd+Opt+Up)
[:-j :acejump] ; G+J (N Colemak) -> AceJump
[:-l :acejump_line] ; G+L (I Colemak) -> AceJump Line
[:-m :acejump_multi] ; G+M -> AceJump Multi
[:left_shift :cursor_select_all] ; G+LShift -> Select All Occurrences (Cmd+Shift+L)
[:l :developer_tools]]} ; G+L (U Colemak) -> Dev Tools (Cmd+Opt+I)
{:des "Delete Mode (J + Key / N Colemak Layer)"
:rules [:delete-mode
;; Deletion actions via J + Key
[:escape :delete_line :code] ; J+Esc -> Delete Line (Code only)
[:escape :!Cdelete_or_backspace] ; J+Esc -> Cmd+Backspace (Fallback)
[:hyphen :delete_line :code] ; J+Hyphen -> Delete Line (Code only)
[:caps_lock :delete_line :code] ; J+Caps -> Delete Line (Code only)
[:hyphen :!Cdelete_or_backspace] ; J+Hyphen -> Cmd+Backspace (Fallback)
;; Word/Line Deletion Variations
[:a :!Odelete_or_backspace nil {:held :delete_line}] ; J+A -> Opt+Backspace (Word), Hold for Delete Line
[:s :delete_or_backspace] ; J+S (R Colemak) -> Backspace
[:d :delete_forward] ; J+D (S Colemak) -> Forward Delete
[:f :!Odelete_forward] ; J+F (T Colemak) -> Opt+FwdDelete (Word Forward)
[:g :!Cdelete_forward] ; J+G (D Colemak) -> Cmd+FwdDelete (Line Forward)
[:e :!COSf]]} ; J+E (K Colemak) -> Cmd+Opt+Shift+F ?
{:des "Nav Mode (K + Key / E Colemak Layer)"
:rules [:nav-mode
;; Editor/Tab navigation via K + Key
;; Application specific rules in :terminal, :slack blocks
;; Generic/Code Navigation
[:hyphen :focus_next_editor_group] ; K+Hyphen -> Focus Next Group (Opt+F16)
[:-a :open_prev_editor] ; K+A -> Prev Editor/Tab (Cmd+Opt+Left)
[:-r :go_back] ; K+R (S Colemak) -> Go Back (Ctrl+-)
[:-s :go_forward] ; K+S (D Colemak) -> Go Forward (Ctrl+Shift+-)
[:-t :open_next_editor] ; K+T (F Colemak) -> Next Editor/Tab (Cmd+Opt+Right)
[:-d :focus_prev_editor_group]]} ; K+D (G Colemak) -> Focus Prev Group (Opt+Shift+F16)
{:des "Snippet Mode (Quote + Key)"
:rules [:snippet-mode
;; Code snippets via Quote + Key
[:-c [:c :o :n :s :o :l :e :period :l :o :g :open_paren :close_paren :left_arrow]] ; '+C -> console.log()
[:-a [:a :w :a :i :t :spacebar]] ; '+A -> await
[:-s [:a :s :y :n :c :spacebar]] ; '+S (D Colemak) -> async
[:-n [:spacebar :c :l :a :s :s :!Sn :a :m :e :equal_sign :!Squote :!Squote :left_arrow]] ; '+N (J Colemak) -> className=""
;; Type stored secrets from macOS Keychain (add your own keychain items)
;; Uses :type-secret template: security find-generic-password -a $USER -s <NAME> -w
[:-e [:type-secret "YOUR_WORK_EMAIL"]] ; '+E -> Type work email from keychain
[:-g [:type-secret "YOUR_PERSONAL_EMAIL"]] ; '+G -> Type personal email from keychain
[:-x [:type-secret "YOUR_OTHER_EMAIL"]] ; '+X -> Type other email from keychain
[:-j [:type-secret "YOUR_USERNAME"]]]} ; '+J -> Type username from keychain
{:des "Password Mode (Shift + Quote + Key)"
:rules [:password-mode ; Activated by :quote simlayer with :shift-mode condition
;; Type secrets securely via Shift + Quote + Number
;; Note: Assumes :shift-mode is active when triggering :password-mode
;; Add your own macOS Keychain items here:
;; security add-generic-password -a $USER -s "MY_SECRET" -w "the-value"
[:1 [:type-secret "YOUR_SECRET_1"]] ; Shift+'+1 -> Type secret 1
[:2 [:type-secret "YOUR_SECRET_2"]] ; Shift+'+2 -> Type secret 2
[:5 [:type-secret "YOUR_SECRET_3"]]]} ; Shift+'+5 -> Type secret 3
{:des "Emoji Mode (Z + Key)"
:rules [:emoji-mode
;; Paste emojis via Z + Key
[:-a [:paste ""]] ; Placeholder
[:-b [:paste "😊"]] ; Z+B -> Blush
[:-c [:paste "👏"]] ; Z+C -> Clap
[:-d [:paste "🧐"]] ; Z+D (G Colemak) -> Monocle
[:-e [:raycast "raycast/emoji-symbols/search-emoji-symbols"]] ; Z+E (K Colemak) -> Emoji Picker
[:-f [:paste "🔥"]] ; Z+F (E Colemak) -> Fire
[:-g [:paste "😬"]] ; Z+G (T Colemak) -> Grimace
[:-h [:paste "😍"]] ; Z+H -> Heart Eyes
[:-i [:paste "👀"]] ; Z+I (L Colemak) -> Eyes
[:-j [:paste "😂"]] ; Z+J (N Colemak) -> Laughing Crying
[:-l [:paste "❤️"]] ; Z+L (U Colemak) -> Love
[:-m {:key :m :modi :hyper}] ; Z+M -> Mind Blown
[:-n :emoji_picker] ; Z+N (J Colemak) -> Emoji Picker
[:-o [:paste "💩"]] ; Z+O (Semicolon Colemak) -> Poop
[:-p [:paste "🎉"]] ; Z+P (R Colemak) -> Party Popper
[:-q [:paste "🤫"]] ; Z+Q -> Shushing
[:-r [:paste "🏎"]] ; Z+R (S Colemak) -> Racecar
[:-s [:paste "😢"]] ; Z+S (D Colemak) -> Sad Crying
[:-t [:paste "🤔"]] ; Z+T (F Colemak) -> Thinking
[:-u [:paste "🤷‍♂️"]] ; Z+U (I Colemak) -> Shrug
[:-v [:paste "😎"]] ; Z+V -> Sunglasses Cool
[:-w [:paste "😉"]] ; Z+W -> Wink
[:-x [:paste "😵"]] ; Z+X -> Dizzy
[:-y [:paste "😅"]] ; Z+Y (O Colemak) -> Sweat Smile
[:left_command [:paste "👍"]] ; Z+Cmd -> Thumbs Up
[:left_option [:paste "👎"]]]} ; Z+Opt -> Thumbs Down
{:des "Command Mode (C + Key)"
:rules [:command-mode
;; Command-modified arrow keys and actions via C + Key
;; Arrow keys with Command
[:##h :!Cleft_arrow] ; C+H -> Cmd+Left
[:##j :!Cdown_arrow] ; C+J (Y Colemak) -> Cmd+Down
[:##k :!Cup_arrow] ; C+K (E Colemak) -> Cmd+Up
[:##l :!Cright_arrow]; C+L (U Colemak) -> Cmd+Right
;; Go Home/End
[:-n :go_end] ; C+N (J Colemak) -> Go to End (Cmd+Down)
[:-e :go_home]
[:left_command {:key :g :modi :hyper}]
;;
]} ; C+E (K Colemak) -> Go to Home (Cmd+Up)
{:des "Ctrl+Opt Mode (X + Key)"
:rules [:ctrl-opt-mode
;; Ctrl+Opt modified arrow keys via X + Key
[:##h :!TOleft_arrow] ; X+H -> Ctrl+Opt+Left
[:##j :!TOdown_arrow] ; X+J -> Ctrl+Opt+Down
[:##k :!TOup_arrow] ; X+K -> Ctrl+Opt+Up
[:##l :!TOright_arrow] ; X+L -> Ctrl+Opt+Right
;; Go Home/End
[:-n :go_end] ; C+N (J Colemak) -> Go to End (Cmd+Down)
[:-e :go_home]
[:left_command {:key :g :modi :hyper}]
;;
]}
{:des "Cmd+Opt Mode (B + Key)"
:rules [:cmd-opt-mode
;; Cmd+Opt modified arrow keys via B + Key
[:##h :!COleft_arrow] ; B+H -> Cmd+Opt+Left
[:##j :!COdown_arrow] ; B+J -> Cmd+Opt+Down
[:##k :!COup_arrow] ; B+K -> Cmd+Opt+Up
[:##l :!COright_arrow] ; B+L -> Cmd+Opt+Right
;; Bookmark shortcuts (merged from bookmark-mode)
[:-m :!COk] ; B+M -> Cmd+Opt+K
[:-n :!COTb]]}
{:des "Command Shift Mode (V + Key)"
:rules [:command-shift-mode
;; Command-modified arrow keys and actions via C + Key
;; Arrow keys with Command
[:##h :!CSleft_arrow] ; C+H -> Cmd+Left
[:##j :!CSdown_arrow] ; C+J (Y Colemak) -> Cmd+Down
[:##k :!CSup_arrow] ; C+K (E Colemak) -> Cmd+Up
[:##l :!CSright_arrow]]}; C+L (U Colemak) -> Cmd+Right
{:des "Media Mode (M + Key)"
:rules [:media-mode
;; Media control keys via M + Key
[:-f :vk_consumer_next] ; M+F (E Colemak) -> Next Track
[:-p :vk_consumer_play] ; M+P (R Colemak) -> Play/Pause
[:-t ["~/.simple/bin/title-case"]] ; M+T (F Colemak) -> Run title-case script
[:-a [:open_bracket :open_bracket]]]} ; M+A -> '[[' sequence
{:des "Kit Mode (N + Key / K Colemak Layer)"
:rules [:kit-mode
;; Open projects in Cursor via N + Key
[:-q [:cursor "~/dev/cdp-cli-container/cdp-cli"]]
[:-s [:zed "~/.scriptkit"]]
[:-r [:cursor "~/dev/rubrics"]]
[:-d [:cursor "~/dev/kit-docs"]]
[:-f [:cursor "~/dev/file-forge"]]
[:-g [:cursor "~/dev/script-generator"]]
[:-v [:cursor "~/.kenv"]]
[:-t [:cursor "~/dev/kit"]]
[:-c [:cursor "~/dev/kit-container"]]
[:-a [:cursor "~/dev/agentconfig"]]
[:-w [:cursor "~/dev/cursor-workshop-marp"]]
[:-x [:cursor "~/dev/exercises"]]
[:-z [:cursor "~/dev/agent"]]
;; GitHub Actions/Releases/Discussions
[:1 ["~/.kenv/bin/focus-tab github.com/johnlindquist/kitapp/actions"]]
[:2 ["~/.kenv/bin/focus-tab github.com/johnlindquist/kitapp/releases"]]
[:3 ["~/.kenv/bin/focus-tab github.com/johnlindquist/kit/discussions"]]
[:escape ["pkill -f 'Electron' && pkill -f 'Electron'"]]]}
;;
{:des "Spacebar Mode (Space + Key / Symbol Layer)"
:rules [:spacebar-mode
;; Symbols and common sequences via Space + Key
;; Brackets/Parentheses/Braces/Angle Brackets
[:a :open_bracket] ; Space+A -> [
[:s :close_bracket] ; Space+S (R Colemak) -> ]
[:d :open_paren] ; Space+D (S Colemak) -> (
[:f :close_paren] ; Space+F (T Colemak) -> )
[:tab [:open_bracket :open_bracket]] ; Space+Tab -> [[
[:j :open_brace] ; Space+J (N Colemak) -> {
[:k :close_brace] ; Space+K (E Colemak) -> }
[:l :less_than] ; Space+L (U Colemak) -> <
[:semicolon :greater_than] ; Space+; -> >
;; Symbol Sequences
[:hyphen [:!S4 :!Sopen_bracket :!Sclose_bracket :left_arrow]] ; Space+Hyphen -> ${}
[:caps_lock [:!S4 :!Sopen_bracket :!Sclose_bracket :left_arrow]] ; Space+Caps -> ${}
[:left_shift [:spacebar :equal_sign :spacebar]] ; Space+LShift -> " = "
[:q [:!S9 :!S0 :equal_sign :greater_than :spacebar]] ; Space+Q -> ()=>
[:e [:!S9 :!S9 :!S0 :equal_sign :greater_than :spacebar :open_brace :close_brace :!S0 :left_arrow :left_arrow]] ; Space+E (K Colemak) -> ()=>()=> {} (check intent)
[:g [:spacebar :equal_sign :greater_than :spacebar]] ; Space+G (D Colemak) -> " => "
[:h [:equal_sign :open_brace :close_brace :left_arrow]] ; Space+H -> ={}
[:b [:equal_sign :open_brace :close_brace :left_arrow]] ; Space+B -> ={}
[:quote [:equal_sign :!Squote :!Squote :left_arrow]]
[:c {:key :c :modi :hyper}] ; hyper c
]} ; Space+' -> =""
{:des "Semicolon Mode (; + Key / O Colemak Layer / Special Chars)"
:rules [:semicolon-mode
;; Special characters (!@#$ etc.) via Semicolon + Key
;; Uses Colemak mnemonics for QWERTY keys
[:-e :!S1] ; ;+E (K Colemak) -> !
[:-a :!S2] ; ;+A -> @
[:-h :!S3] ; ;+H -> #
[:-d :!S4] ; ;+D (G Colemak) -> $
[:-p :!S5] ; ;+P (R Colemak) -> %
[:-c :!S6] ; ;+C -> ^
[:-s :!S7] ; ;+S (D Colemak) -> &
[:-b :!S8]]} ; ;+B -> *
;; {:des "Comma Mode (, + Key / Transcription)"
;; :rules [:comma-mode
;; ;; Audio Hijack transcription script triggers via Comma + Key
;; [:-c [:copy-transcribe-low]] ; ,+C -> Copy Transcribe Low
;; [:-v [:paste-transcribe-low]] ; ,+V -> Paste Transcribe Low
;; [:-s [:copy-transcribe-high]] ; ,+S (D Colemak) -> Copy Transcribe High
;; [:-t [:transcribe]] ; ,+T (F Colemak) -> Transcribe
;; ;; [:-t [:paste-transcribe-high]] ; Duplicate T mapping?
;; ;; [:-t :!COS0] ; Duplicate T mapping? Cmd+Opt+Shift+0?
;; ]}
{:des "Period Mode (. + Key) - Focus or Open URLs"
:rules [:period-mode
;; Focus existing tab or open new (use Comma mode for always-new-tab)
[:-a [:focus-or-open-chrome "aistudio.google.com/prompts/new_chat"]]
[:-c [:focus-or-open-chrome "chatgpt.com"]]
[:-e [:focus-or-open-chrome "egghead.io"]]
[:-g [:focus-or-open-chrome "gemini.google.com"]]
[:-j [:focus-or-open-chrome "js.new"]]
[:-k [:focus-or-open-chrome "github.com/search?q=extension%3A.edn+filename%3Akarabiner.edn&type=Code"]]
[:-l [:focus-or-open-chrome "http://localhost:4200"]]
[:-m [:focus-or-open-chrome "www.youtube.com/watch?v=jfKfPfyJRdk&ab_channel=LofiGirl"]]
[:-p [:focus-or-open-chrome "perplexity.ai"]]
[:-q [:focus-or-open-chrome "chatgpt.com/codex"]]
[:-s [:focus-or-open-chrome "dashboard.stripe.com"]]
[:-t [:focus-or-open-chrome "typefully.com"]]
[:-u [:focus-or-open-chrome "builder.egghead.io"]]
[:-w [:focus-or-open-chrome "calendar.google.com/calendar/u/1/r"]]
[:-x [:focus-or-open-chrome "x.com"]]
[:-y [:focus-or-open-chrome "youtube.com"]]
[:1 [:focus-or-open-chrome "mail.google.com/mail/u/0"]]
[:2 [:focus-or-open-chrome "mail.google.com/mail/u/1"]]]} ; 2 -> Open Gmail (User 1)
{:des "Comma Mode (, + Key) - Always Open New Tab"
:rules [:comma-mode
;; Always opens new tab (use Period mode to focus existing)
[:-a [:open-new-tab "aistudio.google.com/prompts/new_chat"]]
[:-c [:open-new-tab "chatgpt.com"]]
[:-e [:open-new-tab "egghead.io"]]
[:-g [:open-new-tab "gemini.google.com"]]
[:-j [:open-new-tab "js.new"]]
[:-k [:open-new-tab "github.com/search?q=extension%3A.edn+filename%3Akarabiner.edn&type=Code"]]
[:-l [:open-new-tab "http://localhost:4200"]]
[:-m [:open-new-tab "www.youtube.com/watch?v=jfKfPfyJRdk&ab_channel=LofiGirl"]]
[:-p [:open-new-tab "perplexity.ai"]]
[:-t [:open-new-tab "assistant.google.com/tasks"]]
[:-u [:open-new-tab "builder.egghead.io"]]
[:-w [:open-new-tab "calendar.google.com/calendar/u/1/r"]]
[:-x [:open-new-tab "pro.x.com"]]
[:-y [:open-new-tab "youtube.com"]]
[:1 [:open-new-tab "mail.google.com/mail/u/0"]]
[:2 [:open-new-tab "mail.google.com/mail/u/1"]]]} ; 2 -> Open Gmail (User 1)
{:des "Presentation Mode (P + Key / ; Colemak)"
:rules [:presentation-mode
;; Actions useful during presentations via P + Key
[:-f :toggle_fold] ; P+F (E Colemak) -> Toggle Fold
[:-r :rename] ; P+R (S Colemak) -> Rename (F2)
;; Focus specific browser tabs
[:-a ["~/.kenv/bin/focus-tab http://localhost:8080/angular"]]
[:-t ["~/.kenv/bin/focus-tab http://localhost:8080/typescript"]]
[:-w ["~/.kenv/bin/focus-tab http://localhost:8080/."]]
[:-c ["~/.kenv/bin/focus-tab http://localhost:3000/"]]]}
{:des "Launch Mode (F24 Tap Alfred, Hold Layer / U + Key Layer)"
:rules [:launch-mode ; Activated by holding F24 OR U+Key simlayer
;; App launching triggers
[:1 :open_1password] ; Launch+1 -> Open 1Password
[:2 :autofill_1password] ; Launch+1 -> Open 1Password
[:tab [:launch "Screen Sharing"]] ; Launch+Tab -> Focus Screen Sharing
[:spacebar :!Tdown_arrow] ; Launch+Space -> Ctrl+Down Arrow
;; [:-a [:launch "Activity Monitor"]] ; Launch+A -> Launch Activity Monitor
[:-v [:launch "Visual Studio Code - Insiders"]] ; Launch+V -> Launch Cursor Nightly
[:-d [:launch "Discord"]] ; Launch+D (G Colemak) -> Launch Discord
[:-f [:launch "Finder"]] ; Launch+F (E Colemak) -> Launch Finder
;; [:-p [:launch "Pieces"]] ; Launch+P (E Colemak) -> Launch Pieces
[:-g [:launch "Google Chrome"]] ; Launch+G (T Colemak) -> Launch Chrome
;; Available triggers:
;; | Trigger | Action |
;; |-------------------|-------------------------------------|
;; | quick_open | Quick Open picker (Cmd+P) |
;; | quick_open_cursor | Open in Cursor picker (Cmd+Shift+P) |
;; | workspaces | Workspace picker |
;; | command_palette | Command palette |
;; | launcher | Launcher menu |
;; | shortcuts | Keyboard shortcuts help |
;; | themes | Theme picker |
;; | layouts | Layout template picker |
;; | zen | Toggle zen mode |
[:-a [:wez-trigger "app_launcher"]] ; Launch+A -> App launcher
[:-w [:wez-trigger "quick_open"]] ; Launch+T -> Quick Open picker
[:-t [:launch "cmux"]] ; Launch+T -> Open cmux
[:-c [:launch "Cursor"]] ; Launch+C -> Open in Cursor
[:-n [:wez-trigger "notepad"]] ; Launch+N -> Notepad (auto-commits)
[:-p [:wez-trigger "copy_path"]] ; Launch+N -> Notepad (auto-commits)
;; [:-c [:launch "Cursor"]] ; Launch+C -> Launch Cursor
[:-k "launchctl kickstart -k org.pqrs.karabiner.karabiner_console_user_server"] ; Launch+K (E Colemak) -> Restart Karabiner
[:-y [:launch "YouTube Music"]] ; Launch+Y (O Colemak) -> Launch YouTube Music
[:-r [:wezterm "cd ~/research && x --append-system-prompt='Research the users query then write the result to a markdown file ./<shortened-slugified-query>.md'"]] ; Launch+R -> WezTerm research mode
[:-s [:launch "Slack"]] ; Launch+S (D Colemak) -> Launch Slack
;; [:-w [:launch "Windsurf"]] ; Launch+W -> Launch Windsurf
[:-z [:launch "Zed"]] ; Launch+Z -> Launch Zoom
[:-w [:launch "zoom.us"]] ; Launch+Z -> Launch Zoom
[:-x [:wezterm "devx"]]
[:left_shift [:raycast "Codely/google-chrome/search-tab"]]
;;
]} ; Launch+X -> Open WezTerm, select project with fzf, then run "x"
;; cmux: must come BEFORE Colemak Remapping so remapped keys are intercepted first
{:des "cmux: Cmd+Shift+G -> Open GitHub repo at CWD"
:rules [[{:key :t :modi [:command :shift]} [:open-github-cmux] :cmux]]}
{:des "cmux: Cmd+Shift+Z -> Open Zed at CWD"
:rules [{:type :basic
:from {:key_code "z"
:modifiers {:mandatory ["command" "shift"]}}
:to [{:software_function
{:open_application
{:bundle_identifier "dev.zed.Zed"}}}
{:send_user_command
{:endpoint "/tmp/karabiner-zed-cmux.sock"
:payload {:command "open_zed_cmux_cwd"}}}]
:conditions [{:type "frontmost_application_if"
:bundle_identifiers ["com.cmuxterm.app"]}]}]}
;; --- Global Layout Remapping ---
{:des "Colemak Remapping (Qwerty Input -> Colemak Output)"
:rules [; This section remaps QWERTY keys to Colemak layout
;; Top Row
[:##e :f] ; Qwerty E -> Colemak F
[:##r :p] ; Qwerty R -> Colemak P
[:##t :g] ; Qwerty T -> Colemak G
[:##y :j] ; Qwerty Y -> Colemak J
[:##u :l] ; Qwerty U -> Colemak L
[:##i :u] ; Qwerty I -> Colemak U
[:##o :y] ; Qwerty O -> Colemak Y
[:##p :semicolon] ; Qwerty P -> Colemak ;
;; Home Row
[:##s :r] ; Qwerty S -> Colemak R
[:##d :s] ; Qwerty D -> Colemak S
[:##f :t] ; Qwerty F -> Colemak T
[:##g :d] ; Qwerty G -> Colemak D
[:##j :n] ; Qwerty J -> Colemak N
[:##k :e] ; Qwerty K -> Colemak E
[:##l :i] ; Qwerty L -> Colemak I
[:##semicolon :o] ; Qwerty ; -> Colemak O
;; Bottom Row
[:##n :k]]} ; Qwerty N -> Colemak K
;; Special (Check if needed based on keyboard)
;; [:close_bracket :a] ; Qwerty ] -> Colemak A ? Usually Caps Lock maps to Backspace
{:des "cmux: Tap Left Cmd -> Go To File (Cmd+P)"
:rules [:cmux
[:left_command :left_command nil {:alone :go_to_file}]]}
]}
; End of :main
;; End of configuration map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment