تخطَّ إلى المحتوى

Helix

Helix is a post-modern terminal text editor inspired by Kakoune and Vim but with a fresh take on modal editing. The key difference from Vim: in Helix you select first, then act — selections drive every operation. It ships with LSP integration and tree-sitter syntax highlighting out of the box with zero configuration.

Installation

# macOS (Homebrew)
brew install helix

# Linux (AppImage)
curl -L https://github.com/helix-editor/helix/releases/latest/download/helix-*.AppImage -o helix
chmod +x helix
sudo mv helix /usr/local/bin/hx

# Arch Linux
pacman -S helix

# Cargo (from source)
cargo install --locked --git https://github.com/helix-editor/helix helix-term
hx --grammar fetch
hx --grammar build

# Nix
nix-env -iA nixpkgs.helix

# Ubuntu/Debian PPA
sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt update && sudo apt install helix

# Check version
hx --version

# Open Helix
hx
hx file.ts
hx src/  # open directory (file picker)

Configuration

Helix configuration lives at ~/.config/helix/config.toml:

# ~/.config/helix/config.toml

theme = "catppuccin_mocha"

[editor]
line-number = "relative"        # "absolute" | "relative"
cursorline = true               # highlight current line
cursorcolumn = false
gutters = ["diagnostics", "spacer", "line-numbers", "spacer", "diff"]
mouse = true
middle-click-paste = true
scroll-lines = 3
shell = ["bash", "-c"]
rulers = [100]                  # visual ruler at column 100
color-modes = true              # colorize mode indicator
bufferline = "multiple"         # show buffer tabs: "never" | "always" | "multiple"
idle-timeout = 400              # ms before LSP hints appear
completion-trigger-len = 2

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

[editor.file-picker]
hidden = false                  # show hidden files in picker

[editor.auto-save]
after-delay = { enable = true, timeout = 3000 }

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

[editor.whitespace.render]
space = "none"
nbsp = "all"
nnbsp = "all"
tab = "all"
newline = "none"

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

[editor.soft-wrap]
enable = true

[keys.normal]
# Remap keys
"C-/" = "toggle_comments"
"C-s" = ":w"
"space" = { f = "file_picker", e = "file_picker_in_current_directory", b = "buffer_picker", s = "symbol_picker", g = { g = "goto_first_line", e = "goto_last_line" } }

Language-Specific Settings

# ~/.config/helix/languages.toml

[[language]]
name = "javascript"
auto-format = true
formatter = { command = "biome", args = ["format", "--stdin-file-path", "file.js"] }

[[language]]
name = "typescript"
auto-format = true
formatter = { command = "biome", args = ["format", "--stdin-file-path", "file.ts"] }

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

[[language]]
name = "python"
language-servers = ["pyright"]
formatter = { command = "black", args = ["-", "--quiet"] }
auto-format = true

[[language]]
name = "go"
auto-format = true
formatter = { command = "goimports" }

Core Commands

Mode Switching

KeyModeDescription
iNormal → InsertInsert before selection
aNormal → InsertInsert after selection
INormal → InsertInsert at line start
ANormal → InsertInsert at line end
oNormal → InsertOpen line below
ONormal → InsertOpen line above
vNormal → SelectEnter select mode (extend selection)
EscAny → NormalReturn to normal mode
:Normal → CommandEnter command mode

Movement (Normal Mode)

KeyDescription
h j k lMove left/down/up/right
w / bNext / previous word start
e / geNext / previous word end
W / BNext / previous WORD start
f{char}Find next character on line
t{char}Move to before next character
F{char}Find previous character
xSelect current line
XExtend selection to line
gg / geGo to first / last line
gh / glGo to line start / end
Ctrl-d / Ctrl-uScroll half page down / up
Ctrl-f / Ctrl-bScroll page down / up
%Match bracket
m{motion}Select text object (see below)

Text Objects

KeySelection
mi( or mibInside parentheses
ma( or mabAround parentheses
mi[Inside brackets
mi{ or miBInside braces
mi"Inside double quotes
mi'Inside single quotes
mi`` Inside backticks
mifInside function
mafAround function
micInside class
matAround tag (HTML/XML)
mipInside paragraph

Actions (Apply to Selection)

KeyDescription
dDelete selection
cChange selection (delete and enter insert)
yYank (copy) selection
p / PPaste after / before cursor
RReplace selection with yanked text
sSelect all matches of pattern in selection
SSplit selection on regex matches
KKeep only matching selections
~Toggle case
``` ``Lowercase selection
Alt-`Uppercase selection
> / <Indent / unindent selection
=Auto-format selection
JJoin lines
u / UUndo / redo

Advanced Usage

Multiple Cursors

# Add cursor on next match
,  (select next match of current selection)
n  (after search: next match)
N  (after search: add cursor at next match)

# Add cursor on each line of selection
Ctrl-i  (split selection by newline — creates cursor per line)

# Skip current selection, move to next
alt-,

# Remove a cursor
alt-(in select mode, remove main cursor)

# Select all occurrences in file
%s (select all, then: select regex)
# Practical multiple cursor workflow:
# 1. Search for a word: /myVariable
# 2. Select all matches: alt-,  (while selecting)
# 3. Edit all at once (you now have N cursors)

LSP Integration

KeyAction
Space-kShow hover documentation
Space-dGo to definition
Space-DGo to type definition
Space-rRename symbol
Space-aCode actions
Space-fFormat document
[d / ]dPrevious / next diagnostic
Space-l-dOpen diagnostics in picker
Ctrl-spaceTrigger completion
Ctrl-xCompletion from signature

Search and Replace

# In normal mode:
/pattern         # search forward
?pattern         # search backward
n / N            # next / previous match

# Select all matches in selection
s                # prompts for regex, creates multiple cursors

# Global search across files (picker)
<Space>/ or :global-search

# Command-line substitution
:%s/old/new/g    # replace in entire file
:'<,'>s/old/new  # replace in selection (use 's' in visual mode)

File Navigation

# File picker
<Space>f   — open file picker
<Space>F   — open file picker (cwd)
<Space>b   — buffer picker
<Space>/   — global search (grep across files)

# Tree navigation in file picker:
# Enter — open file / expand dir
# Backspace — go up one directory
# Alt-Enter — open without closing picker

Command Mode

:w            " save
:q            " quit
:wq           " save and quit
:q!           " force quit (discard changes)
:e filename   " open file
:r filename   " read file into buffer
:set option=value
:split / :vsplit     " split horizontally / vertically
:bp / :bn            " previous / next buffer
:bd                  " close buffer (delete)
:theme name          " change theme temporarily
:log                 " show log file
:health              " check LSP/tree-sitter health

Tree-sitter Motions

# Navigate by syntax nodes (tree-sitter aware)
Alt-o   — expand selection to parent node
Alt-i   — shrink selection to child node
Alt-n   — next sibling node
Alt-p   — previous sibling node

# These are structurally aware — great for selecting
# entire function arguments, blocks, etc.

Common Workflows

Setting Up for a Project

# Open the project directory (shows file picker)
hx src/

# Check LSP status
:health

# Install language servers (done outside Helix)
# Node.js LSPs
npm install -g typescript-language-server typescript
npm install -g vscode-langservers-extracted  # HTML, CSS, JSON, ESLint
npm install -g pyright                        # Python

Editing Multiple Files

# Open multiple files
hx file1.ts file2.ts file3.ts

# Navigate buffers
<Space>b     — picker
:bp / :bn prev/next

# Open split panes
Ctrl-w s horizontal split
Ctrl-w v vertical split
Ctrl-w h/j/k/l move between splits

Recording and Running Macros (via Q)

Q   — start recording macro
q   — stop recording
Q   — replay macro (after recording)

Tips and Best Practices

Think “select then act” — The core mental model is the opposite of Vim’s verb-object (e.g., dw). In Helix it’s object-verb: select the word with w, then delete with d. Get comfortable selecting before acting.

Use m text objects constantlymib (match inside brackets), mif (match inside function), mi" (match inside quotes) are tree-sitter aware and dramatically faster than manual selection.

Learn s (select in selection) — Press s to run a regex on your selection and split it into multiple cursors. Combined with % (select all), this enables powerful multi-cursor bulk edits across the file.

Use <Space> as a leader — The space menu is discoverable — it shows all available commands with labels. Start there when you don’t remember a specific keybinding.

:health checks LSP status — If completion or go-to-definition isn’t working, run :health to see what language servers are installed and whether they’re working.

Use relative line numbers — Set line-number = "relative" in config.toml. This makes jump commands like 10j and 5k intuitive for navigating by count.

Swap Caps Lock to Escape — In a modal editor, Escape is pressed constantly. Remapping Caps Lock to Escape at the OS level (via keyd, karabiner, or xkb) prevents repetitive strain and speeds up mode switching.

Run :tutor to learn Helix — Helix ships with an interactive tutorial accessed via :tutor in the command line. It covers all core operations in 15–20 minutes and is the fastest way to get productive.