0% found this document useful (0 votes)
57 views136 pages

Helix

The document provides comprehensive installation instructions for the Helix editor, including methods for various operating systems such as Linux, macOS, and Windows. It details the use of package managers, building from source, and configuring runtime files. Additionally, it includes links to further resources like the Helix Wiki and FAQ for more information on usage and troubleshooting.

Uploaded by

Bogdan Marinescu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views136 pages

Helix

The document provides comprehensive installation instructions for the Helix editor, including methods for various operating systems such as Linux, macOS, and Windows. It details the use of package managers, building from source, and configuring runtime files. Additionally, it includes links to further resources like the Helix Wiki and FAQ for more information on usage and troubleshooting.

Uploaded by

Bogdan Marinescu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 136

Firefox https://docs.helix-editor.com/print.

html

Helix
Docs for bleeding edge master can be found at https://docs.helix-editor.com/master.

See the usage section for a quick overview of the editor, keymap section for all available
keybindings and the configuration section for defining custom keybindings, setting
themes, etc. For everything else (e.g., how to install supported language servers), see the
Helix Wiki.

Refer the FAQ for common questions.

1 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Installing Helix
To install Helix, follow the instructions specific to your operating system. Note that:

▪ To get the latest nightly version of Helix, you need to build from source.
▪ To take full advantage of Helix, install the language servers for your preferred
programming languages. See the wiki for instructions.

Pre-built binaries
Download pre-built binaries from the GitHub Releases page. The tarball contents include
an hx binary and a runtime directory. To set up Helix:

1. Add the hx binary to your system's $PATH to allow it to be used from the
command line.
2. Copy the runtime directory to a location that hx searches for runtime files. A
typical location on Linux/macOS is ~/.config/helix/runtime .

To see the runtime directories that hx searches, run hx --health . If necessary, you can
override the default runtime location by setting the HELIX_RUNTIME environment
variable.

2 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Package managers
▪ Linux
▪ Ubuntu
▪ Fedora/RHEL
▪ Arch Linux extra
▪ NixOS
▪ Flatpak
▪ Snap
▪ AppImage
▪ macOS
▪ Homebrew Core
▪ MacPorts
▪ Windows
▪ Winget
▪ Scoop
▪ Chocolatey
▪ MSYS2

3 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Packaging status
Alpine Linux 3.16 22.03
Alpine Linux 3.17 22.08.1
Alpine Linux 3.18 23.03
Alpine Linux 3.19 23.10
Alpine Linux 3.20 24.03
Alpine Linux 3.21 24.07
Alpine Linux Edge 24.07
ALT Linux p10 24.07
ALT Linux p11 24.07
ALT Sisyphus 24.07
AOSC 24.07
Arch Linux 24.07
Arch Linux 32 i686 24.07
Arch Linux 32 pentium4 24.07
Arch Linux ARM aarch64 24.07
AUR 24.07.r114…
Artix 24.07
Baulk 25.01
Chimera Linux 24.07
Chocolatey 24.7.0
Chromebrew 22.12
EPEL 9 24.07
Fedora 37 23.10
Fedora 38 24.03
Fedora 39 24.07
Fedora 40 24.07
Fedora 41 24.07
Fedora Rawhide 24.07
FreeBSD Ports 25.01
Gentoo 24.07
Homebrew 25.01
LiGurOS stable 24.07
LiGurOS develop 24.07
MacPorts 25.01
Mageia 9 23.05
Mageia cauldron 24.03
Manjaro Stable 24.07
Manjaro Testing 24.07
Manjaro Unstable 24.07
MPR 24.03
MSYS2 clang64 24.07
MSYS2 clangarm64 24.07
MSYS2 mingw 24.07
MSYS2 ucrt64 24.07
nixpkgs stable 21.11 0.5.0
nixpkgs stable 22.05 22.03
nixpkgs stable 22.11 22.08.1
nixpkgs stable 23.05 23.05
nixpkgs stable 23.11 23.10
nixpkgs stable 24.05 24.03

4 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

nixpkgs stable 24.11 24.07


nixpkgs unstable 25.01
OpenBSD Ports 24.07
openSUSE Leap 15.5 23.03
openSUSE Leap 15.6 23.03
openSUSE Tumbleweed 25.01
Parabola 24.07
pkgsrc current 23.10
Scoop 25.01
Serpent OS 24.07
Solus 25.01
T2 SDE 24.07
Termux 25.01
Void Linux x86_64 25.01
Wikidata 24.07
winget 24.07

Linux
The following third party repositories are available:

Ubuntu
Add the PPA for Helix:

sudo add-apt-repository ppa:maveonair/helix-editor


sudo apt update
sudo apt install helix

Fedora/RHEL

sudo dnf install helix

Arch Linux extra


Releases are available in the extra repository:

sudo pacman -S helix

When installed from the extra repository, run Helix with helix instead of hx .

For example:

5 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

helix --health

to check health

Additionally, a helix-git package is available in the AUR, which builds the master branch.

NixOS
Helix is available in nixpkgs through the helix attribute, the unstable channel usually
carries the latest release.

Helix is also available as a flake in the project root. Use nix develop to spin up a
reproducible development shell. Outputs are cached for each push to master using
Cachix. The flake is configured to automatically make use of this cache assuming the
user accepts the new settings on first use.

If you are using a version of Nix without flakes enabled, install Cachix CLI and use
cachix use helix to configure Nix to use cached outputs when possible.

Flatpak
Helix is available on Flathub:

flatpak install flathub com.helix_editor.Helix


flatpak run com.helix_editor.Helix

Snap
Helix is available on Snapcraft and can be installed with:

snap install --classic helix

This will install Helix as both /snap/bin/helix and /snap/bin/hx , so make sure /
snap/bin is in your PATH .

AppImage
Install Helix using the Linux AppImage format. Download the official Helix AppImage
from the latest releases page.

6 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

chmod +x helix-*.AppImage # change permission for executable mode


./helix-*.AppImage # run helix

You can optionally add the .desktop file. Helix must be installed in PATH with the name
hx . For example:

mkdir -p "$HOME/.local/bin"
mv helix-*.AppImage "$HOME/.local/bin/hx"

and make sure ~/.local/bin is in your PATH .

macOS

Homebrew Core

brew install helix

MacPorts

sudo port install helix

Windows
Install on Windows using Winget, Scoop, Chocolatey or MSYS2.

Winget
Windows Package Manager winget command-line tool is by default available on
Windows 11 and modern versions of Windows 10 as a part of the App Installer. You can
get App Installer from the Microsoft Store. If it's already installed, make sure it is
updated with the latest version.

winget install Helix.Helix

Scoop

7 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

scoop install helix

Chocolatey

choco install helix

MSYS2
For 64-bit Windows 8.1 or above:

pacman -S mingw-w64-ucrt-x86_64-helix

8 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Building from source


▪ Configuring Helix's runtime files
▪ Linux and macOS
▪ Windows
▪ Multiple runtime directories
▪ Note to packagers
▪ Validating the installation
▪ Configure the desktop shortcut

Requirements:

Clone the Helix GitHub repository into a directory of your choice. The examples in this
documentation assume installation into either ~/src/ on Linux and macOS, or
%userprofile%\src\ on Windows.

▪ The Rust toolchain


▪ The Git version control system
▪ A C++14 compatible compiler to build the tree-sitter grammars, for example GCC or
Clang

If you are using the musl-libc standard library instead of glibc the following
environment variable must be set during the build to ensure tree-sitter grammars can be
loaded correctly:

RUSTFLAGS="-C target-feature=-crt-static"

1. Clone the repository:

git clone https://github.com/helix-editor/helix


cd helix

2. Compile from source:

cargo install --path helix-term --locked

This command will create the hx executable and construct the tree-sitter
grammars in the local runtime folder.

If you do not want to fetch or build grammars, set an environment variable


HELIX_DISABLE_AUTO_GRAMMAR_BUILD

9 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Tree-sitter grammars can be fetched and compiled if not pre-packaged. Fetch


grammars with hx --grammar fetch and compile them with hx --grammar build .
This will install them in the runtime directory within the user's helix config directory
(more details below).

Configuring Helix's runtime files

Linux and macOS

The runtime directory is one below the Helix source, so either export a HELIX_RUNTIME
environment variable to point to that directory and add it to your ~/.bashrc or
equivalent:

export HELIX_RUNTIME=~/src/helix/runtime

Or, create a symbolic link:

ln -Ts $PWD/runtime ~/.config/helix/runtime

If the above command fails to create a symbolic link because the file exists either move
~/.config/helix/runtime to a new location or delete it, then run the symlink command
above again.

Windows

Either set the HELIX_RUNTIME environment variable to point to the runtime files using
the Windows setting (search for Edit environment variables for your account ) or
use the setx command in Cmd:

setx HELIX_RUNTIME "%userprofile%\source\repos\helix\runtime"

%userprofile% resolves to your user directory like C:\Users\Your-Name\ for


example.

Or, create a symlink in %appdata%\helix\ that links to the source code directory:

Method Command

New-Item -ItemType Junction -Target "runtime" -Path


PowerShell
"$Env:AppData\helix\runtime"

10 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Method Command

cd %appdata%\helix
Cmd
mklink /D runtime "%userprofile%\src\helix\runtime"

On Windows, creating a symbolic link may require running PowerShell or Cmd as


an administrator.

Multiple runtime directories

When Helix finds multiple runtime directories it will search through them for files in the
following order:

1. runtime/ sibling directory to $CARGO_MANIFEST_DIR directory (this is intended for


developing and testing helix only).
2. runtime/ subdirectory of OS-dependent helix user config directory.
3. $HELIX_RUNTIME
4. Distribution-specific fallback directory (set at compile time—not run time— with the
HELIX_DEFAULT_RUNTIME environment variable)
5. runtime/ subdirectory of path to Helix executable.

This order also sets the priority for selecting which file will be used if multiple runtime
directories have files with the same name.

Note to packagers

If you are making a package of Helix for end users, to provide a good out of the box
experience, you should set the HELIX_DEFAULT_RUNTIME environment variable at build
time (before invoking cargo build ) to a directory which will store the final runtime files
after installation. For example, say you want to package the runtime into /usr/lib/
helix/runtime . The rough steps a build script could follow are:

1. export HELIX_DEFAULT_RUNTIME=/usr/lib/helix/runtime
2. cargo build --profile opt --locked
3. cp -r runtime $BUILD_DIR/usr/lib/helix/
4. cp target/opt/hx $BUILD_DIR/usr/bin/hx

This way the resulting hx binary will always look for its runtime directory in /usr/lib/
helix/runtime if the user has no custom runtime in ~/.config/helix or
HELIX_RUNTIME .

Validating the installation

11 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

To make sure everything is set up as expected you should run the Helix health check:

hx --health

For more information on the health check results refer to Health check.

Configure the desktop shortcut


If your desktop environment supports the XDG desktop menu you can configure Helix to
show up in the application menu by copying the provided .desktop and icon files to
their correct folders:

cp contrib/Helix.desktop ~/.local/share/applications
cp contrib/helix.png ~/.icons # or ~/.local/share/icons

It is recommended to convert the links in the .desktop file to absolute paths to avoid
potential problems:

sed -i -e "s|Exec=hx %F|Exec=$(readlink -f ~/.cargo/bin/hx) %F|g" \


-e "s|Icon=helix|Icon=$(readlink -f ~/.icons/helix.png)|g" ~/.local/share/
applications/Helix.desktop

To use another terminal than the system default, you can modify the .desktop file. For
example, to use kitty :

sed -i "s|Exec=hx %F|Exec=kitty hx %F|g" ~/.local/share/applications/


Helix.desktop
sed -i "s|Terminal=true|Terminal=false|g" ~/.local/share/applications/
Helix.desktop

12 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Using Helix
For a full interactive introduction to Helix, refer to the tutor which can be accessed via
the command hx --tutor or :tutor .

Currently, not all functionality is fully documented, please refer to the key
mappings list.

Modes
Helix is a modal editor, meaning it has different modes for different tasks. The main
modes are:

▪ Normal mode: For navigation and editing commands. This is the default mode.
▪ Insert mode: For typing text directly into the document. Access by typing i in
normal mode.
▪ Select/extend mode: For making selections and performing operations on them.
Access by typing v in normal mode.

Buffers
Buffers are in-memory representations of files. You can have multiple buffers open at
once. Use pickers or commands like :buffer-next and :buffer-previous to open
buffers or switch between them.

Selection-first editing
Inspired by Kakoune, Helix follows the selection → action model. This means that
whatever you are going to act on (a word, a paragraph, a line, etc.) is selected first and
the action itself (delete, change, yank, etc.) comes second. A cursor is simply a single
width selection.

Multiple selections
Also inspired by Kakoune, multiple selections are a core mode of interaction in Helix. For
example, the standard way of replacing multiple instances of a word is to first select all
instances (so there is one selection per instance) and then use the change action ( c ) to

13 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

edit them all at the same time.

Motions
Motions are commands that move the cursor or modify selections. They're used for
navigation and text manipulation. Examples include w to move to the next word, or f
to find a character. See the Movement section of the keymap for more motions.

14 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Registers
▪ User-defined registers
▪ Default registers
▪ Special registers

In Helix, registers are storage locations for text and other data, such as the result of a
search. Registers can be used to cut, copy, and paste text, similar to the clipboard in
other text editors. Usage is similar to Vim, with " being used to select a register.

User-defined registers
Helix allows you to create your own named registers for storing text, for example:

▪ "ay - Yank the current selection to register a .


▪ "op - Paste the text in register o after the selection.

If a register is selected before invoking a change or delete command, the selection will
be stored in the register and the action will be carried out:

▪ "hc - Store the selection in register h and then change it (delete and enter insert
mode).
▪ "md - Store the selection in register m and delete it.

Default registers
Commands that use registers, like yank ( y ), use a default register if none is specified.
These registers are used as defaults:

Register character Contains

/ Last search

: Last executed command

" Last yanked text

@ Last recorded macro

Special registers
Some registers have special behavior when read from and written to.

15 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Register
When read When written
character

_ No values are returned All values are discarded

Selection indices (first selection is 1 ,


# This register is not writable
second is 2 , etc.)

. Contents of the current selections This register is not writable

% Name of the current file This register is not writable

Joins and yanks to the


+ Reads from the system clipboard
system clipboard

Joins and yanks to the


* Reads from the primary clipboard
primary clipboard

When yanking multiple selections to the clipboard registers, the selections are joined
with newlines. Pasting from these registers will paste multiple selections if the clipboard
was last yanked to by the Helix session. Otherwise the clipboard contents are pasted as
one selection.

16 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Surround
Helix includes built-in functionality similar to vim-surround. The keymappings have been
inspired from vim-sandwich:

Key Sequence Action

ms<char> (after selecting text) Add surround characters to selection

mr<char_to_replace><new_char> Replace the closest surround characters

md<char_to_delete> Delete the closest surround characters

You can use counts to act on outer pairs.

Surround can also act on multiple selections. For example, to change every occurrence of
(use) to [use] :

1. % to select the whole file


2. s to split the selections on a search term
3. Input use and hit Enter
4. mr([ to replace the parentheses with square brackets

Multiple characters are currently not supported, but planned for future release.

17 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Selecting and manipulating text with textobjects


In Helix, textobjects are a way to select, manipulate and operate on a piece of text in a
structured way. They allow you to refer to blocks of text based on their structure or
purpose, such as a word, sentence, paragraph, or even a function or block of code.

▪ ma - Select around the object ( va in Vim, <alt-a> in Kakoune)


▪ mi - Select inside the object ( vi in Vim, <alt-i> in Kakoune)

Key after mi or ma Textobject selected

w Word

W WORD

p Paragraph

( , [ , ' , etc. Specified surround pairs

m The closest surround pair

f Function

t Type (or Class)

a Argument/parameter

c Comment

18 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key after mi or ma Textobject selected

T Test

g Change

f , t , etc. need a tree-sitter grammar active for the current document and a
special tree-sitter query file to work properly. Only some grammars currently have
the query file implemented. Contributions are welcome!

Navigating using tree-sitter textobjects


Navigating between functions, classes, parameters, and other elements is possible using
tree-sitter and textobject queries. For example to move to the next function use ]f , to
move to previous type use [t , and so on.

For the full reference see the unimpaired section of the key bind documentation.

This feature relies on tree-sitter textobjects and requires the corresponding query
file to work properly.

19 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Moving the selection with syntax-aware motions


Alt-p , Alt-o , Alt-i , and Alt-n (or Alt and arrow keys) allow you to move the
selection according to its location in the syntax tree. For example, many languages have
the following syntax for function calls:

func(arg1, arg2, arg3);

A function call might be parsed by tree-sitter into a tree like the following.

(call
function: (identifier) ; func
arguments:
(arguments ; (arg1, arg2, arg3)
(identifier) ; arg1
(identifier) ; arg2
(identifier))) ; arg3

Use :tree-sitter-subtree to view the syntax tree of the primary selection. In a more
intuitive tree format:

┌────┐
│call│
┌─────┴────┴─────┐
│ │
┌─────▼────┐ ┌────▼────┐
│identifier│ │arguments│
│ "func" │ ┌────┴───┬─────┴───┐
└──────────┘ │ │ │
│ │ │
┌─────────▼┐ ┌────▼─────┐ ┌▼─────────┐
│identifier│ │identifier│ │identifier│
│ "arg1" │ │ "arg2" │ │ "arg3" │
└──────────┘ └──────────┘ └──────────┘

If you have a selection that wraps arg1 (see the tree above), and you use Alt-n , it will
select the next sibling in the syntax tree: arg2 .

// before
func([arg1], arg2, arg3)
// after
func(arg1, [arg2], arg3);

Similarly, Alt-o will expand the selection to the parent node, in this case, the
arguments node.

20 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

func[(arg1, arg2, arg3)];

There is also some nuanced behavior that prevents you from getting stuck on a node
with no sibling. When using Alt-p with a selection on arg1 , the previous child node
will be selected. In the event that arg1 does not have a previous sibling, the selection
will move up the syntax tree and select the previous element. As a result, using Alt-p
with a selection on arg1 will move the selection to the "func" identifier .

21 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Using pickers
Helix has a variety of pickers, which are interactive windows used to select various kinds
of items. These include a file picker, global search picker, and more. Most pickers are
accessed via keybindings in space mode. Pickers have their own keymap for navigation.

Filtering Picker Results


Most pickers perform fuzzy matching using fzf syntax. Two exceptions are the global
search picker, which uses regex, and the workspace symbol picker, which passes search
terms to the language server. Note that OR operations ( | ) are not currently supported.

If a picker shows multiple columns, you may apply the filter to a specific column by
prefixing the column name with % . Column names can be shortened to any prefix, so
%p , %pa or %pat all mean the same as %path . For example, a query of helix %p
.toml !lang in the global search picker searches for the term "helix" within files with
paths ending in ".toml" but not including "lang".

You can insert the contents of a register using Ctrl-r followed by a register name. For
example, one could insert the currently selected text using Ctrl-r - . , or the directory
of the current file using Ctrl-r - % followed by Ctrl-w to remove the last path section.
The global search picker will use the contents of the search register if you press Enter
without typing a filter. For example, pressing * - Space-/ - Enter will start a global
search for the currently selected text.

22 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Keymap
▪ Normal mode
▪ Movement
▪ Changes
▪ Shell
▪ Selection manipulation
▪ Search
▪ Minor modes
▪ View mode
▪ Goto mode
▪ Match mode
▪ Window mode
▪ Space mode
▪ Popup
▪ Completion Menu
▪ Signature-help Popup
▪ Unimpaired
▪ Insert mode
▪ Select / extend mode
▪ Picker
▪ Prompt

Mappings marked (LSP) require an active language server for the file.

Mappings marked (TS) require a tree-sitter grammar for the file type.

Some terminals' default key mappings conflict with Helix's. If any of the mappings
described on this page do not work as expected, check your terminal's mappings to
ensure they do not conflict. See the wiki for known conflicts.

Normal mode
Normal mode is the default mode when you launch helix. You can return to it from other
modes by pressing the Escape key.

Movement

23 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

NOTE: Unlike Vim, f , F , t and T are not confined to the current line.

Key Description Command

h , Left Move left move_char_left

j , Down Move down move_visual_line_down

k , Up Move up move_visual_line_up

l , Right Move right move_char_right

w Move next word start move_next_word_start

b Move previous word start move_prev_word_start

e Move next word end move_next_word_end

W Move next WORD start move_next_long_word_start

B Move previous WORD start move_prev_long_word_start

E Move next WORD end move_next_long_word_end

t Find 'till next char find_till_char

f Find next char find_next_char

T Find 'till previous char till_prev_char

F Find previous char find_prev_char

G Go to line number <n> goto_line

Repeat last motion ( f , t , m , [ or


Alt-. repeat_last_motion
])

Home Move to the start of the line goto_line_start

End Move to the end of the line goto_line_end

Ctrl-b , PageUp Move page up page_up

Ctrl-f ,
Move page down page_down
PageDown

Ctrl-u Move cursor and page half page up page_cursor_half_up

Move cursor and page half page


Ctrl-d page_cursor_half_down
down

24 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Ctrl-i Jump forward on the jumplist jump_forward

Ctrl-o Jump backward on the jumplist jump_backward

Save the current selection to the


Ctrl-s save_selection
jumplist

Changes

Key Description Command

r Replace with a character replace

R Replace with yanked text replace_with_yanked

~ Switch case of the selected text switch_case

` Set the selected text to lower case switch_to_lowercase

Alt-` Set the selected text to upper case switch_to_uppercase

i Insert before selection insert_mode

a Insert after selection (append) append_mode

I Insert at the start of the line insert_at_line_start

A Insert at the end of the line insert_at_line_end

o Open new line below selection open_below

O Open new line above selection open_above

. Repeat last insert N/A

u Undo change undo

U Redo change redo

Alt-u Move backward in history earlier

Alt-U Move forward in history later

y Yank selection yank

p Paste after selection paste_after

25 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

P Paste before selection paste_before

"
Select a register to yank to or paste from select_register
<reg>

> Indent selection indent

< Unindent selection unindent

= Format selection (LSP) format_selections

d Delete selection delete_selection

Alt-d Delete selection, without yanking delete_selection_noyank

Change selection (delete and enter insert


c change_selection
mode)

Change selection (delete and enter insert


Alt-c change_selection_noyank
mode, without yanking)

Ctrl-a Increment object (number) under cursor increment

Ctrl-x Decrement object (number) under cursor decrement

Start/stop macro recording to the selected


Q record_macro
register (experimental)

Play back a recorded macro from the selected


q replay_macro
register (experimental)

Shell

Key Description Command

Pipe each selection through shell command,


| shell_pipe
replacing with output

Pipe each selection into shell command, ignoring


Alt-| shell_pipe_to
output

Run shell command, inserting output before each


! shell_insert_output
selection

Run shell command, appending output after each


Alt-! shell_append_output
selection

26 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Pipe each selection into shell command, keep


$ shell_keep_pipe
selections where command returned 0

Selection manipulation

Key Description Command

Select all regex matches


s select_regex
inside selections

Split selection into sub


S split_selection
selections on regex matches

Alt-s Split selection on newlines split_selection_on_newline

Alt-minus Merge selections merge_selections

Alt-_ Merge consecutive selections merge_consecutive_selections

& Align selection in columns align_selections

Trim whitespace from the


_ trim_selections
selection

Collapse selection onto a


; collapse_selection
single cursor

Flip selection cursor and


Alt-; flip_selections
anchor

Ensures the selection is in


Alt-: ensure_selections_forward
forward direction

Keep only the primary


, keep_primary_selection
selection

Remove the primary


Alt-, remove_primary_selection
selection

Copy selection onto the next


C copy_selection_on_next_line
line (Add cursor below)

Copy selection onto the


Alt-C previous line (Add cursor copy_selection_on_prev_line
above)

27 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Rotate main selection


( rotate_selections_backward
backward

Rotate main selection


) rotate_selections_forward
forward

Rotate selection contents


Alt-( rotate_selection_contents_backward
backward

Rotate selection contents


Alt-) rotate_selection_contents_forward
forward

% Select entire file select_all

Select current line, if already


x extend_line_below
selected, extend to next line

Extend selection to line


X extend_to_line_bounds
bounds (line-wise selection)

Shrink selection to line


Alt-x shrink_to_line_bounds
bounds (line-wise selection)

J Join lines inside selection join_selections

Join lines inside selection and


Alt-J join_selections_space
select the inserted space

Keep selections matching the


K keep_selections
regex

Remove selections matching


Alt-K remove_selections
the regex

Comment/uncomment the
Ctrl-c toggle_comments
selections

Alt-o , Alt- Expand selection to parent


expand_selection
up syntax node (TS)

Alt-i , Alt- Shrink syntax tree object


shrink_selection
down selection (TS)

Alt-p , Alt- Select previous sibling node


select_prev_sibling
left in syntax tree (TS)

Alt-n , Alt- Select next sibling node in


select_next_sibling
right syntax tree (TS)

28 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Select all sibling nodes in


Alt-a select_all_siblings
syntax tree (TS)

Alt-I , Alt- Select all children nodes in


select_all_children
Shift-down syntax tree (TS)

Move to end of parent node


Alt-e move_parent_node_end
in syntax tree (TS)

Move to start of parent node


Alt-b move_parent_node_start
in syntax tree (TS)

Search
Search commands all operate on the / register by default. To use a different register,
use "<char> .

Key Description Command

/ Search for regex pattern search

? Search for previous pattern rsearch

n Select next search match search_next

N Select previous search match search_prev

Use current selection as the


search pattern, automatically
* search_selection_detect_word_boundaries
wrapping with \b on word
boundaries

Alt Use current selection as the


search_selection
-* search pattern

Minor modes
These sub-modes are accessible from normal mode and typically switch back to normal
mode after a command.

Key Description Command

29 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

v Enter select (extend) mode select_mode

g Enter goto mode N/A

m Enter match mode N/A

: Enter command mode command_mode

z Enter view mode N/A

Z Enter sticky view mode N/A

Ctrl-w Enter window mode N/A

Space Enter space mode N/A

These modes (except command mode) can be configured by remapping keys.

View mode

Accessed by typing z in normal mode.

View mode is intended for scrolling and manipulating the view without changing the
selection. The "sticky" variant of this mode (accessed by typing Z in normal mode) is
persistent and can be exited using the escape key. This is useful when you're simply
looking over text and not actively editing it.

Key Description Command

z, c Vertically center the line align_view_center

t Align the line to the top of the screen align_view_top

b Align the line to the bottom of the screen align_view_bottom

Align the line to the middle of the screen


m align_view_middle
(horizontally)

j , down Scroll the view downwards scroll_down

k , up Scroll the view upwards scroll_up

Ctrl-f ,
Move page down page_down
PageDown

Ctrl-b ,
Move page up page_up
PageUp

30 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Ctrl-u Move cursor and page half page up page_cursor_half_up

Ctrl-d Move cursor and page half page down page_cursor_half_down

Goto mode

Accessed by typing g in normal mode.

Jumps to various locations.

Key Description Command

g Go to line number <n> else start of file goto_file_start

e Go to the end of the file goto_last_line

f Go to files in the selections goto_file

h Go to the start of the line goto_line_start

l Go to the end of the line goto_line_end

s Go to first non-whitespace character of the line goto_first_nonwhitespace

t Go to the top of the screen goto_window_top

c Go to the middle of the screen goto_window_center

b Go to the bottom of the screen goto_window_bottom

d Go to definition (LSP) goto_definition

y Go to type definition (LSP) goto_type_definition

r Go to references (LSP) goto_reference

i Go to implementation (LSP) goto_implementation

a Go to the last accessed/alternate file goto_last_accessed_file

m Go to the last modified/alternate file goto_last_modified_file

n Go to next buffer goto_next_buffer

p Go to previous buffer goto_previous_buffer

. Go to last modification in current file goto_last_modification

31 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

j Move down textual (instead of visual) line move_line_down

k Move up textual (instead of visual) line move_line_up

Show labels at each word and select the word that


w goto_word
belongs to the entered labels

Match mode

Accessed by typing m in normal mode.

Please refer to the relevant sections for detailed explanations about surround and
textobjects.

Key Description Command

m Goto matching bracket (TS) match_brackets

Surround current selection with


s <char> surround_add
<char>

r Replace surround character <from>


surround_replace
<from><to> with <to>

d <char> Delete surround character <char> surround_delete

a <object> Select around textobject select_textobject_around

i <object> Select inside textobject select_textobject_inner

TODO: Mappings for selecting syntax nodes (a superset of [ ).

Window mode

Accessed by typing Ctrl-w in normal mode.

This layer is similar to Vim keybindings as Kakoune does not support windows.

Key Description Command

w , Ctrl-w Switch to next window rotate_view

v , Ctrl-v Vertical right split vsplit

s , Ctrl-s Horizontal bottom split hsplit

32 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

f Go to files in the selections in horizontal splits goto_file

F Go to files in the selections in vertical splits goto_file

h , Ctrl-h ,
Move to left split jump_view_left
Left

j , Ctrl-j ,
Move to split below jump_view_down
Down

k , Ctrl-k , Up Move to split above jump_view_up

l , Ctrl-l ,
Move to right split jump_view_right
Right

q , Ctrl-q Close current window wclose

Only keep the current window, closing all the


o , Ctrl-o wonly
others

H Swap window to the left swap_view_left

J Swap window downwards swap_view_down

K Swap window upwards swap_view_up

L Swap window to the right swap_view_right

Space mode

Accessed by typing Space in normal mode.

This layer is a kludge of mappings, mostly pickers.

Key Description Command

Open file picker at LSP


f file_picker
workspace root

Open file picker at current


F file_picker_in_current_directory
working directory

b Open buffer picker buffer_picker

j Open jumplist picker jumplist_picker

g Open changed file picker changed_file_picker

33 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

G Debug (experimental) N/A

Show documentation for item


k hover
under cursor in a popup (LSP)

Open document symbol picker


s symbol_picker
(LSP)

Open workspace symbol


S workspace_symbol_picker
picker (LSP)

Open document diagnostics


d diagnostics_picker
picker (LSP)

Open workspace diagnostics


D workspace_diagnostics_picker
picker (LSP)

r Rename symbol (LSP) rename_symbol

a Apply code action (LSP) code_action

h Select symbol references (LSP) select_references_to_symbol_under_cursor

' Open last fuzzy picker last_picker

w Enter window mode N/A

Comment/uncomment
c toggle_comments
selections

Block comment/uncomment
C toggle_block_comments
selections

Alt Line comment/uncomment


toggle_line_comments
-c selections

Paste system clipboard after


p paste_clipboard_after
selections

Paste system clipboard before


P paste_clipboard_before
selections

y Yank selections to clipboard yank_to_clipboard

Yank main selection to


Y yank_main_selection_to_clipboard
clipboard

Replace selections by clipboard


R replace_selections_with_clipboard
contents

34 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

Global search in workspace


/ global_search
folder

? Open command palette command_palette

Global search displays results in a fuzzy picker, use Space + ' to bring it back up
after opening a file.

Popup

Displays documentation for item under cursor. Remapping currently not supported.

Key Description

Ctrl-u Scroll up

Ctrl-d Scroll down

Completion Menu

Displays documentation for the selected completion item. Remapping currently not
supported.

Key Description

Shift-Tab , Ctrl-p , Up Previous entry

Tab , Ctrl-n , Down Next entry

Enter Close menu and accept completion

Ctrl-c Close menu and reject completion

Any other keypresses result in the completion being accepted.

Signature-help Popup

Displays the signature of the selected completion item. Remapping currently not
supported.

35 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description

Alt-p Previous signature

Alt-n Next signature

Unimpaired

These mappings are in the style of vim-unimpaired.

Key Description Command

]d Go to next diagnostic (LSP) goto_next_diag

[d Go to previous diagnostic (LSP) goto_prev_diag

]D Go to last diagnostic in document (LSP) goto_last_diag

[D Go to first diagnostic in document (LSP) goto_first_diag

]f Go to next function (TS) goto_next_function

[f Go to previous function (TS) goto_prev_function

]t Go to next type definition (TS) goto_next_class

[t Go to previous type definition (TS) goto_prev_class

]a Go to next argument/parameter (TS) goto_next_parameter

[a Go to previous argument/parameter (TS) goto_prev_parameter

]c Go to next comment (TS) goto_next_comment

[c Go to previous comment (TS) goto_prev_comment

]T Go to next test (TS) goto_next_test

[T Go to previous test (TS) goto_prev_test

]p Go to next paragraph goto_next_paragraph

[p Go to previous paragraph goto_prev_paragraph

]g Go to next change goto_next_change

[g Go to previous change goto_prev_change

]G Go to last change goto_last_change

36 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Command

[G Go to first change goto_first_change

]Space Add newline below add_newline_below

[Space Add newline above add_newline_above

Insert mode
Accessed by typing i in normal mode.

Insert mode bindings are minimal by default. Helix is designed to be a modal editor, and
this is reflected in the user experience and internal mechanics. Changes to the text are
only saved for undos when escaping from insert mode to normal mode.

New users are strongly encouraged to learn the modal editing paradigm to get
the smoothest experience.

Key Description Command

Switch to normal
Escape normal_mode
mode

Commit undo
Ctrl-s commit_undo_checkpoint
checkpoint

Ctrl-x Autocomplete completion

Insert a register
Ctrl-r insert_register
content

Ctrl-w , Alt-Backspace Delete previous word delete_word_backward

Alt-d , Alt-Delete Delete next word delete_word_forward

Ctrl-u Delete to start of line kill_to_line_start

Ctrl-k Delete to end of line kill_to_line_end

Ctrl-h , Backspace , Shift-


Delete previous char delete_char_backward
Backspace

Ctrl-d , Delete Delete next char delete_char_forward

Ctrl-j , Enter Insert new line insert_newline

37 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

These keys are not recommended, but are included for new users less familiar with
modal editors.

Key Description Command

Up Move to previous line move_line_up

Down Move to next line move_line_down

Left Backward a char move_char_left

Right Forward a char move_char_right

PageUp Move one page up page_up

PageDown Move one page down page_down

Home Move to line start goto_line_start

End Move to line end goto_line_end_newline

As you become more comfortable with modal editing, you may want to disable some
insert mode bindings. You can do this by editing your config.toml file.

[keys.insert]
up = "no_op"
down = "no_op"
left = "no_op"
right = "no_op"
pageup = "no_op"
pagedown = "no_op"
home = "no_op"
end = "no_op"

Select / extend mode


Accessed by typing v in normal mode.

Select mode echoes Normal mode, but changes any movements to extend selections
rather than replace them. Goto motions are also changed to extend, so that vgl , for
example, extends the selection to the end of the line.

Search is also affected. By default, n and N will remove the current selection and select
the next instance of the search term. Toggling this mode before pressing n or N makes
it possible to keep the current selection. Toggling it on and off during your iterative
searching allows you to selectively add search terms to your selections.

38 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Picker
Keys to use within picker. Remapping currently not supported. See the documentation
page on pickers for more info. Prompt keybinds also work in pickers, except where they
conflict with picker keybinds.

Key Description

Shift-Tab , Up , Ctrl-p Previous entry

Tab , Down , Ctrl-n Next entry

PageUp , Ctrl-u Page up

PageDown , Ctrl-d Page down

Home Go to first entry

End Go to last entry

Enter Open selected

Alt-Enter Open selected in the background without closing the picker

Ctrl-s Open horizontally

Ctrl-v Open vertically

Ctrl-t Toggle preview

Escape , Ctrl-c Close picker

Prompt
Keys to use within prompt, Remapping currently not supported.

Key Description

Escape , Ctrl-c Close prompt

Alt-b , Ctrl-Left Backward a word

Ctrl-b , Left Backward a char

Alt-f , Ctrl-Right Forward a word

Ctrl-f , Right Forward a char

39 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description

Ctrl-e , End Move prompt end

Ctrl-a , Home Move prompt start

Ctrl-w , Alt-Backspace , Ctrl-


Delete previous word
Backspace

Alt-d , Alt-Delete , Ctrl-


Delete next word
Delete

Ctrl-u Delete to start of line

Ctrl-k Delete to end of line

Backspace , Ctrl-h , Shift-


Delete previous char
Backspace

Delete , Ctrl-d Delete next char

Insert a word under doc cursor, may be changed to


Ctrl-s
Ctrl-r Ctrl-w later

Ctrl-p , Up Select previous history

Ctrl-n , Down Select next history

Insert the content of the register selected by


Ctrl-r
following input char

Tab Select next completion item

BackTab Select previous completion item

Enter Open selected

40 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Commands
▪ Typable commands
▪ Static commands

Typable commands
Typable commands are used from command mode and may take arguments. Command
mode can be activated by pressing : . The built-in typable commands are:

Name Description

:quit , :q Close the current view.

:quit! , :q! Force close the current view, ignoring unsaved changes.

:open , :o , :edit , :e Open a file from disk into the current view.

:buffer-close , :bc ,
Close the current buffer.
:bclose

:buffer-close! , :bc! , Close the current buffer forcefully, ignoring unsaved


:bclose! changes.

:buffer-close-others ,
Close all buffers but the currently focused one.
:bco , :bcloseother

:buffer-close-
others! , :bco! , Force close all buffers but the currently focused one.
:bcloseother!

:buffer-close-all ,
Close all buffers without quitting.
:bca , :bcloseall

:buffer-close-all! , Force close all buffers ignoring unsaved changes without


:bca! , :bcloseall! quitting.

:buffer-next , :bn ,
Goto next buffer.
:bnext

:buffer-previous ,
Goto previous buffer.
:bp , :bprev

Write changes to disk. Accepts an optional path (:write


:write , :w
some/path.txt)

41 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description

Force write changes to disk creating necessary


:write! , :w! subdirectories. Accepts an optional path (:write! some/
path.txt)

:write-buffer-close , Write changes to disk and closes the buffer. Accepts an


:wbc optional path (:write-buffer-close some/path.txt)

Force write changes to disk creating necessary


:write-buffer-close! ,
subdirectories and closes the buffer. Accepts an optional
:wbc!
path (:write-buffer-close! some/path.txt)

:new , :n Create a new scratch buffer.

Format the file using an external formatter or language


:format , :fmt
server.

Set the indentation style for editing. ('t' for tabs or 1-16 for
:indent-style
number of spaces.)

:line-ending Set the document's default line ending. Options: crlf, lf.

Jump back to an earlier point in edit history. Accepts a


:earlier , :ear
number of steps or a time span.

Jump to a later point in edit history. Accepts a number of


:later , :lat
steps or a time span.

Write changes to disk and close the current view. Accepts an


:write-quit , :wq , :x
optional path (:wq some/path.txt)

:write-quit! , :wq! , Write changes to disk and close the current view forcefully.
:x! Accepts an optional path (:wq! some/path.txt)

:write-all , :wa Write changes from all buffers to disk.

Forcefully write changes from all buffers to disk creating


:write-all! , :wa!
necessary subdirectories.

:write-quit-all ,
Write changes from all buffers to disk and close all views.
:wqa , :xa

:write-quit-all! , Write changes from all buffers to disk and close all views
:wqa! , :xa! forcefully (ignoring unsaved changes).

:quit-all , :qa Close all views.

:quit-all! , :qa! Force close all views ignoring unsaved changes.

42 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description

Quit with exit code (default 1). Accepts an optional integer


:cquit , :cq
exit code (:cq 2).

Force quit with exit code (default 1) ignoring unsaved


:cquit! , :cq!
changes. Accepts an optional integer exit code (:cq! 2).

Change the editor theme (show current theme if no name


:theme
specified).

Yank joined selections. A separator can be provided as first


:yank-join
argument. Default value is newline.

:clipboard-yank Yank main selection into system clipboard.

Yank joined selections into system clipboard. A separator


:clipboard-yank-join
can be provided as first argument. Default value is newline.

:primary-clipboard-
Yank main selection into system primary clipboard.
yank

Yank joined selections into system primary clipboard. A


:primary-clipboard-
separator can be provided as first argument. Default value
yank-join
is newline.

:clipboard-paste-
Paste system clipboard after selections.
after

:clipboard-paste-
Paste system clipboard before selections.
before

:clipboard-paste-
Replace selections with content of system clipboard.
replace

:primary-clipboard-
Paste primary clipboard after selections.
paste-after

:primary-clipboard-
Paste primary clipboard before selections.
paste-before

:primary-clipboard- Replace selections with content of system primary


paste-replace clipboard.

:show-clipboard-
Show clipboard provider name in status bar.
provider

:change-current-
Change the current working directory.
directory , :cd

43 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description

:show-directory ,
Show the current working directory.
:pwd

Set encoding. Based on https://


:encoding
encoding.spec.whatwg.org .

:character-info ,
Get info about the character under the primary cursor.
:char

:reload , :rl Discard changes and reload from the source file.

Discard changes and reload all documents from the source


:reload-all , :rla
files.

:update , :u Write changes only if the file has been modified.

:lsp-workspace-
Open workspace command picker
command

:lsp-restart Restarts the language servers used by the current doc

:lsp-stop Stops the language servers that are used by the current doc

Display tree sitter scopes, primarily for theming and


:tree-sitter-scopes
development.

:tree-sitter-
Display name of tree-sitter highlight scope under the cursor.
highlight-name

Start a debug session from a given template with given


:debug-start , :dbg
parameters.

Connect to a debug adapter by TCP address and start a


:debug-remote , :dbg-
debugging session from a given template with given
tcp
parameters.

:debug-eval Evaluate expression in current debug context.

:vsplit , :vs Open the file in a vertical split.

:vsplit-new , :vnew Open a scratch buffer in a vertical split.

:hsplit , :hs , :sp Open the file in a horizontal split.

:hsplit-new , :hnew Open a scratch buffer in a horizontal split.

:tutor Open the tutorial.

:goto , :g Goto line number.

44 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description

Set the language of current buffer (show current language


:set-language , :lang
if no value specified).

Set a config option at runtime.


:set-option , :set For example to disable smart case search, use :set
search.smart-case false .

Toggle a boolean config option at runtime.


:toggle-option ,
For example to toggle smart case search, use :toggle
:toggle
search.smart-case .

:get-option , :get Get the current value of a config option.

:sort Sort ranges in selection.

:rsort Sort ranges in selection in reverse order.

:reflow Hard-wrap the current selection of lines to a given width.

:tree-sitter-subtree , Display the smallest tree-sitter subtree that spans the


:ts-subtree primary selection, primarily for debugging queries.

:config-reload Refresh user config.

:config-open Open the user config.toml file.

:config-open-
Open the workspace config.toml file.
workspace

:log-open Open the helix log file.

:insert-output Run shell command, inserting output before each selection.

:append-output Run shell command, appending output after each selection.

:pipe Pipe each selection to the shell command.

:pipe-to Pipe each selection to the shell command, ignoring output.

:run-shell-command ,
Run a shell command
:sh

:reset-diff-change ,
Reset the diff change at the cursor position.
:diffget , :diffg

Clear given register. If no argument is provided, clear all


:clear-register
registers.

:redraw Clear and re-render the whole UI

45 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description

Move the current buffer and its corresponding file to a


:move , :mv
different path

Yank diagnostic(s) under primary cursor to register, or


:yank-diagnostic
clipboard by default

:read , :r Load a file into buffer

Static Commands
Static commands take no arguments and can be bound to keys. Static commands can
also be executed from the command picker ( <space>? ). The built-in static commands
are:

Name Description Default keybinds

no_op Do nothing

normal: h ,
move_char_left Move left <left> , insert:
<left>

normal: l ,
move_char_right Move right <right> , insert:
<right>

move_line_up Move up normal: gk

move_line_down Move down normal: gj

normal: k , <up> ,
move_visual_line_up Move up
insert: <up>

normal: j ,
move_visual_line_down Move down <down> , insert:
<down>

extend_char_left Extend left select: h , <left>

select: l ,
extend_char_right Extend right
<right>

extend_line_up Extend up select: gk

extend_line_down Extend down select: gj

46 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

extend_visual_line_up Extend up select: k , <up>

extend_visual_line_down Extend down select: j , <down>

Copy selection normal: C , select:


copy_selection_on_next_line
on next line C

Copy selection normal: <A-C> ,


copy_selection_on_prev_line
on previous line select: <A-C>

Move to start of
move_next_word_start normal: w
next word

Move to start of
move_prev_word_start normal: b
previous word

Move to end of
move_next_word_end normal: e
next word

Move to end of
move_prev_word_end
previous word

Move to start of
move_next_long_word_start normal: W
next long word

Move to start of
move_prev_long_word_start previous long normal: B
word

Move to end of
move_next_long_word_end normal: E
next long word

Move to end of
move_prev_long_word_end previous long
word

Move to start of
move_next_sub_word_start
next sub word

Move to start of
move_prev_sub_word_start previous sub
word

Move to end of
move_next_sub_word_end
next sub word

move_prev_sub_word_end Move to end of


previous sub

47 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


word

Move to end of
move_parent_node_end normal: <A-e>
the parent node

Move to
move_parent_node_start beginning of the normal: <A-b>
parent node

Extend to start
extend_next_word_start select: w
of next word

Extend to start
extend_prev_word_start of previous select: b
word

Extend to end of
extend_next_word_end select: e
next word

Extend to end of
extend_prev_word_end
previous word

Extend to start
extend_next_long_word_start of next long select: W
word

Extend to start
extend_prev_long_word_start of previous long select: B
word

Extend to end of
extend_next_long_word_end select: E
next long word

Extend to end of
extend_prev_long_word_end
prev long word

Extend to start
extend_next_sub_word_start of next sub
word

Extend to start
extend_prev_sub_word_start of previous sub
word

Extend to end of
extend_next_sub_word_end
next sub word

48 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Extend to end of
extend_prev_sub_word_end
prev sub word

Extend to end of
extend_parent_node_end select: <A-e>
the parent node

Extend to
extend_parent_node_start beginning of the select: <A-b>
parent node

Move till next


find_till_char occurrence of normal: t
char

Move to next
find_next_char occurrence of normal: f
char

Extend till next


extend_till_char occurrence of select: t
char

Extend to next
extend_next_char occurrence of select: f
char

Move till
previous
till_prev_char normal: T
occurrence of
char

Move to
previous
find_prev_char normal: F
occurrence of
char

Extend till
previous
extend_till_prev_char select: T
occurrence of
char

Extend to
previous
extend_prev_char select: F
occurrence of
char

49 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Repeat last normal: <A-.> ,


repeat_last_motion
motion select: <A-.>

Replace with normal: r , select:


replace
new char r

Switch (toggle) normal: ~ , select:


switch_case
case ~

Switch to normal: <A-`> ,


switch_to_uppercase
uppercase select: <A-`>

Switch to normal: ` , select:


switch_to_lowercase
lowercase `

normal: <C-b> ,
Z<C-b> , z<C-b> ,
<pageup> ,
Z<pageup> ,
z<pageup> , select:
page_up Move page up <C-b> , Z<C-b> ,
z<C-b> ,
<pageup> ,
Z<pageup> ,
z<pageup> , insert:
<pageup>

normal: <C-f> ,
Z<C-f> , z<C-f> ,
<pagedown> ,
Z<pagedown> ,
z<pagedown> ,
Move page select: <C-f> ,
page_down
down Z<C-f> , z<C-f> ,
<pagedown> ,
Z<pagedown> ,
z<pagedown> ,
insert:
<pagedown>

Move half page


half_page_up
up

Move half page


half_page_down
down

50 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Move page and


page_cursor_up
cursor up

Move page and


page_cursor_down
cursor down

normal: <C-u> ,
Z<C-u> , z<C-u> ,
Z<backspace> ,
Move page and z<backspace> ,
page_cursor_half_up
cursor half up select: <C-u> ,
Z<C-u> , z<C-u> ,
Z<backspace> ,
z<backspace>

normal: <C-d> ,
Z<C-d> , z<C-d> ,
Z<space> ,
Move page and
z<space> , select:
page_cursor_half_down cursor half
<C-d> , Z<C-d> ,
down
z<C-d> ,
Z<space> ,
z<space>

Select whole normal: % , select:


select_all
document %

Select all regex


normal: s , select:
select_regex matches inside
s
selections

Split selections
normal: S , select:
split_selection on regex
S
matches

Split selection normal: <A-s> ,


split_selection_on_newline
on newlines select: <A-s>

normal: <A-
Merge
merge_selections minus> , select:
selections
<A-minus>

Merge
normal: <A-_> ,
merge_consecutive_selections consecutive
select: <A-_>
selections

51 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

normal: / , Z/ ,
Search for regex
search z/ , select: / ,
pattern
Z/ , z/

Reverse search normal: ? , Z? ,


rsearch for regex z? , select: ? ,
pattern Z? , z?

normal: n , Zn ,
Select next
search_next zn , select: Zn ,
search match
zn

normal: N , ZN ,
Select previous
search_prev zN , select: ZN ,
search match
zN

Add next search


extend_search_next match to select: n
selection

Add previous
extend_search_prev search match to select: N
selection

Use current
normal: <A-*> ,
search_selection selection as
select: <A-*>
search pattern

Use current
selection as the
search pattern,
normal: * , select:
search_selection_detect_word_boundaries automatically
*
wrapping with
\b on word
boundaries

Modify current
make_search_word_bounded search to make
it word bounded

Global search in
normal: <space>/ ,
global_search workspace
select: <space>/
folder

extend_line Select current


line, if already
selected, extend

52 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


to another line
based on the
anchor

Select current
line, if already normal: x , select:
extend_line_below
selected, extend x
to next line

Select current
line, if already
extend_line_above
selected, extend
to previous line

Select current
line, if already
selected, extend
select_line_above
or shrink line
above based on
the anchor

Select current
line, if already
selected, extend
select_line_below
or shrink line
below based on
the anchor

Extend selection normal: X , select:


extend_to_line_bounds
to line bounds X

Shrink selection normal: <A-x> ,


shrink_to_line_bounds
to line bounds select: <A-x>

normal: d , select:
delete_selection Delete selection
d

Delete selection normal: <A-d> ,


delete_selection_noyank
without yanking select: <A-d>

Change normal: c , select:


change_selection
selection c

Change
normal: <A-c> ,
change_selection_noyank selection
select: <A-c>
without yanking

53 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Collapse
normal: ; , select:
collapse_selection selection into
;
single cursor

Flip selection
normal: <A-;> ,
flip_selections cursor and
select: <A-;>
anchor

Ensure all
normal: <A-:> ,
ensure_selections_forward selections face
select: <A-:>
forward

Insert before normal: i , select:


insert_mode
selection i

Append after normal: a , select:


append_mode
selection a

Enter command normal: : , select:


command_mode
mode :

normal: <space>f ,
file_picker Open file picker
select: <space>f

Open file picker


at current
file_picker_in_current_buffer_directory
buffer's
directory

Open file picker


at current normal: <space>F ,
file_picker_in_current_directory
working select: <space>F
directory

Perform code normal: <space>a ,


code_action
action select: <space>a

Open buffer normal: <space>b ,


buffer_picker
picker select: <space>b

Open jumplist normal: <space>j ,


jumplist_picker
picker select: <space>j

Open symbol normal: <space>s ,


symbol_picker
picker select: <space>s

54 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Open changed normal: <space>g ,


changed_file_picker
file picker select: <space>g

Select symbol normal: <space>h ,


select_references_to_symbol_under_cursor
references select: <space>h

Open
normal: <space>S ,
workspace_symbol_picker workspace
select: <space>S
symbol picker

Open diagnostic normal: <space>d ,


diagnostics_picker
picker select: <space>d

Open
workspace normal: <space>D ,
workspace_diagnostics_picker
diagnostic select: <space>D
picker

normal: <space>' ,
last_picker Open last picker
select: <space>'

Insert at start of normal: I , select:


insert_at_line_start
line I

Insert at end of normal: A , select:


insert_at_line_end
line A

Open new line normal: o , select:


open_below
below selection o

Open new line normal: O , select:


open_above
above selection O

normal: <esc> ,
Enter normal
normal_mode select: v , insert:
mode
<esc>

Enter selection
select_mode normal: v
extend mode

Exit selection
exit_select_mode select: <esc>
mode

normal: gd ,
goto_definition Goto definition
select: gd

Goto normal: gD ,
goto_declaration
declaration select: gD

55 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Add newline normal: [<space> ,


add_newline_above
above select: [<space>

Add newline normal: ]<space> ,


add_newline_below
below select: ]<space>

Goto type normal: gy ,


goto_type_definition
definition select: gy

Goto normal: gi ,
goto_implementation
implementation select: gi

Goto line
normal: gg ,
goto_file_start number else file
select: gg
start

goto_file_end Goto file end

Goto files/URLs normal: gf ,


goto_file
in selections select: gf

normal: <C-w>f ,
Goto files in
<space>wf , select:
goto_file_hsplit selections
<C-w>f ,
(hsplit)
<space>wf

normal: <C-w>F ,
Goto files in
<space>wF , select:
goto_file_vsplit selections
<C-w>F ,
(vsplit)
<space>wF

normal: gr ,
goto_reference Goto references
select: gr

Goto window normal: gt ,


goto_window_top
top select: gt

Goto window normal: gc ,


goto_window_center
center select: gc

Goto window normal: gb ,


goto_window_bottom
bottom select: gb

Goto last normal: ga ,


goto_last_accessed_file
accessed file select: ga

Goto last normal: gm ,


goto_last_modified_file
modified file select: gm

56 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Goto last normal: g. ,


goto_last_modification
modification select: g.

normal: G , select:
goto_line Goto line
G

normal: ge ,
goto_last_line Goto last line
select: ge

Goto first normal: [D ,


goto_first_diag
diagnostic select: [D

Goto last normal: ]D ,


goto_last_diag
diagnostic select: ]D

Goto next normal: ]d ,


goto_next_diag
diagnostic select: ]d

Goto previous normal: [d ,


goto_prev_diag
diagnostic select: [d

Goto next normal: ]g ,


goto_next_change
change select: ]g

Goto previous normal: [g ,


goto_prev_change
change select: [g

Goto first normal: [G ,


goto_first_change
change select: [G

Goto last normal: ]G ,


goto_last_change
change select: ]G

normal: gh ,
<home> , select:
goto_line_start Goto line start
gh , insert:
<home>

normal: gl ,
goto_line_end Goto line end
<end> , select: gl

normal: gn ,
goto_next_buffer Goto next buffer
select: gn

Goto previous normal: gp ,


goto_previous_buffer
buffer select: gp

57 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Goto newline at
goto_line_end_newline insert: <end>
line end

Goto first non- normal: gs ,


goto_first_nonwhitespace
blank in line select: gs

Trim whitespace normal: _ , select:


trim_selections
from selections _

Extend to line
extend_to_line_start select: <home>
start

Extend to first
extend_to_first_nonwhitespace non-blank in
line

Extend to line
extend_to_line_end select: <end>
end

Extend to line
extend_to_line_end_newline
end

Show signature
signature_help
help

Insert tab if all


cursors have all
whitespace to
smart_tab their left; insert: <tab>
otherwise, run a
separate
command.

insert_tab Insert tab char insert: <S-tab>

Insert newline insert: <C-j> ,


insert_newline
char <ret>

insert: <C-h> ,
Delete previous
delete_char_backward <backspace> ,
char
<S-backspace>

insert: <C-d> ,
delete_char_forward Delete next char
<del>

Delete previous insert: <C-w> ,


delete_word_backward
word <A-backspace>

58 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Delete next insert: <A-d> ,


delete_word_forward
word <A-del>

Delete till start


kill_to_line_start insert: <C-u>
of line

Delete till end of


kill_to_line_end insert: <C-k>
line

normal: u , select:
undo Undo change
u

normal: U , select:
redo Redo change
U

Move backward normal: <A-u> ,


earlier
in history select: <A-u>

Move forward in normal: <A-U> ,


later
history select: <A-U>

Commit
commit_undo_checkpoint changes to new insert: <C-s>
checkpoint

normal: y , select:
yank Yank selection
y

Yank selections normal: <space>y ,


yank_to_clipboard
to clipboard select: <space>y

Yank selections
yank_to_primary_clipboard to primary
clipboard

Join and yank


yank_joined
selections

Join and yank


yank_joined_to_clipboard selections to
clipboard

Yank main
normal: <space>Y ,
yank_main_selection_to_clipboard selection to
select: <space>Y
clipboard

yank_joined_to_primary_clipboard Join and yank


selections to

59 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


primary
clipboard

Yank main
selection to
yank_main_selection_to_primary_clipboard
primary
clipboard

Replace with normal: R , select:


replace_with_yanked
yanked text R

Replace
selections by normal: <space>R ,
replace_selections_with_clipboard
clipboard select: <space>R
content

Replace
selections by
replace_selections_with_primary_clipboard
primary
clipboard

Paste after normal: p , select:


paste_after
selection p

Paste before normal: P , select:


paste_before
selection P

Paste clipboard normal: <space>p ,


paste_clipboard_after
after selections select: <space>p

Paste clipboard
normal: <space>P ,
paste_clipboard_before before
select: <space>P
selections

Paste primary
paste_primary_clipboard_after clipboard after
selections

Paste primary
paste_primary_clipboard_before clipboard before
selections

normal: <gt> ,
indent Indent selection
select: <gt>

Unindent normal: <lt> ,


unindent
selection select: <lt>

60 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Format normal: = , select:


format_selections
selection =

Join lines inside normal: J , select:


join_selections
selection J

Join lines inside


normal: <A-J> ,
join_selections_space selection and
select: <A-J>
select spaces

Keep selections normal: K , select:


keep_selections
matching regex K

Remove
normal: <A-K> ,
remove_selections selections
select: <A-K>
matching regex

Align selections normal: & , select:


align_selections
in column &

Keep primary normal: , , select:


keep_primary_selection
selection ,

Remove primary normal: <A-,> ,


remove_primary_selection
selection select: <A-,>

Invoke
completion completion insert: <C-x>
popup

Show docs for


normal: <space>k ,
hover item under
select: <space>k
cursor

Comment/ normal: <C-c> ,


toggle_comments uncomment <space>c , select:
selections <C-c> , <space>c

normal:
Line comment/
<space><A-c> ,
toggle_line_comments uncomment
select:
selections
<space><A-c>

Block comment/
normal: <space>C ,
toggle_block_comments uncomment
select: <space>C
selections

61 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Rotate
normal: ) , select:
rotate_selections_forward selections
)
forward

Rotate
normal: ( , select:
rotate_selections_backward selections
(
backward

Rotate selection
normal: <A-)> ,
rotate_selection_contents_forward contents
select: <A-)>
forward

Rotate
selections normal: <A-(> ,
rotate_selection_contents_backward
contents select: <A-(>
backward

Reverse
reverse_selection_contents selections
contents

Expand
normal: <A-o> ,
selection to
expand_selection <A-up> , select:
parent syntax
<A-o> , <A-up>
node

Shrink selection
normal: <A-i> ,
to previously
shrink_selection <A-down> , select:
expanded
<A-i> , <A-down>
syntax node

normal: <A-n> ,
Select next
<A-right> , select:
select_next_sibling sibling in the
<A-n> , <A-
syntax tree
right>

Select previous normal: <A-p> ,


select_prev_sibling sibling the in <A-left> , select:
syntax tree <A-p> , <A-left>

Select all
normal: <A-a> ,
select_all_siblings siblings of the
select: <A-a>
current node

select_all_children Select all normal: <A-I> ,


children of the <S-A-down> ,
current node select: <A-I> ,

62 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


<S-A-down>

normal: <C-i> ,
Jump forward
jump_forward <tab> , select:
on jumplist
<C-i> , <tab>

Jump backward normal: <C-o> ,


jump_backward
on jumplist select: <C-o>

Save current
normal: <C-s> ,
save_selection selection to
select: <C-s>
jumplist

normal: <C-w>l ,
<space>wl , <C-
w><C-l> , <C-
w><right> ,
<space>w<C-l> ,
Jump to right <space>w<right> ,
jump_view_right
split select: <C-w>l ,
<space>wl , <C-
w><C-l> , <C-
w><right> ,
<space>w<C-l> ,
<space>w<right>

normal: <C-w>h ,
<space>wh , <C-
w><C-h> , <C-
w><left> ,
<space>w<C-h> ,
<space>w<left> ,
jump_view_left Jump to left split
select: <C-w>h ,
<space>wh , <C-
w><C-h> , <C-
w><left> ,
<space>w<C-h> ,
<space>w<left>

jump_view_up Jump to split normal: <C-w>k ,


above <C-w><up> ,
<space>wk , <C-
w><C-k> ,
<space>w<up> ,
<space>w<C-k> ,
select: <C-w>k ,

63 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


<C-w><up> ,
<space>wk , <C-
w><C-k> ,
<space>w<up> ,
<space>w<C-k>

normal: <C-w>j ,
<space>wj , <C-
w><C-j> , <C-
w><down> ,
<space>w<C-j> ,
Jump to split <space>w<down> ,
jump_view_down
below select: <C-w>j ,
<space>wj , <C-
w><C-j> , <C-
w><down> ,
<space>w<C-j> ,
<space>w<down>

normal: <C-w>L ,
Swap with right <space>wL , select:
swap_view_right
split <C-w>L ,
<space>wL

normal: <C-w>H ,
Swap with left <space>wH , select:
swap_view_left
split <C-w>H ,
<space>wH

normal: <C-w>K ,
Swap with split <space>wK , select:
swap_view_up
above <C-w>K ,
<space>wK

normal: <C-w>J ,
Swap with split <space>wJ , select:
swap_view_down
below <C-w>J ,
<space>wJ

transpose_view Transpose splits normal: <C-w>t ,


<space>wt , <C-
w><C-t> ,
<space>w<C-t> ,
select: <C-w>t ,
<space>wt , <C-
w><C-t> ,

64 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


<space>w<C-t>

normal: <C-w>w ,
<space>ww , <C-
w><C-w> ,
Goto next <space>w<C-w> ,
rotate_view
window select: <C-w>w ,
<space>ww , <C-
w><C-w> ,
<space>w<C-w>

Goto previous
rotate_view_reverse
window

normal: <C-w>s ,
<space>ws , <C-
w><C-s> ,
Horizontal <space>w<C-s> ,
hsplit
bottom split select: <C-w>s ,
<space>ws , <C-
w><C-s> ,
<space>w<C-s>

normal: <C-w>ns ,
<space>wns , <C-
w>n<C-s> ,
Horizontal
<space>wn<C-s> ,
hsplit_new bottom split
select: <C-w>ns ,
scratch buffer
<space>wns , <C-
w>n<C-s> ,
<space>wn<C-s>

normal: <C-w>v ,
<space>wv , <C-
w><C-v> ,
Vertical right <space>w<C-v> ,
vsplit
split select: <C-w>v ,
<space>wv , <C-
w><C-v> ,
<space>w<C-v>

vsplit_new Vertical right normal: <C-w>nv ,


split scratch <space>wnv , <C-
buffer w>n<C-v> ,
<space>wn<C-v> ,
select: <C-w>nv ,

65 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


<space>wnv , <C-
w>n<C-v> ,
<space>wn<C-v>

normal: <C-w>q ,
<space>wq , <C-
w><C-q> ,
<space>w<C-q> ,
wclose Close window
select: <C-w>q ,
<space>wq , <C-
w><C-q> ,
<space>w<C-q>

normal: <C-w>o ,
<space>wo , <C-
w><C-o> ,
Close windows <space>w<C-o> ,
wonly
except current select: <C-w>o ,
<space>wo , <C-
w><C-o> ,
<space>w<C-o>

normal: " , select:


select_register Select register
"

insert_register Insert register insert: <C-r>

Align view normal: Zm , zm ,


align_view_middle
middle select: Zm , zm

normal: Zt , zt ,
align_view_top Align view top
select: Zt , zt

normal: Zc , Zz ,
Align view
align_view_center zc , zz , select:
center
Zc , Zz , zc , zz

Align view normal: Zb , zb ,


align_view_bottom
bottom select: Zb , zb

normal: Zk , zk ,
Z<up> , z<up> ,
scroll_up Scroll view up
select: Zk , zk ,
Z<up> , z<up>

scroll_down Scroll view down normal: Zj , zj ,


Z<down> ,

66 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


z<down> , select:
Zj , zj , Z<down> ,
z<down>

Goto matching normal: mm ,


match_brackets
bracket select: mm

normal: ms ,
surround_add Surround add
select: ms

Surround normal: mr ,
surround_replace
replace select: mr

normal: md ,
surround_delete Surround delete
select: md

Select around normal: ma ,


select_textobject_around
object select: ma

Select inside normal: mi ,


select_textobject_inner
object select: mi

Goto next normal: ]f ,


goto_next_function
function select: ]f

Goto previous normal: [f ,


goto_prev_function
function select: [f

Goto next type normal: ]t ,


goto_next_class
definition select: ]t

Goto previous normal: [t ,


goto_prev_class
type definition select: [t

Goto next normal: ]a ,


goto_next_parameter
parameter select: ]a

Goto previous normal: [a ,


goto_prev_parameter
parameter select: [a

Goto next normal: ]c ,


goto_next_comment
comment select: ]c

Goto previous normal: [c ,


goto_prev_comment
comment select: [c

normal: ]T ,
goto_next_test Goto next test
select: ]T

67 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

Goto previous normal: [T ,


goto_prev_test
test select: [T

Goto next normal: ]e ,


goto_next_entry
pairing select: ]e

Goto previous normal: [e ,


goto_prev_entry
pairing select: [e

Goto next normal: ]p ,


goto_next_paragraph
paragraph select: ]p

Goto previous normal: [p ,


goto_prev_paragraph
paragraph select: [p

normal:
Launch debug
dap_launch <space>Gl , select:
target
<space>Gl

Restart normal:
dap_restart debugging <space>Gr , select:
session <space>Gr

normal:
Toggle
dap_toggle_breakpoint <space>Gb , select:
breakpoint
<space>Gb

Continue normal:
dap_continue program <space>Gc , select:
execution <space>Gc

normal:
Pause program
dap_pause <space>Gh , select:
execution
<space>Gh

normal:
dap_step_in Step in <space>Gi , select:
<space>Gi

normal:
dap_step_out Step out <space>Go , select:
<space>Go

normal:
dap_next Step to next <space>Gn , select:
<space>Gn

68 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds

normal:
dap_variables List variables <space>Gv , select:
<space>Gv

normal:
End debug
dap_terminate <space>Gt , select:
session
<space>Gt

normal:
Edit breakpoint
<space>G<C-c> ,
dap_edit_condition condition on
select:
current line
<space>G<C-c>

normal:
Edit breakpoint
<space>G<C-l> ,
dap_edit_log log message on
select:
current line
<space>G<C-l>

normal:
Switch current <space>Gst ,
dap_switch_thread
thread select:
<space>Gst

normal:
Switch stack <space>Gsf ,
dap_switch_stack_frame
frame select:
<space>Gsf

Enable normal:
dap_enable_exceptions exception <space>Ge , select:
breakpoints <space>Ge

Disable normal:
dap_disable_exceptions exception <space>GE , select:
breakpoints <space>GE

Pipe selections
normal: | , select:
shell_pipe through shell
|
command

Pipe selections
into shell normal: <A-|> ,
shell_pipe_to
command select: <A-|>
ignoring output

shell_insert_output Insert shell normal: ! , select:


command !

69 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Name Description Default keybinds


output before
selections

Append shell
command normal: <A-!> ,
shell_append_output
output after select: <A-!>
selections

Filter selections
normal: $ , select:
shell_keep_pipe with shell
$
predicate

Suspend and normal: <C-z> ,


suspend
return to shell select: <C-z>

normal: <space>r ,
rename_symbol Rename symbol
select: <space>r

Increment item normal: <C-a> ,


increment
under cursor select: <C-a>

Decrement item normal: <C-x> ,


decrement
under cursor select: <C-x>

normal: Q , select:
record_macro Record macro
Q

normal: q , select:
replay_macro Replay macro
q

Open command normal: <space>? ,


command_palette
palette select: <space>?

Jump to a two-
goto_word normal: gw
character label

Extend to a two-
extend_to_word select: gw
character label

goto next
goto_next_tabstop snippet
placeholder

goto next
goto_prev_tabstop snippet
placeholder

70 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Language Support
The following languages and Language Servers are supported. To use Language Server
features, you must first configure the appropriate Language Server.

You can check the language support in your installed helix version with hx --health .

Also see the Language Configuration docs and the Adding Languages guide for more
language configuration information.

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

ada ✓ ✓ ada_language_server

adl ✓ ✓ ✓

agda ✓

amber ✓

astro ✓

awk ✓ ✓ awk-language-server

bash ✓ ✓ ✓ bash-language-server

bass ✓ bass

beancount ✓

bibtex ✓ texlab

bicep ✓ bicep-langserver

bitbake ✓ bitbake-language-server

blade ✓

blueprint ✓ blueprint-compiler

c ✓ ✓ ✓ clangd

c-sharp ✓ ✓ OmniSharp

haskell-language-server-
cabal
wrapper

cairo ✓ ✓ ✓ cairo-language-server

capnp ✓ ✓

71 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

cel ✓

circom ✓ circom-lsp

clojure ✓ clojure-lsp

cmake ✓ ✓ ✓ cmake-language-server

comment ✓

common-lisp ✓ ✓ cl-lsp

cpon ✓ ✓

cpp ✓ ✓ ✓ clangd

crystal ✓ ✓ crystalline

vscode-css-language-
css ✓ ✓
server

cue ✓ cuelsp

cylc ✓ ✓ ✓

d ✓ ✓ ✓ serve-d

dart ✓ ✓ ✓ dart

dbml ✓

devicetree ✓

dhall ✓ ✓ dhall-lsp-server

diff ✓

docker-compose-
docker-compose ✓ ✓ ✓ langserver , yaml-
language-server

dockerfile ✓ ✓ docker-langserver

dot ✓ dot-language-server

dtd ✓

dune ✓

72 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

earthfile ✓ ✓ ✓ earthlyls

edoc ✓

eex ✓

ejs ✓

elisp ✓

elixir ✓ ✓ ✓ elixir-ls

elm ✓ ✓ elm-language-server

elvish ✓ elvish

env ✓ ✓

erb ✓

erlang ✓ ✓ erlang_ls , elp

esdl ✓

fidl ✓

fish ✓ ✓ ✓

forth ✓ forth-lsp

fortran ✓ ✓ fortls

fsharp ✓ fsautocomplete

gas ✓ ✓

gdscript ✓ ✓ ✓

gemini ✓

gherkin ✓

git-attributes ✓

git-commit ✓ ✓

git-config ✓ ✓

git-ignore ✓

73 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

git-rebase ✓

typescript-language-
server , vscode-eslint-
gjs ✓ ✓ ✓
language-server , ember-
language-server

gleam ✓ ✓ gleam

glimmer ✓ ember-language-server

glsl ✓ ✓ ✓ glsl_analyzer

gn ✓

gopls , golangci-lint-
go ✓ ✓ ✓
langserver

godot-resource ✓ ✓

gomod ✓ gopls

gotmpl ✓ gopls

gowork ✓ gopls

gpr ✓ ada_language_server

graphql ✓ ✓ graphql-lsp

groovy ✓

typescript-language-
server , vscode-eslint-
gts ✓ ✓ ✓
language-server , ember-
language-server

hare ✓

haskell-language-server-
haskell ✓ ✓
wrapper

haskell-

persistent

hcl ✓ ✓ ✓ terraform-ls

heex ✓ ✓ elixir-ls

74 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

helm ✓ helm_ls

hocon ✓ ✓ ✓

hoon ✓

hosts ✓

vscode-html-language-
html ✓
server , superhtml

hurl ✓ ✓ ✓

hyprlang ✓ ✓ hyprls

idris idris2-lsp

iex ✓

ini ✓

inko ✓ ✓ ✓

janet ✓

java ✓ ✓ ✓ jdtls

typescript-language-
javascript ✓ ✓ ✓
server

jinja ✓

jjdescription ✓

jq ✓ ✓ jq-lsp

jsdoc ✓

vscode-json-language-
json ✓ ✓ ✓
server

json5 ✓

vscode-json-language-
jsonc ✓ ✓
server

jsonnet ✓ jsonnet-language-server

75 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

typescript-language-
jsx ✓ ✓ ✓
server

julia ✓ ✓ ✓ julia

just ✓ ✓ ✓

kdl ✓ ✓ ✓

koka ✓ ✓ koka

kotlin ✓ kotlin-language-server

koto ✓ ✓ ✓ koto-ls

latex ✓ ✓ texlab

ld ✓ ✓

ldif ✓

lean ✓ lean

ledger ✓

llvm ✓ ✓ ✓

llvm-mir ✓ ✓ ✓

llvm-mir-yaml ✓ ✓

log ✓

lpf ✓

lua ✓ ✓ ✓ lua-language-server

make ✓ ✓

markdoc ✓ markdoc-ls

markdown ✓ marksman , markdown-oxide

markdown.inline ✓

matlab ✓ ✓ ✓

mermaid ✓

meson ✓ ✓ mesonlsp

76 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

mint mint

mojo ✓ ✓ ✓ magic

move ✓

msbuild ✓ ✓

nasm ✓ ✓

nestedtext ✓ ✓ ✓

nginx ✓

nickel ✓ ✓ nls

nim ✓ ✓ ✓ nimlangserver

nix ✓ ✓ nil , nixd

nu ✓ nu

nunjucks ✓

ocaml ✓ ✓ ocamllsp

ocaml-interface ✓ ocamllsp

odin ✓ ✓ ✓ ols

ohm ✓ ✓ ✓

opencl ✓ ✓ ✓ clangd

openscad ✓ openscad-lsp

org ✓

pascal ✓ ✓ pasls

passwd ✓

pem ✓

perl ✓ ✓ ✓ perlnavigator

pest ✓ ✓ ✓ pest-language-server

php ✓ ✓ ✓ intelephense

77 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

php-only ✓

pkgbuild-language-server ,
pkgbuild ✓ ✓ ✓
bash-language-server

pkl ✓ ✓

po ✓ ✓

pod ✓

ponylang ✓ ✓ ✓

powershell ✓

prisma ✓ ✓ prisma-language-server

prolog swipl

protobuf ✓ ✓ ✓ bufls , pb

prql ✓

purescript-language-
purescript ✓ ✓
server

ruff , jedi-language-
python ✓ ✓ ✓
server , pylsp

qml ✓ ✓ qmlls

quint ✓ quint-language-server

r ✓ R

racket ✓ ✓ racket

regex ✓

rego ✓ regols

rescript ✓ ✓ rescript-language-server

rmarkdown ✓ ✓ R

robot ✓ robotframework_ls

ron ✓ ✓

78 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

rst ✓

ruby ✓ ✓ ✓ solargraph

rust ✓ ✓ ✓ rust-analyzer

sage ✓ ✓

scala ✓ ✓ ✓ metals

scheme ✓ ✓

vscode-css-language-
scss ✓
server

slint ✓ ✓ ✓ slint-lsp

smali ✓ ✓

smithy ✓ cs

sml ✓

snakemake ✓ ✓ pylsp

solidity ✓ ✓ solc

spade ✓ ✓ spade-language-server

spicedb ✓

sql ✓ ✓

sshclientconfig ✓

starlark ✓ ✓

strace ✓

supercollider ✓

svelte ✓ ✓ svelteserver

sway ✓ ✓ ✓ forc

swift ✓ ✓ sourcekit-lsp

t32 ✓

tablegen ✓ ✓ ✓

79 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

tact ✓ ✓ ✓

task ✓

tcl ✓ ✓

teal ✓

templ ✓ templ

textproto ✓ ✓ ✓

tfvars ✓ ✓ terraform-ls

thrift ✓

todotxt ✓

toml ✓ ✓ taplo

tsq ✓ ts_query_ls

typescript-language-
tsx ✓ ✓ ✓
server

twig ✓

typescript-language-
typescript ✓ ✓ ✓
server

typespec ✓ ✓ ✓ tsp-server

typst ✓ tinymist , typst-lsp

ungrammar ✓

unison ✓ ✓ ✓

uxntal ✓

v ✓ ✓ ✓ v-analyzer

vala ✓ ✓ vala-language-server

vento ✓

verilog ✓ ✓ svlangserver

vhdl ✓ vhdl_ls

80 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Syntax Treesitter Auto


Language Default language servers
Highlighting Textobjects Indent

vhs ✓

vue ✓ vue-language-server

wast ✓

wat ✓

webc ✓

wgsl ✓ wgsl_analyzer

wit ✓ ✓

wren ✓ ✓ ✓

xit ✓

xml ✓ ✓

xtc ✓

yaml-language-server ,
yaml ✓ ✓ ✓
ansible-language-server

yuck ✓

zig ✓ ✓ ✓ zls

81 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Migrating from Vim


Helix's editing model is strongly inspired from Vim and Kakoune, and a notable
difference from Vim (and the most striking similarity to Kakoune) is that Helix follows the
selection → action model. This means that whatever you are going to act on (a word,
a paragraph, a line, etc.) is selected first and the action itself (delete, change, yank, etc.)
comes second. A cursor is simply a single width selection.

See also Kakoune's Migrating from Vim and Helix's Migrating from Vim.

TODO: Mention textobjects, surround, registers

82 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Configuration
To override global configuration parameters, create a config.toml file located in your
config directory:

▪ Linux and Mac: ~/.config/helix/config.toml


▪ Windows: %AppData%\helix\config.toml

You can easily open the config file by typing :config-open within Helix normal
mode.

Example config:

theme = "onedark"

[editor]
line-number = "relative"
mouse = false

[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "underline"

[editor.file-picker]
hidden = false

You can use a custom configuration file by specifying it with the -c or --config
command line argument, for example hx -c path/to/custom-config.toml . You can
reload the config file by issuing the :config-reload command. Alternatively, on Unix
operating systems, you can reload it by sending the USR1 signal to the Helix process,
such as by using the command pkill -USR1 hx .

Finally, you can have a config.toml local to a project by putting it under a .helix
directory in your repository. Its settings will be merged with the configuration directory
config.toml and the built-in configuration.

83 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Editor
▪ [editor] Section
▪ [editor.statusline] Section
▪ [editor.lsp] Section
▪ [editor.cursor-shape] Section
▪ [editor.file-picker] Section
▪ [editor.auto-pairs] Section
▪ [editor.search] Section
▪ [editor.whitespace] Section
▪ [editor.indent-guides] Section
▪ [editor.gutters] Section
▪ [editor.gutters.line-numbers] Section
▪ [editor.gutters.diagnostics] Section
▪ [editor.gutters.diff] Section
▪ [editor.gutters.spacer] Section
▪ [editor.soft-wrap] Section
▪ [editor.smart-tab] Section
▪ [editor.inline-diagnostics] Section

[editor] Section

Key Description Default

Number of lines of padding


scrolloff around the edge of the screen 5
when scrolling

mouse Enable mouse mode true

default- Default register used for yank/


"
yank-register paste

middle-
Middle click paste support true
click-paste

Number of lines to scroll per


scroll-lines 3
scroll wheel step

Shell to use when running Unix: ["sh", "-c"]


shell
external commands Windows: ["cmd", "/C"]

84 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

Line number display: absolute


simply shows each line's number,
while relative shows the
line-number distance from the current line. absolute
When unfocused or in insert
mode, relative will still show
absolute line numbers

cursorline Highlight all lines with a cursor false

Highlight all columns with a


cursorcolumn false
cursor

if helix should automatically add


continue- a line comment token if you
true
comments create a new line inside a
comment.

Gutters to display: Available are


diagnostics and diff and
line-numbers and spacer ,
["diagnostics", "spacer",
note that diagnostics also
gutters "line-numbers", "spacer",
includes other features like
"diff"]
breakpoints, 1-width padding
will be inserted if gutters is non-
empty

auto- Enable automatic pop up of


true
completion auto-completion

Enable filepath completion.


Show files and directories if an
existing path at the cursor was
path- recognized, either absolute or
true
completion relative to the current opened
document or current working
directory (if the buffer is not yet
saved). Defaults to true.

Enable automatic formatting on


auto-format true
save

Time in milliseconds since last


idle-timeout keypress before idle timers 250
trigger.

85 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

Time in milliseconds after typing


completion- a word character before
250
timeout completions are shown, set to 5
for instant.

preview-
Whether to apply completion
completion- true
item instantly when selected
insert

completion- The min-length of word under


2
trigger-len cursor to trigger autocompletion

Set to true to make


completion- completions always replace the
false
replace entire word and not just the part
before the cursor

auto-info Whether to display info boxes true

Set to true to override


automatic detection of terminal
true-color false
truecolor support in the event of
a false negative

Set to true to override


automatic detection of terminal
undercurl false
undercurl support in the event of
a false negative

List of column positions at which


to display the rulers. Can be
rulers []
overridden by language specific
rulers in languages.toml file

Renders a line at the top of the


editor displaying open buffers.
bufferline Can be always , never or never
multiple (only shown if more
than one buffer is in use)

Whether to color the mode


color-modes indicator with different colors false
depending on the mode itself

text-width Maximum line length. Used for 80


the :reflow command and soft-
wrapping if soft-wrap.wrap-

86 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default


at-text-width is set

Directories relative to the


workspace- workspace root that are treated
[]
lsp-roots as LSP roots. Should only be set
in .helix/config.toml

The line ending to use for new


documents. Can be native , lf ,
default- crlf , ff , cr or nel . native
native
line-ending uses the platform's native line
ending ( crlf on Windows,
otherwise lf ).

Whether to automatically insert


insert-
a trailing line-ending on write if true
final-newline
missing

Draw border around popup ,


popup-border none
menu , all , or none

How the indentation for a newly


inserted line is computed:
simple just copies the
indentation level from the
previous line, tree-sitter
computes the indentation based
indent-
on the syntax tree and hybrid hybrid
heuristic
combines both approaches. If
the chosen heuristic is not
available, a different one will be
used as a fallback (the fallback
order being hybrid -> tree-
sitter -> simple ).

The characters that are used to


jump-label- generate two character jump
"abcdefghijklmnopqrstuvwxyz"
alphabet labels. Characters at the start of
the alphabet are used first.

Minimum severity of diagnostics


to render at the end of the line.
end-of-line- Set to disable to disable
"disable"
diagnostics entirely. Refer to the setting
about inline-diagnostics for
more details

87 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

Which API to use for clipboard


interaction. One of pasteboard
(MacOS), wayland , x-clip , x-
clipboard- Platform and environment
sel , win-32-yank , termux ,
provider specific.
tmux , windows , termcode ,
none , or a custom command
set.

[editor.clipboard-provider] Section
Helix can be configured either to use a builtin clipboard configuration or to use a
provided command.

For instance, setting it to use OSC 52 termcodes, the configuration would be:

[editor]
clipboard-provider = "termcode"

Alternatively, Helix can be configured to use arbitary commands for clipboard


integration:

[editor.clipboard-provider.custom]
yank = { command = "cat", args = ["test.txt"] }
paste = { command = "tee", args = ["test.txt"] }
primary-yank = { command = "cat", args = ["test-primary.txt"] } # optional
primary-paste = { command = "tee", args = ["test-primary.txt"] } # optional

For custom commands the contents of the yank/paste is communicated over stdin/
stdout.

[editor.statusline] Section
Allows configuring the statusline at the bottom of the editor.

The configuration distinguishes between three areas of the status line:

[ ... ... LEFT ... ... | ... ... ... CENTER ... ... ... | ... ... RIGHT ...
... ]

Statusline elements can be defined as follows:

88 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[editor.statusline]
left = ["mode", "spinner"]
center = ["file-name"]
right = ["diagnostics", "selections", "position", "file-encoding", "file-
line-ending", "file-type"]
separator = "│"
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"

The [editor.statusline] key takes the following sub-keys:

Key Description Default

A list of elements aligned ["mode", "spinner", "file-name",


left to the left of the "read-only-indicator", "file-
statusline modification-indicator"]

A list of elements aligned


center to the middle of the []
statusline

A list of elements aligned ["diagnostics", "selections",


right to the right of the "register", "position", "file-
statusline encoding"]

The character used to


separator separate elements in the "│"
statusline

The text shown in the


mode.normal mode element for normal "NOR"
mode

The text shown in the


mode.insert mode element for insert "INS"
mode

The text shown in the


mode.select mode element for select "SEL"
mode

The following statusline elements can be configured:

Key Description

The current editor mode ( mode.normal / mode.insert /


mode
mode.select )

89 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description

spinner A progress spinner indicating LSP activity

file-name The path/name of the opened file

file-absolute-path The absolute path/name of the opened file

file-base-name The basename of the opened file

file-modification- The indicator to show whether the file is modified (a [+]


indicator appears when there are unsaved changes)

file-encoding The encoding of the opened file if it differs from UTF-8

file-line-ending The file line endings (CRLF or LF)

read-only- An indicator that shows [readonly] when a file cannot be


indicator written

total-line-numbers The total line numbers of the opened file

file-type The type of the opened file

diagnostics The number of warnings and/or errors

workspace-
The number of warnings and/or errors on workspace
diagnostics

selections The number of active selections

primary-selection-
The number of characters currently in primary selection
length

position The cursor position

position- The cursor position as a percentage of the total number of


percentage lines

The string defined in editor.statusline.separator (defaults


separator
to "│" )

Inserts a space between elements (multiple/contiguous


spacer
spacers may be specified)

The current branch name or detached commit hash of the


version-control
opened workspace

register The current selected register

90 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[editor.lsp] Section

Key Description Default

Enables LSP integration. Setting to false will


enable completely disable language servers regardless of true
language settings.

display-messages Display LSP progress messages below statusline1 false

Enable automatic popup of signature help


auto-signature-help true
(parameter hints)

display-inlay-hints Display inlay hints2 false

display-signature-
Display docs under signature help popup true
help-docs

Enables snippet completions. Requires a server


snippets restart ( :lsp-restart ) to take effect after true
:config-reload / :set .

goto-reference-
Include declaration in the goto references popup. true
include-declaration

1 By default, a progress spinner is shown in the statusline beside the file path.
2 You may also have to activate them in the language server config for them to appear, not just in
Helix. Inlay hints in Helix are still being improved on and may be a little bit laggy/janky under some
circumstances. Please report any bugs you see so we can fix them!

[editor.cursor-shape] Section
Defines the shape of cursor in each mode. Valid values for these options are block ,
bar , underline , or hidden .

Due to limitations of the terminal environment, only the primary cursor can
change shape.

Key Description Default

normal Cursor shape in normal mode block

insert Cursor shape in insert mode block

91 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

select Cursor shape in select mode block

[editor.file-picker] Section
Set options for file picker and global search. Ignoring a file means it is not visible in the
Helix file picker and global search.

All git related options are only enabled in a git repository.

Key Description Default

hidden Enables ignoring hidden files true

follow-
Follow symlinks instead of ignoring them true
symlinks

deduplicate- Ignore symlinks that point at files already shown in the


true
links picker

parents Enables reading ignore files from parent directories true

ignore Enables reading .ignore files true

git-ignore Enables reading .gitignore files true

Enables reading global .gitignore , whose path is


git-global true
specified in git's config: core.excludesfile option

git-exclude Enables reading .git/info/exclude files true

Set with an integer value for maximum depth to Unset by


max-depth
recurse default

Ignore files can be placed locally as .ignore or put in your home directory as
~/.ignore . They support the usual ignore and negative ignore (unignore) rules used in
.gitignore files.

Additionally, you can use Helix-specific ignore files by creating a local .helix/ignore file
in the current workspace or a global ignore file located in your Helix config directory:

▪ Linux and Mac: ~/.config/helix/ignore


▪ Windows: %AppData%\helix\ignore

Example:

92 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

# unignore in file picker and global search


!.github/
!.gitignore
!.gitattributes

[editor.auto-pairs] Section
Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a simple
boolean value, or a specific mapping of pairs of single characters.

To disable auto-pairs altogether, set auto-pairs to false :

[editor]
auto-pairs = false # defaults to `true`

The default pairs are (){}[]''""`` , but these can be customized by setting auto-
pairs to a TOML table:

[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'

Additionally, this setting can be used in a language config. Unless the editor setting is
false , this will override the editor config in documents with this language.

Example languages.toml that adds <> and removes ''

[[language]]
name = "rust"

[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'

[editor.auto-save] Section
Control auto save behavior.

93 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

Enable automatic saving on the focus moving away from


focus-lost false
Helix. Requires focus event support from your terminal

after- Enable automatic saving after auto-save.after-


false
delay.enable delay.timeout milliseconds have passed since last edit.

after- Time in milliseconds since last edit before auto save


3000
delay.timeout timer triggers.

[editor.search] Section
Search specific options.

Key Description Default

smart- Enable smart case regex searching (case-insensitive unless


true
case pattern contains upper case characters)

wrap-
Whether the search should wrap after depleting the matches true
around

[editor.whitespace] Section
Options for rendering whitespace with visible characters. Use :set whitespace.render
all to temporarily enable visible whitespace.

Key Description Default

Whether to render whitespace. May either be all or


render none , or a table with sub-keys space , nbsp , nnbsp , none
tab , and newline

Literal characters to use when rendering whitespace.


See example
characters Sub-keys may be any of tab , space , nbsp , nnbsp ,
below
newline or tabpad

Example

94 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[editor.whitespace]
render = "all"
# or control each character
[editor.whitespace.render]
space = "all"
tab = "all"
nbsp = "none"
nnbsp = "none"
newline = "none"

[editor.whitespace.characters]
space = "·"
nbsp = "⍽"
nnbsp = "␣"
tab = "→"
newline = "⏎"
tabpad = "·" # Tabs will look like "→···" (depending on tab width)

[editor.indent-guides] Section
Options for rendering vertical indent guides.

Key Description Default

render Whether to render indent guides false

character Literal character to use for rendering the indent guide │

skip-levels Number of indent levels to skip 0

Example:

[editor.indent-guides]
render = true
character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽"
skip-levels = 1

[editor.gutters] Section
For simplicity, editor.gutters accepts an array of gutter types, which will use default
settings for all gutter components.

[editor]
gutters = ["diff", "diagnostics", "line-numbers", "spacer"]

To customize the behavior of gutters, the [editor.gutters] section must be used. This

95 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

section contains top level settings, as well as settings for specific gutter components as
subsections.

Key Description Default

A vector of gutters to ["diagnostics", "spacer", "line-numbers",


layout
display "spacer", "diff"]

Example:

[editor.gutters]
layout = ["diff", "diagnostics", "line-numbers", "spacer"]

[editor.gutters.line-numbers] Section

Options for the line number gutter

Key Description Default

min-width The minimum number of characters to use 3

Example:

[editor.gutters.line-numbers]
min-width = 1

[editor.gutters.diagnostics] Section

Currently unused

[editor.gutters.diff] Section

The diff gutter option displays colored bars indicating whether a git diff represents
that a line was added, removed or changed. These colors are controlled by the theme
attributes diff.plus , diff.minus and diff.delta .

Other diff providers will eventually be supported by a future plugin system.

There are currently no options for this section.

[editor.gutters.spacer] Section

Currently unused

96 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[editor.soft-wrap] Section
Options for soft wrapping lines that exceed the view width:

Key Description Default

enable Whether soft wrapping is enabled. false

max-wrap Maximum free space left at the end of the line. 20

max-indent- Maximum indentation to carry over when soft wrapping


40
retain a line.

Text inserted before soft wrapped lines, highlighted with


wrap-indicator ↪
ui.virtual.wrap

wrap-at-text- Soft wrap at text-width instead of using the full


false
width viewport size.

Example:

[editor.soft-wrap]
enable = true
max-wrap = 25 # increase value to reduce forced mid-word wrapping
max-indent-retain = 0
wrap-indicator = "" # set wrap-indicator to "" to hide it

[editor.smart-tab] Section
Options for navigating and editing using tab key.

Key Description Default

If set to true, then when the cursor is in a position with non-


whitespace to its left, instead of inserting a tab, it will run
enable move_parent_node_end . If there is only whitespace to the left, true
then it inserts a tab as normal. With the default bindings, to
explicitly insert a tab character, press Shift-tab.

supersede Normally, when a menu is on screen, such as when auto false


-menu complete is triggered, the tab key is bound to cycling through
the items. This means when menus are on screen, one cannot
use the tab key to trigger the smart-tab command. If this
option is set to true, the smart-tab command always takes
precedence, which means one cannot use the tab key to cycle
through menu items. One of the other bindings must be used

97 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default


instead, such as arrow keys or C-n / C-p .

Due to lack of support for S-tab in some terminals, the default keybindings don't fully
embrace smart-tab editing experience. If you enjoy smart-tab navigation and a terminal
that supports the Enhanced Keyboard protocol, consider setting extra keybindings:

[keys.normal]
tab = "move_parent_node_end"
S-tab = "move_parent_node_start"

[keys.insert]
S-tab = "move_parent_node_start"

[keys.select]
tab = "extend_parent_node_end"
S-tab = "extend_parent_node_start"

[editor.inline-diagnostics] Section
Options for rendering diagnostics inside the text like shown below

fn main() {
let foo = bar;
└─ no such value in this scope
}

Key Description Default

The minimum severity that a diagnostic must have to be


shown inline on the line that contains the primary cursor.
Set to disable to not show any diagnostics inline. This
cursor-line "disable"
option does not have any effect when in insert-mode and
will only take effect 350ms after moving the cursor to a
different line.

The minimum severity that a diagnostic must have to be


other-lines shown inline on a line that does not contain the cursor- "disable"
line. Set to disable to not show any diagnostics inline.

How many horizontal bars ─ are rendered before the


prefix-len 1
diagnostic text.

Equivalent of the editor.soft-wrap.max-wrap option for


max-wrap 20
diagnostics.

98 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description Default

max- Maximum number of diagnostics to render inline for a


10
diagnostics given line

The allowed values for cursor-line and other-lines are: error , warning , info ,
hint .

The (first) diagnostic with the highest severity that is not shown inline is rendered at the
end of the line (as long as its severity is higher than the end-of-line-diagnostics
config option):

fn main() {
let baz = 1;
let foo = bar; a local variable with a similar name exists: baz
└─ no such value in this scope
}

The new diagnostic rendering is not yet enabled by default. As soon as end of line or
inline diagnostics are enabled the old diagnostics rendering is automatically disabled.
The recommended default setting are:

[editor]
end-of-line-diagnostics = "hint"
[editor.inline-diagnostics]
cursor-line = "warning" # show warnings and errors on the cursorline inline

99 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Themes
To use a theme add theme = "<name>" to the top of your config.toml file, or select it
during runtime using :theme <name> .

Creating a theme
Create a file with the name of your theme as the file name (i.e mytheme.toml ) and place
it in your themes directory (i.e ~/.config/helix/themes or %AppData%\helix\themes
on Windows). The directory might have to be created beforehand.

The names "default" and "base16_default" are reserved for built-in themes and
cannot be overridden by user-defined themes.

Overview
Each line in the theme file is specified as below:

key = { fg = "#ffffff", bg = "#000000", underline = { color = "#ff0000",


style = "curl"}, modifiers = ["bold", "italic"] }

Where key represents what you want to style, fg specifies the foreground color, bg
the background color, underline the underline style / color , and modifiers is a list
of style modifiers. bg , underline and modifiers can be omitted to defer to the
defaults.

To specify only the foreground color:

key = "#ffffff"

If the key contains a dot '.' , it must be quoted to prevent it being parsed as a dotted
key.

"key.key" = "#ffffff"

For inspiration, you can find the default theme.toml here and user-submitted themes
here.

The details of theme creation


100 of 136 1/7/25, 21:39
Firefox https://docs.helix-editor.com/print.html

Color palettes
It's recommended to define a palette of named colors, and refer to them in the
configuration values in your theme. To do this, add a table called palette to your theme
file:

"ui.background" = "white"
"ui.text" = "black"

[palette]
white = "#ffffff"
black = "#000000"

Keep in mind that the [palette] table includes all keys after its header, so it should be
defined after the normal theme options.

The default palette uses the terminal's default 16 colors, and the colors names are listed
below. The [palette] section in the config file takes precedence over it and is merged
into the default palette.

Color Name

default

black

red

green

yellow

blue

magenta

cyan

gray

light-red

light-green

light-yellow

light-blue

light-magenta

101 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Color Name

light-cyan

light-gray

white

Modifiers
The following values may be used as modifier, provided they are supported by your
terminal emulator.

Modifier

bold

dim

italic

underlined

slow_blink

rapid_blink

reversed

hidden

crossed_out

The underlined modifier is deprecated and only available for backwards


compatibility. Its behavior is equivalent to setting underline.style="line" .

Underline style
One of the following values may be used as a value for underline.style , providing it is
supported by your terminal emulator.

Modifier

line

102 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Modifier

curl

dashed

dotted

double_line

Inheritance
Extend other themes by setting the inherits property to an existing theme.

inherits = "boo_berry"

# Override the theming for "keyword"s:


"keyword" = { fg = "gold" }

# Override colors in the palette:


[palette]
berry = "#2A2A4D"

Scopes
The following is a list of scopes available to use for styling:

Syntax highlighting

These keys match tree-sitter scopes.

When determining styling for a highlight, the longest matching theme key will be used.
For example, if the highlight is function.builtin.static , the key function.builtin
will be used instead of function .

We use a similar set of scopes as Sublime Text. See also TextMate scopes.

▪ attribute - Class attributes, HTML tag attributes

▪ type - Types

▪ builtin - Primitive types provided by the language ( int , usize )


▪ parameter - Generic type parameters ( T )
▪ enum
▪ variant

103 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

▪ constructor

▪ constant (TODO: constant.other.placeholder for %v )

▪ builtin Special constants provided by the language ( true , false , nil etc)
▪ boolean
▪ character
▪ escape
▪ numeric (numbers)
▪ integer
▪ float
▪ string (TODO: string.quoted.{single, double}, string.raw/.unquoted)?

▪ regexp - Regular expressions


▪ special
▪ path
▪ url
▪ symbol - Erlang/Elixir atoms, Ruby symbols, Clojure keywords
▪ comment - Code comments

▪ line - Single line comments ( // )


▪ block - Block comments (e.g. ( /* */ )
▪ documentation - Documentation comments (e.g. /// in Rust)
▪ variable - Variables

▪ builtin - Reserved language variables ( self , this , super , etc.)


▪ parameter - Function parameters
▪ other
▪ member - Fields of composite data types (e.g. structs, unions)
▪ private - Private fields that use a unique syntax (currently just
ECMAScript-based languages)
▪ label

▪ punctuation

▪ delimiter - Commas, colons


▪ bracket - Parentheses, angle brackets, etc.
▪ special - String interpolation brackets.
▪ keyword

▪ control
▪ conditional - if , else
▪ repeat - for , while , loop
▪ import - import , export

104 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

▪ return
▪ exception
▪ operator - or , in
▪ directive - Preprocessor directives ( #if in C)
▪ function - fn , func
▪ storage - Keywords describing how things are stored
▪ type - The type of something, class , function , var , let , etc.
▪ modifier - Storage modifiers like static , mut , const , ref , etc.
▪ operator - || , += , >

▪ function

▪ builtin
▪ method
▪ private - Private methods that use a unique syntax (currently just
ECMAScript-based languages)
▪ macro
▪ special (preprocessor in C)
▪ tag - Tags (e.g. <body> in HTML)

▪ builtin
▪ namespace

▪ special

▪ markup

▪ heading
▪ marker
▪ 1 , 2 , 3 , 4 , 5 , 6 - heading text for h1 through h6
▪ list
▪ unnumbered
▪ numbered
▪ checked
▪ unchecked
▪ bold
▪ italic
▪ strikethrough
▪ link
▪ url - URLs pointed to by links
▪ label - non-URL link references
▪ text - URL and image descriptions in links

105 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

▪ quote
▪ raw
▪ inline
▪ block
▪ diff - version control changes

▪ plus - additions
▪ gutter - gutter indicator
▪ minus - deletions
▪ gutter - gutter indicator
▪ delta - modifications
▪ moved - renamed or moved files/changes
▪ conflict - merge conflicts
▪ gutter - gutter indicator

Interface

These scopes are used for theming the editor interface:

▪ markup
▪ normal
▪ completion - for completion doc popup UI
▪ hover - for hover popup UI
▪ heading
▪ completion - for completion doc popup UI
▪ hover - for hover popup UI
▪ raw
▪ inline
▪ completion - for completion doc popup UI
▪ hover - for hover popup UI

Key Notes

ui.background

ui.background.separator Picker separator below input line

ui.cursor

ui.cursor.normal

ui.cursor.insert

106 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Notes

ui.cursor.select

ui.cursor.match Matching bracket etc.

ui.cursor.primary Cursor with primary selection

ui.cursor.primary.normal

ui.cursor.primary.insert

ui.cursor.primary.select

ui.debug.breakpoint Breakpoint indicator, found in the gutter

Indicator for the line at which debugging


ui.debug.active
execution is paused at, found in the gutter

ui.gutter Gutter

ui.gutter.selected Gutter for the line the cursor is on

ui.linenr Line numbers

ui.linenr.selected Line number for the line the cursor is on

ui.statusline Statusline

ui.statusline.inactive Statusline (unfocused document)

Statusline mode during normal mode (only if


ui.statusline.normal
editor.color-modes is enabled)

Statusline mode during insert mode (only if


ui.statusline.insert
editor.color-modes is enabled)

Statusline mode during select mode (only if


ui.statusline.select
editor.color-modes is enabled)

ui.statusline.separator Separator character in statusline

ui.bufferline Style for the buffer line

ui.bufferline.active Style for the active buffer in buffer line

ui.bufferline.background Style for bufferline background

ui.popup Documentation popups (e.g. Space + k)

ui.popup.info Prompt for multiple key options

107 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Notes

ui.picker.header Header row area in pickers with multiple columns

ui.picker.header.column Column names in pickers with multiple columns

The column name in pickers with multiple


ui.picker.header.column.active
columns where the cursor is entering into.

ui.window Borderlines separating splits

ui.help Description box for commands

Default text style, command prompts, popup


ui.text
text, etc.

ui.text.focus The currently selected line in the picker

Same as ui.text but when the text is inactive


ui.text.inactive
(e.g. suggestions)

ui.text.info The key: command text in ui.popup.info boxes

ui.text.directory Directory names in prompt completion

ui.virtual.ruler Ruler columns (see the editor.rulers config)

ui.virtual.whitespace Visible whitespace characters

ui.virtual.indent-guide Vertical indent width guides

ui.virtual.inlay-hint Default style for inlay hints of all kinds

ui.virtual.inlay- Style for inlay hints of kind parameter (language


hint.parameter servers are not required to set a kind)

Style for inlay hints of kind type (language


ui.virtual.inlay-hint.type
servers are not required to set a kind)

Soft-wrap indicator (see the editor.soft-wrap


ui.virtual.wrap
config)

ui.virtual.jump-label Style for virtual jump labels

ui.menu Code and command completion menus

ui.menu.selected Selected autocomplete item

fg sets thumb color, bg sets track color of


ui.menu.scroll
scrollbar

ui.selection For selections in the editing area

108 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Notes

ui.selection.primary

ui.highlight Highlighted lines in the picker preview

ui.highlight.frameline Line at which debugging execution is paused at

The line of the primary cursor (if cursorline is


ui.cursorline.primary
enabled)

The lines of any other cursors (if cursorline is


ui.cursorline.secondary
enabled)

The column of the primary cursor (if


ui.cursorcolumn.primary
cursorcolumn is enabled)

The columns of any other cursors (if


ui.cursorcolumn.secondary
cursorcolumn is enabled)

warning Diagnostics warning (gutter)

error Diagnostics error (gutter)

info Diagnostics info (gutter)

hint Diagnostics hint (gutter)

diagnostic Diagnostics fallback style (editing area)

diagnostic.hint Diagnostics hint (editing area)

diagnostic.info Diagnostics info (editing area)

diagnostic.warning Diagnostics warning (editing area)

diagnostic.error Diagnostics error (editing area)

diagnostic.unnecessary Diagnostics with unnecessary tag (editing area)

diagnostic.deprecated Diagnostics with deprecated tag (editing area)

109 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key remapping
Helix currently supports one-way key remapping through a simple TOML configuration
file. (More powerful solutions such as rebinding via commands will be available in the
future).

There are three kinds of commands that can be used in keymaps:

▪ Static commands: commands like move_char_right which are usually bound to


keys and used for movement and editing. A list of static commands is available in
the Keymap documentation and in the source code in helix-term/src/
commands.rs at the invocation of static_commands! macro.
▪ Typable commands: commands that can be executed from command mode ( : ),
for example :write! . See the Commands documentation for a list of available
typeable commands or the TypableCommandList declaration in the source code at
helix-term/src/commands/typed.rs .
▪ Macros: sequences of keys that are executed in order. These keybindings start with
@ and then list any number of keys to be executed. For example @miw can be used
to select the surrounding word. For now, macro keybindings are not allowed in
keybinding sequences due to limitations in the way that command sequences are
executed. Modifier keys (e.g. Alt+o) can be used like "<A-o>" , e.g. "@miw<A-o>"

To remap keys, create a config.toml file in your helix configuration directory (default
~/.config/helix on Linux systems) with a structure like this:

To set a modifier + key as a keymap, type A-X = ... or C-X = ... for Alt + X or
Ctrl + X. Combine with Shift using a dash, e.g. C-S-esc . Within macros, wrap them
in <> , e.g. <A-X> and <C-X> to distinguish from the A or C keys.

110 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

# At most one section each of 'keys.normal', 'keys.insert' and 'keys.select'


[keys.normal]
C-s = ":w" # Maps Ctrl-s to the typable command :w which is an alias for
:write (save file)
C-o = ":open ~/.config/helix/config.toml" # Maps Ctrl-o to opening of the
helix config file
a = "move_char_left" # Maps the 'a' key to the move_char_left command
w = "move_line_up" # Maps the 'w' key move_line_up
"C-S-esc" = "extend_line" # Maps Ctrl-Shift-Escape to extend_line
g = { a = "code_action" } # Maps `ga` to show possible code actions
"ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below
then re-enter normal mode
"A-x" = "@x<A-d>" # Maps Alt-x to a macro selecting the whole line and
deleting it without yanking it

[keys.insert]
"A-x" = "normal_mode" # Maps Alt-X to enter normal mode
j = { k = "normal_mode" } # Maps `jk` to exit insert mode

Minor modes
Minor modes are accessed by pressing a key (usually from normal mode), giving access
to dedicated bindings. Bindings can be modified or added by nesting definitions.

[keys.insert.j]
k = "normal_mode" # Maps `jk` to exit insert mode

[keys.normal.g]
a = "code_action" # Maps `ga` to show possible code actions

# invert `j` and `k` in view mode


[keys.normal.z]
j = "scroll_up"
k = "scroll_down"

# create a new minor mode bound to `+`


[keys.normal."+"]
m = ":run-shell-command make"
c = ":run-shell-command cargo build"
t = ":run-shell-command cargo test"

Special keys and modifiers


Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes C- , S- and A- .

The Super key - the Windows/Linux key or the Command key on Mac keyboards - is also
supported when using a terminal emulator that supports the enhanced keyboard

111 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

protocol. The super key is encoded with prefixes Meta- , Cmd- or Win- . These are all
synonyms for the super modifier - binding a key with a Win- modifier will mean it can
be used with the Windows/Linux key or the Command key.

[keys.normal]
C-s = ":write" # Ctrl and 's' to write
Cmd-s = ":write" # Cmd or Win or Meta and 's' to write

Special keys are encoded as follows:

Key name Representation

Backspace "backspace"

Space "space"

Return/Enter "ret"

Left "left"

Right "right"

Up "up"

Down "down"

Home "home"

End "end"

Page Up "pageup"

Page Down "pagedown"

Tab "tab"

Delete "del"

Insert "ins"

Null "null"

Escape "esc"

Keys can be disabled by binding them to the no_op command.

All other keys such as ? , ! , - etc. can be used literally:

112 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[keys.normal]
"?" = ":write"
"!" = ":write"
"-" = ":write"

Note: - can't be used when combined with a modifier, for example Alt + - should be
written as A-minus . A-- is not accepted.

113 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Languages
Language-specific settings and settings for language servers are configured in
languages.toml files.

languages.toml files
There are three possible locations for a languages.toml file:

1. In the Helix source code, which lives in the Helix repository. It provides the default
configurations for languages and language servers.
2. In your configuration directory. This overrides values from the built-in language
configuration. For example, to disable auto-formatting for Rust:

# in <config_dir>/helix/languages.toml

[language-server.mylang-lsp]
command = "mylang-lsp"

[[language]]
name = "rust"
auto-format = false

3. In a .helix folder in your project. Language configuration may also be overridden


local to a project by creating a languages.toml file in a .helix folder. Its settings
will be merged with the language configuration in the configuration directory and
the built-in configuration.

Language configuration
Each language is configured by adding a [[language]] section to a languages.toml
file. For example:

114 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[[language]]
name = "mylang"
scope = "source.mylang"
injection-regex = "mylang"
file-types = ["mylang", "myl"]
comment-tokens = "#"
indent = { tab-width = 2, unit = " " }
formatter = { command = "mylang-formatter" , args = ["--stdin"] }
language-servers = [ "mylang-lsp" ]

These configuration keys are available:

Key Description

name The name of the language

The language-id for language servers, checkout the table at


language-id
TextDocumentItem for the right id

A string like source.js that identifies the language. Currently, we


strive to match the scope names used by popular TextMate
scope
grammars and by the Linguist library. Usually source.<name> or
text.<name> in case of markup languages

regex pattern that will be tested against a language name in order


injection-
to determine whether this language should be used for a potential
regex
language injection site.

The filetypes of the language, for example ["yml", "yaml"] . See


file-types
the file-type detection section below.

The interpreters from the shebang line, for example ["sh",


shebangs
"bash"]

A set of marker files to look for when trying to find the workspace
roots
root. For example Cargo.lock , yarn.lock

auto-format Whether to autoformat this language when saving

diagnostic- Minimal severity of diagnostic for it to be displayed. (Allowed


severity values: error , warning , info , hint )

The tokens to use as a comment token, either a single token "//"


or an array ["//", "///", "//!"] (the first token will be used for
comment-tokens
commenting). Also configurable as comment-token for backwards
compatibility

block-comment- The start and end tokens for a multiline comment either an array
tokens or single table of { start = "/*", end = "*/"} . The first set of
tokens will be used for commenting, any pairs in the array can be

115 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description
uncommented

The indent to use. Has sub keys unit (the text inserted into the
indent document when indenting; usually set to N spaces or "\t" for
tabs) and tab-width (the number of spaces rendered for a tab)

The Language Servers used for this language. See below for more
language-
information in the section Configuring Language Servers for a
servers
language

grammar The tree-sitter grammar to use (defaults to the value of name )

The formatter for the language, it will take precedence over the lsp
formatter when defined. The formatter must be able to take the original file
as input from stdin and write the formatted file to stdout

soft-wrap editor.softwrap

Maximum line length. Used for the :reflow command and soft-
text-width wrapping if soft-wrap.wrap-at-text-width is set, defaults to
editor.text-width

path- Overrides the editor.path-completion config key for the


completion language.

Directories relative to the workspace root that are treated as LSP


workspace-lsp-
roots. Should only be set in .helix/config.toml . Overwrites the
roots
setting of the same name in config.toml if set.

An array of LSP diagnostic sources assumed unchanged when the


persistent-
language server resends the same set of diagnostics. Helix can
diagnostic-
track the position for these diagnostics internally instead. Useful
sources
for diagnostics that are recomputed on save.

File-type detection and the file-types key


Helix determines which language configuration to use based on the file-types key
from the above section. file-types is a list of strings or tables, for example:

file-types = ["toml", { glob = "Makefile" }, { glob = ".git/config" }, {


glob = ".github/workflows/*.yaml" } ]

When determining a language configuration to use, Helix searches the file-types with the
following priorities:

116 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

1. Glob: values in glob tables are checked against the full path of the given file. Globs
are standard Unix-style path globs (e.g. the kind you use in Shell) and can be used
to match paths for a specific prefix, suffix, directory, etc. In the above example, the
{ glob = "Makefile" } config would match files with the name Makefile , the {
glob = ".git/config" } config would match config files in .git directories,
and the { glob = ".github/workflows/*.yaml" } config would match any yaml
files in .github/workflow directories. Note that globs should always use the Unix
path separator / even on Windows systems; the matcher will automatically take
the machine-specific separators into account. If the glob isn't an absolute path or
doesn't already start with a glob prefix, */ will automatically be added to ensure it
matches for any subdirectory.
2. Extension: if there are no glob matches, any file-types string that matches the
file extension of a given file wins. In the example above, the "toml" config
matches files like Cargo.toml or languages.toml .

Language Server configuration


Language servers are configured separately in the table language-server in the same
file as the languages languages.toml

For example:

[language-server.mylang-lsp]
command = "mylang-lsp"
args = ["--stdio"]
config = { provideFormatter = true }
environment = { "ENV1" = "value1", "ENV2" = "value2" }

[language-server.efm-lsp-prettier]
command = "efm-langserver"

[language-server.efm-lsp-prettier.config]
documentFormatting = true
languages = { typescript = [ { formatCommand ="prettier --stdin-filepath
${INPUT}", formatStdin = true } ] }

These are the available options for a language server.

Key Description

The name or path of the language server binary to execute.


command
Binaries must be in $PATH

args A list of arguments to pass to the language server binary

117 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Key Description

config Language server initialization options

The maximum time a request to the language server may take, in


timeout
seconds. Defaults to 20

Any environment variables that will be used when starting the


environment
language server { "KEY1" = "Value1", "KEY2" = "Value2" }

required-root- A list of glob patterns to look for in the working directory. The
patterns language server is started if at least one of them is found.

A format sub-table within config can be used to pass extra formatting options to
Document Formatting Requests. For example, with typescript:

[language-server.typescript-language-server]
# pass format options according to https://github.com/typescript-language-
server/typescript-language-server#workspacedidchangeconfiguration omitting
the "[language].format." prefix.
config = { format = { "semicolons" = "insert",
"insertSpaceBeforeFunctionParenthesis" = true } }

Configuring Language Servers for a language


The language-servers attribute in a language tells helix which language servers are
used for this language.

They have to be defined in the [language-server] table as described in the previous


section.

Different languages can use the same language server instance, e.g. typescript-
language-server is used for javascript, jsx, tsx and typescript by default.

The definition order of language servers affects the order in the results list of code
action menu.

In case multiple language servers are specified in the language-servers attribute of a


language , it's often useful to only enable/disable certain language-server features for
these language servers.

As an example, efm-lsp-prettier of the previous example is used only with a


formatting command prettier , so everything else should be handled by the
typescript-language-server (which is configured by default). The language
configuration for typescript could look like this:

118 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

[[language]]
name = "typescript"
language-servers = [ { name = "efm-lsp-prettier", only-features = [ "format"
] }, "typescript-language-server" ]

or equivalent:

[[language]]
name = "typescript"
language-servers = [ { name = "typescript-language-server", except-features
= [ "format" ] }, "efm-lsp-prettier" ]

Each requested LSP feature is prioritized in the order of the language-servers array. For
example, the first goto-definition supported language server (in this case
typescript-language-server ) will be taken for the relevant LSP request (command
goto_definition ). The features diagnostics , code-action , completion , document-
symbols and workspace-symbols are an exception to that rule, as they are working for
all language servers at the same time and are merged together, if enabled for the
language. If no except-features or only-features is given, all features for the
language server are enabled. If a language server itself doesn't support a feature, the
next language server array entry will be tried (and so on).

The list of supported features is:

▪ format
▪ goto-definition
▪ goto-declaration
▪ goto-type-definition
▪ goto-reference
▪ goto-implementation
▪ signature-help
▪ hover
▪ document-highlight
▪ completion
▪ code-action
▪ workspace-command
▪ document-symbols
▪ workspace-symbols
▪ diagnostics
▪ rename-symbol
▪ inlay-hints

119 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Tree-sitter grammar configuration


The source for a language's tree-sitter grammar is specified in a [[grammar]] section in
languages.toml . For example:

[[grammar]]
name = "mylang"
source = { git = "https://github.com/example/mylang", rev =
"a250c4582510ff34767ec3b7dcdd3c24e8c8aa68" }

Grammar configuration takes these keys:

Key Description

name The name of the tree-sitter grammar

source The method of fetching the grammar - a table with a schema defined below

Where source is a table with either these keys when using a grammar from a git
repository:

Key Description

git A git remote URL from which the grammar should be cloned

rev The revision (commit hash or tag) which should be fetched

A path within the grammar directory which should be built. Some grammar
repositories host multiple grammars (for example tree-sitter-
subpath typescript and tree-sitter-ocaml ) in subdirectories. This key is used to
point hx --grammar build to the correct path for compilation. When
omitted, the root of repository is used

Choosing grammars
You may use a top-level use-grammars key to control which grammars are fetched and
built when using hx --grammar fetch and hx --grammar build .

# Note: this key must come **before** the [[language]] and [[grammar]]
sections
use-grammars = { only = [ "rust", "c", "cpp" ] }
# or
use-grammars = { except = [ "yaml", "json" ] }

120 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

When omitted, all grammars are fetched and built.

121 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Guides
This section contains guides for adding new language server configurations, tree-sitter
grammars, textobject queries, and other similar items.

122 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Adding new languages to Helix


In order to add a new language to Helix, you will need to follow the steps below.

Language configuration
1. Add a new [[language]] entry in the languages.toml file and provide the
necessary configuration for the new language. For more information on language
configuration, refer to the language configuration section of the documentation. A
new language server can be added by extending the [language-server] table in
the same file.
2. If you are adding a new language or updating an existing language server
configuration, run the command cargo xtask docgen to update the Language
Support documentation.

If you are adding a new Language Server configuration, make sure to update the
Language Server Wiki with the installation instructions.

Grammar configuration
1. If a tree-sitter grammar is available for the new language, add a new [[grammar]]
entry to the languages.toml file.
2. If you are testing the grammar locally, you can use the source.path key with an
absolute path to the grammar. However, before submitting a pull request, make
sure to switch to using source.git .

Queries
1. In order to provide syntax highlighting and indentation for the new language, you
will need to add queries.
2. Create a new directory for the language with the path runtime/queries/<name>/ .
3. Refer to the tree-sitter website for more information on writing queries.
4. A list of highlight captures can be found on the themes page.

In Helix, the first matching query takes precedence when evaluating queries,
which is different from other editors such as Neovim where the last matching query
supersedes the ones before it. See this issue for an example.

123 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Common issues
▪ If you encounter errors when running Helix after switching branches, you may
need to update the tree-sitter grammars. Run the command hx --grammar fetch
to fetch the grammars and hx --grammar build to build any out-of-date
grammars.
▪ If a parser is causing a segfault, or you want to remove it, make sure to remove the
compiled parser located at runtime/grammars/<name>.so .
▪ If you are attempting to add queries and Helix is unable to locate them, ensure that
the environment variable HELIX_RUNTIME is set to the location of the runtime
folder you're developing in.

124 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Adding textobject queries


Helix supports textobjects that are language specific, such as functions, classes, etc.
These textobjects require an accompanying tree-sitter grammar and a textobjects.scm
query file to work properly. Tree-sitter allows us to query the source code syntax tree and
capture specific parts of it. The queries are written in a lisp dialect. More information on
how to write queries can be found in the official tree-sitter documentation.

Query files should be placed in runtime/queries/{language}/textobjects.scm when


contributing to Helix. Note that to test the query files locally you should put them under
your local runtime directory ( ~/.config/helix/runtime on Linux for example).

The following captures are recognized:

Capture Name

function.inside

function.around

class.inside

class.around

test.inside

test.around

parameter.inside

comment.inside

comment.around

entry.inside

entry.around

Example query files can be found in the helix GitHub repository.

Queries for textobject based navigation


Tree-sitter based navigation in Helix is done using captures in the following order:

▪ object.movement
▪ object.around
▪ object.inside

125 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

For example if a function.around capture has been already defined for a language in
its textobjects.scm file, function navigation should also work automatically.
function.movement should be defined only if the node captured by function.around
doesn't make sense in a navigation context.

126 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Adding indent queries


Helix uses tree-sitter to correctly indent new lines. This requires a tree- sitter grammar
and an indent.scm query file placed in runtime/queries/ {language}/indents.scm .
The indentation for a line is calculated by traversing the syntax tree from the lowest
node at the beginning of the new line (see Indent queries). Each of these nodes
contributes to the total indent when it is captured by the query (in what way depends on
the name of the capture.

Note that it matters where these added indents begin. For example, multiple indent level
increases that start on the same line only increase the total indent level by 1. See Capture
types.

By default, Helix uses the hybrid indentation heuristic. This means that indent queries
are not used to compute the expected absolute indentation of a line but rather the
expected difference in indentation between the new and an already existing line. This
difference is then added to the actual indentation of the already existing line. Since this
makes errors in the indent queries harder to find, it is recommended to disable it when
testing via :set indent-heuristic tree-sitter . The rest of this guide assumes that
the tree-sitter heuristic is used.

Indent queries
When Helix is inserting a new line through o , O , or <ret> , to determine the indent
level for the new line, the query in indents.scm is run on the document. The starting
position of the query is the end of the line above where a new line will be inserted.

For o , the inserted line is the line below the cursor, so that starting position of the query
is the end of the current line.

fn need_hero(some_hero: Hero, life: Life) -> {


matches!(some_hero, Hero { // ←─────────────────╮
strong: true,//←╮ ↑ ↑ │
fast: true, // │ │ ╰── query start │
sure: true, // │ ╰───── cursor ├─ traversal
soon: true, // ╰──────── new line inserted │ start node
}) && // │
// ↑ │
// ╰───────────────────────────────────────────────╯
some_hero > life
}

For O , the newly inserted line is the current line, so the starting position of the query is
the end of the line above the cursor.

127 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

fn need_hero(some_hero: Hero, life: Life) -> { // ←─╮


matches!(some_hero, Hero { // ←╮ ↑ │
strong: true,// ↑ ╭───╯ │ │
fast: true, // │ │ query start ─╯ │
sure: true, // ╰───┼ cursor ├─ traversal
soon: true, // ╰ new line inserted │ start node
}) && // │
some_hero > life // │
} // ←──────────────────────────────────────────────╯

From this starting node, the syntax tree is traversed up until the root node. Each indent
capture is collected along the way, and then combined according to their capture types
and scopes to a final indent level for the line.

Capture types
▪ @indent (default scope tail ): Increase the indent level by 1. Multiple occurrences
in the same line do not stack. If there is at least one @indent and one @outdent
capture on the same line, the indent level isn't changed at all.
▪ @outdent (default scope all ): Decrease the indent level by 1. The same rules as
for @indent apply.
▪ @indent.always (default scope tail ): Increase the indent level by 1. Multiple
occurrences on the same line do stack. The final indent level is @indent.always –
@outdent.always . If an @indent and an @indent.always are on the same line,
the @indent is ignored.
▪ @outdent.always (default scope all ): Decrease the indent level by 1. The same
rules as for @indent.always apply.
▪ @align (default scope all ): Align everything inside this node to some anchor. The
anchor is given by the start of the node captured by @anchor in the same pattern.
Every pattern with an @align should contain exactly one @anchor . Indent (and
outdent) for nodes below (in terms of their starting line) the @align node is added
to the indentation required for alignment.
▪ @extend : Extend the range of this node to the end of the line and to lines that are
indented more than the line that this node starts on. This is useful for languages
like Python, where for the purpose of indentation some nodes (like functions or
classes) should also contain indented lines that follow them.
▪ @extend.prevent-once : Prevents the first extension of an ancestor of this node.
For example, in Python a return expression always ends the block that it is in. Note
that this only stops the extension of the next @extend capture. If multiple
ancestors are captured, only the extension of the innermost one is prevented. All
other ancestors are unaffected (regardless of whether the innermost ancestor
would actually have been extended).

128 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

@indent / @outdent

Consider this example:

fn shout(things: Vec<Thing>) {
// ↑
// ├───────────────────────╮ indent level
// @indent ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// │
let it_all = |out| { things.filter(|thing| { // │ 1
// ↑ ↑ │
// ├───────────────────────┼─────┼┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// @indent @indent │
// │ 2
thing.can_do_with(out) // │
})}; // ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
//↑↑↑ │ 1
} //╰┼┴──────────────────────────────────────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// 3x @outdent

((block) @indent)
["}" ")"] @outdent

Note how on the second line, we have two blocks begin on the same line. In this case,
since both captures occur on the same line, they are combined and only result in a net
increase of 1. Also note that the closing } s are part of the @indent captures, but the 3
@outdent s also combine into 1 and result in that line losing one indent level.

@extend / @extend.prevent-once

For an example of where @extend can be useful, consider Python, which is whitespace-
sensitive.

]
(parenthesized_expression)
(function_definition)
(class_definition)
] @indent

129 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

class Hero:
def __init__(self, strong, fast, sure, soon):# ←─╮
self.is_strong = strong # │
self.is_fast = fast # ╭─── query start │
self.is_sure = sure # │ ╭─ cursor │
self.is_soon = soon # │ │ │
# ↑ ↑ │ │ │
# │ ╰──────╯ │ │
# ╰─────────────────────╯ │
# ├─ traversal
def need_hero(self, life): # │ start node
return ( # │
self.is_strong # │
and self.is_fast # │
and self.is_sure # │
and self.is_soon # │
and self > life # │
) # ←─────────────────────────────────────────╯

Without braces to catch the scope of the function, the smallest descendant of the cursor
on a line feed ends up being the entire inside of the class. Because of this, it will miss the
entire function node and its indent capture, leading to an indent level one too small.

To address this case, @extend tells helix to "extend" the captured node's span to the line
feed and every consecutive line that has a greater indent level than the line of the node.

(parenthesized_expression) @indent

]
(function_definition)
(class_definition)
] @indent @extend

class Hero:
def __init__(self, strong, fast, sure, soon):# ←─╮
self.is_strong = strong # │
self.is_fast = fast # ╭─── query start ├─ traversal
self.is_sure = sure # │ ╭─ cursor │ start node
self.is_soon = soon # │ │ ←───────────────╯
# ↑ ↑ │ │
# │ ╰──────╯ │
# ╰─────────────────────╯
def need_hero(self, life):
return (
self.is_strong
and self.is_fast
and self.is_sure
and self.is_soon
and self > life
)

130 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Furthermore, there are some cases where extending to everything with a greater indent
level may not be desirable. Consider the need_hero function above. If our cursor is on
the last line of the returned expression.

class Hero:
def __init__(self, strong, fast, sure, soon):
self.is_strong = strong
self.is_fast = fast
self.is_sure = sure
self.is_soon = soon

def need_hero(self, life):


return (
self.is_strong
and self.is_fast
and self.is_sure
and self.is_soon
and self > life
) # ←─── cursor
#←────────── where cursor should go on new line

In Python, the are a few tokens that will always end a scope, such as a return statement.
Since the scope ends, so should the indent level. But because the function span is
extended to every line with a greater indent level, a new line would just continue on the
same level. And an @outdent would not help us here either, since it would cause
everything in the parentheses to become outdented as well.

To help, we need to signal an end to the extension. We can do this with


@extend.prevent-once .

(parenthesized_expression) @indent

]
(function_definition)
(class_definition)
] @indent @extend

(return_statement) @extend.prevent-once

@indent.always / @outdent.always

As mentioned before, normally if there is more than one @indent or @outdent capture
on the same line, they are combined.

Sometimes, there are cases when you may want to ensure that every indent capture is
additive, regardless of how many occur on the same line. Consider this example in YAML.

131 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

- foo: bar
# ↑ ↑
# │ ╰─────────────── start of map
# ╰───────────────── start of list element
baz: quux # ←─── cursor
# ←───────────── where the cursor should go on a new line
garply: waldo
- quux:
bar: baz
xyzzy: thud
fred: plugh

In YAML, you often have lists of maps. In these cases, the syntax is such that the list
element and the map both start on the same line. But we really do want to start an
indentation for each of these so that subsequent keys in the map hang over the list and
align properly. This is where @indent.always helps.

((block_sequence_item) @item @indent.always @extend


(#not-one-line? @item))

((block_mapping_pair
key: (_) @key
value: (_) @val
(#not-same-line? @key @val)
) @indent.always @extend
)

Predicates
In some cases, an S-expression cannot express exactly what pattern should be matched.
For that, tree-sitter allows for predicates to appear anywhere within a pattern, similar to
how #set! declarations work:

(some_kind
(child_kind) @indent
(#predicate? arg1 arg2 ...)
)

The number of arguments depends on the predicate that's used. Each argument is either
a capture ( @name ) or a string ( "some string" ). The following predicates are supported
by tree-sitter:

▪ #eq? / #not-eq? : The first argument (a capture) must/must not be equal to the
second argument (a capture or a string).
▪ #match? / #not-match? : The first argument (a capture) must/must not match the

132 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

regex given in the second argument (a string).


▪ #any-of? / #not-any-of? : The first argument (a capture) must/must not be one of
the other arguments (strings).

Additionally, we support some custom predicates for indent queries:

▪ #not-kind-eq? : The kind of the first argument (a capture) must not be equal to the
second argument (a string).
▪ #same-line? / #not-same-line? : The captures given by the 2 arguments must/
must not start on the same line.
▪ #one-line? / #not-one-line? : The captures given by the fist argument must/must
span a total of one line.

Scopes
Added indents don't always apply to the whole node. For example, in most cases when a
node should be indented, we actually only want everything except for its first line to be
indented. For this, there are several scopes (more scopes may be added in the future if
required):

▪ tail : This scope applies to everything except for the first line of the captured
node.
▪ all : This scope applies to the whole captured node. This is only different from
tail when the captured node is the first node on its line.

For example, imagine we have the following function

fn aha() { // ←─────────────────────────────────────╮
let take = "on me"; // ←──────────────╮ scope: │
let take = "me on"; // ├─ "tail" ├─ (block) @indent
let ill = be_gone_days(1 || 2); // │ │
} // ←───────────────────────────────────┴──────────┴─ "}" @outdent
// scope: "all"

We can write the following query with the #set! declaration:

((block) @indent
(#set! "scope" "tail"))
("}" @outdent
(#set! "scope" "all"))

As we can see, the "tail" scope covers the node, except for the first line. Everything up to
and including the closing brace gets an indent level of 1. Then, on the closing brace, we
encounter an outdent with a scope of "all", which means the first line is included, and the

133 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

indent level is cancelled out on this line. (Note these scopes are the defaults for @indent
and @outdent —they are written explicitly for demonstration.)

134 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Adding Injection Queries


Writing language injection queries allows one to highlight a specific node as a different
language. In addition to the standard language injection options used by tree-sitter,
there are a few Helix specific extensions that allow for more control.

And example of a simple query that would highlight all strings as bash in Nix:

((string_expression (string_fragment) @injection.content)


(#set! injection.language "bash"))

Capture Types
▪ @injection.language (standard): The captured node may contain the language
name used to highlight the node captured by @injection.content .

▪ @injection.content (standard): Marks the content to be highlighted as the


language captured with @injection.language et al.

▪ @injection.filename (extension): The captured node may contain a filename with


a file-extension known to Helix, highlighting @injection.content as that
language. This uses the language extensions defined in both the default
languages.toml distributed with Helix, as well as user defined languages.
▪ @injection.shebang (extension): The captured node may contain a shebang used
to choose a language to highlight as. This also uses the shebangs defined in the
default and user languages.toml .

Settings
▪ injection.combined (standard): Indicates that all the matching nodes in the tree
should have their content parsed as one nested document.
▪ injection.language (standard): Forces the captured content to be highlighted as
the given language
▪ injection.include-children (standard): Indicates that the content node’s entire
text should be re-parsed, including the text of its child nodes. By default, child
nodes’ text will be excluded from the injected document.
▪ injection.include-unnamed-children (extension): Same as injection.include-
children but only for unnamed child nodes.

135 of 136 1/7/25, 21:39


Firefox https://docs.helix-editor.com/print.html

Predicates
▪ #eq? (standard): The first argument (a capture) must be equal to the second
argument (a capture or a string).
▪ #match? (standard): The first argument (a capture) must match the regex given in
the second argument (a string).
▪ #any-of? (standard): The first argument (a capture) must be one of the other
arguments (strings).

136 of 136 1/7/25, 21:39

You might also like