Look, Zed's config system is actually pretty sane compared to most editors. No XML hell like IntelliJ's project structure, no 500-line init files like Emacs, just JSON with comments that actually makes sense. But there are gotchas that VS Code users won't expect.
Where Your Config Actually Lives (And Why It Sometimes Doesn't Work)
Global Settings (the ones that matter most):
- macOS/Linux:
~/.config/zed/settings.json
- Windows:
%APPDATA%/Zed/settings.json
Project Settings (where team configs go to die):
.zed/settings.json
in project root- These override global settings when they feel like working
- Half your team will forget to commit this file, guaranteed
Keybindings (prepare for vim mode pain):
- Global:
~/.config/zed/keymap.json
- Project:
.zed/keymap.json
(rarely used, thankfully)
Settings That Actually Work (Learned the Hard Way)
Here's a config that won't make you rage-quit back to VS Code:
{
// Basic shit that should just work
"theme": "Ayu Dark", // "Ayu Mirage" breaks syntax highlighting on some languages
"vim_mode": true, // Prepare for 2 hours of keybinding conflicts
"tab_size": 2, // Your team will fight over this, just pick 2
"soft_wrap": "editor_width", // Without this, long lines disappear into the void
// Font settings (because Zed's defaults are tiny)
"buffer_font_family": "JetBrains Mono", // Or whatever monospace font doesn't hurt your eyes
"buffer_font_size": 14, // 12 is for people with better eyes than me
"ui_font_size": 16,
// File handling that won't lose your work
"autosave": "on_focus_change", // "on_window_change" is more aggressive but saved my ass
"format_on_save": "off", // Turn this ON and watch your git diffs explode
"show_whitespaces": "selection",
// Collaboration panels (that nobody uses yet)
"chat_panel": {"dock": "right"},
"collaboration_panel": {"dock": "left"}
}
Pro tip: Start with format_on_save
: off
until you configure your formatters properly. I've seen 50-line commits turn into 500-line reformats because someone had different prettier settings or eslint configs. EditorConfig helps but doesn't solve everything.
Language Servers That Won't Make You Cry
Language servers in Zed are fast when they work, but they crash more often than VS Code's LSP implementation. The Language Server Protocol is supposed to standardize this, but different implementations have different reliability. Here's how to make them actually work:
TypeScript: Don't Let It Kill Your CPU
{
"languages": {
"TypeScript": {
"format_on_save": "off", // Start with this OFF, enable per-project
"formatter": "prettier", // Works but slower than you'd expect
"code_actions_on_format": {
"source.organizeImports": true // This breaks on large codebases
}
}
},
"lsp": {
"vtsls": { // They switched from typescript-language-server, fyi
"settings": {
"typescript": {
"preferences": {
"includeCompletionsForModuleExports": false // Reduces noise
},
"suggest": {
"autoImports": false // Enable this and watch your CPU melt
}
}
}
}
}
}
Python: Just Use Ruff (It Does Everything Now)
{
"languages": {
"Python": {
"format_on_save": "on", // Ruff server handles this fast
"formatter": [
{
"code_actions": {
"source.organizeImports.ruff": true,
"source.fixAll.ruff": true
}
},
{
"language_server": {
"name": "ruff"
}
}
],
"language_servers": ["pyright", "ruff"] // pyright for completion, ruff for linting/formatting
}
},
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lineLength": 100,
"lint": {
"select": ["E", "W", "F", "I"] // E=errors, W=warnings, F=pyflakes, I=isort
}
}
}
}
}
}
Rust: rust-analyzer That Actually Works
{
"lsp": {
"rust-analyzer": {
"settings": {
"rust-analyzer": {
"check": {
"command": "clippy", // Slower but catches more issues
"extraArgs": ["--", "-W", "clippy::pedantic"]
},
"cargo": {
"loadOutDirsFromCheck": true, // Necessary for proc macros
"features": "all" // Don't ask me why this isn't default
},
"procMacro": {
"enable": true // Required for most modern Rust projects
}
}
}
}
}
}
Language servers die. vtsls crashes when you hit 50MB+ JSON files. rust-analyzer locks up on proc macros that generate 10,000+ lines. When this shit happens, Cmd+Shift+P
→ "zed: restart language server" is your lifeline. I've bound this to <leader>lr
because I use it 3+ times per day on our React monorepo.
Vim Mode: Better Than Expected, Still Annoying
Zed's vim mode is actually pretty good, but prepare for some muscle memory adjustments. Here's what works and what'll make you scream:
Leader Key Setup That Won't Drive You Insane:
// keymap.json - THIS GOES IN A SEPARATE FILE
[
{
"context": "VimControl && !menu",
"bindings": {
"space": "vim::Leader", // Space leader key, fight me
"space f": "file_finder::Toggle", // Works like fzf, mostly
"space b": "tab_switcher::Toggle",
"space p": "command_palette::Toggle", // Actually useful
"space /": "editor::ToggleComments" // Better than gcc
}
}
]
LSP Navigation (The Good Stuff):
[
{
"context": "Editor && VimControl && !VimWaiting && !menu",
"bindings": {
"g d": "editor::GoToDefinition", // Works 90% of the time
"g r": "editor::FindAllReferences", // When it works, it's fast
"g i": "editor::GoToImplementation",
"[ d": "editor::GoToPrevDiagnostic", // Better than :cnext
"] d": "editor::GoToNextDiagnostic",
"shift-k": "editor::Hover" // K for hover info, like real vim
}
}
]
What doesn't work (this cost me 2 hours yesterday):
- No
:s/find/replace/g
- had to manually fix 47 import statements - Visual block mode crashes on files >1000 lines
- Macro recording? Doesn't exist. I miss my
@q
workflow from Neovim - Registers are wonky -
"1p
sometimes pastes old clipboard content
Team Configuration: How to Not Hate Each Other
Project .zed/settings.json
that won't cause merge conflicts:
{
"formatter": "prettier", // Pick ONE formatter and stick with it
"format_on_save": "off", // LEAVE THIS OFF until everyone agrees
"tab_size": 2, // Non-negotiable for sanity
"preferred_line_length": 100, // 80 is for the 1980s
"git": {
"git_gutter": "tracked_files" // Shows changed lines, actually useful
},
"languages": {
"TypeScript": {
"code_actions_on_format": {
"source.organizeImports": true // Only enable if your imports are a mess
}
}
}
}
Team migration reality: Our React team of 8 devs tried switching last quarter. 3 loved the speed boost and stayed. 2 went back to VS Code after a week because they needed specific extensions. 3 are still complaining but using it anyway.
Dave (our senior dev) switched in 2 days because he's used to vim. Sarah took 3 weeks and kept asking "where's the Python debugger?" Our junior devs adapted fastest - less muscle memory to unlearn.
Start with one team, not the whole engineering org. We rolled it out to frontend first, then backend 6 months later after working out the kinks.