This guide focuses on practical shortcut configuration in keyrs.
Think in this order:
- Modmap: raw key-to-key remap (global or conditional)
- Multipurpose: tap/hold behavior on one key
- Keymap: combo mappings with optional app conditions
- Sequence actions: delays, text, setting toggles, bind semantics
For most shortcut work, you will use [[keymap]].
[[keymap]]
name = "global_basic"
[keymap.mappings]
"Super-c" = "Ctrl-c"
"Super-v" = "Ctrl-v"Terminal often needs different copy/paste combos:
[[keymap]]
name = "terminal_shortcuts"
condition = "wm_class =~ '(?i)terminal|kitty|alacritty|wezterm'"
[keymap.mappings]
"Super-c" = "Ctrl-Shift-c"
"Super-v" = "Ctrl-Shift-v"Editor/browser fallback:
[[keymap]]
name = "editor_browser_shortcuts"
condition = "wm_class =~ '(?i)code|cursor|firefox|chrome|chromium'"
[keymap.mappings]
"Super-c" = "Ctrl-c"
"Super-v" = "Ctrl-v"
"Super-f" = "Ctrl-f"Delete to end of line:
"Super-k" = ["Shift-End", "Backspace"]Terminal word delete style:
"Alt-Delete" = ["Combo(Esc)", "Delay(25)", "Combo(d)"]Browser macro example:
"Super-comma" = ["Ctrl-l", "Delay(120)", "Text(about:preferences)", "Delay(160)", "Enter"]Use plain output when you want to preserve currently held physical modifiers. Use Combo(...) in a non-bind sequence when you need the emitted key/combo to ignore held modifiers for that step.
# Direct remap semantics
"Super-j" = "Enter"
# Sequence-step combo semantics
"Super-j" = ["Combo(Enter)"]Decision rule:
- Use plain string output when preserving held modifiers is desired.
- Use
Combo(...)inside a non-bindsequence when you need step-local output (held modifiers temporarily lifted). bindkeeps held modifiers; non-bindsequences do not.["Enter"]does not forceCombo(...)semantics; it behaves as single-key output.
Use SetSetting(...) for mode-like flows:
"Enter" = ["SetSetting(Enter2Ent_Cmd=false)", "F2"]
"Esc" = ["SetSetting(Enter2Ent_Cmd=true)", "Esc"]And gate keymaps by that setting:
condition = "wm_class =~ '(?i)nemo|nautilus' and settings.Enter2Ent_Cmd"In modular config (config.d), files are composed in sorted filename order.
Recommended naming:
000_base.toml100_terminals.toml200_editors.toml300_filemanagers.toml900_fallback.toml
Keep specific rules earlier and generic fallback rules later, or vice versa based on your tested precedence strategy. The important part is: keep ordering intentional and documented.
- Avoid duplicate mappings for the same combo in overlapping conditions unless you intentionally rely on precedence.
- Keep condition regexes explicit (
(?i)^kitty$is safer than broad fuzzy matching when needed). - Document why each app-specific exception exists.
- Edit
~/.config/keyrs/config.d/*.toml - Apply safely:
~/.local/bin/keyrs-service apply-config- If debugging matching behavior:
~/.local/bin/keyrs --config ~/.config/keyrs/config.toml --verbose- If needed, validate directly:
~/.local/bin/keyrs --check-config --config ~/.config/keyrs/config.toml- Press in target app where it should map.
- Press in non-target app where it should not map.
- Press repeatedly (fast) to detect repeat/press-release issues.
- Switch focus between windows and retest.
- Confirm no conflict with fallback keymaps.
- Cmd-like copy/paste by context
- Terminal special mappings
- App-launcher macros with
Text(...) - state-machine toggles with
SetSetting(...) - desktop/distro-specific branches using settings flags
- Use conditions for window/app context (
wm_class,wm_name). - Use settings flags for environment or user-mode toggles (desktop distro, keyboard mode, workflow mode).
Prefer small focused keymaps over giant mixed blocks. It is easier to debug one intent per keymap than many unrelated mappings in one table.
- CONFIG_SYNTAX_REFERENCE.md - Full syntax reference for all config sections
- CONDITION_PATTERNS.md - Copy-paste ready condition patterns
- CONFIG_EXAMPLES.md - Real-world configuration examples
- CONFIG_COMPOSE_WORKFLOW.md - Modular config workflow