Custom Keybindings for the Atuin TUI
One of the longest-standing feature requests for Atuin has finally landed: full custom keybinding support for the search TUI. No more being stuck with our defaults, no more wishing ctrl-d did something else. Your TUI, your rules.
One of the longest-standing feature requests for Atuin has finally landed: full custom keybinding support for the search TUI. No more being stuck with our defaults, no more wishing ctrl-d did something else. Your TUI, your rules.
With the new [keymap] config system, you can now fully customize every keybinding in the TUI, with conditional execution.
# Simple binding: ctrl-c returns to your original command
[keymap.emacs]
"ctrl-c" = "return-original"
# Conditional binding: left arrow exits when cursor is at start
[keymap.emacs]
"left" = [
{ when = "cursor-at-start", action = "exit" },
{ action = "cursor-left" },
]
The first matching rule wins. No match? The key passes through.
Conditional Bindings
This is where it gets interesting. You can now express keybindings that depend on the current state of the app:
# ctrl-d: delete char, unless input is empty, then exit
[keymap.emacs]
"ctrl-d" = [
{ when = "cursor-at-start && input-empty", action = "return-original" },
{ action = "delete-char-after" },
]
The condition system supports boolean expressions with &&, ||, !, and parentheses. Available conditions include:
cursor-at-start/cursor-at-endinput-emptyvim-normal-mode/vim-insert-mode- And more in the docs
Accept vs Return Selection
We've split the old Accept action into two distinct behaviors:
accept: Execute the command immediately (whatenterdoes by default)return-selection: Place the command on your command line without executing (whattabdoes by default)
Previously, enter_accept toggled this behavior at runtime. Now you can bind whichever action you want to whichever key you want:
# Make enter insert for editing, tab execute immediately
[keymap.emacs]
"enter" = "return-selection"
"tab" = "accept"
There's also return-selection-1 through return-selection-9 for selecting numbered history entries without executing, as well as return-query for returning what you've typed in the search box.
See the docs for the full list of actions
Five Keymaps
The system supports five separate keymaps:
[keymap.emacs]- Default mode[keymap.vim-normal]- Vim normal mode[keymap.vim-insert]- Vim insert mode[keymap.inspector]- The history inspector view[keymap.prefix]- After pressing the prefix key (ctrl+aby default)
Each has sensible defaults, and you only need to override what you want to change.
Backward Compatibility
If you're using the old [keys] config (with scroll_exits, exit_past_line_start, etc.), it still works. The new [keymap] takes precedence when present, but your existing config won't break.
If you have both [keys] and [keymap] defined, Atuin will use [keymap] config only and log a warning.
Example: Recreating the Default Emacs Bindings
Want to see what the defaults look like? Here's a taste:
[keymap.emacs]
"ctrl-c" = "return-original"
"ctrl-g" = "return-original"
"ctrl-d" = [
{ when = "cursor-at-start && input-empty", action = "return-original" },
{ action = "delete-char-after" },
]
"esc" = "return-original"
"enter" = "accept"
"tab" = "return-selection"
"ctrl-r" = "cycle-filter-mode"
"ctrl-s" = "cycle-search-mode"
"ctrl-o" = "open-inspector"
"up" = [
{ when = "at-top", action = "exit" },
{ action = "history-prev" },
]
"down" = [
{ when = "no-selection", action = "return-query" },
{ action = "history-next" },
]
"left" = [
{ when = "cursor-at-start", action = "exit" },
{ action = "cursor-left" },
]
"right" = "cursor-right"
"ctrl-a" = "cursor-start"
"ctrl-e" = "cursor-end"
"ctrl-u" = "clear-input"
"ctrl-w" = "delete-word-before"
"backspace" = "delete-char-before"
"delete" = "delete-char-after"
"ctrl-y" = "copy-command"
"page-up" = "page-up"
"page-down" = "page-down"
The full list of actions and conditions is in the advanced keybinding docs.
Getting Started
Update to the latest Atuin and add a [keymap.emacs] section (or whichever mode you use) to your ~/.config/atuin/config.toml. Override just the keys you want to change.
The system is designed to be additive - you don't need to specify everything, just your customizations.
Thanks to everyone who's been asking for this over the years. Your keybindings are finally yours.
Check out the full documentation at docs.atuin.sh/cli/configuration/advanced-key-binding/