Computer Things

Archives
Log in
Subscribe
August 18, 2026

Vim wants you to control, VSCode wants you to consume

The two sides of the editor divide, and why I'm on the losing side.

Newsletter updates were sporadic in July because of two weddings, two conferences (with two different talks!), and finishing Logic for Programmers. Huge thank you to everybody who bought a copy, as well as for your patience with the schedule. There's some podcast appearances, a conf talk, and a book sale at the end of this post.

Newsletter updates will be sporadic in August because I just started my Developer Educator job at Antithesis. I'll have less time to write because I'll be working 40 hour workweeks, about 8 hours of which being actual work and the other 32 being bashing my head against NixOS.

NixOS is the standard developer OS at the company. It's also a notoriously difficult distro to learn even for Linux heads, and I'm coming from Windows. The only way I am going to get anywhere is to go all in and commit fully to the NixOS philosophy.1 For one, I'm seeing how long I can last without my customary 2000-line Neovim config.

Which immediately raises the question as to why I have 2000 lines of Neovim config. It's because Vim2 (and Emacs) think of configuration in a very different way than more popular editors do.

Control and Consumption

Say we want to make ctrl+n to save the current file. In VSCode, you put this in keybindings.json:

[
  {
    "key": "ctrl+n",
    "command": "workbench.action.files.save"
  }
]

In Neovim, you put this in init.lua:

vim.keymap.set('n', '<c-n>', function() vim.cmd.write() end)

Now, a couple of differences to see. First, the VSCode example is invoking a fixed, built-in command, while Neovim can bind an arbitrary function. Second, in VSCode you edit a static configuration file with static data, while in Neovim you execute a command that edits the running editor state. In fact, it doesn't even need to be in a configuration file: you can add a new keymap directly from the command line. Though you'd probably instead do that command in the OG Vim way:

map <c-n> :w<CR>

And that does something different than a function: it makes pressing ctrl+n mean "do whatever typing :w and pressing Enter would do." In default Vim that is the same as saving a file, but if you remapped : to o then it would instead do the equivalent of ow<cr>, which would type the character w on its own line. 3

In other words, Vim gives you incredible programmatic control over the state of the editor. Want to make typing ;r paste from the clipboard? Easy. Want different setting options in normal and insert mode? Go ahead. Want to make "writing a file" do something different during a full moon? You could if you want. 4

Now, you can do some amount of customization in VSCode, especially with multicommands, but for the majority of complex stuff you need to write a plugin. And making a plugin in VSCode is a much heavier process than making one in Neo/Vim. If you want to make a command that prints the word count, you have to 1) learn TypeScript, 2) scaffold a special VSCode extension project, 3) define a wordcount function, 4) register the mycode.wordcount command, 5) add mycode.wordcount as a contributes record in the extension manifest, 6) package or publish your extension, and 7) import the extension. It's very clear that the plugin system is not meant to let you tweak in a bit of functionality, but rather to let specialists produce complete plugins for other developers to consume. And since so much of the advanced functionality of VSCode is only possible through plugins, this limits the control the average user has over their environment.

Neovim also has plugins, but they can't do anything you couldn't already do in your default config. Admittedly, some bits of the APIs are meant specifically for plugin specialists, but they're still documented and available for your personal configuration. You never know what someone's gonna need!

In summary:

  • VSCode has a two-tier system, where plugin makers make plugins that users consume. The plugin has more power than the user. Most users aren't expected to make their own extensions.
  • Vim has a one-tier system: the user can do anything a plugin can. Everybody is always able to extend the system and have as much control as they want.

Most people should be consumers

Confession: this all is unintentionally a little ragebaity. "Consumer" is a dirty word in software. A consumer is somebody at the mercy of a producer's decisions. I think there's even a connotation of passiveness in being a consumer. It sort of starts leaning into a moral judgment: developers should use Neovim because it gives them control.

But, and this is intentionally a little ragebaity, it's the other way around. Most developers are better off sticking with the consumer model and only switching to a control-editor if they really, really want to. 5

First of all, learning to configure and extend Vim is hard. It took me a long time to get comfortable with even making basic scripts. And even if I'm comfortable hacking Vim, I still need to consume other people's plugins if I want a modern developer experience. I'm not writing my own treesitter integration from scratch! 6

Second, while the experience of developing plugins is worse on VSCode, the experience of consuming them is far, far better:

  • All plugins install, set up, and are used the same way. When I install a new plugin I don't have to spend ten minutes reading docs to get it working.
  • I can read a list of all the new commands, keybindings, and configuration options added by the extension. I can edit any configuration option in the same settings UI, which has features like global search and input validation.
  • I can enable and disable extensions without changing my startup scripts, and I can enable extensions for only specific workspaces.
  • If a plugin adds a keybinding that conflicts with my custom keybindings (or another plugin's keybindings), VSCode will tell me instead of silently clobbering the older one.
  • I can't break a plugin through a weird script I run at startup or by installing a different plugin.
  • A plugin can't break my startup.

These are all possible precisely because the VSCode plugin system is so heavyweight and inflexible and because everything is configured through static JSON files. Figuring out what configuration options a Neovim extension has is tantamount to solving the Halting Problem.

(The broader principle here is the ability-guarantee tradeoff. 7 A VSCode extension can do fewer things than a Vim extension can, and therefore we have more guarantees about what it actually does. Exploring the AGT is one of the running themes of Logic for Programmers.)

The consumption paradigm is worse than the control paradigm in a lot of ways but it's so much better in this one specific, extremely important way that it's the right choice for most developers. To some extent I wonder if preferring control is more a personality trait than a measured tradeoff. I'm unhappy when I can't tweak some software just to my liking, it just grates on me that something's off and can't be fixed. If tomorrow I woke up and was just not bothered by that, would I still prefer Neovim to VSCode? I dunno. Maybe I'll find out as part of The Nix Experience.


Now there's a third point in the design space I haven't talked about: what if the editor restricted both your control and consumption? Helix, for example, allows adding LSP servers and treesitter grammars but not any other kind of plugin.8 It also has a static and very limited configuration language. You can't even set different keybindings for different filetypes.

That seems crazy to me! But a lot of people seem to like it, and I've been interested in Kakoune-style modal editing for a while now. So now I'm running Helix as my main terminal editor. I don't know if I will stick with it; I feel like I'll eventually crave a more hackable editor. But at least then I'll be more comfortable with Nix before trying to import my thousands of lines of Neovim conf.


Appearances and stuff

Three this time:

  • I was on the Pragmatic Engineer podcast, talking about math, formal methods, AI, and the Crossover Project. Listen if you like the word "like" and check out the video for mad Stan hands.
  • I was also on Leanpub Launch advertising LfP (accompanying blog).
  • Last month I was at the inaugural Software Should Work conference, giving my standard talk on practical ideas in formal methods. But for some reason my computer wouldn't connect to A/V and nobody on the staff had Powerpoint, and large chunks of the presentation just Didn't Work on keynote. Watch me tapdance on a tightrope in an earthquake here. Somehow I pulled through.

Oh, also Amazon is selling Logic for Programmers for 15% off for some reason. I confirmed I get the same royalties either way, so hey, it's cheaper with no downside. I have no idea how long the sale will last.


  1. Technically I don't have to use NixOS because I'm not on the core engineering team, but I'm not a quitter ↩

  2. I'm going to use Vim and Neovim interchangeably because the core essence is the same (even if the APIs and scripting languages are different) and because I have less time than usual to edit this newsletter. ↩

  3. For this reason it's best practice to use noremap instead of map, which doesn't do recursive remapping. There are some niche uses for map though! ↩

  4. via the BufWriteCmd event. This is useful for things like editing stuff in a zip file or over FTP. ↩

  5. For the record, this is talking about developers who want/need an IDE like experience. There are reasons to use vim besides controllability, like its ubiquitousness on Linux servers. ↩

  6. But I will write my own task runner. ↩

  7. I originally called this the capability-tractability tradeoff but now think "ability-guarantee" is less pretentious. ↩

  8. I know there's been some work on a Scheme-based plugin system but I don't know how close that is to actually being official. ↩

If you're reading this on the web, you can subscribe here. Updates are once a week. My main website is here.

Logic for Programmers is now available in print!

Don't miss what's next. Subscribe to Computer Things:
Older → Logic for Programmers is Done

Add a comment:

Posting this comment will subscribe you to this newsletter with the email address you enter.
Powered by Buttondown, the easiest way to start and grow your newsletter.