How to Configure Custom Key Bindings in Ghostty: A Complete Guide
You configure custom key bindings in Ghostty by editing the keybind field in your configuration file (default ~/.config/ghostty/config) using the syntax keybind = <prefixes><key-spec>=<action>.
Ghostty’s input system is defined in the ghostty-org/ghostty repository and centers on the Config struct in src/config/Config.zig. When the terminal launches, it parses your configuration file and builds an internal key map that translates incoming key events into executable actions. This guide explains the exact syntax, prefixes, and internal flow used by the configuration parser to help you customize your workflow.
Understanding the Key Binding Syntax
Every binding in Ghostty consists of three distinct components parsed from the keybind field (defined at line 1860 of src/config/Config.zig).
1. Optional Prefixes
Prefixes modify how the binding behaves and can be stacked using colons. According to the source comments at lines 49-51, the available prefixes are:
- global: – Activates the binding even when Ghostty is not focused (requires OS-level support on macOS and Wayland).
- unconsumed: – Executes the action but allows the raw key event to pass through to the running terminal program.
- performable: – Only consumes the input if the associated action can actually be executed in the current context.
Example of stacked prefixes:
keybind = global:unconsumed:ctrl+a=reload_config
2. Key Specification
This defines the physical input using modifier keys and key names. Valid modifiers are ctrl, alt, shift, super (or cmd on macOS). Keys are referenced by their textual name, such as a, backquote, or escape.
You can also define key sequences by separating keystrokes with >. This is documented at lines 87-90:
# Trigger action only after pressing Ctrl+A followed by N
keybind = ctrl+a>n=new_window
3. Action
The final component is the action name, which must match an entry in the Action enum defined in src/input/Binding.zig (lines 45-71). Common actions include new_window, new_split, copy_to_clipboard, reload_config, and quit.
Creating Chained Actions
You can trigger multiple actions from a single key press using the chain= keyword. The first line establishes the base binding; subsequent lines prefixed with chain= add additional steps. All chained actions inherit the prefixes of the original binding.
# Open a new split to the right, then immediately focus the left pane
keybind = ctrl+shift+s=new_split:right
keybind = chain=goto_split:left
Using Key Tables for Modal Bindings
Ghostty supports named key tables that function like modal modes in Vim. This allows you to create dedicated key maps for specific contexts, such as copy mode or command palettes.
Define a table by prefixing the binding with <table>/. For example, creating a vim table is shown in the source at lines 25-30:
keybind = vim/esc=deactivate_key_table
keybind = vim/h=move_left
keybind = vim/j=move_down
keybind = vim/k=move_up
keybind = vim/l=move_right
You control table activation using actions defined in src/input/Binding.zig (lines 78-99):
- activate_key_table – Switches to the named table indefinitely.
- activate_key_table_once – Switches to the table for one action only, then returns to the default table.
- deactivate_key_table – Returns to the default key table.
How Ghostty Processes Key Bindings Internally
The binding system follows a three-phase pipeline:
- Configuration Loading – The
Config.loadfunction reads your configuration file and populates thekeybind: Keybinds = .{}field. This occurs at startup and during config reloads. - Key Map Construction –
Keybinds.initbuilds an internal hash table that maps encoded key events (generated by src/input/key_encode.zig) to their correspondingActionvalues. - Event Dispatch – When a key event arrives in src/termio/Termio.zig, the system calls
Keybinds.lookup. If a match exists, the associated action is dispatched immediately; otherwise, the raw key event is passed through to the terminal’s PTY.
Inspecting Your Active Configuration
To verify which bindings are currently loaded without launching the full terminal, use the built-in CLI command implemented in src/cli/list_keybinds.zig:
ghostty +list-keybinds
This outputs the complete mapping table, including any custom tables you have defined.
Summary
- Ghostty stores bindings in the
keybindfield of src/config/Config.zig, parsed at startup viaConfig.load. - Use prefixes (
global:,unconsumed:,performable:) to modify binding scope and consumption behavior. - Define sequences with
>and chained actions withchain=to build complex workflows. - Create modal key tables by prefixing bindings with a table name (e.g.,
vim/ctrl+h=move_left) and switch tables usingactivate_key_table. - Inspect the active configuration by running
ghostty +list-keybinds.
Frequently Asked Questions
How do I make a key binding work even when Ghostty is not focused?
Add the global: prefix to your binding. For example, keybind = global:cmd+backquote=toggle_quick_terminal allows you to toggle the quick terminal from any application on supported platforms (macOS and Wayland). This requires OS-specific APIs and may not function on all systems.
What is the difference between unconsumed: and standard key bindings?
A standard binding consumes the key event, meaning the running terminal application never receives it. The unconsumed: prefix executes your configured action but still passes the raw key event to the shell or program running in the terminal. This is useful for reloading configuration while keeping the keystroke available to the underlying process.
Can I use key sequences like Emacs or Vim chorded commands?
Yes. Ghostty supports sequences using the > character. For example, keybind = ctrl+a>n=new_window requires pressing Ctrl+A, releasing it, then pressing N to trigger the action. Sequences can be combined with any prefix or action type.
Where can I find the complete list of available actions for key bindings?
The authoritative list is the Action enum in src/input/Binding.zig (lines 45-71). You can also view your currently active bindings and their associated actions by running ghostty +list-keybinds from your terminal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →