Not a knock on either — both are excellent, mature tools. But the render path has extra stops most people never think about, because they've never felt the alternative.
VSCode: keystroke → Chromium renderer → DOM/layout → (for extensions) an IPC hop to the Node.js extension host and back.
WebStorm: keystroke → Swing/AWT UI on the JVM → PSI model update → garbage collector somewhere in the loop.
Keystroke → native Rust → GPUI's GPU compositor. No browser, no JVM, no interpreter sitting between your finger and the pixel.
Zed's own GPU-accelerated UI framework. The text buffer, the tab bar, the settings panel, the project tree — all of it renders through one framework, straight to the GPU. There's no separate layout/paint/composite pipeline built for general web pages doing double duty as your editor's UI.
A model trained specifically to predict your next edit across the whole file — not just the next token at the cursor — built into the core, on by default.
A first-class chat/agent surface in the sidebar with pluggable providers — Anthropic, OpenAI, or a local model via Ollama — your choice, your key.
2026's addition: run several agent threads at once against different parts of a task, instead of one linear conversation queue.
The difference that actually matters: because AI features share the same Rope/CRDT buffer model as everything else, streamed edits apply as incremental patches — not a full-file rewrite dropped on top of whatever you were mid-typing.
Zed's buffers are built on CRDTs — Conflict-free Replicated Data Types — from day one, not retrofitted for a "Live Share" feature later.
Multiplayer is core editor behavior: open a project, invite someone, see their cursor and selection live. Concurrent edits merge deterministically — no lock, no "waiting for the other person to save."
A separate extension with its own sign-in and its own transport, layered on top of an editor that wasn't built assuming two people would type in the same buffer at once.
A tool worth switching to is worth describing honestly. Here's where Zed still loses to what you're using today.
The marketplace is a fraction of VSCode's. Core languages are covered well; niche tooling sometimes isn't there yet.
No built-in DB client, HTTP client, or JVM-grade refactor/find-usages the way WebStorm ships out of the box — Zed leans on each language's LSP instead.
macOS and Linux got first-class support years earlier; Windows support is real but younger, and it shows in polish for edge cases.
settings.json is still just JSON with per-language override blocks — the mental model doesn't change, only some key names do..code-workspace file: Zed remembers whatever folders were open in a window and restores that layout automatically. Add a second project root anytime via File → Add Folder to Project — same idea as VSCode's multi-root workspaces, no file to maintain.tsserver WebStorm ultimately talks to anyway, so quality is close; for less-tooled languages, it can be thinner.zed CLI into your PATH automatically — no separate "install shell command" step.zed .Cmd+Shift+X to install language extensions you actually use (see slide 16).zed .base_keymap to whatever you already type without thinking — VSCode or JetBrains.zed . — not a scratch folder. First impressions on toy code lie.Genericized from an actual monorepo (server + client + shared packages) — the shape, not the specifics.
formatter: [] + code_actions_on_format: {"source.fixAll.eslint": true} — ESLint's autofix is the only formatting action. Matches VSCode's codeActionsOnSave: fixAll plus formatOnSave: false exactly, because it's respecting the same one source of truth: whatever this project's own ESLint config says.npx prettier after the ESLint fix "for projects that use it." A project with no .prettierrc at all still had prettier resolvable via npx (a transitive dependency), so it silently reformatted with Prettier's generic defaults on every save — fighting the project's real Airbnb/ESLint style. fixAll.eslint alone already covers projects that use Prettier through eslint-plugin-prettier too. Don't chain a formatter your config can't confirm the project actually wants.workingDirectories: [{mode:"auto"}] — ESLint resolves the right package's config per file by itself. In a packages/* monorepo that means zero hardcoded package paths to keep in sync as packages come and go."Vue.js" entry is not optional in a Vue project — languages blocks match Zed's language name, and a .vue SFC is Vue.js, not TypeScript. Leave it out and the TypeScript block silently never applies: the SFC falls back to the default formatter, where Volar formats through Prettier's generic defaults — double quotes, collapsed attribute lines — and undoes eslint-plugin-vue's style on every single save. Same trap for any other embedded-language file; name the language the file is, not the language inside it.project_panel.dock, tabs.file_icons/git_status, minimap.show — the visual-parity knobs from slide 09. None of these touch behavior; they exist purely so the tree and tab bar don't feel like a step down from what you're used to.| Stack | Extension | Needed? |
|---|---|---|
| Vue 3 SFCs | Vue.js | install |
| Astro | Astro | install |
| Tailwind CSS | — none — | built in, no extension |
| Icon theme, Material-style | optional | cosmetic only |
Zed's own habit is minimal-by-default — most core language support (TS, Python, Go, Rust, Markdown) ships without an extension at all. Install what a project actually needs, not a marketplace's worth up front.
zed ~/repo-a ~/repo-b, or inside Zed, File → Add Folder to Project. Both show as separate roots in the same project panel — search and AI context span both.Ctrl+R — Open Recent, same key on macOS and Linux. Plain click reuses the window; Cmd/Ctrl+Enter or Cmd/Ctrl+Click opens a new one instead.base_keymap | Muscle memory from |
|---|---|
| VSCode | VSCode / Cursor |
| JetBrains | WebStorm / IntelliJ |
| SublimeText | Sublime Text |
| None | Zed's own defaults |
terminal.working_directory: "current_project_directory" (default) — the integrated terminal opens rooted at whichever project folder your active file belongs to. A separate setting from ESLint's workingDirectories on slide 14 — same word, two different jobs.Straight from Zed's own default keymaps on GitHub — default-macos.json / default-linux.json — not guessed. Select the table to copy it as-is, or use the buttons.
| Action | macOS | Linux / Windows |
|---|---|---|
| Command palette | ⌘⇧P | Ctrl+Shift+P |
| Quick open file | ⌘P | Ctrl+P |
| Show / hide project panel | ⌘⇧E | Ctrl+Shift+E |
| Show / hide terminal | ⌃` | Ctrl+` |
| Show / hide git panel | ⌃⇧G | Ctrl+Shift+G |
| Switch project (Open Recent) | ⌃R | Ctrl+R |
| Show / hide AI agent panel | ⌘? | Ctrl+? |
| Split pane right | ⌘\ | Ctrl+\ |
| Close tab | ⌘W | Ctrl+W |
| Save | ⌘S | Ctrl+S |
| Go to line | ⌃G | Ctrl+G |
| Go to definition | F12 | F12 |
| Format document | ⌘⇧I | Ctrl+Shift+I |
| Rename symbol | F2 | F2 |
| Toggle line comment | ⌘/ | Ctrl+/ |
The same gesture VSCode and Sublime trained your fingers on. Copy or save this one too.
| Action | macOS | Linux / Windows |
|---|---|---|
| Add cursor above | ⌘⌥↑ | Shift+Alt+↑ |
| Add cursor below | ⌘⌥↓ | Shift+Alt+↓ |
| Add cursor at click point | ⌥+Click | Alt+Click |
| Select next occurrence | ⌘D | Ctrl+D |
| Select all occurrences | ⌘⇧L | Ctrl+Shift+L |
| Undo last cursor / selection | ⌘U | Ctrl+U |
⌘⌥↑/↓ on macOS — VSCode's own default is ⌥⌘↑/↓ too, so this one already matches even before you touch base_keymap.None of that is a reason to skip Zed for everything else — it's a reason to keep the old tool one Cmd-Tab away for those specific jobs, and let Zed take the daily driving.
Two failures that look like editor bugs but aren't. Both start the same way: open ~/.local/share/zed/logs/Zed.log and read what Zed already knows.
ntfs-3g, plus sshfs and friends). FUSE can't emit inotify events, so Zed's file watcher falls back to polling: a full directory walk every cycle — and node_modules alone can be a hundred thousand entries. The log says it outright: fs_watcher watcher error for Poll.ntfs3 driver: inotify works through it, so the poll fallback never starts, and I/O stops round-tripping through userspace.file_scan_exclusions with **/node_modules, **/dist, build output. The list replaces the defaults (VCS dirs, .DS_Store…), so repeat those before appending — exclusions cost nothing on a healthy filesystem either.languages blocks match Zed's language name: a .vue single-file component is "Vue.js", not TypeScript — and a block that never matches fails silently, no error anywhere. The file falls through to the default formatter (Volar → Prettier's generic defaults), which undoes the project's ESLint style on every save. Slide 14's config names the language the file is; slide 15 has the full story.GPUI, the Rope, Tree-sitter, and the CRDT layer that makes multiplayer work — and how each compares to what VSCode and WebStorm actually do under their own hoods.
| → Space | Next slide |
| ← | Previous slide |
| Home / End | First / last slide |
| 1–9 | Jump to slide N |
| O | Overview grid |
| G | Go to slide |
| F | Toggle fullscreen |
| B | Blackout screen |
| ? | Toggle this help |
| Click left / right half | Prev / next slide |
| Swipe (touch) | Prev / next slide |