A Review of Helix after 1.5 Years

2025-03-16

A Review of Helix after 1.5 Years

I've been using Helix for roughly 1.5 years now, and for the latest release (25.01) I decided to summarized the thoughts I've been collecting until now.

This article has first been released in the german IT-magazine Golem. Link to article (paywalled)

Helix is a modal terminal editor, like Vim. That means you have multiple modes, one of them dedicated to inserting text into a document (insert-mode) and the others to modifying it in different ways, turning your keyboard into a big game pad specialized in text editing (the default mode of those is called normal-mode). Before I started using Helix, I've been using Vim for a good 7 years, and I want to provide a comparison of these two.

Helix core is much more powerful than Vim, but since there is no plugin system (yet), there is functionality that vim can acquire through plugins, that Helix does not have. The upside is, that you basically don't need to configure Helix. My last Vim config was roughly 100 lines of Vim-script + 500 lines of Lua. My Helix config is 30 lines of toml, and 3/4 of that are keybindings I added to address Vim habits.

A lot of things that require plugins in Vim like autojump, file-pickers, language server support, etc. are built right in and just work. My mind was blown when I opened the editor for the first time in a rust project and was immediately able to use rust-analyzer, without adding a single line of config.

Getting into using a modal editor when you come from something like VSCode is hard, but it's worth the effort. Helpfully, Helix has a built-in tutorial. After opening it you can type :tutor and a text file is opened that contains an interactive tutorial. You can quit Helix by typing :q!<Return>, in normal mode btw. If you're not in normal mode, you typically get there by pressing Esc

A Tour of Helix

First let me show you a selection of the things Helix can do out of the box, without plugins and without configuration

The File-Picker

I think having a file picker is central in an editor. And I don't mean a file tree, but a picker. Let me show you:

Image of the file-picker

This gives you access to all files of the current project. Helix will look for the project root by searching for a .git directory or one of multiple language dependent files that typically are in a projects root, and show all files that are within this root. The picker gives you a fuzzy search, but can also understand regex. Did you type a filename to then realize it exists multiple times within different directories? Just add the directory afterward with a space:

Image of the file-picker demonstrating fuzzy search

Do you want a list of all toml files in a project? Just use regex and type toml$:

Image of the file-picker demonstrating regex

There are multiple file pickers. You can open the picker in the project root, in the working directory in which you started Helix, in the directory which contains the file you're currently editing (although the last one requires you to define a custom hotkey), or in the root but only shows those files that are not clean according to git.

You can also move the selection in the file-picker by using <C-n> (for the uninitiated: this means Control + n) and <C-p>

Overall the picker is pretty powerful, but some people just prefer a file tree. This has arrived a couple of days ago in the latest master. Building Helix from source is quite easy, and I've never had a problem using the master branch, but if you are not comfortable doing so, just know that you will have a file tree from the next release on.

LSP integration

Helix primary view on code is defined by two things: The language server protocol and the treesitter. There is a huge list of supported languages and if you use one of those languages, Helix will just work with the standard tooling for that language. If you want to use something that's not supported instead, you can add a treesitter grammar and a language server config, and you're good to go. But most people will not need that. Helix even has support for niche things like Justfiles, cabal config and Elvish.

The fact that Helix just works with about every language (if that language has a good language server) is its biggest strength in my opinion.

The Diagnostics Picker

I really like this picker. It's like the file picker, but it displays errors. The difference is that the picker here resembles a table:

Image demonstrating the diagnostics picker

And the great thing is: you can filter this table by column. Do you want only the errors?

Image demonstrating column filtering in the diagnostics picker

Maybe you want to filter by error code? Also, easy. Just type a percent sign followed by enough letters to unambiguously define the column name, a space and then the value filter.

You can open the diagnostics picker for the current file or the whole project. By the point when I compile a program there are no issues left, because I'll use the project wide diagnostics picker to clean up all errors before I try it.

Autojump

Want to jump the cursor to another place on the screen? Just type gw and every word will have its first two letters overwritten like this:

Image demonstrating autojump

Then just type the two letters of the word you want to jump to and the cursor will go there.

Tree sitter code navigation

Another great thing is the tree sitter based code navigation. You get working motions e.g. mat - "mark around type", maf mark around function, ]f go to next function and so on. But best feature is the ability to manipulate the current selection by expanding along the syntax-tree. The following image shows what happens to the selection if you repeatedly press <A-o>. The inverse operation is <A-i>.

Image demonstrating code expansion using a treesitter grammar movement

Selection Manipulation and Multi-Cursor

Helix has very powerful selection manipulation capabilities. For example, you can split a selection on a regex, which is the main way to substitute Vim's substitute command. You first press % to select the whole document, you then press s to split the selection, and type the word you want to substitute, press enter, and now all the occurrences of this word are selected. You just press c now, to change the selections, and type the new word, to replace all occurrences. Afterward you go back to normal mode and type , to collapse all selections into a single one. To modify all lines in a certain way, you would first select the whole file, and then split the selection at \n.

If you have a bunch of selections you can remove some of them using another regex and so on. The possibilities are endless here, and it's this feature that I would miss the most from Helix if I went back to Vim (which I don't see happening).

Other features

You also get a picker for symbols, can perform lsp code actions easily, rename symbols, replace a selection with clipboard content, get a built-in "toggle code comment" command, a huge list of built-in color themes, lsp-snippet support, and have experimental support for interactive debugging. Going into detail for all of those will make this article way too long, so for now I'll just point out that they exist.

A comparison with Vim

Key map

While Helix is pretty similar to Vim in many regards, there are differences. The most significant one is the Kakoune-like input grammar. In Vim the grammar is <Action><Scope>. E.g. diw for delete in word or yt$ for yank till line end. In Helix, you are basically always in a pseudo visual mode where every movement action of the cursor will change the current selection. Your actions then always apply to the current selection. It's as if you always hit v in Vim before doing anything else. E.g. in Helix, to do diw you'd press ebd. e moves the cursor to the word end, b moves it to the beginning of the word. Since the cursor was at the end of the word before you now have selected exactly that word, and d will delete the current selection. To yank the remainder of the line, you'd do t<Return>y. t<Return> will move the cursor to the end of the line and select everything between the old and the new position, which will then be yanked if you press y.

I've often read the opinion that this key map is more effective, but I can't agree with that. Granted, it's a little more intuitive for users new to modal editing. However, in general the key maps are pretty similar, and it didn't take me more than a week to get used to it. I still use Vim navigation in the shell, in my browser, etc. and don't have trouble with using my Vim muscle memory. I guess the trick is to keep using it, so you have both available.

A few things still trip me up though. For example, pressing a in normal mode at the end of a line will put the cursor at the start of the next line. You need to use A to get a cursor at the end of the current line.

Plugins

Vim has a scripting language for configuration that can be used to write plugins, and people do so. A small Vim-config still has ~10 plugins, and a lot of people have much more than that. Plugins can be buggy, they can break your config when you update them, you need to configure them, and if you use too many, the startup time will take a noticeable hit.

Helix doesn't have plugins, and the important stuff is in the core. The config language is toml. For me that's an upside, but many people dislike that. There is a plugin system in the making, it will use steel as language of choice. However, since Helix has so much functionality in the core, you will be free to ignore it, if you also dislike the plugin situation in Vim.

The Redo Command

I just love Vim's redo command (I mean .). Helix has it too, but it only repeats the last action, not the motion before that, which makes it much less useful. I miss Vim's version.

Marks

I did use marks a lot, and Helix doesn't have them. You can set a jump point with <C-s>, but that will quickly get lost in the jump-list. This is the Vim feature I miss the most.

Jump-list

In Vim, you can use <C-o> and <C-i> to jump back to where you were before, and then jump forward again. Helix also has this functionality, but sometimes, you end up in unexpected places. When this happens, I'm always more concerned with getting to where I wanted to go than to reconstruct what exactly just happened, and why <C-o> or <C-i> behaved unexpectedly. I tried to construct a situation where this happens to give an example but didn't succeed.

It doesn't happen often, but often enough, and then it feels like driving and steering left, but your car turns right. It's a small shock and completely breaks the flow.

Everything else

Other features known from Vim like splits, buffer management, grep search, highlight search, macros, etc. are present in Helix, and typically work as well or better. With tabs being the only notable exception. I never used them though, so I don't miss them.

Some Tips

If you haven't used a modal editor before, and this article inspired you to use Helix, let me give you a few tips:

Use jk as Esc

Esc to go back to normal mode is a choice from a time when the escape key was in the place where we have capslock on a normal keyboard. Reaching for escape every time is annoying. Add this to your config to go back to normal mode by pressing jk in insert mode.

[keys.insert]
j = { k = "normal_mode"}

Bind gw to return

gw is the most useful movement command, and having it available at a single keystroke is quite useful

[keys.normal]
"ret" = "goto_word"

File picker in current file's directory

To have a file-picker in the directory of the current buffer you need to add a keybinding for it; I chose <Space>o:

[keys.normal."space"]
o = "file_picker_in_current_buffer_directory"

Cursorline

There is a handy feature called "Cursorline" which highlights the background of the line that the cursor currently is at. To enable it, add this to your config:

[editor]
cursorline = true

Inline hints & diagnostics

Inline hints are awesome, enable them with:

[editor]
lsp.display-inlay-hints = true

The same goes for inline diagnostics:

[editor.inline-diagnostics]
cursor-line = "hint"

Theme

The default theme is ... interesting, but "everforest_dark" is great.

theme = "everforest_dark"

Documentation

You can find Helix's documentation here: https://docs.Helix-editor.com/. It's very useful.

Conclusion

I'm pretty happy with Helix. It's not perfect, but Vim isn't either. You have to adjust to a slightly different key map, lose marks and ., and perhaps there's a feature from a plugin you're using that doesn't exist in Helix. In return, you get a near-zero-config editor that works with just about every language out of the box and doesn't require ongoing configuration maintenance.

If you're willing to adjust to it a bit, Helix generally works just as well as Vim, but with much less effort.

Also, Vim on Windows was a nightmare, because many plugins expect standard Unix tools to exist, while Helix didn't cause any problems in a short test.