Zed
8 min read
High-performance code editor built in Rust by the creators of Atom and Tree-sitter. GPU-rendered UI (GPUI framework) — stays fast at any file size. Designed for speed, collaboration, and AI-assisted development.
Key Features
• GPU-rendered UI via GPUI — no Electron
• Tree-sitter for syntax and semantic parsing
• First-class LSP integration
• Vim mode (modal editing with LSP/Tree-sitter awareness)
• Inline AI editing, agent panel, edit prediction
• SSH remote development (UI local, everything else remote)
• Real-time collaboration via Channels
• Multi-buffer editing — compose views across multiple files
• Built-in debugger (DAP)
• Tasks system with editor context variables
Config using Nix
Home Manager module programs.zed-editor:
nix
programs.zed-editor = {
enable = true;
package = pkgs.zed-editor;
installRemoteServer = true; # symlinks headless server for SSH remote dev
defaultEditor = true; # sets $EDITOR and $VISUAL
# mutable = Zed can still write changes from the GUI
mutableUserSettings = true;
mutableUserKeymaps = true;
extensions = [ "toml" "nix" "catppuccin" "html" ];
userSettings = {
vim_mode = true;
theme = "Catppuccin Mocha";
buffer_font_family = "Zed Mono";
buffer_font_size = 14;
format_on_save = "on";
assistant = {
default_model = {
provider = "anthropic";
model = "claude-sonnet-4-6";
};
version = "2";
};
};
userKeymaps = [
{
context = "Editor && vim_mode == normal";
bindings = { "space f" = "file_finder::Toggle"; };
}
];
userTasks = [
{
label = "cargo check";
command = "cargo check";
cwd = "$ZED_WORKTREE_ROOT";
reveal = "always";
}
];
};
Important: by default Home Manager writes a read-only settings.json. Zed cannot modify read-only files, so GUI settings changes won't persist unless you set mutableUserSettings = true.
Config (~/.config/zed/settings.json)
json
{
"vim_mode": true,
"theme": "One Dark",
"buffer_font_family": "Zed Mono",
"buffer_font_size": 14,
"tab_size": 2,
"hard_tabs": false,
"soft_wrap": "none",
"format_on_save": "on",
"autosave": "off",
"ensure_final_newline_on_save": true,
"remove_trailing_whitespace_on_save": true,
"cursor_shape": "bar",
"current_line_highlight": "all",
"show_edit_predictions": true,
"git": {
"git_gutter": "tracked_files",
"inline_blame": { "enabled": true }
},
"assistant": {
"default_model": {
"provider": "anthropic",
"model": "claude-sonnet-4-6"
}
},
"lsp": {
"rust-analyzer": {
"initialization_options": {
"check": { "command": "clippy" }
}
}
}
}
Key Settings
| Setting | Default | Description |
|---|---|---|
vim_mode | false | Enable Vim keybindings |
helix_mode | false | Enable Helix keybindings |
base_keymap | "VSCode" | Base keymap style (VSCode/Atom/JetBrains/None) |
buffer_font_size | 15 | Editor font size (6–100) |
tab_size | 4 | Spaces per indent level |
hard_tabs | false | Use tabs instead of spaces |
soft_wrap | "none" | Line wrap mode |
format_on_save | "on" | Auto-format on save |
autosave | "off" | off / on_focus_change / on_window_change / after_delay |
cursor_shape | "bar" | bar / block / underline / hollow |
semantic_tokens | "off" | LSP semantic highlighting: off / combined / full |
code_lens | "off" | LSP inline metadata: off / on / menu |
inlay_hints | — | Type/param hints (object) |
show_edit_predictions | true | AI inline edit suggestions |
disable_ai | false | Disable all AI features |
formatter | "auto" | language_server / external / code_actions / none |
preferred_line_length | 80 | Soft-wrap column |
Settings can also be scoped per-language:
json
{
"languages": {
"Python": { "tab_size": 4, "format_on_save": "off" }
}
}
Project-level overrides go in .zed/settings.json at the worktree root.
Keybindings
Open the keymap editor: Cmd+K Cmd+S (macOS) / Ctrl+K Ctrl+S.
Custom bindings go in ~/.config/zed/keymap.json.
| Action | macOS | Linux/Win |
|---|---|---|
| Command palette | Cmd+Shift+P | Ctrl+Shift+P |
| Open file | Cmd+P | Ctrl+P |
| Project symbol search | Cmd+T | Ctrl+T |
| File symbol outline | Cmd+Shift+O | Ctrl+Shift+O |
| Project search | Cmd+Shift+F | Ctrl+Shift+F |
| Go to definition | F12 | F12 |
| Find all references | Alt+Shift+F12 | Alt+Shift+F12 |
| Project panel | Cmd+Shift+E | Ctrl+Shift+E |
| Outline panel | Cmd+Shift+B | Ctrl+Shift+B |
| Tab switcher | Ctrl+Tab | Ctrl+Tab |
Editing
| Action | macOS | Linux/Win |
|---|---|---|
| Multi-cursor (next match) | Cmd+D | Ctrl+D |
| Select all matches | Cmd+Shift+L | Ctrl+Shift+L |
| Rename symbol | F2 | F2 |
| Code actions | Cmd+. | Ctrl+. |
| Format document | Cmd+Shift+I | Ctrl+Shift+I |
| Toggle comment | Cmd+/ | Ctrl+/ |
| Move line up/down | Ctrl+Cmd+↑/↓ | Alt+↑/↓ |
Panes & Tabs
| Action | macOS | Linux/Win |
|---|---|---|
| Split right | Cmd+K → | Ctrl+K → |
| Split down | Cmd+K ↓ | Ctrl+K ↓ |
| Focus pane (direction) | Cmd+K Cmd+←/→ | Ctrl+K Ctrl+←/→ |
| Close tab | Cmd+W | Ctrl+W |
| Open terminal | Ctrl+` | Ctrl+` |
Git
| Action | macOS | Linux/Win |
|---|---|---|
| Stage all | Cmd+Ctrl+Y | Ctrl+Space |
| Commit | Cmd+Enter | Ctrl+Enter |
| Push | Ctrl+G ↑ | Ctrl+G ↑ |
| Pull | Ctrl+G ↓ | Ctrl+G ↓ |
| Fetch | Ctrl+G Ctrl+G | Ctrl+G Ctrl+G |
AI
| Action | macOS | Linux/Win |
|---|---|---|
| Inline assistant | Ctrl+Enter | Ctrl+Enter |
| Accept edit prediction | Tab | Tab |
| Open agent panel | Cmd+? | Ctrl+? |
| Generate commit message | Alt+Tab | Alt+L |
Vim Mode
Enable with vim_mode: true or toggle via workspace: toggle vim mode.
Zed's Vim mode integrates with LSP and Tree-sitter rather than emulating Vim exactly.
LSP-aware commands
| Command | Action |
|---|---|
gd | Go to definition |
gD | Go to declaration |
cd | Rename symbol |
g. | Code actions |
gA | Find all references |
Tree-sitter text objects
| Object | Inner | Around |
|---|---|---|
| Function | if | af |
| Class | ic | ac |
| Argument | ia | aa |
| HTML/XML tag | it | at |
Tree-sitter motions
| Key | Action |
|---|---|
]m / [m | Next/prev method |
]] / [[ | Next/prev section |
Git motions (Vim)
| Key | Action |
|---|---|
]c / [c | Next/prev diff hunk |
do | Expand hunk |
dO | Toggle staging |
Built-in plugin equivalents
| Feature | Keys |
|---|---|
| Surround add | ys<motion><char> |
| Surround change | cs<old><new> |
| Surround delete | ds<char> |
| Comment (normal) | gcc |
| Comment (visual) | gc |
| vim-exchange | cx |
| ReplaceWithRegister | gR |
Vim settings
json
{
"vim": {
"default_mode": "normal",
"use_system_clipboard": "always",
"use_smartcase_find": true,
"toggle_relative_line_numbers": true,
"highlight_on_yank_duration": 200
}
}
Regex differences from Vim
Zed uses its own regex engine — capture groups use ( ) not \( \), backreferences use $1 not \1, and substitutions are global by default (no /g needed).
AI Features
Edit Prediction
Inline suggestions on each keystroke, accepted with Tab. Disable per file glob:
json
{
"edit_predictions": {
"disabled_globs": ["**/.env", "**/secrets/**"]
}
}
Inline Assistant
Select code → Ctrl+Enter → describe the change → model rewrites in place. Works on multiple cursors simultaneously.
Agent Panel
Full conversation interface for multi-step tasks. The agent can read/write files, run terminal commands, and use MCP tools. Open with Cmd+?.
Supported AI Providers
Anthropic, OpenAI, Google, GitHub Copilot, Ollama, Codestral, and others. Bring your own API key or use local models. Configure in settings:
json
{
"assistant": {
"default_model": {
"provider": "anthropic",
"model": "claude-opus-4-7"
},
"version": "2"
}
}
MCP (Model Context Protocol)
Extend the agent with external tools and data sources. Add servers to settings:
json
{
"context_servers": {
"my-server": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
},
"remote-server": {
"url": "https://example.com/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Also installable as Zed extensions (GitHub, Puppeteer, Brave Search, Figma, etc.).
Tool permissions:
json
{
"agent": {
"tool_permissions": {
"default": "confirm",
"mcp:my-server:read_file": "allow"
}
}
}
Rules
Configure agent behavior and constraints via ~/.config/zed/rules.md or .zed/rules.md in the project.
SSH Remote Development
Local machine handles UI, syntax highlighting, and AI. Remote handles LSP, terminal, and tasks. No FUSE, no file sync — Zed runs a headless server instance on the remote.
Connect: Ctrl+Cmd+Shift+O (macOS) / Alt+Ctrl+Shift+O → "Connect New Server"
json
{
"ssh_connections": [
{
"host": "myserver.example.com",
"username": "user",
"port": 22,
"args": ["-i", "~/.ssh/work_key"],
"nickname": "dev-box",
"upload_binary_over_ssh": true
}
]
}
Port forwarding:
json
{
"port_forwards": [
{ "local_port": 8080, "remote_port": 3000, "local_host": "127.0.0.1" }
]
}
Limitations: Cannot open files from remote terminal with zed CLI. Avoid opening very large directories (>100k files).
Tasks
Run commands with access to editor context. Define in ~/.config/zed/tasks.json (global) or .zed/tasks.json (project).
json
[
{
"label": "Run tests",
"command": "cargo test",
"args": ["--", "$ZED_SYMBOL"],
"cwd": "$ZED_WORKTREE_ROOT",
"env": { "RUST_BACKTRACE": "1" },
"use_new_terminal": false,
"allow_concurrent_runs": false,
"reveal": "always",
"hide": "on_success",
"save": "all"
}
]
Available Variables
| Variable | Value |
|---|---|
$ZED_FILE | Absolute path of current file |
$ZED_FILENAME | Filename only |
$ZED_DIRNAME | Directory of current file |
$ZED_RELATIVE_FILE | Path relative to worktree root |
$ZED_STEM | Filename without extension |
$ZED_ROW / $ZED_COLUMN | Cursor position |
$ZED_SELECTED_TEXT | Current selection |
$ZED_SYMBOL | Symbol under cursor |
$ZED_LANGUAGE | Language of current buffer |
$ZED_WORKTREE_ROOT | Project root |
$ZED_MAIN_GIT_WORKTREE | Main git worktree root |
Run: task: spawn (task picker), task: rerun (repeat last).
Git-tagged tasks
Tasks with "tags": ["git-command"] appear in Git Graph context menus:
json
{
"label": "Checkout commit",
"command": "git checkout $ZED_GIT_SHA",
"tags": ["git-command"]
}
Hooks
json
{
"label": "Copy .env to worktree",
"command": "cp",
"args": ["$ZED_MAIN_GIT_WORKTREE/.env", "$ZED_WORKTREE_ROOT/.env"],
"hooks": ["create_worktree"],
"reveal": "no_focus",
"hide": "on_success"
}
Debugger
Implements the Debug Adapter Protocol (DAP). Supports: C/C++, Go, JavaScript/TypeScript, PHP, Python, Rust (built-in) + Java, Ruby, Swift (via extensions).
Create .zed/debug.json (or loads .vscode/launch.json as fallback):
json
[
{
"adapter": "CodeLLDB",
"label": "Debug binary",
"request": "launch",
"program": "${ZED_WORKTREE_ROOT}/target/debug/myapp",
"cwd": "$ZED_WORKTREE_ROOT"
}
]
Start: F4 to open process modal, debugger: start.
Settings:
json
{
"debugger": {
"dock": "bottom",
"stepping_granularity": "line",
"save_breakpoints": true,
"inlay_hints": { "show_value_hints": true }
}
}
Git
• Gutter — colored bars for added/modified/deleted lines
• Inline blame — author/commit on current line (editor: toggle git blame inline)
• Diff view — split or unified, editable as multibuffers
• Git panel — stage files, write commit message, push/pull
• AI commit messages — git: generate commit message
Multi-buffer
Search results, diagnostics, and references all open as multi-buffers — excerpts from many files in one view. Edit directly; changes propagate to source files immediately. Save all with the workspace save command.
Open source file from an excerpt: click the divider, or editor: open excerpts.
Extensions
Install via command palette: zed: extensions. Adds language support, themes, debugger adapters, and MCP servers.
Rust, Python, JavaScript/TypeScript, Go, C/C++, JSON, Markdown are built-in — no extension needed.
Language Support
| Extension | Adds |
|---|---|
nix | Nix syntax + nixd/nil LSP |
toml | TOML syntax + taplo LSP |
html | HTML + Emmet |
vue | Vue SFCs |
svelte | Svelte |
astro | Astro |
lua | Lua + lua-language-server |
xml | XML |
c-sharp | C# via Roslyn LSP |
java | Java via jdtls |
kotlin | Kotlin |
php | PHP via Intelephense |
ruby | Ruby via Solargraph |
elixir | Elixir via ElixirLS |
swift | Swift |
dart | Dart + Flutter |
zig | Zig via ZLS |
terraform | Terraform/HCL |
prisma | Prisma schema |
latex | LaTeX via texlab |
sql | SQL syntax |
dockerfile | Dockerfile |
scss | SCSS/SASS |
make | Makefile |
log | Log file highlighting |
Themes
| Extension | Style |
|---|---|
catppuccin | Soothing pastel — Latte, Frappé, Macchiato, Mocha |
tokyo-night | Tokyo Night / Tokyo Storm / Tokyo Moon |
one-dark-pro | Atom-style One Dark |
github-theme | GitHub Light/Dark |
dracula | Official Dracula |
nightfox-themes | Neovim Nightfox ports |
rose-pine | Rosé Pine |
gruvbox | Gruvbox dark/light variants |
Icon Themes
| Extension | Style |
|---|---|
catppuccin-icons | Catppuccin-colored file icons |
material-icon-theme | Material Design icons |
Enable file icons in tabs:
json
{ "tabs": { "file_icons": true } }
Tools
| Extension | What it does |
|---|---|
git-firefly | Git syntax highlighting (diff, commit messages) |
emmet | Emmet abbreviation expansion for HTML/CSS |
opencode | Open-source AI coding agent integration |
Debugger Extensions
Java, Ruby, and Swift debugger adapters are extension-provided (built-in adapters cover C/C++, Go, JS/TS, Python, Rust).
MCP Extensions
Popular MCP servers installable as extensions: GitHub, Puppeteer, Brave Search, Figma. Browse with the MCP filter on the extensions page.
Collaboration
Real-time collaborative editing via Channels. Multiple users edit the same buffer simultaneously (Google Docs-style). Start from collab: join channel or share a channel link.