VOMPECCC: A Modular Completion Framework for Emacs

VOMPECCC: A Modular Completion Framework for Emacs

1. About   emacs completion modularity

vompeccc-banner.jpeg

Figure 1: JPEG produced with DALL-E 3

Completion is not a feature. It is a system — one composed of at least half a dozen orthogonal concerns that most users never think about separately. This post introduces VOMPECCC, a loose acronym for eight packages that, together, form a complete, modular, Unix-philosophy-aligned completion framework for Emacs: V​ertico, O​rderless, M​arginalia, P​rescient, E​mbark, C​onsult, C​orfu, and C​ape. Each package does one thing. All eight compose through Emacs's standard APIs. And any subset works without the others.

2. TLDR   tldr

Emacs completion is at least six orthogonal problems. VOMPECCC is eight independent packages — Vertico, Orderless, Marginalia, Prescient, Embark, Consult, Corfu, Cape — each handling one concern, all built on Emacs's native APIs. Any subset works, any component can be swapped, and nothing breaks.

3. The Hidden Complexity of Completion   complexity design

When you press M-x and start typing, what happens next seems simple: a list appears, you pick something, it runs. But beneath that interaction lies a system of surprising depth. Consider what a fully featured completion experience actually requires:

Completion is not one problem. It is at least six, and most frameworks pretend otherwise.

Candidate display. Where do completion candidates appear? In the minibuffer, vertically? Horizontally? In a separate buffer? In a popup at point? The display layer determines how you scan and navigate candidates — and the optimal display varies by context. Switching buffers might want a vertical list; completing a symbol in code might want a popup near the cursor.

Filtering. How does your input match against candidates? Prefix matching is the simplest: find-f matches find-file. But what about fuzzy matching, where ff matches find-file? What about splitting your input into multiple components and matching all of them in any order? What about mixing strategies — one component as a regexp, another as an initialism?

Sorting. Once you have your filtered candidates, in what order do you see them? Alphabetically? By string length? By how recently you selected them? By frequency of use? A good sorting strategy means the candidate you want is almost always within the first few results. A bad one means scrolling every time.

Annotation. A bare list of candidate names is often insufficient. When selecting a command, you want to see its keybinding and docstring. When selecting a file, you want to see its size and modification date. When selecting a buffer, you want to see its major mode and file path. Annotations transform a list of strings into a list of informed choices.

Actions. Selecting a candidate is the most common action, but not the only one. What if you want to delete the file instead of opening it? Kill the buffer instead of switching to it? Describe the function instead of running it? A completion system without contextual actions forces you out of the flow: complete, exit, invoke a separate command.

In-buffer completion. Everything above applies to the minibuffer — the prompt at the bottom of the screen. But completion also happens inside buffers: symbol completion while writing code, dictionary words while writing prose, file paths while editing configuration. In-buffer completion has its own display requirements (a popup near the cursor, not the minibuffer) and its own backend requirements (language servers, dynamic abbreviations, file system paths). A truly complete completion system must handle both contexts.

These six concerns are orthogonal. The way you display candidates has nothing to do with how you filter them. The way you sort them has nothing to do with what actions you can take. And in-buffer completion is an entirely separate context from minibuffer completion. Any system that collapses all of these into a single package is either ignoring some of them or coupling things that should not be coupled.

4. The Monolith Era: Helm and Ivy   helm ivy legacy

For the better part of a decade, two frameworks dominated Emacs completion: Helm and Ivy. Both were genuinely transformative — they proved that Emacs's built-in completion experience was inadequate, and they inspired everything that followed. But both, in retrospect, made the same architectural trade-off: they bundled every concern into a single package with a proprietary API. The benefits were immediate; the costs emerged over time.

4.1. Helm: The Kitchen Sink

Helm traces its lineage to anything.el, created by Tamas Patrovics in 2007. Thierry Volpiatto — a French alpine guide who taught himself programming after discovering Linux in 20061 — forked it as Helm in 2011 and contributed nearly 7,000 commits over the following decade. Helm became the most downloaded package on MELPA2 and the default completion framework in Spacemacs, which drove massive adoption during 2013–2018.

Helm's ambition was total. It provided its own candidate display, its own filtering, its own action system, its own source API (via EIEIO classes), and dozens of built-in commands: file finding, buffer switching, grep, occur, man pages, color picking, process management, and more. It offered 44+ file actions alone.

Helm showed what great completion could feel like. Its architecture showed what happens when a single maintainer carries every concern alone.

The cost was proportional to the ambition. Users reported multi-second delays on basic operations after extended use, 100–500ms lag on window popups, and CPU-intensive fuzzy matching that required disabling for large projects. Samuel Barreto's widely cited "From Helm to Ivy" essay called Helm "a big behemoth size package" and reported using only a third of its capabilities.

Most critically, Helm replaced Emacs's completing-read entirely with its own proprietary helm-source API. Every Helm extension was written against this API. None of them could be reused with any other completion system. If Helm's development stalled — and it did, twice, in 2018 and 20203 — every downstream package was stranded.

4.2. Ivy: The Lighter Monolith

Ivy emerged in 2015 as Oleh Krehel's direct reaction to Helm's complexity. Where Helm tried to do everything, Ivy aimed to be minimalist. The package split its concerns into three logical components: Ivy (the completion UI), Swiper (an isearch replacement), and Counsel (enhanced commands).

In practice, the split was cosmetic. All three lived in a single repository. Counsel required Ivy's internals. And the core architectural choice was the same as Helm's: Ivy defined its own completion API, ivy-read, and Counsel commands called ivy-read directly rather than completing-read. Code written for Ivy worked only with Ivy.

The ivy-read function grew organically to accept roughly 20 arguments with multiple special cases4. As the Selectrum developers noted: "When Ivy became a more general-purpose interactive selection package, more and more special cases were added to make various commands work properly." Users reported performance degradation after extended use, and Ivy broke with Emacs 28 and again with Emacs 30, forcing compatibility polyfills.

When Ivy's original maintainer stepped back, the project entered a period of reduced maintenance. A new maintainer has since taken over and released version 0.15.1, but active feature development has slowed considerably from the 2016–2020 peak.

4.3. The Unix Philosophy Lens

The Unix philosophy, as articulated by Doug McIlroy5, is straightforward: "Write programs that do one thing and do it well. Write programs to work together." Viewed through this lens, both Helm and Ivy bundle multiple concerns — completion UI, matching engine, action framework, command library — into packages that communicate through proprietary APIs (helm-source, ivy-read) rather than Emacs's native completing-read contract. The result is that extensions and backends written for one framework cannot be reused with another. The investment is non-transferable.

None of this diminishes what they achieved. Helm and Ivy showed the community what great completion felt like. The question is whether the architecture that delivered those features is the one we want to build on going forward.

The irony is that Emacs already provides the right abstraction. completing-read is a stable, well-specified API that any UI can render6. completion-styles is a pluggable system for controlling how input matches candidates7. completion-at-point-functions is a standard hook for in-buffer completion backends. The infrastructure for composable completion has existed for years. It just needed packages that actually used it.

5. The VOMPECCC Framework   vompeccc framework

VOMPECCC is not a framework in the traditional sense. There is no single repository, no shared dependency, no coordinating package. It is eight independent packages, maintained by three different developers, that compose through Emacs's standard APIs to cover every concern of a complete completion system.

Package Concern Author
Vertico Minibuffer display Daniel Mendler
Orderless Filtering / matching Omar Antolin Camarena & Daniel Mendler
Marginalia Candidate annotations Omar Antolin Camarena & Daniel Mendler
Prescient Sorting / ranking Radon Rosborough
Embark Contextual actions Omar Antolin Camarena
Consult Enhanced commands Daniel Mendler
Corfu In-buffer display Daniel Mendler
Cape In-buffer backends Daniel Mendler

The architecture maps cleanly onto the six concerns identified earlier:

                Minibuffer                     Buffer
                ----------                     ------
Display:        Vertico                        Corfu
Filtering:      Orderless          (shared across both)
Sorting:        Prescient          (shared across both)
Annotations:    Marginalia         (shared across both)
Actions:        Embark             (shared across both)
Backends:       Consult                        Cape

Each package targets a single layer. Each layer communicates through standard Emacs APIs: completing-read, completion-styles, completion-at-point-functions, annotation functions, and keymaps. No package knows about the others' internals. All of them can be replaced without affecting the rest.

6. Vertico: The Display Layer   vertico display

Vertico (VERTical Interactive COmpletion) provides a vertical candidate list in the minibuffer. It is roughly 600 lines of code, excluding its extensions. It replaced Selectrum, which was deprecated in its favor because Selectrum deviated from the completing-read API and couldn't properly handle dynamic completion tables8.

Vertico's defining characteristic is strict adherence to the completing-read contract. It doesn't filter candidates (that's your completion style's job). It doesn't sort them (that's your sorting function's job). It doesn't annotate them (that's your annotation function's job). It displays them. Any command that calls completing-read — whether built-in or third-party — automatically gets Vertico's UI with zero configuration.

Vertico ships with 13 built-in extensions that modify the display behavior:

Extension Effect
vertico-buffer Display in a regular buffer instead of the minibuffer
vertico-directory Ido-like directory navigation (backspace deletes path components)
vertico-flat Horizontal, flat display
vertico-grid Grid layout
vertico-indexed Select candidates by numeric prefix argument
vertico-mouse Mouse scrolling and selection
vertico-multiform Per-command or per-category display configuration
vertico-quick Avy-style quick selection keys
vertico-repeat Repeat last completion session
vertico-reverse Bottom-to-top display
vertico-suspend Suspend and restore completion sessions
vertico-unobtrusive Show only a single candidate

vertico-multiform is particularly powerful: it lets you configure different display modes per command or per completion category. File completion could use the flat display while M-x uses the default vertical list. Buffer switching could open in a separate buffer while symbol completion stays in the minibuffer.

The vertico-multiform extension is particularly worth configuring: it lets you set per-command display modes, so consult-line can open in a full buffer while M-x stays in the minibuffer.

Created: April 2021. Stars: ~1,800. Available on: GNU ELPA.

7. Orderless: The Filtering Layer   orderless filtering

Orderless is a completion style — it plugs into Emacs's completion-styles variable, the standard mechanism for controlling how user input is matched against candidates. Where built-in styles like basic require prefix matching and flex does single-pattern fuzzy matching, Orderless splits your input into space-separated components and matches candidates that contain all components in any order.

Each component can independently use a different matching method:

Style Example Matches
orderless-literal buffer switch-to-buffer
orderless-regexp ^con.*mode$ conf-mode
orderless-initialism stb switch-to-buffer
orderless-flex stbf switch-to-buffer
orderless-prefixes s-t-b switch-to-buffer
orderless-literal-prefix swi switch-to-buffer

Style dispatchers let you select a matching method per component using affix characters: =​= for literal, ~ for flex, , for initialism, ! for negation, & to match annotations. The system is fully extensible.

The typical configuration sets completion-styles to '(orderless basic), with partial-completion for the file category so that ~/d/s expands path components like ~/Documents/src. The fallback to basic is deliberate: some Emacs features (TRAMP hostname completion, dynamic completion tables) require a prefix-matching style.

Because Orderless is a standard completion style, it works with any completion UI that uses Emacs's completing-read API: Vertico, Icomplete, the default *Completions* buffer, and even the minibuffer in Emacs's stock configuration.

Created: April 2020. Stars: ~979. Available on: GNU ELPA.

8. Marginalia: The Annotation Layer   marginalia annotations

Marginalia adds contextual, colorful annotations to minibuffer completion candidates. The name refers to notes written in the margins of books — here, it means metadata displayed alongside each candidate.

Marginalia detects the category of the current completion (files, commands, variables, faces, buffers, bookmarks, packages, etc.) and selects an appropriate annotator function. The detection works through two mechanisms: marginalia-classify-by-command-name (lookup table keyed by calling command) and marginalia-classify-by-prompt (regex matching against the minibuffer prompt text).

Category Annotations shown
Command Keybinding, docstring summary
File Size, modification date, permissions
Variable Current value, docstring
Face Preview of the face styling
Symbol Class indicator (v/f/c), docstring
Buffer Mode, size, file path
Bookmark Type, target location
Package Version, status, description

marginalia-cycle (typically bound to M-A) lets you cycle between annotation levels: detailed, abbreviated, or disabled entirely. This is useful when annotations are consuming screen space during narrow completions.

Marginalia hooks into Emacs's annotation-function and affixation-function properties in completion metadata. This means it works with any completion UI that respects these properties — no special integration code needed. It is the framework-agnostic successor to ivy-rich9, which provided similar annotations but was Ivy-specific.

Created: December 2020. Stars: ~919. Available on: GNU ELPA.

9. Prescient: The Sorting Layer   prescient sorting

Prescient provides intelligent sorting and filtering of completion candidates based on recency and frequency of use. Where Orderless answers "which candidates match?", Prescient answers "in what order should they appear?"

The sorting is hierarchical:

  1. Recency — most recently selected candidates appear first
  2. Frequency — frequently selected candidates next, with scores that decay over time
  3. Length — remaining candidates sorted by string length (shorter first)

Usage statistics persist across Emacs sessions via prescient-persist-mode, which writes to a save file. This means Prescient learns your habits: if you frequently run magit-status from M-x, it surfaces near the top after a few uses, regardless of where it falls alphabetically.

Prescient ships as a core library plus framework-specific adapters — vertico-prescient and corfu-prescient being the relevant ones for VOMPECCC (adapters for Ivy, Company, and Selectrum also exist for other stacks).

A common and powerful configuration combines Orderless for filtering with Prescient for sorting. Among the candidates filtered by Orderless, the most recent and frequent ones get promoted to the top:

Prescient also provides its own filtering methods (literal, regexp, initialism, fuzzy, prefix, anchored) with on-the-fly toggling via M-s prefix commands. However, many users prefer Orderless for filtering and use Prescient purely for its sorting intelligence.

Created: August 2017. Stars: ~695. Available on: MELPA.

10. Embark: The Action Layer   embark actions

Embark provides a framework for performing context-sensitive actions on "targets" — the thing at point or the current completion candidate. Think of it as a keyboard-driven right-click context menu that works everywhere in Emacs: in the minibuffer, in normal buffers, in Dired, in help buffers.

The core command is embark-act. When invoked, Embark determines the type of the target (file, buffer, URL, symbol, command, etc.) and opens a keymap of single-letter actions appropriate to that type:

Target Example actions
File Open, delete, copy, rename, byte-compile, open as root
Buffer Switch to, kill, bury, open in other window
URL Browse, download, copy
Symbol Describe, find definition, find references
Package Install, delete, describe, browse homepage

There are over 100 preconfigured actions across all target types.

Beyond embark-act, Embark provides several other capabilities:

  • embark-dwim runs the default action without showing the menu
  • embark-act-all applies the same action to every current candidate (e.g., kill all matching buffers)
  • embark-collect snapshots current candidates into a persistent buffer
  • embark-live creates a live-updating collection that refreshes as you type
  • embark-export exports candidates into the appropriate Emacs major mode: file candidates become a Dired buffer, grep results become a grep-mode buffer (editable with wgrep), buffer candidates become an Ibuffer buffer
  • embark-become switches to a different command mid-stream, transferring your input

Embark is a difference of kind, not quantity, compared to Helm and Ivy's action systems — because it works everywhere, across all types of objects10.

The embark-consult integration package connects Embark with Consult: exporting consult-ripgrep results gives you a wgrep-editable grep buffer. This workflow — search with Consult, export with Embark, edit with wgrep — is one of the most powerful patterns in the modern Emacs ecosystem.

Created: May 2020. Stars: ~1,200. Available on: GNU ELPA.

11. Consult: The Command Layer   consult commands

Consult provides 50+ enhanced commands built on completing-read. It is the spiritual successor to Counsel (from the Ivy ecosystem) but designed to work with any completion UI. Where Counsel called ivy-read directly, Consult uses the native contract, which means its commands work with Vertico, Icomplete, fido-mode, or even Emacs's default completion buffer.

Consult's commands span several categories:

Search:

Command Purpose Replaces
consult-line Search lines in current buffer Swiper
consult-line-multi Search across multiple buffers Swiper-all
consult-ripgrep Async ripgrep search counsel-rg
consult-grep Async grep search counsel-grep
consult-git-grep Git-aware grep counsel-git-grep
consult-find Async file finding counsel-find

Navigation:

Command Purpose Replaces
consult-buffer Enhanced buffer switching helm-mini
consult-imenu Flat imenu with grouping helm-imenu
consult-outline Navigate headings with preview Built-in
consult-goto-line Goto line with live preview Built-in
consult-bookmark Enhanced bookmark selection Built-in
consult-recent-file Recent file selection with preview counsel-recentf

Editing and miscellaneous:

Command Purpose
consult-yank-from-kill-ring Browse kill ring interactively
consult-theme Preview themes before applying
consult-man Async man page lookup
consult-flymake Navigate Flymake diagnostics
consult-org-heading Navigate org headings

Three features make Consult particularly powerful:

Live preview: Most commands show a real-time preview as you navigate candidates. consult-line highlights the matching line in the buffer. consult-theme applies the theme before you select it. consult-goto-line scrolls to the line as you type the number.

Narrowing and grouping: consult-buffer combines buffers, recent files, bookmarks, and project items into a single unified list. Narrowing keys filter to a single source: b SPC for buffers, f SPC for files, m SPC for bookmarks. Custom sources can be added via consult-buffer-sources.

Two-level async filtering: Commands like consult-ripgrep split input at #: everything before it goes to the external tool as the search pattern, everything after it filters the results locally with your completion style. error#handler searches for "error" with ripgrep, then narrows to results containing "handler" using Orderless.

Created: November 2020. Stars: ~1,600. Available on: GNU ELPA.

12. Corfu: The In-Buffer Display Layer   corfu completion

Corfu (COmpletion in Region FUnction) is the in-buffer counterpart to Vertico. Where Vertico handles minibuffer completion display, Corfu handles the popup that appears at point when you complete a symbol while writing code or text. It is roughly 1,220 lines of code.

Corfu's defining architectural choice mirrors Vertico's: it hooks into Emacs's built-in completion-in-region mechanism rather than inventing its own backend system. Any mode that provides a completion-at-point-function (Eglot, Tree-sitter, elisp-mode, etc.) works with Corfu automatically. Any completion-style (basic, partial-completion, orderless) can be used for filtering.

This is the fundamental difference from Company, the incumbent in-buffer completion framework11. Company uses its own proprietary company-backends API. Company backends don't work with completion-at-point, and Capfs don't work with Company (without an adapter). Corfu eliminates this split. Doom Emacs recognized this: Company is now deprecated in Doom in favor of Corfu, with plans to remove it post-v312.

Aspect Company Corfu
Backend system Proprietary Emacs-native Capfs
Popup technology Overlays Child frames
Completion styles Limited Any Emacs style
Codebase size Many files, 3,900+ LOC in main file Single file, ~1,220 LOC
Created 2009 2021

Corfu ships with seven built-in extensions:

Extension Purpose
corfu-echo Brief candidate documentation in the echo area
corfu-history Sort by selection history/frequency
corfu-indexed Select candidates by numeric prefix argument
corfu-info Access candidate location and documentation
corfu-popupinfo Documentation popup adjacent to the completion menu
corfu-quick Avy-style quick key selection

Created: April 2021. Stars: ~1,400. Available on: GNU ELPA.

13. Cape: The In-Buffer Backend Layer   cape backends

Cape (Completion At Point Extensions) provides a collection of modular completion backends (Capfs) and a powerful set of Capf transformers for composing and adapting them. If Corfu is the frontend (how completions are displayed), Cape is the backend toolkit (what completions are available).

Cape provides 13 completion backends. The ones you'll reach for most often:

Capf Purpose
cape-dabbrev Dynamic abbreviation from current buffers
cape-file File path completion
cape-elisp-block Elisp completion inside Org/Markdown blocks
cape-keyword Programming language keyword completion
cape-history History completion in Eshell/Comint

The remaining backends cover dictionary words, emoji, abbreviations, line completion, and Unicode input via TeX, SGML, and RFC 1345 mnemonics.

Cape's Capf transformers are higher-order functions that wrap and modify backends:

  • cape-capf-super merges multiple Capfs into a single unified source
  • cape-capf-case-fold adds case-insensitive matching
  • cape-capf-inside-code / cape-capf-inside-string / cape-capf-inside-comment restrict activation to specific syntactic regions
  • cape-capf-prefix-length requires a minimum prefix before activating
  • cape-capf-predicate filters candidates with a custom predicate
  • cape-capf-sort applies custom sorting

The cape-company-to-capf adapter converts any Company backend into a standard Capf — without requiring Company to be installed. This bridges the two ecosystems: you can use Company-era backends (like company-yasnippet) with Corfu.

Created: November 2021. Stars: ~760. Available on: GNU ELPA.

14. The Subset Property: Use What You Want   modularity flexibility

The most important property of VOMPECCC is that any subset works. You don't need to buy into all eight packages. You can start with one, add another when you feel a gap, and swap any component for an alternative without breaking anything else.

This works because every package communicates through the native Emacs APIs rather than depending on each other's internals. There are no hard dependencies between any of the eight packages. Here is a map of what each package can be replaced with — or simply omitted:

Package Alternative Or simply…
Vertico Icomplete-vertical, Mct, Ido, fido-mode Default *Completions* buffer
Orderless Hotfuzz, Fussy, Prescient (filtering mode) Built-in flex or substring
Marginalia (none equivalent) No annotations (still works)
Prescient savehist-mode + vertico-sort-override Alphabetical sorting
Embark (none equivalent) Direct command invocation
Consult Built-in switch-to-buffer, grep, etc. Standard Emacs commands
Corfu Company, completion-preview-mode Default *Completions* buffer
Cape Company backends, hippie-expand Mode-provided Capfs

Some practical subset configurations:

Minimal (2 packages): Vertico + Orderless. You get a vertical candidate list with multi-component matching. No annotations, no actions, no enhanced commands — but a dramatically better M-x and find-file experience than stock Emacs.

Comfortable (4 packages): Vertico + Orderless + Marginalia + Consult. Now you have annotations on every candidate and enhanced commands with live preview. This is probably the sweet spot for most users.

Full stack (8 packages): All of VOMPECCC. Complete coverage of both minibuffer and in-buffer completion, with intelligent sorting, contextual actions, and modular backends.

The key insight is that "full stack" is not a prerequisite. Each package adds value independently. You never need to understand all eight before starting.

For reference, here is a consolidated configuration for the full stack:

;; --- Minibuffer display ---
(use-package vertico
  :ensure t
  :init (vertico-mode)
  :config
  (vertico-multiform-mode)
  (setq vertico-multiform-commands
        '((consult-line buffer)
          (consult-ripgrep buffer)
          (consult-imenu reverse))))

;; --- Filtering ---
(use-package orderless
  :ensure t
  :config
  (setq completion-styles '(orderless basic)
        completion-category-overrides
        '((file (styles partial-completion)))))

;; --- Annotations ---
(use-package marginalia
  :ensure t
  :bind (:map minibuffer-local-map ("M-A" . marginalia-cycle))
  :init (marginalia-mode))

;; --- Sorting ---
(use-package prescient :ensure t :config (prescient-persist-mode))
(use-package vertico-prescient :ensure t :after vertico :config (vertico-prescient-mode))

;; --- Actions ---
(use-package embark
  :ensure t
  :bind (("C-." . embark-act)
         ("C-;" . embark-dwim)
         ("C-h B" . embark-bindings)))

;; --- Enhanced commands ---
(use-package consult
  :ensure t
  :bind (("C-x b" . consult-buffer)
         ("M-g g" . consult-goto-line)
         ("M-g i" . consult-imenu)
         ("M-s l" . consult-line)
         ("M-s r" . consult-ripgrep)
         ("M-y" . consult-yank-pop)))

;; --- Embark + Consult integration ---
(use-package embark-consult
  :ensure t
  :after (embark consult)
  :hook (embark-collect-mode . consult-preview-at-point-mode))

;; --- In-buffer completion ---
(use-package corfu
  :ensure t
  :init (global-corfu-mode)
  :config
  (setq corfu-auto t
        corfu-auto-delay 0.2
        corfu-quit-no-match 'separator))

(use-package corfu-prescient :ensure t :after corfu :config (corfu-prescient-mode))

;; --- In-buffer backends ---
(use-package cape
  :ensure t
  :init
  (add-hook 'completion-at-point-functions #'cape-dabbrev)
  (add-hook 'completion-at-point-functions #'cape-file)
  (add-hook 'completion-at-point-functions #'cape-elisp-block))

15. Growth and Adoption Timeline   timeline adoption

The history of Emacs completion frameworks is a progression from monolithic solutions toward composable ones.

Year Event
1996 Kim F. Storm begins Ido
2007 Ido included in Emacs 22; anything.el created (Helm's ancestor)
2011 Volpiatto forks anything.el as Helm
2013–2018 Helm's golden era: most-downloaded MELPA package, default in Spacemacs
2015 Krehel creates Ivy/Swiper/Counsel
2016 "From Helm to Ivy" blog post sparks migration; Ivy peaks ~2016–2020
2017 Rosborough creates Prescient
2018 Helm enters bug-fix-only mode (maintainer burnout)
2019 Rosborough creates Selectrum (first completing-read​-native UI)
2020 Apr Antolin Camarena creates Orderless
2020 May Antolin Camarena creates Embark
2020 Sep Helm development officially stopped
2020 Nov Mendler creates Consult
2020 Dec Antolin Camarena & Mendler create Marginalia
2021 Apr Mendler creates Vertico and Corfu
2021 May "Replacing Ivy and Counsel with Vertico and Consult" (System Crafters)
2021 Selectrum deprecated in favor of Vertico; Doom Emacs adds Vertico module
2021 Nov Mendler creates Cape
2022 Doom Emacs switches default completion from Ivy to Vertico
2024 Ivy breaks with Emacs 30; Company deprecated in Doom in favor of Corfu

GitHub stars tell part of the story, but not all of it. Helm and Ivy accumulated stars over a longer period; the newer packages are growing faster relative to their age (counts as of early 2026):

Package Stars Created Approx. age
Helm ~3,500 2011 15 years
Ivy/Swiper ~2,400 2015 11 years
Vertico ~1,800 April 2021 5 years
Consult ~1,600 Nov 2020 5 years
Corfu ~1,400 April 2021 5 years
Embark ~1,200 May 2020 6 years
Orderless ~979 April 2020 6 years
Marginalia ~919 Dec 2020 5 years
Cape ~760 Nov 2021 4 years
Prescient ~695 Aug 2017 9 years

The community momentum is clear. Doom Emacs, one of the most popular Emacs distributions, has moved to Vertico + Corfu as its defaults13. Modern configuration guides almost universally recommend the modular stack14. And the upstream Emacs project itself has been integrating ideas from this ecosystem: Emacs 30 added completion-preview-mode, and Emacs 31 is incorporating Mct-inspired features.

16. The Trade-Off: Monolith vs. Composition   tradeoffs analysis

Engineering is about trade-offs. The modular approach has real advantages, but it also has real costs. Here is an honest accounting.

16.1. Advantages of VOMPECCC

No vendor lock-in. Every package builds on the same native contracts. If any one of the eight packages is abandoned, you replace it. Your other packages continue to work. Contrast this with Helm, where the maintainer's burnout announcement stranded an entire ecosystem of downstream packages.

Independent maintenance. Three different developers maintain the eight packages. Daniel Mendler maintains five (Vertico, Consult, Corfu, Cape, and co-maintains Marginalia) — so the overall bus factor is not dramatically higher than a monolith. But the key difference is structural: if Mendler stepped away, the remaining packages would continue to function independently. Omar Antolin Camarena's Embark and Orderless would keep working. Radon Rosborough's Prescient would keep working. Nobody's contribution is stranded by someone else's absence.

Incremental adoption. You start with one package and add more as you discover needs. There is no cliff of initial configuration. You never need to understand all eight before getting value from any one.

Smaller, auditable codebases. Vertico is ~600 lines. Corfu is ~1,220 lines. These are packages you can actually read end to end. Bugs are easier to find and fix in small, focused codebases.

Automatic ecosystem benefits. Because everything uses the native completion protocol, third-party packages benefit for free. Any command that calls completing-read gets your chosen UI, filtering, sorting, annotations, and actions without any integration code.

Future compatibility. Emacs itself continues to improve its built-in completion system. Packages built on the native protocol benefit from those improvements automatically. Packages built on proprietary APIs do not.

16.2. Disadvantages of VOMPECCC

Higher initial discovery cost. A newcomer searching "Emacs completion" finds eight packages instead of one. Understanding the role of each, and which subset to start with, requires more research than "install Helm" or "install Ivy." The conceptual overhead is non-trivial.

Configuration across packages. Eight packages means eight use-package declarations, eight sets of configuration variables, and eight places where something could be misconfigured. Helm's all-in-one approach means one declaration, one set of variables, one source of truth.

Interaction effects. While the packages are independent, some combinations require awareness of how they interact. Combining Orderless with Prescient requires understanding that Orderless handles filtering while Prescient handles sorting. The embark-consult integration package exists because the two packages benefit from knowing about each other in specific workflows.

Less out-of-the-box polish. Helm ships with dozens of purpose-built commands — helm-find-files has 44+ actions. With VOMPECCC, you compose those workflows yourself. The result is often more powerful, but you build it rather than unwrap it.

Documentation is distributed. Each package has its own README, its own issue tracker, its own wiki. There is no single "VOMPECCC manual." Cross-cutting workflows (search with Consult, export with Embark, edit with wgrep) are documented across multiple repositories.

16.3. When to Choose What

Choose VOMPECCC if:

  • You value understanding your tools and want to read the source code
  • You want completion that works identically with built-in and third-party commands
  • You want to invest incrementally rather than all at once
  • You care about long-term maintainability and Emacs version compatibility
  • You want to mix and match components as your needs evolve

Consider Helm if:

  • You want maximum out-of-the-box functionality with minimal configuration
  • You prefer a single point of documentation and support
  • You are comfortable depending on a single package and its API
  • You need one of Helm's highly specific, purpose-built features (like helm-top or helm-colors) and don't want to replicate them

Consider Ivy if:

  • You are already invested in the Ivy ecosystem with custom ivy-read code
  • You prefer Ivy's action selection UX
  • You need Spacemacs's Ivy layer specifically

For new configurations today, the community consensus points strongly toward the modular stack. Doom Emacs's switch to Vertico and Corfu, the deprecation of Selectrum, and the ongoing maintenance challenges of both Helm and Ivy have made the direction clear. The question is no longer whether to use the modular approach, but which subset to start with.

17. Conclusion   conclusion

I came to this stack the way most people probably do: one package at a time, over the course of a year or so. I started with Vertico and Orderless because my Ivy config had started fighting with Emacs 28 upgrades and I was tired of debugging someone else's ivy-read edge cases. Two packages, ten minutes of configuration, and M-x already felt better. Marginalia came next — once you've seen keybindings and docstrings next to every command, you can't unsee their absence. Consult replaced Counsel, Embark replaced the "exit completion, run a different command" dance, and Corfu replaced Company when I realized the same Orderless filtering I'd grown to depend on in the minibuffer wasn't available in my code buffers.

The whole migration happened incrementally, which is the point. I never sat down to "install VOMPECCC." I solved one friction at a time, and each solution composed with the ones I already had. That's the experience the architecture is designed to produce.

Nobody calls it VOMPECCC in Emacs circles — the name is mine, a mnemonic for an article, not a brand. But the packages it describes have quietly become the default recommendation for modern Emacs completion, adopted by Doom Emacs, recommended by Protesilaos Stavrou15, documented by System Crafters16, and built on by a growing ecosystem of third-party packages.

The shift from Helm to Ivy to the modular stack follows a familiar pattern in software: monoliths are convenient until they aren't. Composable tools with clear interfaces outlast the frameworks that try to be everything17. Emacs figured this out forty years ago. Its completion ecosystem just needed a few years to catch up.

Footnotes:

1

Sacha Chua's interview with Thierry Volpiatto (2018) provides a candid account of Helm's history. Volpiatto describes being a mountain guide with no programming background, discovering Linux in 2006, and gradually becoming Helm's sole maintainer. He also discusses the financial unsustainability of maintaining a package used by hundreds of thousands of users as a volunteer.

2

Helm accumulated over 640,000 downloads on MELPA, making it the most downloaded package on the archive at its peak. MELPA download counts are visible on the MELPA package page. The figure is cumulative since MELPA began tracking downloads in 2013.

3

Volpiatto's 2020 announcement (GitHub Issue #2386) was definitive: "Helm development is now stopped, please don't send bug reports or feature request, you will have no answers." The issue was locked to collaborators. The Hacker News discussion that followed highlights the difficulty of sustaining large open-source projects without institutional support.

4

The ivy-read signature can be inspected in ivy.el on GitHub. The Selectrum README (radian-software/selectrum) provides a detailed comparison of ivy-read with completing-read and explains why the deviation from the standard API created long-term maintainability problems.

5

McIlroy's articulation of the Unix philosophy appears in the Bell System Technical Journal's 1978 special issue on Unix (available at archive.org). The full quote is: "Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new 'features'." See also Eric S. Raymond's The Art of Unix Programming, Chapter 1, which elaborates on the philosophy's implications for software design.

6

The completing-read API is documented in the Emacs Lisp Reference Manual. The key design insight is that completing-read supports programmatic completion tables — functions that can compute candidates lazily based on the current input — which is essential for large or dynamic candidate sets like TRAMP hosts or LSP symbols.

7

Emacs's completion styles system is documented in the GNU Emacs Manual. The variable completion-styles controls which matching strategies are tried, in order, until one produces results. The completion-category-overrides variable allows per-category customization, so file completion can use partial-completion while M-x uses orderless.

8

The deprecation of Selectrum in favor of Vertico is discussed in Selectrum Issue #598. Radon Rosborough, Selectrum's original author, acknowledged that Vertico's design was superior because it properly supported dynamic completion tables — a corner of the completing-read API that Selectrum handled incorrectly.

9

ivy-rich (Yevgnen/ivy-rich) was a popular Ivy extension that added columns of information to Ivy completion candidates — essentially the same concept as Marginalia. The key limitation was that it was structurally coupled to Ivy: if you switched away from Ivy, you lost your annotations. Marginalia solves the same problem through the standard annotation-function API, making it framework-agnostic.

10

This characterization comes from Karthinks's "Fifteen Ways to Use Embark", one of the most comprehensive third-party guides to the package. The post demonstrates workflows that were impossible or impractical before Embark: acting on multiple candidates simultaneously, exporting completion results into native Emacs modes, and switching commands mid-stream without losing context.

11

Company-mode (company-mode/company-mode) was created by Nikolaj Schumacher in 2009 and has been maintained by Dmitry Gutov since 2013. It remains actively maintained with ~2,300 GitHub stars. The architectural critique here is specific to the backend API: company-backends is a separate protocol from completion-at-point-functions, which means backends written for Company don't work with other completion UIs, and vice versa.

12

The Doom Emacs Corfu module was merged in PR #7002 in March 2024. The Discourse discussion explains the rationale: Corfu aligns with Emacs's native completion infrastructure, while Company's proprietary API creates friction with the rest of the modern completion stack.

13

Doom Emacs's completion modules are documented at docs.doomemacs.org. The Vertico module includes pre-configured integration with Orderless, Marginalia, Consult, and Embark. The older Ivy and Helm modules remain available but are no longer the recommended default.

14

Notable guides recommending the modular stack include: Martin Fowler's "Improving my Emacs experience with completion" (2024), which documents his switch to the Vertico ecosystem; the "Guide to Modern Emacs Completion" by Jonathan Neidel, which walks through the full Vertico/Corfu stack; and Kristoffer Balintona's multi-part "Vertico, Marginalia, All-the-icons-completion, and Orderless" series (2022).

15

Protesilaos Stavrou's "Emacs: modern minibuffer packages (Vertico, Consult, etc.)" is a ~44 minute video demonstrating the full stack. Stavrou is also the author of Mct (Minibuffer and Completions in Tandem), an alternative approach that reuses the built-in *Completions* buffer with automatic updates. His recommendation of Vertico despite having written a competing package speaks to the strength of the ecosystem.

16

System Crafters' "Streamline Your Emacs Completions with Vertico" and the companion video "Replacing Ivy and Counsel with Vertico and Consult" (May 2021) were early catalysts for community adoption. David Wilson (System Crafters) documented his own migration from Ivy and provided configuration examples that became widely copied.

17

The pattern of monoliths giving way to composable architectures is well-documented in software engineering. Fred Brooks described the "second system effect" in The Mythical Man-Month (1975), where the follow-up to a successful lean system tends to be an overdesigned monolith. More recently, the microservices movement explicitly applies the Unix philosophy to distributed systems — with similar trade-offs around discovery cost, operational complexity, and distributed debugging.