Using Zed as a Neovim User

Why I'm using Zed as a long-time Neovim user

I have been a Neovim user since at least June of 2020 and I have absolutely loved it! I learned about modal editing and have never looked back. Even in environments where I was forced to use other editors, I found the Vim mode and used it. So why would I look elsewhere, especially Zed? I specifically remember this interview between ThePrimeagen and Thorsten Ball about editors and the amount of work that went into developing the Vim mode for Zed. I was captivated by the level of care that went into porting a solid Vim experience into a different editor, a far cry from the Vim mode of VSCode. Furthermore, I became interested in Zed’s WASM-based plugin system, an idea i have been advocating for in other projects I am a part of. So I decided to give it a shot for about a month to see what I liked about Zed.

Setting up my environment

My Neovim workflow largely revolves around Telescope, Harpoon, gitsigns.nvim, and nvim-lspconfig. I don’t use tools like mason.nvim as I had already written tooling to handle only loading installed LSPs on my PATH. This is because I don’t like having my editor manage my tools (a problem I am still not jazzed about in Zed). With that in mind, how can I emulate the functionality of these plugins?

First up, Harpoon. In my Neovim config, I have harpooned files mapped to <leader>-<number>. Where number is mapped from zero to eight. Since Zed uses tabs, we can emulate this be using something like this:

{
	"context": "Editor && (vim_mode == normal || vim_mode == visual) && !VimWaiting && !menu",
	"bindings": {
	  ", 1": ["pane::ActivateItem", 0],
	  ", 2": ["pane::ActivateItem", 1],
	  ", 3": ["pane::ActivateItem", 2],
	  ", 4": ["pane::ActivateItem", 3],
	  ", 5": ["pane::ActivateItem", 4],
	  ", 6": ["pane::ActivateItem", 5],
	  ", 7": ["pane::ActivateItem", 6],
	  ", 8": ["pane::ActivateItem", 7]
	}
}

For Telescope, I use two specific finders, find files and fuzzy search. Luckily, Zed supports this functionality. For finding files I generally use <leader>-ff (for find files) and <leader>-fg for fuzzy search.

{
	"context": "Editor && vim_mode == normal",
	"bindings": {
	  ", f f": "file_finder::Toggle",
	  ", f g": "pane::DeploySearch",
	}
}

Lastly, what about LSP keybinds? I largely use hover, code actions, go-to-definition, and rename. So I matched those keybinds in Zed:

{
	"context": "Editor && vim_mode == normal",
	"bindings": {
	  ", c r": "editor::Rename",
	  ", c a": "editor::ToggleCodeActions",
	  "shift-k": "editor::Hover",
	  "g d": "editor::GoToDefinition",
	}
},

Great! We know have a usable dev environment! Now to the editing!

The Good

One thing I really liked about Zed is that it is fast. There is no noticeable latency when typing and it feels like an extension of my fingertips when working. Similarly for the integrated terminal. Very rarely have I come across an GUI-editorterminal that is as fast as my native terminal, but Zed is one of them. Additionally, I found the built-in themes excellent and with treesitter-based highlights built-in I almost never had to find highlights for files (there are some exceptions to this we will get to later). Furthermore, Zed has an excellent LSP implementation that compliments multi-cursors and multi-buffer editing (features I had not experienced in Neovim).

One feature that I love the adoption of is WebAssembly-based plugins. These plugins provide a simple ABI using the WASM Interface Type (WIT), enabling a simple yet powerful API for interfacing with host systems. In my opinion, this is a great design choice that I would love to see grow. There is even room to expand the zed_extension_api to write plugins in non-Rust languages using a similar to the approach to what is done in zig-spin!

Additionally, the Python experience is excellent in Zed, working with virtual environments is a breeze with auto-activation of virtual environments or direnv. You also get support for Ruff out of the box.

While I am trying to use AI functionality less, Zed has a great implementation that provides numerous models and even supports Ollama for local applications. I find it useful when I need it and generally pretty intuitive. What I like about it is that it is less invasive by default when compared to using my personal favorite of copilot-cmp in Neovim.

The best part about all of this is you get it out of the box with minimal and declarative configuration.

The Less Good

I find having my terminal docked in one spot to be a bit cumbersome. In my workflow, I generally run two terminals, one with my editor and one with everything else (although this is shifting). This experience just is not as nice in Zed (although doable) but I find this to be just a nitpick.

I am not a huge fan of using JSON for configuration, I find it hard to read and cumbersome. This is a huge failure for Zed, especially when they are already deep in the Rust ecosystem. I would love to see the use of TOML for managing configuration. For simple configs, I find it easy to read and maintain.

While for most my work, I can jump into any file and it just works, there are a few exceptions when it comes to newer technologies. A great example of this is actually one of the languages used in this blog, SuperMD. While SuperMD does have treesitter queries, they have not been added as a language extension yet into Zed (in fact Neovim hasn’t merged this in upstream due to instability). Zed is still a young editor when it comes to plugins, so I won’t fault its shortcomings in being able to work with new filetypes, but I do believe leaning into allowing other languages to use their WASM interface would help to flesh out their ecosystem.

One big missing piece from my workflow was what I use gitsigns.nvim for, staging hunks. While I love the Git UI that currently exists in Zed, I really miss having a keybind to quickly stage a hunk. I have no problem using Git in the terminal, but I much prefer staging hunks from my editor.

Early on in this experiment, I did have a few issues with running Zed on an old version of Gnome Wayland that caused my machine to stutter, but I imagine this is more of a Linux issue than a Zed one. I expect that as Wayland adoption is better, support in Linux with Zed might get better over time.

Where am I going from here?

All and all, I am loving Zed on my Mac. I am not sure if I will be returning to Neovim full-time anytime soon but I do find that when I need to quickly edit a config, Neovim is still my go-to. This whole experience of having an editor that requires less work to maintain, has led me to consider slimming down my Neovim config to have just the essentials, a few keybindings, a few LSPs, and less programmatic configuration. I find that I love that I can open my editor and it just works. I don’t have to worry about installing many extensions or my editor slowing down because it just works. If you are on macOS and are considering using Zed, give it a try and share your experience! Thank you Neovim, you have forever changed how I write code, but for now, I think we need a break.

Reply on Bluesky here to join the conversation.