Two bugs caused MCP server child processes (e.g. `npm`/`node` for
`mcp-remote`) to accumulate as zombie processes that were never cleaned
up:
**Bug 1: `stop_server()` only called `stop()` for `Running` servers**
If a server completed initialization but was still in `Starting` state
when `stop_server()` was called (a race between the init task completing
and `maintain_servers` restarting), the client/transport/process were
never released. The `Arc<ContextServer>` was moved into a `Stopped`
state with its inner client still holding the transport and child
process handle.
Fix: call `stop()` unconditionally in `stop_server()`. It is a safe
no-op when the client has not been initialized (`None`).
**Bug 2: `kill_on_drop` only killed the direct child, not the process
tree**
`StdioTransport` used a raw `smol::process::Child` with
`kill_on_drop(true)`, which sends SIGKILL only to the direct child
process (the shell/`npm` wrapper). The actual MCP server (e.g. `node
mcp-remote`) runs as a grandchild and survives the kill, getting
reparented to launchd.
Fix: use `util::process::Child`, which already exists in the codebase
for exactly this purpose. It calls `setsid()` via `pre_exec` to make the
child a process group leader, and uses `killpg()` to terminate the
entire process tree on kill. This requires passing a
`std::process::Command` (via `build_std_command`) instead of a
`smol::process::Command` (via `build_smol_command`), because that is
what `util::process::Child::spawn` accepts — it needs to call `pre_exec`
on the `std::process::Command` before internally converting it to
`smol::process::Command` for async I/O.
Release Notes:
- Fixed zombie MCP server processes accumulating over time
Helps with https://github.com/zed-industries/zed/issues/38927
- **editor: Add a benchmark for find/replace**
- **text: batch fragment insertions before turning them into a SumTree**
## Context
<!-- What does this PR do, and why? How is it expected to impact users?
Not just what changed, but what motivated it and why this approach.
Link to Linear issue (e.g., ENG-123) or GitHub issue (e.g., Closes#456)
if one exists — helps with traceability. -->
## How to Review
<!-- Help reviewers focus their attention:
- For small PRs: note what to focus on (e.g., "error handling in
foo.rs")
- For large PRs (>400 LOC): provide a guided tour — numbered list of
files/commits to read in order. (The `large-pr` label is applied
automatically.)
- See the review process guidelines for comment conventions -->
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Improved performance of "Replace All" in buffer search
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Brings in backported fixes to solve some panics we've been seeing
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Adds `editor: convert to base64` and `editor: convert from base64` to
the command palette. Both commands operate on the current selection, or
the word under the cursor when nothing is selected. The decode command
silently no-ops on invalid base64 input or non-UTF-8 decoded bytes,
consistent with how other convert commands handle untransformable input.
Release Notes:
- Added `editor: convert to base64` and `editor: convert from base64`
commands to the command palette
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Pulls in latest cranelift and wasmtime to address security and bug fixes
(to hopefully address some panics on windows in wasmtime)
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- agent: Improve reliability when LLM edits file
Follow up to #54826, after which the fallback model would be selected
instead of the cloud model when starting Zed
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
## Context
Previously the Run Debugger gutter arrow would fail silently when the
Cargo.toml had garbage lines such as “asdfasdf”. This fix makes it so
that the error is detected and bubbles up to the editor, which will
notify the user with a toast diagnostic.
Closes#46716
## Fix
https://github.com/user-attachments/assets/2e9ac7e9-1306-4607-a762-457131473572
## How to Review
Small PR - focused on four different files:
In - `crates/languages/src/rust.rs`:
- `target_info_from_abs_path()` - The function signature was changed
from `Option<(Option<TargetInfo>, Arc<Path>)>` to
`Result<Option<(Option<TargetInfo>, Arc<Path>)>>`. A condition was added
to ensure that if the Cargo metadata command is unsuccessful, the
function returns an error instead of causing an EOF error while
deserializing the stdout of the command.
- `build_context()` - Added a `?` in `target_info_from_abs_path(path,
project_env.as_ref()).await` in order to return the error.
In - `crates/project/src/task_store.rs`:
- `local_task_context_for_location()` and
`remote_task_context_for_location()` - The functions signatures were
changed from `Task<Option<TaskContext>>` to
`Task<anyhow::Result<Option<TaskContext>>>` for the purpose of
propagating the error.
In - `crates/editor/src/editor_tests.rs`:
- `build_tasks_context()` - The function signature was changed from
`Task<Option<TaskContext>>` to
`Task<anyhow::Result<Option<TaskContext>>>` .
- `toggle_code_actions()` - In case `build_tasks_context()` fails, the
functions notifies the error to the user as a Toast notification.
In - `crates/editor/src/runnables.rs`:
- Since `build_tasks_context()` and
`task_store.task_context_for_location()` now return a Result, the
callers` spawn_nearest_task() `and `task_context()` were modified. The
resulting Result types are transformed to match the expected return
types of `TaskContext` and `Task<Option<TaskContext>>`
Two new tests were added. The first, `target_info_from_abs_path_failed`
in `crates/languages/src/rust.rs`, checks if the system properly catches
the error. The second,
`test_toggle_code_actions_build_tasks_context_error_notifies` in
`crates/editor/src/editor_tests.rs`, confirms that the editor triggers
the expected error notification.
## Self-Review Checklist
- [X] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [X] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
Release Notes:
- Fixed the error: Run Debugger failing silently due to invalid
Cargo.toml content
---------
Co-authored-by: Lukas Wirth <lukas@zed.dev>
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A or Added/Fixed/Improved ...
## Summary
Fixes the missing Windows icon and version resource metadata for the
executable installed as `bin\zed.exe`.
On Windows, the bundling process builds `cli.exe` and installs it as
`bin\zed.exe`. The root `Zed.exe` already embeds the Zed Windows icon
and version metadata through `crates/zed/build.rs`, but the CLI
executable did not embed equivalent Windows resources.
As a result, Windows integrations that discover or display Zed through
`bin\zed.exe` may show a missing/default application icon.
This change adds Windows resource embedding to the `cli` crate and uses
the same release-channel icon selection as the main Zed executable.
Fixes#51154
## Testing
- Built the Windows CLI executable:
```powershell
cargo build --release --package cli --target x86_64-pc-windows-msvc
--locked --offline
```
- Verified `target\x86_64-pc-windows-msvc\release\cli.exe` contains:
- `FileDescription = Zed`
- `ProductName = Zed`
- Verified the executable displays the Zed icon in Windows Explorer.
- Confirmed the Windows bundling script installs `cli.exe` as
`bin\zed.exe`.
- Started a full Windows bundle build and confirmed it passed license
generation and progressed into executable builds. The local full bundle
build could not be completed because the machine is missing the VS
Spectre-mitigated C++ libraries.
## Release Notes
- N/A
## Notes
This change is limited to Windows executable resource metadata for the
CLI binary. It does not change Zed runtime behavior.
---------
Co-authored-by: John Tur <john-tur@outlook.com>
This PR adds a feature to automatically cycle through screen shares
during calls, designed for demo days or any call that has a lot of
screen share use.
This is a preliminary attempt behind a feature flag so we can dogfood
and iterate, or toss it out.
There's a new toggle next to the active channel name in the collab
panel: **Auto Watch Screens**.
https://github.com/user-attachments/assets/ae6eccec-7921-4c1f-8921-c8093631c705
This video demonstrates some cases:
Basic auto-watch
- Toggle on → automatically opens the next screen share that starts
- When the watched screen share ends, switches to the next available
share
Queuing
- Someone starts sharing while another share is active → doesn't
interrupt the current share
- When the current share ends, the queued share is picked up
automatically
Paused while sharing
- Auto-watch pauses when you start sharing your own screen, so other
shares don't pop up during your presentation
- When you stop sharing, auto-watch resumes and opens the next available
share
Multiple watchers
- Multiple people can have auto-watch enabled independently — they all
see the same transitions
Note that we don't manage the screenshares, livekit does, so this change
is entirely on the client. I think that's mostly fine, but there is a
chance 2 separate clients queues up a different person as the next
watched peer if they both engage screenshare around the same time,
depending on how it hits the clients, but it seems pretty edge case. We
can move the implementation to collab, but it will be more of a project,
and adding a secondary source alongside of livekit that could get out of
sync and have its own issues.
UI/UX needs work (@danilo-leal for suggestions)
Self-Review Checklist:
- [X] I've reviewed my own diff for quality, security, and reliability
- [X] Unsafe blocks (if any) have justifying comments
- [X] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A
---------
Co-authored-by: Yara 🏳️⚧️ <11743287+yara-blue@users.noreply.github.com>
Removes the Vercel v0 Provider, as the v0 API has been
depredated/removed (https://api.v0.dev/v1)
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- agent: Removed Vercel v0 provider as it has been deprecated by Vercel
Leftovers after https://github.com/zed-industries/zed/pull/53651
Updated models:
- **Zen**: GPT 5.5 and GPT 5.5 Pro - not tested because I don't have a
Zen subscription and I stubbornly refuse to get one
- **Go**: DeepSeek V4 Pro and DeepSeek V4 Flash - failing due to
https://github.com/anomalyco/opencode/issues/24224
- **Go**: MiMo V2.5 and MiMo V2.5 Pro - tested, confirmed working
- **Free**: Ling 2.6 Flash, [available for "a limited
time"](https://x.com/opencode/status/2046717718028513694) - tested,
confirmed working
- **Free**: Hy3 Preview, [available until May
8](https://x.com/opencode/status/2047328981435756824) - tested,
confirmed working
When testing the new models and comparing with OpenCode CLI, I realized
the
[variants](https://opencode.ai/docs/models/#built-in-variants)/thinking
effort configuration was not supported by the Zed Agent implementation.
I added that for OpenCode Go models, after manually checking what each
model supports in OpenCode. Reasoning levels and everything seems to
work (UI looks good, model works) but I have no idea how to specifically
test reasoning levels without doing a full benchmark 🤷
I did not add the same thing for OpenCode Zen models because I could not
figure out a way to get the supported variants.
@benbrandt let me know if you want me to take this out of this PR and to
keep just the model updates!
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- OpenCode: add new models (GPT 5.5, DeepSeek V4, MiMo V2.5, Ling 2.6,
Hy3)
- OpenCode Go: add support for configurable reasoning effort levels
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#54737.
#48752 added empty-prefix `block_comment` entries to several language
configs (Go, C, C++, JSONC, Python, JSX inner) to support the new
toggle-block-comments action.
In `Editor::rewrap_impl`, the comment-format matcher used
`buffer.contains_str_at(indent_end, &config.prefix)` to decide whether
the current line is a continuation of a block comment. When the language
is configured with an empty prefix, this is true on every line. `//`
(and `#`) line comments inside a `comment` override scope were
classified as `BlockLine("")` and never reached the line-comment
fallback. The result was that the line-comment prefix was not stripped
before wrapping and not re-prepended after, embedding `//` markers as
text in the wrapped paragraph.
Skip the BlockLine arm when the configured prefix is empty so the
matcher falls through to `line_comment_prefixes`.
I've included regression tests for both golang (which adds a new
treesitter dep to the editor package) and C/C++.
Release Notes:
- Fixed line comment rewrapping in golang and C/C++
Changes Made:
- Adding the `Item::can_save()`, `save()`, `save_as()`, `can_save_as()`
functions to help the Editor save when a checkbox is toggled
- Small refactor to seperate checkbox toggle and refreshing preview
- Adding support for both `/...` and `\\...` for windows users. [NOTE: I
no longer own a window's machine and I am unsure if this is correct, and
will fix it immediately if this is wrong]
- Resolving preview paths, strips out the fragment, and image paths are
coalesced to None if they don't exist
- Adding Tests for the added behaviour [NOTE: would love feedback since
this is the first time I am writing tests, and had a bit of assistance
from an AI, but manually reviewed the code and ran the application and
it seemed fine]
Self-Review Checklist:
- [X] I've reviewed my own diff for quality, security, and reliability
- [X] Unsafe blocks (if any) have justifying comments
- [X] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
Closes#46901
Release Notes:
- Fixed Crtl+S saving while toggling checkbox in preview mode
Closes https://github.com/zed-industries/zed/issues/54545
With the release of the parallel agents feature, we changed the default
panel positions optimizing for an agentic-first layout. Even though we
introduced a settings backfill _and_ the ability to revert after
interacting with the announcement toast, this change seems to be causing
a bit of frustration still. In response, this PR adds a "Panel Layout"
menu in the user menu that allows to quickly toggle between the
"Classic" layout and the "Agentic" layout. If you have a different set
up, you'll see a "custom" item there just confirming that.
| Panel Layout | Custom set up |
|--------|--------|
| <img width="1110" height="866" alt="Screenshot 2026-04-24 at 12
52@2x"
src="https://github.com/user-attachments/assets/197fc4ec-b4b3-4b13-bcb3-9d3495cf0d0a"
/> | <img width="1156" height="866" alt="Screenshot 2026-04-24 at 12
55@2x"
src="https://github.com/user-attachments/assets/ca791b1b-eb6a-47a9-8aa5-c2015f33e5bd"
/> |
Release Notes:
- Added a menu item in the user menu called "Panel Layout" which offers
the ability to quickly swap between the two standard panel layouts:
classic (project panel, git panel, etc., on the left) and agentic (agent
panel on the left, everything else on the right).
## Summary
Fixes an oversight in the agent threads archive sidebar's header: on
Linux and Windows it only accounted for macOS traffic lights, so the
custom window controls (minimize/maximize/close) rendered on top of the
sidebar. The main sidebar
(`crates/sidebar/src/sidebar.rs::render_sidebar_header`) already handles
this correctly — this PR mirrors that pattern in
`ThreadsArchiveView::render_header`.
### What changed
- `crates/agent_ui/src/threads_archive_view.rs`
- `render_header` now computes `traffic_lights`, `left_window_controls`,
and `right_window_controls` (matching `sidebar.rs`) and reserves space /
renders controls accordingly when not fullscreen.
- Added `render_left_window_controls` / `render_right_window_controls`
helpers that delegate to `platform_title_bar`.
- Imported `workspace::CloseWindow`.
- `crates/agent_ui/Cargo.toml`
- Added `platform_title_bar` dependency.
### Behavior
- macOS (sidebar on left): unchanged — traffic-light padding + divider.
- Linux/Windows, sidebar on left: renders left-side window controls
inside the header.
- Linux/Windows, sidebar on right: renders right-side window controls
inside the header.
- Fullscreen: no controls rendered, same as before.
#### Closes#54596
### Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
### Video
[Screencast from 2026-04-24
14-27-51.webm](https://github.com/user-attachments/assets/47009458-2acb-4b65-bff6-d25302a0342e)
Release Notes:
- Agent: Fixed the threads sidebar overlapping the window control
buttons on Linux and Windows.
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
This reduces the size of Sharedstring from 32 bytes to 24 while also
allowing for small-string optimization, meaning strings with length < 23
bytes will not actually allocate.
Release Notes:
- N/A or Added/Fixed/Improved ...
Painting primitives at non-integer pixel coordinates produces blurry
output. Pixel snapping converts layout coordinates into integer
device-pixel coordinates so painted edges land exactly on physical pixel
boundaries.
Non-integer coordinates can arise for several reasons, including:
- flex distribution, percentages, centering, and text measurement can
produce fractional element sizes and positions;
- at fractional scale factors (for example 125% or 150%), integer
logical-pixel values can map to non-integer device-pixel values.
We pixel-snap by rounding in device-pixel space, after multiplying by
`scale_factor`, so that snapping targets physical pixels. Bounds are
divided by `scale_factor` before being returned to GPUI.
Midpoints are rounded toward zero. This is a stylistic choice: a
1-logical-pixel line at 150% scale should render as 1 dp rather than 2
dp.
Pixel snapping is done in two phases:
1. Pre-layout metric snapping. Before Taffy computes layout, all
authored absolute lengths are rounded in `to_taffy`. This includes
borders, padding, gaps, and explicit sizes. Custom-measured leaf nodes
have their measured sizes rounded up to integer device-pixel lengths.
2. Post-layout edge snapping. After Taffy resolves the tree, layout
relationships such as flex shares, grid tracks, percentages, and
centering can produce new fractional edge positions. Boxes now have
edges in absolute coordinates, and snapping must decide where those
edges land on the device-pixel grid.
Ideally, post-layout snapping would satisfy:
- Edge closure. Two raw layout edges at the same absolute position
should snap to the same pixel column.
- Translation stability. A component's internal geometry should not
change when it moves to a new absolute position.
These goals are in tension because rounding is not associative. The
simple local schemes make different tradeoffs:
- Absolute edge rounding gives each window coordinate one answer, so
coincident edges always close globally. But a span's snapped length is
`round(far) - round(near)`, which may change by 1 dp as its absolute
origin moves.
- Parent-relative edge rounding rounds each child inside its parent's
coordinate space. This guarantees translation stability, but a shared
edge reached through different parents can accumulate different
rounding, causing non-closure between cousins.
- Length rounding rounds each width, height, and thickness independently
and then places boxes from those rounded lengths. Sizes stay stable
under translation, but neighboring boxes derive their shared boundary
from different sources, so closure is not guaranteed.
We apply absolute edge rounding for each element's outer box in
post-layout rounding to preserve closure. Border and padding widths are
not touched by post-layout rounding; they keep their pre-layout rounded
value so that they remain stable under translation.
This gives both closure and translation stability in the case that all
local metrics are integer device-pixel lengths. Pre-layout rounding
covers that in most cases. The exception is metrics resolved by layout
relationships, such as percentages. Outer box edges will still close
globally, and painted border widths are still snapped independently, but
the raw content-box origin can carry a 1 dp residual into descendants.
---
Fixes https://github.com/zed-industries/zed/issues/46360
Fixes https://github.com/zed-industries/zed/issues/44528
Fixes https://github.com/zed-industries/zed/issues/40282
Fixes https://github.com/zed-industries/zed/issues/42257
---
Release Notes:
- Fixed potentially blurry appearance of UI elements when using
fractional display scaling.
## Summary
This PR replaces the git file history view with the git graph view that
doesn't render the graph canvas. This has several advantages
1. Benefits from the graphs performance and lazy loading
2. Gets the graph's search for free
3. Resizable columns
4. The commit information panel
5. Is persistent
6. Cleans up a lot of code
The one con of this change is the graph doesn't have support
remote/collab support yet, but that is a WIP and should be merged within
a week.
Also, the git graph now propagates errors to the UI, which is the last
thing on the graph's stable launch todo list!
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A *or* Added/Fixed/Improved ...
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>
No, sadly, the title is not a typo. See
https://www.githubstatus.com/incidents/zsg1lk7w13cf for the context.
I'll read with joy and popcorn through that root cause analysis.
It makes literally zero sense what happened here, but for some completly
bonkers reason GitHub completely messed up the merge queue with
https://github.com/zed-industries/zed/pull/54632.
I have no idea how it happened. It makes literally zero sense. A PR
going into the merge queue should have the same LoC when getting out of
it. GitHub obviously does not check this. GitHub causes extra work with
a feature that is supposed to save time.
Thanks, I guess.
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
## Summary
Adds two user-facing settings that let the markdown preview render with
a font family and theme independent from the editor. Both are optional
and fall back to the editor defaults when unset.
```json
{
"markdown_preview_font_family": "Georgia",
"markdown_preview_theme": "Solarized Light"
}
```
## Details
- New `MarkdownFont::Preview` variant, used only by the preview surface.
- New `MarkdownStyle::themed_with_overrides()` that accepts explicit
`ThemeColors` and `SyntaxTheme` so the preview can render with a theme
other than the active editor theme. Existing `themed()` callers are
unchanged.
- The preview pane background adopts the chosen theme's
`editor_background`.
- Follows the pattern already used by `agent_ui_font_size` /
`agent_buffer_font_size`.
## Scope
Sizing-related changes (`markdown_preview_font_size`,
`markdown_preview_line_height`, typography tweaks, responsive max-width
container) were in an earlier revision of this PR and have been removed
per review feedback — they interact with the Cmd+/- zoom behavior in
ways that still need design work, and will land in a follow-up.
## Files Changed
- `crates/settings_content/src/theme.rs` — schema
- `crates/theme_settings/src/settings.rs` — runtime + accessor
- `crates/markdown/src/markdown.rs` — `MarkdownFont::Preview` +
`themed_with_overrides()`
- `crates/markdown_preview/src/markdown_preview_view.rs` — theme
resolution, style selection, background
- `crates/markdown_preview/Cargo.toml` — `theme` dependency
- `crates/settings/src/vscode_import.rs` — new fields in struct literal
Release Notes:
- Added `markdown_preview_font_family` and `markdown_preview_theme`
settings to customize the markdown preview independently from the
editor.
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
Needs https://github.com/zed-industries/zed/pull/54635 for the profile
overrides added into default settings json to work.
Part of https://github.com/zed-industries/zed/issues/48968
Another part of the fix related seems to be
https://github.com/zed-industries/zed/pull/45669 ?
Using the steps from the issue and profiling on macOs had shown that Zed
has 2 memory "leaks" in play when a certain file is being rewritten a
lot of times.
* First, the thread profiler registers a lot of tasks' data and fills
its buffer to the limit:
<img width="3456" height="2158" alt="image"
src="https://github.com/user-attachments/assets/f183312d-4389-4072-8915-d54e60419b08"
/>
* Second, if the buffer gets open, the undo history fragments start to
creep up infinitely:
<img width="3456" height="2158" alt="image"
src="https://github.com/user-attachments/assets/61a2b66b-81fd-4973-9c3c-c339f886d9b2"
/>
The PR aims to solve the first issue by disabling the profiling by
default, yet leaving the way to turn in on quickly with settings.
The memory usage profiling shows that the memory usage is now
dynamically affected by the new setting:
<img width="2032" height="1136" alt="image"
src="https://github.com/user-attachments/assets/8a6c76b9-6fb7-44bc-ac1d-3c34afe7c575"
/>
While the test directory being thrashed with the script from the issue,
* first, Zed starts with the profiling disabled
* then gets the profiling enabled which results in the memory growth
close to 1 minute mark of the screenshot
* last, the profiling gets disabled again, releasing all the memory
accumulated
Release Notes:
- Improved Zed's default memory usage
This PR brings back the button to filter remote branches when accessing
the title bar's branch picker with the mouse. It was unintentionally
removed when we introduced the new worktree picker.
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#39339
Release Notes:
- Fixed hyperlinks in the terminal on UNIX
When opening the file finder in a large project, it was impossible to
tell whether the scan was complete and if the results were final. Now we
show an animated arrow circle while the scan is active.
<img width="425" height="380" alt="Screenshot 2026-04-22 at 18 42 01"
src="https://github.com/user-attachments/assets/6d772483-a6c8-406b-bbf8-db810df7ab68"
/>
Closes#48009
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#51340
Release Notes:
- Linux/WSL: Added polling filesystem watching support in order to
support file watching on file systems that do emit events through
`inotify`, for example `/mnt/c` in WSL, network filesystems, and FUSE
mounts. Polling should be automatically chosen over `inotify` when
necessary, however it can be manually chosen by setting the
`ZED_FILE_WATCHER_MODE=poll` env var
---------
Co-authored-by: Lilith River <lilith@imazen.io>
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
This PR fixes a regression that was likely caused by:
https://github.com/zed-industries/zed/pull/54183 and wasn't caught
because I didn't add a regression test when I originally created the
feature.
The fix was only running the hooks when the worktree was just created,
and I added an integration test to prevent regressions from occurring
again in the future.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#54598
Release Notes:
- git: Fix create worktree hook tasks running when switching worktrees
Adds very basic property tests for navigation within a single pane, with
these operations:
```rust
enum Operation {
Open { path: Arc<RelPath>, allow_preview: bool },
GoBack,
GoForward,
}
```
It primarily tests that a single backward or forward navigation step
results in the correct item being active. It doesn't currently test that
going back multiple times in a row results in the correct items because
the deduplication logic that Zed uses for this turned out to be hard to
model in an "obviously correct" way, and I aimed to keep it really
simple.
These tests surfaced a navigation bug that this PR also fixes, where
replacing an inactive preview tab would sometimes corrupt the navigation
history.
Before:
https://github.com/user-attachments/assets/52e21002-1319-4b16-93d7-8f84fb8858c0
After:
https://github.com/user-attachments/assets/790b6e3b-4c2b-4f2e-a705-70b1bc034872
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed a bug where replacing a preview tab would sometimes break
navigation.
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
> **Draft / open question for maintainers.** The failure mode this fixes
is narrow — a new-Zed-created container exists under the `name`-field
project while a CLI-derivation tool (`@devcontainers/cli`, VS Code)
operates on the same folder (the container persists in Docker, so the
originating Zed session doesn't need to still be open). See issue #54255
failure mode 3 and the fixture's step 6.
>
> I'd like to pose this as a question rather than a claim: is matching
`@devcontainers/cli`'s `getProjectName` precedence something the project
wants to take on, given the narrowness of the bug? I wrote this
implementation mostly as a way to explore what parity would actually
cost — happy to close it if you'd rather leave it as-is, or pare it down
(e.g. just rule 4) if a partial match is preferable.
>
> The broader value beyond this specific bug: devcontainer impls
agreeing on the same project name means containers created by Zed, the
devcontainer CLI, and VS Code are interchangeable for the same folder,
which feels worth it to me — but you know the project's priorities
better.
>
> Folds in #54068 (detection) — closing that PR unmerged; its
`MultipleMatchingContainers` error lands here.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#54255
## Summary
**Match `@devcontainers/cli`'s full `getProjectName` precedence.**
Replaces `safe_id_lower(devcontainer.json's name)` with the five-step
chain the reference CLI walks (see [`src/spec-node/dockerCompose.ts` in
devcontainers/cli](https://github.com/devcontainers/cli/blob/main/src/spec-node/dockerCompose.ts)):
1. `COMPOSE_PROJECT_NAME` from the local environment.
2. `COMPOSE_PROJECT_NAME=` in the workspace `.env` file.
3. Top-level `name:` on the merged compose config, when at least one
fragment declared it explicitly.
4. `${workspaceFolderBasename}_devcontainer` — only when the first
compose file's directory is `<workspace>/.devcontainer/`.
5. Otherwise, the plain basename of the first compose file's directory
(no suffix).
The old Zed implementation diverged at every one of those inputs: any
user setting `COMPOSE_PROJECT_NAME`, shipping a `.env` with one,
declaring a top-level compose `name:`, or pointing `dockerComposeFile`
outside `.devcontainer/` (e.g. `"../docker-compose.yml"`) got a
different project namespace than the CLI and VS Code, producing two
compose projects for the same folder.
Adds a small `sanitize_compose_project_name()` helper implementing the
CLI's rules (lowercase + strip `[^-_a-z0-9]`) — notably preserving
hyphens, which `safe_id_lower` would have replaced with underscores.
Adds two helpers used by the precedence walk:
- `parse_dotenv_compose_project_name` — line scan extracting
`COMPOSE_PROJECT_NAME=…` from the workspace `.env`, matching the subset
the CLI's regex dotenv reader recognizes.
- `compose_fragment_declares_name` — parses each compose fragment with
`yaml-rust2` (already a transitive workspace dep; slated to become a
direct dep via #53922) and checks for a `name` key on the root mapping
(block, quoted, or flow style all work), matching the CLI's own
`yaml.load`. `docker compose config` always injects `name: devcontainer`
into its merged output when no fragment declared one, so rule 3 needs to
distinguish the user-provided case from the injected default — this
helper supplies that signal. On YAML parse failure it returns "not
declared" (rule 4 applies), matching the CLI's fallback.
`project_name()` becomes async and fallible (`async fn
project_name(&self) -> Result<String, DevContainerError>`) so it can
load the `.env` file and each compose fragment via `self.fs.load`. Four
call sites now `.await?` the derivation. Real I/O errors on the `.env`
read propagate as `FilesystemError` (matching the CLI's narrow
`ENOENT`/`EISDIR` swallow); fragment-rescan read errors are logged and
skipped (matching the CLI's broader try/catch over its fragment read +
parse).
The `name` field is still used as the features image-tag prefix
(`generate_features_image_tag`); only the compose project namespace is
decoupled from it.
**Duplicate-container detection (from #54068).** When
`check_for_existing_container`'s label-based lookup returns more than
one match, propagate `MultipleMatchingContainers(ids)` with instructions
to clean up the stale one(s). This covers the mixed-version upgrade edge
case where a pre-fix Zed left a container under the legacy project name
alongside a CLI-style one — transparent to users in the common case (one
tool, one container), explicit error when two legacy siblings need
manual cleanup.
## Why
Full write-up with verified fixtures and captured output: #54255.
Three failure modes from the same root cause, all resolved by this
change:
1. **Interop** — opening a folder in both Zed and `devcontainer up` (or
Zed and VS Code) creates two compose projects with identical
`devcontainer.local_folder` + `devcontainer.config_file` labels,
breaking the spec's uniqueness invariant.
2. **Cross-worktree silent db/volume reuse** — if multiple git worktrees
share a `devcontainer.json` with the same `name`, Zed uses the same
compose project for all of them; Compose reuses stateful siblings (db,
cache, localstack) by config-hash, so worktree B silently inherits
worktree A's database. Fixture + captured output:
[antont/zed-devcontainer-db-share-repro](https://github.com/antont/zed-devcontainer-db-share-repro).
3. **Mixed-version Zed sessions** — the Rust impl landed in stable
v0.232.2 (2026-04-15, #52338). Older Zed (≤v0.231.x) shelled out to
`@devcontainers/cli` so it used the reference derivation. The collision
shows up when a new-Zed-created container exists under the name-field
project while a CLI-derivation tool (old Zed, `devcontainer up`, VS
Code) operates on the same folder.
## Migration / compatibility
Existing Zed-created containers (under the old `safe_id_lower(name)`
project) continue to be found via `check_for_existing_container`'s
label-based lookup — they're looked up by `devcontainer.local_folder` +
`devcontainer.config_file`, not by project name. A user with duplicate
legacy containers from a prior Zed session sees
`MultipleMatchingContainers` with cleanup instructions.
## Revision — 2026-04-22
Revised per @KyleBarton review on the prior version:
- Swapped the YAML parser from `serde_yaml_ng` to `yaml-rust2` (already
transitive via `tree-sitter-yaml`; net reduction of one direct workspace
dep; also what #53922 will pull in).
- Dropped the mixed-version tiebreak (`pick_canonical_container`) and
its `com.docker.compose.project` serde label. The edge case it covered
is transient enough to address via the explicit
`MultipleMatchingContainers` error rather than permanent tiebreaking
code.
- Folded #54068's detection commit into this PR; #54068 closed unmerged.
- Rebased onto `main`.
## Test plan
- [x] `cargo test -p dev_container --lib` — 89 passed, including:
- `sanitize_compose_project_name_matches_cli_rules`
- `--project-name` assertion added to
`test_spawns_devcontainer_with_docker_compose`
- `check_for_existing_container_errors_when_multiple_match`
- `derive_project_name_env_wins_over_everything`
- `derive_project_name_dotenv_wins_over_compose_and_fallback`
- `derive_project_name_compose_name_wins_over_fallback`
- `derive_project_name_skips_compose_name_when_not_explicitly_declared`
-
`derive_project_name_omits_suffix_when_compose_file_outside_devcontainer_dir`
- `derive_project_name_normalizes_compose_path_for_rule_4`
- `compose_fragment_declares_name_detects_top_level_name_key` (covers
block, quoted-key, and flow-style roots, plus parse failure →
not-declared)
- `is_missing_file_error_only_accepts_notfound_and_isadirectory`
- [x] `cargo fmt --all` — clean
- [x] `./script/clippy -p dev_container` — clean
- [x] **End-to-end with fixture**
[antont/zed-devcontainer-compose-test](https://github.com/antont/zed-devcontainer-compose-test):
- Build `zed` from this branch.
- Clean slate: `docker ps -a --filter
"label=devcontainer.local_folder=$PWD" -q | xargs -r docker rm -f`
- `zed --dev-container /path/to/devcontainer-compose-test` → Zed creates
container under project `devcontainer-compose-test_devcontainer` (was
`compose_duplicate_repro` before the fix).
- `devcontainer up --workspace-folder $PWD` → CLI reports the same
`containerId` Zed created; no second compose project is introduced.
- Captured: `devcontainer-compose-test_devcontainer-app-1`,
`composeProjectName: "devcontainer-compose-test_devcontainer"` reported
by both tools.
Release Notes:
- Fixed dev container Docker Compose project name now matches the full
`getProjectName` precedence from the reference devcontainer CLI
(`COMPOSE_PROJECT_NAME` in the environment, then in the workspace
`.env`, then an explicit top-level `name:` on the merged compose config,
then the basename of the first compose file's directory — with the
`_devcontainer` suffix only when that directory is
`<workspace>/.devcontainer`). This prevents duplicate containers when
the same folder is opened with both Zed and the devcontainer CLI / VS
Code.
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: Eric Holk <eric@zed.dev>
Testing out Niko's new SDK design
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Drop the `count_tokens` API and related implementations across
providers, and remove the unused `tiktoken-rs` dependency.
I was going to update the dependency becuase they finally released a fix
we needed. But then I realized we only used this api in one place, the
Rules library. And for most models it would have been wildly incorrect
becuase we use tiktoken, i.e. OpenAI tokenizers, for almost every model,
which is going to give incorrect results.
Given that, I just removed these because the difference in how we get
these has caused plenty of confusion in the past.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Closes#46551
Zed was using the `terminal.shell` setting for some actions unrelated to
the terminal GUI, like environment capture, ACP agent startup, context
server startup, and vim `:!`, and so if a user set it to `tmux` or
`nushell`, those paths would fail.
This PR ensures paths unrelated to Zed's terminal use the system path
instead.
Manual testing:
Set `terminal.shell` to `tmux` or any another non-bash executable.
Starting an external agent thread shouldn't break.
Release Notes:
- Fixed ACP agent and other breakage when `terminal.shell` was set to a
non-shell program like `tmux`
When opening a remote session, sometimes you get a message:
/bin/bash: line 1: cd: /Users/pep: No such file or directory
which suggests that that the local home dir (/Users/pep) is used for the
remote terminal session, where it should be something like /home/ubuntu.
Release Notes:
- Fixed remote terminals incorrectly trying to change to a local home
directory.