Skip to content

Helix ​

Helix 25.07, painted in SilkCircuit glow, with the Space leader laid out the way AstroNvim taught your hands

Overview ​

Helix is a modal editor with no plugin system: tree-sitter, LSP, pickers, multiple cursors and a file explorer are built in, and the whole setup is two TOML files. It is Kakoune-shaped rather than Vim-shaped, so you select first and act second. That model is the reason to try it, and the config here leaves it alone. What it does carry over from the Neovim setup is the muscle memory that has nothing to do with motions: the Space groups, Ctrl-s, ]b and [b, and Esc clearing your selection.

What you get:

  • The same language servers and formatters as Neovim: Rust, Python (ruff and ty), TypeScript (vtsls), HTML, CSS, Tailwind, JSON, YAML, TOML, Markdown, Bash, Lua and Docker, with prettier, stylua and shfmt for formatting
  • One master switch for format-on-save, off by default like the Neovim config, toggled with Space u F
  • Inlay hints, inline diagnostics on the cursor line, a bufferline when more than one file is open, a statusline that shows the git branch
  • lazygit in a tmux popup, one-line git blame, and a Space a y that copies a file:line reference for pasting at an agent

Structure ​

helix/
├── config.toml      # Editor options and keymap (→ ~/.config/helix/config.toml)
├── languages.toml   # Language servers and formatters (→ ~/.config/helix/languages.toml)
└── README.md
sh/helix.sh          # Puts Mason's binaries on PATH so Helix finds the servers

The SilkCircuit installer drops its five Helix themes into ~/.config/helix/themes/, which is why the two files are linked individually rather than the directory. Pick another variant any time with :theme silkcircuit-neon (also vibrant, soft and dawn); the tracked default is glow.

Quick start ​

hx .                # File explorer at the project root
hx file.py          # Open a file

Space f f           # Find files
Space f w           # Grep the project
Space f c           # Grep the word under the cursor
Space e             # File explorer
Space x x           # Diagnostics for this buffer
Space l f           # Format buffer
Space g g           # lazygit (tmux popup)
Space ?             # Command palette, searchable by description
:config-reload      # After editing config.toml
hx --health python  # What a language resolved to

Coming from Neovim ​

The unlearning is smaller than it looks. Everything that is not in this table works the way you expect.

HabitHelix
dw, ciw, yapSelect first, then act: wd, miwc, mapy. w, e, b and friends leave a selection behind
v then moveYou are always selecting. v toggles select mode, where motions extend instead of replace
xSelects the whole line (repeat to grow). d deletes what is selected
%Selects the whole file. mm jumps to the matching bracket
Ctrl-rU redoes, and Ctrl-r is mapped to it too
K for hoverSpace k (or Space l h). K keeps selections matching a regex, which you will want
. repeatRepeats the last insert. Multiple cursors cover most of what . did: s splits a selection
into one cursor per regex match, C copies the cursor down, , collapses back to one
:%s/a/b/g% to select all, s to pick the matches, then c and type. Live, with every match visible
f, tNot confined to the line
:terminal, lazygitNo terminal. Space g g opens lazygit in a tmux popup; anywhere else Ctrl-z drops you to the
shell and fg brings Helix back
:Mason, :LazyNothing to manage. hx --health reports what each language found on PATH
which-keyPress Space and wait; the infobox lists the group. Same for g, m, z, Ctrl-w
q:, :helpSpace ? searches every command by description
gd, gr, gi, gySame keys. gd definition, gr references, gi implementation, gy type definition
]d, [d, ]g, [gSame keys: diagnostics and git hunks. Also ]f function, ]t type, ]a argument, ]p paragraph

Keybindings ​

Notation: Space is the leader, C-x is Ctrl. Mode is normal unless a table says otherwise. Mappings marked (ours) come from helix/config.toml; the rest are Helix defaults kept because they already matched.

Files and windows ​

KeyAction
Space wSave (ours)
Space q / Space QClose view / close all views (ours)
Space nNew scratch buffer (ours)
Space c / Space CClose buffer / force close (ours)
Space e / Space EFile explorer at workspace root / at this file's directory
Space | / Space \\Vertical / horizontal split (ours)
C-h C-j C-k C-lMove between splits (ours)
C-wWindow mode: v s split, q close, o only, H J K L swap
C-sSave, in normal and insert mode (ours)
C-qQuit everything, discarding changes (ours, same as AstroNvim)
]b / [bNext / previous buffer (ours)
EscCollapse to one cursor, drop extra selections (ours)

Find (Space f) ​

KeyAction
Space f fFiles in the workspace
Space f FFiles under the current directory
Space f wGrep the workspace, live
Space f cGrep the word under the cursor
Space f bBuffers
Space f sSymbols in this file
Space f SSymbols in the workspace
Space f jJumplist
Space f gFiles changed in git
Space 'Reopen the last picker

Buffers (Space b) ​

KeyAction
Space b bBuffer picker
Space b n / Space b pNext / previous buffer
Space b dClose this buffer
Space b cClose every other buffer
Space b CClose all buffers

Language tools (Space l) ​

KeyAction
Space l aCode action
Space l r / Space rRename symbol
Space l h / Space kHover documentation
Space l fFormat buffer
Space l s / Space l GDocument / workspace symbols
Space l d / Space l DDocument / workspace diagnostics
Space l RReferences
Space l i / Space l yImplementation / type definition
Space l lRestart the language servers
Space l LOpen the Helix log
Space x x / Space x XDiagnostics picker, buffer / workspace

Git (Space g) ​

KeyAction
Space g glazygit in a tmux popup
Space g flazygit filtered to this file's history
Space g sPicker of files changed in the working tree
Space g bBlame the current line: commit, author, age and subject
]g / [gNext / previous hunk

Outside tmux, Space g g prints a reminder instead of failing quietly: Ctrl-z, run lazygit, fg.

Agents (Space a) ​

KeyAction
Space a yCopy path:line for the cursor, or path:start-end for a multi-line selection, to the system clipboard

Works in normal and select mode. It uses pbcopy, wl-copy or xclip, whichever the box has.

Toggles (Space u) ​

KeyToggles
Space u nRelative / absolute line numbers
Space u wSoft wrap
Space u iInlay hints
Space u gIndent guides
Space u hVisible whitespace
Space u cCursor line highlight
Space u bBufferline
Space u mMouse
Space u dInline and end-of-line diagnostics
Space u FFormat on save, for every language at once

Kept from Helix ​

Space y, Space p, Space P and Space R move text through the system clipboard. Space j is the jumplist, Space h selects every reference to the symbol under the cursor, Space G is the debugger, Space / comments the selection (matching AstroNvim, and replacing Helix's Space c). Two defaults moved: Space a is the agents group, so code actions are Space l a, and Space w saves, so window mode is Ctrl-w.

Statusline and bufferline ​

The bar follows the heirline layout from Neovim: a colored mode block on the left (NORMAL, INSERT and SELECT, each with a Nerd Font glyph, the LSP spinner beside it), then the git branch, the file name and its modified or read-only state. The right side carries diagnostics for the buffer and the workspace as colored dots, the selection count and length, the active register, position and percentage, and the file type. Sections sit on the SilkCircuit highlight surface with cyan separators; the mode block takes purple, pink or cyan for normal, insert or select, the same hues heirline uses. Those colors live in the SilkCircuit Helix theme, generated from the helix extra in that repo, because Helix draws the bar from ui.statusline scopes rather than from config.

With more than one buffer open the bufferline appears on top, active buffer in bold purple on the editor background, the rest muted on the section surface, matching the heirline tabline.

Helix has no custom statusline components, so a few heirline pieces have no equivalent: git added, changed and removed counts, attached server names and the scrollbar. The spinner covers server activity and Space l L opens the log.

Language servers ​

Everything below resolves to the binaries Mason installed for Neovim under ~/.local/share/nvim/mason/bin, which sh/helix.sh appends to PATH. Nothing gets installed twice, and a box that has never run Neovim shows the gaps in hx --health.

LanguageServer(s)Formatter
Rustrust-analyzer, with clippy as the check commandLSP
Pythonty, ruffLSP
TypeScript, JavaScriptvtsls (tsx and jsx also get tailwindcss-ls)prettier
HTML, CSS, SCSSvscode html and css servers, tailwindcss-lsprettier
JSON, YAML, Markdownvscode-json-language-server, yaml-language-server, marksmanprettier
TOMLtaploLSP
Lualua-language-serverstylua
Bashbash-language-servershfmt, honoring .editorconfig
Dockerfile, Composedocker-language-server (compose adds yaml-language-server)none

Formatting is off on save until you flip Space u F, matching the Neovim config. Space l f formats on demand. Helix has no separate linter hook, so the markdownlint and yamllint passes that nvim-lint runs in Neovim stay in make lint.

Gotchas ​

  • hx --health warns that ~/.config/helix/runtime does not exist. That is where a source build keeps grammars; the Homebrew install ships them elsewhere and the warning is noise.
  • Helix expands the first word of a :sh command only when the whole word is an expansion, so s=%{cursor_line} stays literal there. Space a y goes through set -- for exactly that reason.
  • git blame -l prefixes boundary commits with ^; Space g b uses --porcelain to get a clean hash.
  • Space f c deliberately does not press Enter: global search runs as you type, and Enter would jump to the first match instead of leaving the picker open.
  • Run make install after pulling: it links the two files and lets the SilkCircuit installer lay down the themes.

Released under the MIT License