Avoiding Emacs bankruptcy, with good financial habits

Disclaimer: All ways of using Emacs are valid ways of using Emacs. This is describing just one.

Emacs is a complex program, to the point that the dreaded emacs bankruptcy afflicts many, in which your config “gets so large that you really need to start over”.

I’ve nearly been there, drawn in with the allure of a useful package here and there, which results in various long-term costs:

But over time I’ve settled on an approach that has kept me far from bankruptcy using off-the-shelf financial advice: frugality, and paying back debt.


This idea is that packages must have a high power-to-weight ratio: providing useful functionality, but not incurring many long-term costs.

Emacs provides a set of subsystems that play well together, and offer hooks for extension. Third party packages vary on how well they adhere to these subsystems.

Minibuffer completion

Emacs has a variety of minibuffer completion tools: the UI you see when you M-x. Older tools such as Ivy/Helm/Swiper offer a popular UI, but do so without interoperating with the wider ecosystem.

Around 2020, a suite of interopable alternatives were developed that build upon the built-in completing-read function: Vertico, Orderless, Consult, and the built-in (vertical-fido-mode).

Vertico’s docs discuss this more.

Recommendation: Use the built-in (vertical-fido-mode). If you want something more, look into Vertico.

Syntax checking

Flymake has been in Emacs since 2004. Due to its lack of features, the third-party flycheck brought in a wave of innovation, and became the defacto standard syntax checker.

Since Emacs 26, Flymake has achieved ~feature parity. Flycheck’s extensive checkers can be used in Flymake via the flymake-flycheck adapter.

Recommendation: Use the built-in Flymake. Try (consult-flymake) as a UI.

Language server protocol

Language Server Protocol is the open protocol to allow editors to use external servers that provide language intelligence tools.

lsp-mode was the first popular implementation, which came with its own ecosystem.

Eglot was then developed, reusing other Emacs subsystems such as Flymake, ElDoc, Xref and Project. Eglot is now built-in with Emacs.

Recommendation: Use the built-in eglot.


In 2011, Projectile was created to provide project support, e.g. find files within a Git repo.

Emacs 25 introduced built-in project support, which now has integration with other subsysytems.

Projectile still has a wider feature set, but I live without these.

Recommendation: Use the built-in project package. Try C-x p p.

Version control

Emacs has built-in version control support, which abstracts which VCS (Git, Hg, SVN, …) you are using. diff-hl extends this to provide in-buffer highlighting of diffs.

Magit is a great UI for interacting with Git.

I have no recommendations here. I use magit and vc.el. I’d love to see a Magit-inspired UI built on top of vc.el.

Visualising the undo tree

Emacs stores a rich undo history that is best visualised as a tree.

Historically, undo-tree provided this, but in doing so it reimplemented a large part of undo functionality, resulting in a 4500 line package.

vundo is a simpler package that reuses the built-in undo functionality, and weighs in at 1500 lines.

Recommendation: Use vundo.

Paying back debt

The second idea is to pay back debt.

All config is debt. The ideal way to reduce this is to upstream an improvement that makes you happy with defaults. But sometimes that’s not always possible.

The next best alternative is to ruthlessly delete config that’s providing marginal value:

All gone!

Did I throw the baby out with the bath water?

Since Emacs’s strength is its customisability, then have I sacrified its very strength by taking this frugal approach?

A little bit, yes. But Emacs’s primary benefits for me (introspectibility, extensibility, durability) still stand, even in the face of frugality.

What about Emacs distributions, such as Doom Emacs?

I don’t have any experience with these, but Doom Emacs looks to produce a great out-the-box experience. I prefer my upstream to be Emacs, and to build my base on the well thought-out and documented abstractions of plain Emacs.


In summary: