How I'm using Helix editor

Last updated on October 11, 2025, in other

I've been using Helix as my editor to develop on remote servers for quite some time now.

There are a lot of emerging supply-chain attacks, and I simply don't like the idea of installing tens of plugins to Vim/Neovim to make the editor usable.

To make the switch from Neovim easier, I had to make some changes to the configuration. I want to share them to save you some time, because discovering them is not straightforward.

Tmux setup

I use tmux as a terminal multiplexer.

One thing that I miss from Neovim setup is a good file manager and TUI for git. I rarely use a file manager, but when I need to, I usually want to move a bunch of selected files quickly. Unfortunately, Helix does not support file editing in the explorer. You can only view them.

To overcome it, I added new keybindings to my tmux config:

# Yazi related
set -g allow-passthrough on
set -ga update-environment TERM
set -ga update-environment TERM_PROGRAM

bind-key y display-popup -d '#{pane_current_path}' -x R -h 95% -w 95% -E 'tmux new-session yazi \; set status off'
bind-key g popup -E -w 95% -h 95%  -d '#{pane_current_path}' lazygit
bind-key e display-popup -w 95% -h 90% -E "tmux capture-pane -Jp -S- | hx -"

When I hit one of the keys, a new pop-up window opens.

  • prefix - y - opens yazi file manager
  • prefix - g - opens lazygit
  • prefix - e - opens Helix editor with tmux output history.

The default prefix for tmux is Ctrl + b, but I'm using Ctrl + \.

The last binding is useful when you want to work with terminal output in your editor. I use it to search the history using regexes or copy selected output quickly. For example, I use it quite a lot to copy output from clickhouse client that outputs SQL results in CSV or JSON to the terminal. Although it can output it to a file, that's an extra step, since I usually only need to copy-paste the output to Slack. This can be done via mouse, but painful with tmux setup, since you need to scroll the buffer when the output does not fit in one screen.

The yazi and lazygit tools are usually opened on top of the Helix Editor.

Vim bindings

I'm pretty used to Helix keybinds now, but there are still some bindings that I ported from vim:

[keys.select]
0 = "goto_line_start"
"$" = "goto_line_end"
"^" = "goto_first_nonwhitespace"
G = "goto_file_end"
D = ["extend_to_line_bounds", "delete_selection", "normal_mode"]
k = ["extend_line_up", "extend_to_line_bounds"]
j = ["extend_line_down", "extend_to_line_bounds"]

[keys.normal]
D = ["ensure_selections_forward", "extend_to_line_end", "delete_selection"]
0 = "goto_line_start"
"$" = "goto_line_end"
"^" = "goto_first_nonwhitespace"
G = "goto_file_end"
V = ["select_mode", "extend_to_line_bounds"]
esc = ["collapse_selection", "keep_primary_selection"]

I don't like how Helix selects lines in visual mode. That's why I switched to vim-like behavior. Going one line up/down in a select mode selects the whole line. Helix selects them partially.

I have also rebinded ESC so it resets multiple cursors as well. By default, you need to press comma.

Lastly, removing text until the end of the line takes too many keypresses, so I ported the D motion as well. It removes everything to the right of your cursor in select mode.

Improved status line

The default status line lacks some important information, such as the current git branch.

I'm using the following config for my status line:

[editor.statusline]
left = [
  "mode",
  "spinner",
  "version-control",
  "spacer",
  "separator",
  "file-name",
  "read-only-indicator",
  "file-modification-indicator",

]
center = []
right = [
  "diagnostics",
  "workspace-diagnostics",
  "position",
  "total-line-numbers",
  "position-percentage",
  "file-encoding",
  "file-line-ending",
  "file-type",
  "register",
  "selections",
]
separator = "│"

Useful keybindings

You can make your life way easier with custom keybindings. Discovering them took me some time.

In my opinion, the most useful are: file reloading, soft wrap toggle, git undo, and git blame, git diff.

Here is a full list of my custom bindings:

  • space - e - w - Write current buffer to file.
  • space - e - c - Close current buffer.
  • space - e - x - Close other buffers. This is useful when you have tens of buffers open.
  • space - e - l - Toggle inlay type hints. They can be useful, but also noisy to display them every time.
  • + - f - Format current file.
  • + - w - Render whitespace symbols. Useful to check what kind of invisible characters are in the document.
  • + - W - Disable rendering whitespace symbols.
  • space - f - . - Show/hide git ignored files in file picker.
  • space - f - r - Reload all files. This is very useful, since Helix does not support auto-reloading right now. When a file gets changes externally or when I commit changes, I press this keybinding to update the gutters and sync file changes.
  • space - f - x - Undo git change at the current cursor.
  • space - f - w - Show git blame for the current line.
  • space - f - d - Show git diff.
[keys.normal.space]
e = { w = ":write", c = ":bc", x = ":bco", l = ":toggle lsp.display-inlay-hints" }
q = ":quit"

[keys.normal."+"]
f = ":format"
w = ":toggle whitespace.render all"
W = ":set whitespace.render none"
s = ":toggle soft-wrap.enable"

[keys.normal.space.f]
f = "file_picker_in_current_directory"
F = "file_picker"
b = "file_picker_in_current_buffer_directory"
"." = ":toggle-option file-picker.git-ignore"
g = "global_search"
e = "file_explorer"
r = ":reload-all"
x = ":reset-diff-change"
w = ":echo %sh{git blame -L %{cursor_line},+1 %{buffer_name}}"
d = [":vsplit-new", ":lang diff", ":insert-output git diff"]

Editor config

After using Helix for 6 months, I discovered that it supports autosave when you switch tabs in your terminal. Some of the newer features in Helix are disabled by default, so old users won't see unexpected changes. You need to go through each option to discover them.

Here is my config:

[editor]
line-number = "relative"
mouse = true
rulers = [120]
true-color = true
completion-replace = true
trim-trailing-whitespace = true
end-of-line-diagnostics = "hint"
color-modes = true
rainbow-brackets = true

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

[editor.file-picker]
hidden = false

[editor.indent-guides]
render = true
character = "╎"
skip-levels = 0

[editor.soft-wrap]
enable = false

[editor.auto-save]
focus-lost  = true
after-delay.enable = true
after-delay.timeout = 300000

Some notable options:

  • true-color - Forces true color support.
  • editor.file-picker.hidden - Show dot files in file picker.
  • rulers - Sets visual vertical rulers. Useful when you want to limit the maximum line length of your code without autoformatting.
  • completion-replace - Competitions replace the whole word.
  • editor.inline-diagnostics.cursor-line - Makes diagnostics look better. See screenshot.
  • color-modes - Makes the mode indicator colored.
  • editor.indent-guides - Adds visual indent guides.
  • editor.auto-save.focus-lost - Automatically saves file when focus is lost. Requires terminal support.
  • editor.auto-save.after-delay.enable - Automatically saves file after specified delay.
  • rainbow-brackets - Use different colors for nested brackets. Recent feature, not part of the most recent release yet.

LSP tweaks

For every language, I usually add harper-ls LSP to highlight grammar errors in comments.

Custom Tree-sitter injections

Helix allows specifying custom tree sitter injections. You can use them to highlight one language inside another language.

I use it to highlight SQL queries inside Python and Go, YAML front matter, and code blocks in markdown. This can be also used to highlight HTML snippets.

I've uploaded my config files to Github, so you can grab custom injections or my config.

SQL execution from Helix

One of my recent additions is the ability to query a selected SQL query and get results back in a new buffer (tab).

All I need to do is select a query and press a hotkey that calls clickhouse-client and stores its output in a new buffer.

[keys.select.space.e]
q = [
  "yank_to_clipboard", "collapse_selection", ":new",
  ":set-language csv",
  ":insert-output pbpaste | clickhouse-client --connection default"
]

This replaces the need of opening CLI client or database management software for simple tasks.

User setups

I'm curious to hear more tricks from Helix users. So please share your findings in the comments!


If you have any questions, feel free to ask them via e-mail displayed in the footer.

Comments

  • Amber 2025-10-13 #

    thanks for yazi author, using Yazi in Helix without tmux is possible now yazi#2461

    reply

  • Fred 2025-10-16 #

    thanks for these tips Artem, really useful and help me optimize my productivity with Helix

    reply

  • Matt 2025-10-16 #

    It would be nice if you could link directly to your config in source control so we don't have to go hunting for it through links elsewhere

    reply

    • Artem 2025-10-16 #

      My link points to all the config files related to Helix. That includes config, LSP setup and Tree-Sitter injections.

      reply