Helix emulation layer for Emacs
Find a file
2026-09-03 02:23:15 +03:00
docs docs: fix cursors type variables names 2026-09-03 02:23:15 +03:00
.dir-locals.el fix: requirements for publishing on MELPA 2026-07-09 00:33:23 +03:00
.gitignore feat: agent-shell extension 2026-04-30 13:25:15 +03:00
.gitmodules remove emacs-pcre module 2025-06-08 02:30:40 +03:00
CHANGELOG.org new release 2026-09-02 16:45:00 +03:00
hel-commands.el new release 2026-09-02 16:45:00 +03:00
hel-core.el new release 2026-09-02 16:45:00 +03:00
hel-integration.el new release 2026-09-02 16:45:00 +03:00
hel-keybindings.el new release 2026-09-02 16:45:00 +03:00
hel-lib.el new release 2026-09-02 16:45:00 +03:00
hel-macros.el new release 2026-09-02 16:45:00 +03:00
hel-multiple-cursors-core.el new release 2026-09-02 16:45:00 +03:00
hel-scroll.el new release 2026-09-02 16:45:00 +03:00
hel-search.el new release 2026-09-02 16:45:00 +03:00
hel-vars.el new release 2026-09-02 16:45:00 +03:00
hel.el new release 2026-09-02 16:45:00 +03:00
LICENSE add license 2025-12-14 02:23:11 +03:00
README.org docs 2026-09-01 01:57:03 +03:00

Hel — Helix Emulation Layer for Emacs

MELPA GNU Emacs License: GPLv3

https://github.com/user-attachments/assets/09d1a77d-2a3e-4cae-a005-e69ae03e5a7e

https://github.com/user-attachments/assets/df9f6785-a359-4191-908d-2b2abb274d22

Key features

  • Multiple cursors based modal editing inside Emacs!
  • Undo/redo that plays well with multiple cursors.
  • PCRE regexps by default (thanks to pcre2el).
  • Smooth scrolling commands out of the box.

Can I use Hel without knowing Emacs keys?

[!IMPORTANT] What Vim, Helix, and other modal editors call Normal and Insert modes, Hel refers to as states. This is because the word "mode" in Emacs is already used for its major and minor modes.

When several years ago I came to Emacs from Neovim, I was in love with Vim editing model, found Emacs native keybindings ugly and had zero interest in learning them. I want Emacs not as text editor (which it obviously lacks of) but as an operation system with Lisp and all its power. So the first question I asked myself was "Can I use Evil without learning Emacs keys?"

The answer is yes. I have never used — and still don't know — most Emacs keys. I know only a few that you need when something breaks early during Emacs startup and you don't have your Hel keys available. They are:

  • M-x — Command palette. The main key you need; all other commands can be invoked from it.
  • M-w — Copy the selected text to google the error message or feed it to LLM.
  • C-x C-s — Save current buffer.
  • C-x C-c — Exit Emacs.

That's it.

Hel and Emacs do not interfere much, because Emacs is not a modal editor: letters and numbers are self-inserting, and most command key chords begin with C-x or C-c (e.g. C-x n d). Due to this, Hel works as a layer on top of Emacs.

In Normal state you have selection-based editing, multiple cursors, and all the other Hel features. In Insert state, Hel steps aside and standard Emacs keys work as usual. Also Hel doesn't touch C-x and C-c so they are always available. This allows you to mix Hel and Emacs in any proportion.

Kakoune vs Helix

The main difference between Kakoune and Helix, in terms of text editing, is how they handle expanding selections: Kakoune uses Shift + motions, while Helix uses a separate state on the v key. Since I originally came from Vim, I prefer Helix's v key, so I chose Helix. However, Kakoune (as far as I know) was the original inventor of this keyboard-driven multiple-selections approach, and it deserves credit.

Installation

[!TIP] If you want a Spacemacs / Doom like configuration framework but for Hel try Helheim Emacs.

Hel is on MELPA.

Emacs built-in package manager

This is the most minimal example of the init.el file:

;;; init.el -*- lexical-binding: t; no-byte-compile: t; -*-

(setq package-archives '(("melpa"  . "https://melpa.org/packages/")
                         ("gnu"    . "https://elpa.gnu.org/packages/")
                         ("nongnu" . "https://elpa.nongnu.org/nongnu/")))
(use-package hel
  :ensure t
  :custom (inhibit-startup-screen t)
  :config (hel-mode))

;;; init.el ends here

Elpaca

(elpaca 'hel
  (setopt inhibit-startup-screen t)
  (hel-mode))

Straight

(straight-use-package 'hel)
(setopt inhibit-startup-screen t)
(hel-mode)

Documentation

Differences from Helix text editor

This package is not a one-to-one emulation. Some commands are implemented in a slightly different way (improved from the author's point of view), and some features like keyboard macros, registers, and jumplists already have their alternatives in Emacs.

  • In Emacs the cursor ("point" in Emacs terms) is located between two characters rather than on a character like in Helix or Vim. I decided to keep this behavior, instead of emulating original one, as Evil does, because the primary object of interaction in Helix approach is a selection, not the cursor itself. This has consequences. In Helix, the cursor is a one-character selection, so Helix always operates on a selection. Hel does not. It has two distinct states: either selection exists, or not. Hel provides some DWIM ("do what I mean"):

    • d / D

      • When there is a selection, both d and D remove it from the buffer: d copies the deleted text to the clipboard, D does not (Vim taught me that you don't always want to copy deleted text to the clipboard).
      • When there is no selection, common text editors provide two keys for deleting a character: Backspace deletes the character before the cursor, Delete — after it. Hel adopts this idea: d deletes the character before the cursor, D — after. None of them touches the clipboard, since it makes no sense to copy a single character into it.
    • r / R

      • When there is a selection they behave the same as in Helix.
      • With no selection r replaces character before cursor, R — after.
  • x and X commands expand or contract line-wise selections down when the cursor is at the end of the selection, or up when the cursor is at the beginning of the selection.
  • Inner objects are additionally available directly under m prefix to reduce keystrokes: mw is the same as miw — select word.
  • Mark commands accept numeric arguments: m2ip or 2mip — select 2 paragraphs.
  • You can restore last multiple selections with gv.
  • gs, gh, and gl create selections. This is for consistency, since all other motions also create selections. In Helix they only move the cursor without creating a selection.
  • Keys that are relevant only when multiple cursors are present will be active only in that case (e.g. K, &, , — full list is in hel-multiple-cursors-mode-map keymap). This allows you to reuse, for example, K for documentation lookup or , for localleader while there is only one cursor in the buffer.
  • Scrolling keybindings are taken from Vim instead of Helix.
  • gg and G are taken from Vim. With numeric argument:

    • gg — goes to N/10 of the way from the beginning of the buffer;
    • G — goes to line N.
  • Six easymotion commands are provided:

    • gw / gb — choose and mark word forward/backward.
    • gW / gB — choose and mark WORD forward/backward.
    • gj / gk — go to line down/up.

    Helix provides only gw to place 2-char hints at the beginning of each word.

  • f, F, t, T commands to move to char are enhanced: they show hints for targets, and while hints are active, they can be repeated with n / N keys.
  • When you search backward with ? command, while hints are active n and N keys are swapped: n will repeat search backward and N — forward, like in Vim.

Undo

Undo tree

Helix stores undo history in a tree, which you can traverse with M-u / M-U. Emacs' undo history can also be represented as a tree. Hel doesn't provide M-u, M-U commands, but there is an even better option — the excellent vundo package, which gives you a real undo-tree UI.

(undo-tree is not supported — it implements its own undo system instead of using Emacs' native one.)

Using custom undo commands

You can use your own undo commands, for example undo-fu:

(hel-keymap-global-set :state 'normal
  "u" #'undo-fu-only-undo
  "U" #'undo-fu-only-redo)

But they must meet two conditions: they must work with the native Emacs undo system, and they must deactivate the mark before undoing.

[!IMPORTANT] Hel doesn't support Emacs' undo in region. It conflicts with multiple cursors, and in Normal state a selection is active most of the time, so region-aware undo by default makes no sense. Undo commands must therefore deactivate the mark before undoing.

undo-fu deactivates the mark by default (see undo-fu-allow-undo-in-region).

Commands that are not implemented

  • M-u, M-U — traverse undo tree. See undo tree section.
  • q, Q — record keyboard macros

Extensions

Tips

[!TIP] By default, Hel uses a bar cursor for Normal state and a box cursor for Insert state — the opposite of what Vim does. Your first instinct may be to switch them back to what you're used to, but I recommend not doing so. This was the first I done myself, and went through all the stages of acceptance, give default settings a try — the bar cursor is better suited for Normal state.

[!TIP] You can set localleader keymap to ,. It will act as the local leader while there is only one cursor in the buffer, and will delete all secondary cursors when there are multiple cursors.

[!TIP] Bind Caps Lock to Esc, and configure Space to tap+hold behavior: Space on tap and Ctrl on hold. You can use any of the these tools: kanata, kmonad, keyd (Linux), Karabiner-Elements (Mac).

Acknowledgments

Hel depends on dash.el, pcre2el, avy and ultra-scroll wonderful packages.

Hel is heavily inspired by:

You are welcome to go and give them all at least a star!

Contributing

Share

A quick post about this package on your blog or social network could bring new users to Emacs, which would be great!

Support the development

Hel was developed on an old laptop with a cracked screen, and I worked on it instead of grinding LeetCode. If you'd like to support Hel's development, you can do so with a donation:

Every contribution is greatly appreciated.