Learn Practice Daily golf Reference
Guides · Vim in your editor

Vim mode in Zed: setup, keys and settings

Zed has Vim mode built in: tick the Vim mode checkbox on the welcome screen, run workspace: toggle vim mode from the command palette, or add "vim_mode": true to your settings. Motions, operators, text objects, macros and many : commands work, plus Zed-specific keys such as gd for go to definition and cd for rename. Customise keys in keymap.json with contexts like vim_mode == insert.

Zed-specific keys in Normal mode (from the Zed docs)
KeysWhat they do
gd / gD Go to definition / declaration
gy / gI Go to type definition / implementation
cd Rename the symbol (language server)
gA All references to the symbol
gs / gS Symbols in this file / in the project
]d / [d Next / previous diagnostic
gh / g. Show the error under the cursor / code actions
]c / [c Next / previous git change
gl / gL Add a cursor at the next / previous copy of the word
ga Select every copy of the visual selection
af / if, ac / ic Function and class text objects (Tree-sitter)
ia / aa Argument text object, without / with its trailing comma

Turn on Vim mode

Three ways, all doing the same thing:

  • First launch: tick the Vim mode checkbox on the welcome screen.
  • Command palette: run workspace: toggle vim mode.
  • Settings file: add "vim_mode": true to your user settings.

Esc takes you back to Normal mode as usual. For relative line numbers, set Zed's core "relative_line_numbers" to "enabled", or use the Vim setting toggle_relative_line_numbers (below) to have them only in Normal mode.

Vim settings worth changing

Vim options go in a "vim" object in your settings:

  • "use_system_clipboard": "always" (the default), "never", or "on_yank". Unlike Vim, Zed uses the system clipboard by default; pick "never" if you want yanks to stay inside the editor.
  • "use_smartcase_find": makes f and t case-insensitive when the letter you type is lowercase. Off by default.
  • "toggle_relative_line_numbers": relative numbers in Normal mode, absolute in Insert mode. Off by default.
  • "highlight_on_yank_duration": how long a yank is highlighted, in milliseconds (200 by default; 0 turns it off).
  • "gdefault": makes :s replace every match on a line by default; the g flag then flips it back. Off by default.
  • "default_mode": the mode new editors start in, "normal" by default.

One core setting matters too: "command_aliases" maps names you type at the : prompt to Zed commands, for example "W": "w".

Customise keys: jk to Escape and more

Key bindings live in Zed's keymap.json (~/.config/zed/keymap.json on macOS and Linux); run zed: open keymap file from the command palette to open it. It holds an array, and each entry has a "context" that says when it applies and a set of "bindings". For j k to leave Insert mode, add this entry to the array:

  • {
  • "context": "vim_mode == insert",
  • "bindings": { "j k": "vim::NormalBefore" }
  • }

The contexts that matter for Vim are vim_mode == normal, visual, insert, replace, waiting and operator, and VimControl, which covers Normal, Visual and Operator-pending together. Combine them with && and ||, for example "Editor && vim_mode == normal".

The Zed docs include ready-made snippets for the most common requests: Ctrl-w with h j k l to move between docks and panes, subword motions for w, b and e (vim::NextSubwordStart and friends), s as a sneak motion (vim::PushSneak) instead of substitute, and giving Ctrl-c, Ctrl-v and Ctrl-f back to Zed.

Plugins you get for free

Zed has its own versions of several favourite Vim plugins, on by default:

  • Surround: ys, cs and ds, as in vim-surround.
  • Comment: gcc in Normal mode, gc in Visual mode, as in vim-commentary.
  • ReplaceWithRegister: gR. Exchange: cx.
  • Indent navigation: [-, ]-, [+, ]+, [=, ]= jump by indentation level, as in vim-indentwise.
  • Tree-sitter motions: ]m and [m for the next and previous method, ]] and [[ for sections, ]/ for comments.
  • Insert mode completion: Ctrl-x Ctrl-o for completions, Ctrl-x Ctrl-l for code actions.
Try it here

Warm up: a text object and a comment

Two things Zed's Vim mode does out of the box. Change the string with ci" (change inside the quotes), then comment out the debug line with gcc.

1 of 2Change the text inside the quotes to zed: ci", type, Esc
1let name = "vim";
1println!("hello, {}", name);
2dbg!(name);
NORMALLoading the editor…1/20.0s1:14

This editor needs a keyboard. Read on, and play it at your computer.

Which colon commands work

Zed's command line covers the everyday ones: :w, :wq, :q, :wa, :qa, :x, :up, splits (:sp, :vs, :new, :vne), tabs (:tabnew, :tabn, :tabp, :tabc), :bd and :ls. It also has jumps (:42, :$, :/foo), :s with ranges, :j, :d, :y, :sort and :sort i, and :set for wrap, number, relativenumber and ignorecase. Commands such as :E (explore), :te (terminal) and :G (git) open Zed's own panels.

What it doesn't do is take arguments: you can't name a file in :w newname.txt, and most of Vim's command-line power isn't emulated.

Known differences from Vim

The Zed docs are upfront that Vim mode is not a one-to-one copy:

  • Language-aware motions. Zed uses its own semantics in places: in Rust, % also jumps between matching | characters, and w treats $ as part of a word in JavaScript.
  • Visual block mode is emulated with multiple cursors, so text you insert appears on every line as you type rather than when you press Esc.
  • Macros use Zed's own recording, which can capture actions such as accepting a completion.
  • Regex in search and :s uses ( and ) for groups instead of \( and \), and $1 instead of \1 in replacements. Searches are global by default.
  • No vimrc and no Vim plugins. All configuration goes through Zed's settings and keymap.json.

For most editing, none of this gets in the way. The motions are the same as in Vim, and the course teaches them in a real editor in the browser.

Practise the keys

The keys behind the differences

Each of these works in Zed, with the differences described above. Type them from memory.

Start Visual block mode (multiple cursors, in Zed).
scroll here, then press the keys
1 of 5
Start Visual block mode (multiple cursors, in Zed).

Questions

How do I turn off Vim mode in Zed?
Run workspace: toggle vim mode from the command palette, or set "vim_mode": false in your settings.
How do I map jk to Escape in Zed?
In keymap.json, add an entry with "context": "vim_mode == insert" and "bindings": { "j k": "vim::NormalBefore" }.
Does Zed vim mode read my .vimrc?
No. Zed reads its own settings and keymap.json. Vim options go in the "vim" settings object, and mappings go in keymap.json with a Vim context.

Sources