What Is Multi-Cursor Editing in Helix?
Helix takes a distinctive approach to multi-cursor editing. Instead of arbitrary mouse-driven cursors like VSCode or Sublime, Helix uses a multiple selection model inherited from Kakoune. Every operation in Helix operates on selections — and when you have more than one selection active, your edits apply to all of them simultaneously. This means you can type, delete, or transform text across dozens of locations in a single action, without ever reaching for the mouse.
At its core, Helix multi-cursor editing is about building and manipulating selection sets. You start with one selection, then grow it into many using a rich set of selection commands. The power comes from the fact that every editing command in Helix is inherently multi-cursor aware — if you have 50 selections and press d, all 50 get deleted at once.
Key Terminology
- Selection — A range of text (can be a single character, a word, or a block). Helix always operates on selections.
- Primary selection — The "main" selection that determines where certain commands apply. It's usually the last one added.
- Cursor — In Helix, each selection has a cursor (the active end). Multiple selections = multiple cursors.
- Select mode — Accessed with
vors, where you build and refine selections.
Why Multi-Cursor Editing Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Single-cursor editing forces you to repeat the same action over and over — rename a variable across 20 lines, add a comma to 15 list items, or reformat 30 log statements. Multi-cursor editing collapses that repetition into one operation. Here's why it's indispensable:
- Speed — Edit N locations in the time it takes to edit one.
- Consistency — Every change is identical; no risk of typos creeping in on the seventh repetition.
- Flow — You stay in thinking mode instead of switching to mechanical repetition mode.
- Precision — Helix selections are regex-aware and structurally aware (via tree-sitter), so you can target exactly what you want.
- Reversible — All edits go into one undo step. One
ureverts everything.
How to Use Multi-Cursor Editing in Helix
1. Entering Select Mode
Press v to enter select mode from normal mode. This anchors your current position as the selection start. Move around and the selection extends. Alternatively, press s to create a selection and immediately go into select mode.
# In Normal mode:
v # Enter select mode (anchors current position)
jjj # Extend selection down 3 lines
e # Extend to end of word
2. Adding Selections with % (Select All)
The % key in select mode picks all occurrences of the current selection's content. This is the fastest way to get multiple cursors. Select a word, hit %, and every identical match in the document becomes a selection.
# Example: Rename 'user' to 'customer' everywhere
# 1. Move cursor onto the word "user"
# 2. Press 'o' to select the word (or 'miw' style with 'miw')
# Actually in Helix:
w # Move to word "user"
* # Select word and move to next occurrence (sets search)
% # Select ALL occurrences of "user" in the document
c customer # Change all selections to "customer"
The * key (star search) selects the word under cursor and jumps to the next match, while also populating the search register. Then % selects every match in the buffer. Together they give you an instant document-wide multi-cursor.
3. Adding Selections One by One
Sometimes you don't want every occurrence — you want specific ones. Helix gives you several ways to add selections incrementally:
| Keybinding | Action | Context |
|---|---|---|
% | Select all occurrences of current selection | Select mode |
A-s (Alt-s) | Add selection above | Normal/Select |
A-S (Alt-Shift-s) | Add selection below | Normal/Select |
C | Copy selection onto next matching line | Normal mode |
A-c | Copy selection onto previous matching line | Normal mode |
o | Jump to the other end of each selection | Select mode |
A-o | Jump to primary selection | Any mode |
# Practical example: Add comma to end of 5 specific lines
# Move to line 1, press:
v j j j j # Select 5 lines (or use 5j)
A-s # Not needed here, just demonstrating
# Actually to edit line endings:
v 5j # Select across 5 lines
A # Append at end of each selection's line
, # Type comma
<Esc> # Done — comma added to all 5 lines
4. Using C to Copy Selection Down
The C command is uniquely powerful. It copies the current selection onto the next line that has the same search match. Chain it to build selections on consecutive matching lines.
# Select all lines containing "TODO" and prepend "FIX:"
# 1. Search for TODO: /TODO Enter
# 2. Clear search highlight with :noh (optional)
# 3. With cursor on first "TODO" line, select the line:
x # Select entire line
C # Copy selection to next line with same search match
C # Again — keep pressing C to add more
C
# Now you have selections on all TODO lines
I # Insert at start of each line
FIX: # Type the prefix
<Esc> # Done
5. Global Search Selections (:select-all)
For regex-based multi-cursor, Helix provides the :select-all command (also bound to % in select mode). You can use it with patterns:
# Select all Markdown headings
:select-all ^#.*$ # Selects every line starting with #
# Now edit all headings at once
A<space>---<Esc> # Append " ---" to each heading
# Select all occurrences of a regex pattern
:select-all \bfixme\b # Select every "fixme" word
c TODO # Change all to "TODO"
6. Splitting Selections
Helix can split a selection into multiple smaller selections using delimiters. This turns one large selection into many cursors.
:split-selection-on-newline # Split selection into one per line
:split-selection-on-space # Split on spaces
:split-selection-on-tabs # Split on tabs
:split-selection-on , # Split on commas (custom delimiter)
# Practical: Convert comma-separated list to bullet points
# Select the entire list: v 5j (select across lines)
# If it's one line with commas:
:split-selection-on , # Now each comma-separated item is a selection
# Wrap each in quotes:
`"` # Surround each selection with quotes
# Then join with newlines using :split-selection-on-newline approach
7. Aligning Selections
When selections have different lengths, you can align them to the same column for consistent editing:
:align-selections-left # Align all selections flush left
:align-selections-right # Align to rightmost column
8. The Multi-Insert Trick (mi)
Helix has a mi command (multiple insert) that lets you place cursors at specific positions manually, then edit them all at once. Enter mi, move around placing cursors with Enter, then type to edit all cursors simultaneously.
# Place cursors manually at different positions
mi # Enter multi-insert mode
# Move around with hjkl, press Enter to drop a cursor
# Press Enter at each spot you want a cursor
# Once done, press q to confirm cursors
# Now type — all cursors receive the input
<Esc> # Exit when done
9. Using Tree-sitter for Structural Selections
Helix's tree-sitter integration lets you make semantically aware multi-cursors. Select a function argument, and % will select all arguments at the same position in other function calls.
# Select all occurrences of a specific node type
:select-all-object function_definition # Select all function definitions
:select-all-object string # Select all string literals
:select-all-object comment # Select all comments
# Practical: Rename a function parameter across all method signatures
# 1. Select the parameter with tree-sitter (mi( to select inside parentheses)
# 2. % to select all identical parameters
# 3. c newName Esc — renames everywhere
10. Removing and Managing Selections
When you have too many selections, you can trim them:
| Keybinding | Action |
|---|---|
, | Remove primary selection (keep others) |
A-, | Keep only primary selection (remove all others) |
A-o | Jump cursor to primary selection |
<Space> | Remove all selections except primary |
# If you accidentally selected too much with %
, # Remove the current (primary) selection
, , , # Keep removing until you have what you want
# Or
<Space> # Clear all selections, keep only the main one
Best Practices for Multi-Cursor Editing
Build Gradually, Edit Once
The most common mistake is trying to select everything perfectly in one go. Instead, build your selection set incrementally: start with one, use C or % to expand, use , to prune mistakes, then perform your edit. Helix's undo (u) reverts the entire multi-edit as one step, so you can always back out cleanly.
Prefer Structural Selections Over Manual
Whenever possible, use *, %, tree-sitter objects, or regex :select-all rather than manually placing cursors with mi. Manual cursors break when code structure changes; semantic selections are robust.
Use A-s and A-S for Adjacent Lines
When you need cursors on consecutive lines, A-s (add selection above) and A-S (add selection below) are faster than visual line selection. They preserve each line as an independent selection.
# Add cursors to 10 consecutive lines
A-S # Add selection on line below
# Repeat 9 more times, or use a macro
# Alternatively: v 10j then :split-selection-on-newline
Combine with Macros for Repeated Patterns
For patterns that require per-selection adjustments, record a macro with q, perform one edit, then replay it across all selections. This gives you per-cursor custom logic.
q a # Record macro 'a'
# Perform edit on first selection
q # Stop recording
# Now with multiple selections active:
Q a # Replay macro 'a' on ALL selections simultaneously
Leverage : Commands for Complex Selection Logic
When built-in keys aren't enough, Helix's command mode opens up advanced selection manipulation:
:select-all \b\w+\b # Select all words
:keep-selections \d+ # Keep only selections matching digits
:trim-selections # Trim whitespace from selections
:reverse-selections # Reverse selection order
:pipe-selections sort -u # Pipe selections through external command
Use o to Flip Selection Orientation
Selections have direction (forward/backward). Pressing o flips the cursor to the other end of each selection. This matters for commands like A (append) vs I (insert) which depend on cursor position.
# Select multiple words
w * % # Select all occurrences of the word
o # Flip cursor to end of each selection
A ! # Append "!" to the end of each word
Watch Out for Selection Count
With thousands of selections, editing can become sluggish. Helix handles hundreds efficiently, but if you select 10,000+ occurrences, consider whether a global :substitute command (:s/pattern/replacement/g) would be more appropriate. Use multi-cursor for interactive, visual edits; use :s for mass find-and-replace.
Real-World Workflows
Workflow 1: Rename a Local Variable
# Inside a function, rename 'temp' to 'buffer'
# 1. Move cursor to 'temp'
# 2. Press * to select the word (also sets search to 'temp')
# 3. Press % to select ALL occurrences in the document
# 4. But wait — you only want local ones. Use , to prune extras.
# 5. c buffer Esc — renames all remaining selections
Workflow 2: Add Trailing Commas to a Multi-Line List
# Given:
items = [
"apple"
"banana"
"cherry"
]
# Select the three lines:
v 3j # Select across the three items
# Or: /" Enter, then C, C to build selections
A , # Append comma+space to each line
# Result:
items = [
"apple",
"banana",
"cherry",
]
Workflow 3: Convert All Inline Styles to a CSS Class
# HTML file with inline styles:
# <div style="color:red">...</div>
# <span style="color:red">...</span>
# 1. Select one 'style="color:red"'
# 2. % to select all identical style attributes
# 3. c class="red" Esc — replaces all
# 4. Now select all style="color:blue" similarly and repeat
Workflow 4: Bulk Comment Toggle
# Comment out 20 scattered debug print lines
# 1. /print! Enter — search for print statements
# 2. On first match, press C repeatedly to build selections
# 3. I // Esc — insert comment prefix on all lines
# Undo with one u if needed
Conclusion
Helix's multi-cursor editing is a fundamental paradigm shift from traditional modal editing. Rather than thinking about "the cursor," you think about selection sets. Commands like % (select all matches), C (copy selection to next match), mi (manual multi-insert), and the tree-sitter-powered :select-all-object give you surgical control over exactly which text gets edited. The key insight is that every Helix command is multi-cursor native — there's no separate "multi-cursor mode" to toggle. Once you internalize the flow of building, pruning, and then editing selections, you'll find yourself performing complex refactors in seconds that would have taken minutes of repetitive keystrokes. Start with * followed by % for your next variable rename, and you'll immediately see why this model is so compelling.