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) - 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 - patch
settings_changed()incrates/editor/src/editor.rsto properly reload the buffer font family, so I can switch trivially between a monospace and proportional font (I am not sure why only my fork needs it, andZed.appdoesn't)
- on viewing an image, the
ImageViewerkey context is enabled, previously there was no context
- implement a filterable clipboard history model (opened via
clipboard_history_modal::ToggleClipboardHistory) which keeps tracks of copy text actions likeeditor::Copy. On confirming it pastes in the selected entry- inspired from
Choose Content to Pastefrom JetBrains IDEs - in
crates/workspace/src/persistence.rsthere is own SQL tableclipboard_history, so the recent entries is remembered across restarts
- inspired from
This is inspired by oil.nvim for Neovim (https://github.com/stevearc/oil.nvim) or vinegar for Vim (https://github.com/tpope/vim-vinegar).
Take care to only modify the file names in the editor, not the top directory name or the newlines below the directory name, otherwise the logic on saving will not work.
You can empty a line to trash a file. It only works on macOS because it is using the trash CLI.
Deleting or adding lines is not supported, this is for file browsing and file renaming via usual editor keybindings.
workspace::FileExplorerOpen(the entry point)workspace::FileExplorerOpenFile(has aclose: boolparameter to close the file explorer after opening the file, default istrue)workspace::FileExplorerNavigateToParentDirectoryworkspace::FileExplorerSaveModified(show a confirmation dialog which lists all changes)workspace::FileExplorerCreateFile(show a modal to input a file name and open the newly created file; this also works outside this file explorer)workspace::FileExplorerReload(reload the current directory listing while preserving the cursor position on file name)
See crates/editor/src/editor.rs, search for file_explorer and related functions.
FileIcon(usize) was added to pub enum InlayId to display the SVG icon from the theme, same as the file icons from the file tabs.
set_vim_insert_on_focus was added to editor.rs to start in Vim insert mode when the editor is focused. I needed this for the crates/editor/src/create_file_modal.rs since I want to use Vim mode there, and start in insert mode instead of the default normal mode.
Implement emoji_picker_modal::ToggleEmojiPicker which opens a modal and on picking an emoji, it is copied into the clipboard.
You modify the emojis in your settings.json like this in the root setting object:
"emoji_picker": [
"😄 smile",
"😮 surprise",
"😢 sad"
]- allow
cmd-escapeto break out of theSearch by Keystrokemode
- allow mouse left click on the action name or context to copy into clipboard
- color the Last Keystroke action name to the same color as the
(match),(low precedence)and(no match)labels- on my smaller screen, I often do not see the end of a text row, and placing the color at front, helps immensely
- wrap the context labels, so they are always fully readable. I need this for my smaller screen
- 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- their server might be buggy, I have adjusted
map_event()inopen_ai.rsto handle the case when thetool_callsarray containsid: "" - their models keep sending start and end line as strings (instead as numbers as the Zed Agent requires), so I adjusted
crates/agent/src/tools/read_file_tool.rsand the terminal tooltimeout_msto allow both integers and strings - 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
- their server might be buggy, I have adjusted
- the notifications now include
- add
agent::DismissOsNotificationsaction to dismiss the top right OS notification from Zed Agent. With multiple tabs, I feel that gets stuck sometimes - 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
- estimate tokens via
tiktoken-rscrate for ACP agents, or display ACP server token info when provided (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
- 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" }]
See crates/agent_ui/src/ui/agent_notification.rs.
- increase button size
- use vertical lines and display the agent tab name in the notification, if set
- 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 - change
command palette: toggleto sort by recency instead of hit count - remove
GlobalCommandPaletteInterceptorusage which contains Vim things like:delete, :edit, :help, :join, :quit, :sort, :write, :xit, :yankbecause I do not use them. Apparently, this removes 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.
- renaming a file uses a vim compatible editor and starts in vim normal mode
- add a JSON boolean key
highest_precedenceto the keymap dictionaries for tricky keybindings which otherwise require rewriting many other keybinding blocks- I originally implemented it for the vim mode support in project panel rename file editor to handle
Enterin vim's insert mode
- I originally implemented it for the vim mode support in project panel rename file editor to handle
A new modal for recent file functionality which tracks every opened buffer in a new persistence.rs SQL table to quickly jump to a recent file (which can in turn open a new workspace).
projects::OpenRecentZoxide for Zoxide (https://github.com/ajeetdsouza/zoxide)
A new modal which displays recent directories from the zoxide CLI binary.
It displays no footer and abbreviates paths to tildes.
highlighted_label.rs was adjusted for its filtering. Here cmd+enter is flipped, so by default, it always opens in a new window.
Markdown::ScrollPageLittleDownandMarkdown::ScrollPageLittleUpwhich scroll a quarter of a pageworkspace::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
- never prefill the buffer search input field with the word under the cursor
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
- 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
A new custom modal which bypasses the macOS native dialog to allow for easier keybindings and nicer UI. This replaces Zed's unsaved changes modal.
See crates/workspace/src/confirmation_dialog.rs. The dismiss action is currently hardcoded to key h.
- 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.