To test modifications, I am only using cargo run (note that when webrtc-sys takes too long, use Warp for a faster download) to compile and start Zed in debug mode which is faster than building the release binaries.
Once, I am satisfied with a batch of changes, I install Zed into /Applications/Zed Dev.app with this:
./script/bundle-mac-without-licenses -l -o -i && \
rm -f "$HOME/.cargo/bin/zed" && \
ln -s "/Applications/Zed Dev.app/Contents/MacOS/cli" "$HOME/.cargo/bin/zed"To have easier Zed's main branch merges, I am not really adding or modifying existing unit tests to my own functionality, so some are failing. I try to satisfy ./script/clippy, though.
AI is heavily used for pretty much every feature implemented. I use a mix of those models, all free:
- Google's Gemini 3 Pro (https://aistudio.google.com/prompts/new_chat)
- Qwen Code (https://github.com/QwenLM/qwen-code)
- Windsurf's SWE 1.5 (until it is not free anymore)
For anything more complicated, I use the Architect + Editor pattern (see https://aider.chat/2024/09/26/architect.html) with Gemini 3 Pro being the Architect and the other models being the Editor.
git checkout main && git pull zed main && git push && git checkout dima && git merge mainIf there are merge conflicts, I resolve them via IntelliJ IDEA.
https://github.com/zed-industries/zed/compare/main...Dima-369:zed:dima
- add many defaults in
project_settings.rsto not crash on startup (not sure if that is only from my code) - add
bundle-mac-without-licenseswhich is faster than generating licenses, and skips thesentry-cliat end - try to fix panic in
anchor_at_offsetwhen buffer has Umlaute, seems to work, no idea if my fix has other consequences - changed
fn do_copy(&self, strip_leading_indents: bool, cx: &mut Context<Self>) {to only strip trailing newlines instead of leading indents - lower
MIN_NAVIGATION_HISTORY_ROW_DELTAto 3, from 10, as a test which seems fine - opening a workspace which has no tabs initially, will trigger
workspace::NewFilefor proper editor focus. Before, there seems to be a bug where the project panel does not have proper focus - improved the
go to next/previous diagnosticaction to always jump to errors first. Only if there are no errors, it jumps to warnings. Before, this was mixed - moving up/down in outline panel does not wrap around anymore
- fixed that a large
vertical_scroll_margininsettings.jsonto have a centered cursor jumps buffer scrolls around (zed-industries#42155) - fixed that on entering the project search, there can be instances where visual mode is entered (zed-industries#43878)
- integrate file explorer modal from zed-industries#43961 file explorer modal, PR closed)
- integrated live refreshing project search from zed-industries#42889, enable in
settings.jsonviasearch > search_on_input - integrated smooth scroll from zed-industries#31671
- modified
compute_style_internal()incrates/gpui/src/elements/div.rsto not apply the mouse hover style, since it clashes when one only uses the keyboard- I also unset the mouse hover background change on enabled
sticky_scroll
- I also unset the mouse hover background change on enabled
- improved
outline::Toggleto work in multi buffers, it shows the file headings only - improve
editor::SelectLargerSyntaxNodefor inline code blocks in Markdown files (foo bar), so that it first extends the selection to the word inside the quotes, then the text inside the quotes and only then to the inner text plus the outer quotes - add structured outline for Markdown, modifies
crates/languages/src/markdown/outline.scm(from zed-industries#45643) - integrated 'Multibuffer breadcrumbs toolbar redesign' from zed-industries#45547
- improve
editor::AcceptNextWordEditPredictionto not insert a sole space when a space is before a word in the suggestion. Now, it inserts both the space and the word
- add
vim_visualcontext which can be set tonormal,lineorblockfor more fine-grained keybindings - modified
vim/.../delete_motion.rssovim::DeleteRightat end of line stays on the newline character - made
clip_at_line_end()incrates/editor/src/display_map.rsa no-op, to have an always enabledvirtualedit=onemoremode- this also allows mouse clicking beyond the end of the line where no characters are, to select the newline character in vim mode
- fix bug that when in vim visual line mode and cursor is on right newline character, that the line below is incorrectly copied on
editor::Copy. This mostly happens in my own Zed config because I mixingeditorandvimactions to ensure that I can move cursor on the right newline character, and usually not in proper Zed keybindings. - integrate Helix jump list from zed-industries#44661 and implemented
vim::HelixOpenJumpListInMultibufferaction
- add
"proxy_no_verify": truesupport insettings.json
- add
blame > git_blame_font_familysetting to specify the font family for the git blame view because I am using a proportional font and the blame view misaligns otherwise - add
git::DiffWithCommitfrom zed-industries#44467 and based on that code,git::DiffWithBranchis implemented - add
({file count})in the git panel to every directory, inspired by zed-industries#45846 (Improve Git Panel with TreeView, VSCode-style grouping, commit history, and auto-fetch)
- make the title dynamic: if there are no files, it shows
No Changes, otherwise it showsUncommitted Changes (1 file)orUncommitted Changes (n files) - make the icon and text foreground dynamic when the tab is not selected with the same logic as the "Recent Branches" from
crates/title_bar/src/title_bar.rs. Seefn tab_content(&self, params: TabContentParams, _window: &Window, cx: &App) -> AnyElement
- move git commit modal to the right side instead of being centered, so it does not overlap the left git dock, which makes it impossible to see what files are staged on a small screen. One could lower the size of the git dock to make it fit, but then it is quite small
- and use
text_accentfor its border color to be easier to see
- and use
- preset git commit message with "Update {file count} files" on multiple files and add every file name to the commit description as a list with a
-prefix
Add --stdin-cursor-at-end flag to CLI to position cursor at end of buffer when reading from stdin instead of at start which I find more useful.
I developed and tested it like this:
timeout 15s bash -c 'cat README.md | target/debug/cli --zed target/debug/zed --stdin-cursor-at-end --foreground -' 2>&1 || echo "Timeout reached"- remove abbreviated
cwddisplay in terminal title - add
terminal::OpenScrollbackBufferaction to open the scrollback buffer in a new buffer. It positions the cursor at the end
- add little indicator at top of terminal view to display if Vi Mode is enabled
- modify Vi Mode keys to my custom Dvorak Programmer keyboard layout inspired by https://github.com/xahlee/xah-fly-keys
- see diff in
crates/terminal/src/terminal.rscompared to Zed'smainbranch for key changes entersets the cursor position for a selectionescapeclears the selection if there is one, otherwise exits Vi Mode
- see diff in
- fix bug that in Vi Mode on key press, the terminal does not rerender, so the cursor position is not updated
- allow AI edit predictions in the following places:
- Zed's
settings.json - Zed's
keymap.json - buffers without files like ones from
workspace: new file - AI agent text threads
- Zed's
- add the Qwen provider with models
qwen3-coder-plusandqwen3-coder-flashwhich can be used for Inline Assist and in Zed Agent- the implementation is based on how https://github.com/RooCodeInc/Roo-Code interacts with Qwen and requires the
~/.qwen/oauth_creds.jsonfile to set which can be done by using theqwenbinary and authenticating with OAuth - inside the Zed Agent, it performs weirdly, you often do not see the
Color::Mutedtool call rows, although the model does call them. Andagent::OpenActiveThreadAsMarkdownthen sometimes shows incorrect context. I did not investigate that further
- the implementation is based on how https://github.com/RooCodeInc/Roo-Code interacts with Qwen and requires the
- add concurrent agent tabs from wzulfikar#8 (which was based on zed-industries#42387)
- remove the opacity animation for the tabs when waiting for a response and instead rotate a circle like Windsurf
- add
agent::CloseActiveThreadTabOrDock
- Zed Agent, External Agents and text thread title summaries are now generated on every AI message received (WIP)
- estimate tokens for ACP agents, or displays ACP token info when provided (although both Gemini and Qwen do not provide it)
- add
agent::ActivateNextTabandagent::ActivatePreviousTab - add
agent::DismissErrorNotificationandagent::CopyErrorNotification - change
agent::OpenActiveThreadAsMarkdownto always open to end of buffer instead of start, and when there are more than 90k lines, open asPlain Textbecause Markdown lags hard for me, seecrates/agent_ui/src/acp/thread_view.rs - add
agent::TogglePlanwhich toggles the plan of the current thread - always allow all edits, otherwise it kepts asking for "Allow All Edits" every single time a new ACP thread is started which is just annoying. Note that it still asks for tool permissions
- show command output for
acp::ToolKind::Executealways below theRun Commandview in a plain text view to preserve newlines- I added
prepare_execute_tool_output_from_qwen()to strip trailing and leading information for cleaner output
- I added
- integrate external agent history from zed-industries#45734
- allow
New From Summaryfor ACP agents, instead of only for Zed Agent - add
agent::LaunchAgentaction which takes an external agent name and can be bound like this:"cmd-t": ["agent::LaunchAgent", { "agent_name": "qwen" }]
- the command palette sorting now sorts the same for
close workandwork close, and it does not search individual character matches anymore, like when you enterbsp, it would showeditor: backspacebefore. I do not like that behavior, so I removed that - changed
command palette: toggleto sort by recency instead of hit count - removed
GlobalCommandPaletteInterceptorusage which contains Vim things like:delete, :edit, :help, :join, :quit, :sort, :write, :xit, :yankbecause I do not use them. Apparently, this also removed the ability to jump to a line via:144. I still removed this behavior because it is hard to sort those dynamic actions by recency in combination with the other real editor action commands.
workspace::OpenRecentFile for recent file functionality which tracks every opened buffer to quickly jump to a recent file or open a recent workspace
Markdown::ScrollPageLittleDownandMarkdown::ScrollPageLittleUpwhich scroll a quarter of a pageprojects::OpenRecentZoxidewhich displays recent directories fromzoxideCLI binary. It displays no footer and abbreviates paths to~.highlighted_label.rswas adjusted for its filtering. Herecmd+enteris flipped, so by default, it always opens in a new windowworkspace::NewFileFromClipboardwhich pastes in the clipboard contents- the action supports setting an initial language like
"space n j": [ "workspace::NewFileFromClipboard", { "language": "json" } ],inkeymap.json
- the action supports setting an initial language like
workspace::CopyFilePathswhich opens a picker to copy the file path to clipboardworkspace::MakeSinglePanewhich closes all other panes except the active onesnippets::ReloadSnippetsbecause auto-reloading snippets is not working for meeditor::CreateNavHistoryEntryeditor::CopyAllto copy entire buffer content to clipboardeditor::CountTokenswhich counts the tokens in the current buffer usingo200k_basevia thetiktokencrateeditor::StopAllLanguageServerswhich stops all language servers. It works like the bottom button inLanguage Servers > Stop All Serversproject_lsp_treesitter_symbol_search::Togglebased onsearch_everywhere::Togglefrom zed-industries#45720. I ripped out everything else except the symbol search. The reason this is better than the built-inproject_symbols::Toggleis that it uses both Tree-sitter and LSP with indexing which is faster and more reliable.editor::MoveToStartOfLargerSyntaxNodefrom zed-industries#45331buffer_search_modal::ToggleBufferSearchwhich shows a modal to search the current buffer content (code is incrates/search/src/buffer_search_modal.rs) based on zed-industries#44530 (Add quick search modal). This is a basic implementation of Swiper from Emacs orSnacks.picker.lines()from Neovim. I tried matching every line withnucleo, but it was kinda slow, so it just split on spaces and then every line which has all words from the query is matched.ctrl-candctrl-tcan be used to insert history items into the search fieldctrl-ris to toggle between line (case-insensitive) and exact match (case-sensitive) mode- it also works in multi buffers, although the preview editor mixes lines
From https://github.com/tebben/zed/tree/feature/jump
With the following changes:
- modify key jump hints to my custom Dvorak Programmer keyboard layout
- implement multiple character jump hints
- set the opacity of the dialog to 50% to see hints below
- implement
jump::JumpToUrlbased on this code to jump tohttp...URLs - note that it does not work in multi buffers, but it works to jump across panes of regular text editors
From zed-industries#43733
- improved UI to look like the
jump::Toggleaction - removed the
helix > "jump_label_accent"setting since the UI is now the same asjump::Toggle - modified key jump hints to my custom Dvorak Programmer keyboard layout
- I am only using this is inside multi buffers, whereas
jump::Toggledoes not. And this also does not work to jump across editor panes - note that escape does not work to break out of this mode, apparently. I have no idea how to adjust the code for it
There is this new actoin: zed::DeeplTranslate which translates the current selection or the current line. It needs the DEEPL_API_KEY environment variable to be set. Bind like this:
"space c g": [
"zed::DeeplTranslate",
{
"source_lang": "EN",
"target_lang": "DE",
}
],file_finder > modal_max_width=fulldoes not take full width anymore because it looks weird, but subtracts 128 pixels- show scrollbar
- try to improve matching to use substring through
nucleocrate. I dislike fuzzy matching which is annoying. Based on zed-industries#37123, but that had fuzzy matchingnucleohas its issues when you search in this repo for justREADME, it does not prioritize the rootREADME.md, but other READMEs from other crates, but at least there is no weird fuzzy matching anymore
- on macOS, the unsaved changes model uses the native macOS dialog instead of Zed's custom one which has bad keyboard support, so
unsaved_changes_model.rswas created which allows keyboard navigation (and just looks nicer) - use larger font size (
LabelSize::Default) for the line/column and selection info in the bottom bar and usetext_accentfor it when a selection is active - lower status bar height, see
impl Render for StatusBar - add scrollbar to
outline::Toggle,file_finder::Toggleandcommand_palette::Toggle(why is it not shown in the first place?) - lower
toolbar.rsheight to save space, same inbreadcrumbs.rs(here no padding is set). This applies for terminals, as well - lower
DEFAULT_TOAST_DURATIONfrom 10 to 5 seconds
- hide horizontal scrollbar when soft wrap is enabled
- adjust scrollbar UI to look rounded and more native to macOS (idea is from this fork: https://github.com/notnotjake/zed)
- align the right slot of tabs (the directory) to the file name baseline, meaning in such cases:
README.md db(see diff incrates/editor/src/items.rs)- as recommended in
Refactoring UI > Baseline, not center
- as recommended in
- lower excessive tab height
- switch system tab background color from
title_bar_backgroundtotab_bar_background, so I can style active tabs far nicer because the default just uses a slightly different foreground color which is hard to spot
The vertical tabs stack to next rows without scrollbars. Enable in settings.json with:
"tab_bar": {
"vertical_stacking": true
}It places pinned tabs in an own row, separated to non-pinned tabs.
Note: Since it was too difficult to only render tab borders where exactly required, every tab now has a full border, so it looks a bit bold between tabs, but I don't mind. It looks better that way, instead of missing top borders in second row, for instance, when first row has pinned tabs.
Welcome to Zed, a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.
On macOS, Linux, and Windows you can download Zed directly or install Zed via your local package manager (macOS/Linux/Windows).
Other platforms are not yet available:
- Web (tracking issue)
See CONTRIBUTING.md for ways you can contribute to Zed.
Also... we're hiring! Check out our jobs page for open roles.
License information for third party dependencies must be correctly provided for CI to pass.
We use cargo-about to automatically comply with open source licenses. If CI is failing, check the following:
- Is it showing a
no license specifiederror for a crate you've created? If so, addpublish = falseunder[package]in your crate's Cargo.toml. - Is the error
failed to satisfy license requirementsfor a dependency? If so, first determine what license the project has and whether this system is sufficient to comply with this license's requirements. If you're unsure, ask a lawyer. Once you've verified that this system is acceptable add the license's SPDX identifier to theacceptedarray inscript/licenses/zed-licenses.toml. - Is
cargo-aboutunable to find the license for a dependency? If so, add a clarification field at the end ofscript/licenses/zed-licenses.toml, as specified in the cargo-about book.