Fixes menu a11y, and adds landmarks with `F6`-navigation.
Also fixes a GPUI bug, and adds debug actions for dumping a11y tree
info.
Since `F6` was already in use by the pause debugger keybind, also
tightens up the debugger keybind context so they require an active
debugger session. When there is one active, `F6` stays as pause
debugger. `ctrl-F6` always works to go to the next landmark.
Also adds an "accessible mode" setting. Currently, this only controls
whether we show all menus all the time, but I suspect it will expand
significantly in the future.
Also adds `.aria_keyshortcuts()` API, but it's not wired up within
accesskit adapters, so is not yet reported to screen readers.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
The branch picker collapses remote branches that are tracked by a local
branch (e.g. `origin/main` when local `main` tracks it). That makes
sense for checkout, where the remote ref is redundant, but it was also
applied to the branch diff base picker, where `main` and `origin/main`
can point to different commits. As a result, once you switched the diff
base from `origin/main` to `main`, there was no way to switch back.
The tracked-remote collapsing is now only applied in checkout mode (no
changed here). The select (diff base) picker lists both local branches
and their remote upstreams.
Release Notes:
- Fixed remote branches (e.g. `origin/main`) not appearing in the branch
diff base picker, making it impossible to switch back after changing the
base to another branch.
Fixes ZED-7XR
CVDisplayLink has no safe teardown: `CVDisplayLinkStop` only flags the
io thread to exit "soon" and returns, `CVDisplayLinkRelease` frees the
link immediately, and there is no way to learn when a final output
callback has finished. This produced two distinct use-after-free crash
classes on the display-link thread: the io thread reading the freed
link's internals (`CVHWTime::reset`, worked around by leaking the link
in #32116), and a straggler output callback dereferencing the freed
dispatch source through its context pointer
(`dispatch_source_merge_data`, ZED-7XR). Because we tore down a
`DisplayLink` on every resize tick, window activation, and occlusion
change, the existing workaround also leaked a stopped CVDisplayLink per
teardown, unboundedly.
This replaces per-window links with a static registry holding one
immortal `CVDisplayLink` per display. Windows subscribe to their
display's link with the dispatch source that paces their frames; the
output callback's context is a display id rather than a pointer, so the
only memory it ever dereferences is the registry itself, under its lock.
Links start and stop at subscriber-count edges (so multiple windows on
one display can't interleave starts/stops incorrectly), and a window's
dispatch source lives for the life of the window, is removed from the
registry on close, and is then genuinely released. Both crash classes
become unreachable — the link because it is never released, the source
because a straggler callback either finds it live in the registry or
doesn't find it at all — and there are no leaks and no `mem::forget`.
Since we never hold the registry lock across CoreVideo calls, no lock
cycle through CVDisplayLink's undocumented internal locks is possible;
the module doc comment spells out the invariants.
This supersedes #60481, which fixed ZED-7XR by leaking the dispatch
source on teardown.
Release Notes:
- Fixed a rare crash on macOS when closing, resizing, or switching
between windows, and eliminated a memory leak in display-link teardown
# Objective
write_to_clipboard was a no-op and read_from_clipboard returned None.
## Solution
Writes go through the browser's asynchronous Clipboard API,
fire-and-forget, invoked synchronously inside the user's input event so
the user-activation requirement holds.
Reads cannot be implemented the same way: the async clipboard read API
cannot fit read_from_clipboard's synchronous signature. Paste is instead
delivered by a DOM paste listener on the hidden input, whose
ClipboardEvent exposes clipboardData synchronously; the text feeds the
active input handler. This covers keyboard-, menu-bar- and
context-menu-initiated paste. Note the keyboard path requires the paste
chord's keydown to reach the browser unconsumed (apps should not bind
cmd/ctrl-v on web).
## Testing
Tested locally
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
## Problem
Built-in tools like `Fetch` render their primary argument next to the
tool name in the collapsed tool-call header (e.g. `Fetch
https://example.com`). MCP tools don't — they always show `Run MCP tool
<name>` and the argument is hidden inside the expandable "Raw Input"
JSON block.
For Playwright, fetch, search, or any MCP tool where one argument
carries all the context, this makes every call opaque. You have to click
to expand just to see which URL is being opened or which file is being
read.
Before:
```
⊙ mcp__playwright__open_url_in_browser
[click to expand]
Raw Input:
{
"url": "https://linkedin.com/in/neuodev"
}
```
After:
```
⊙ Run MCP tool `mcp__playwright__open_url_in_browser` https://linkedin.com/in/neuodev
```
## Root cause
`ContextServerTool::initial_title` at
`crates/agent/src/tools/context_server_registry.rs` discards the input:
```rust
fn initial_title(&self, _input: serde_json::Value, _cx: &mut App) -> SharedString {
format!("Run MCP tool `{}`", self.tool.name).into()
}
```
Built-in tools read the input (`fetch_tool.rs`: `format!("Fetch {}",
MarkdownEscaped(&input.url))`) but the generic MCP path never did.
## Change
When the MCP tool's input is a JSON object with exactly one
string-valued field, inline that value next to the tool name. All other
shapes (multi-field objects, non-string values, null/empty input) fall
back to the existing `Run MCP tool <name>` label, so behavior is
unchanged for them.
- Value is truncated at 120 chars with `…` on overflow (char-safe, not
byte-safe — "café" won't panic).
- Value is run through `MarkdownEscaped` so markdown metacharacters
render literally.
- Single-string heuristic was chosen because the MCP spec has no
standard field for a display template, and the common case (`url`,
`path`, `query`, `selector`, `name`) is covered. I considered honoring
`Tool.annotations.title` or `_meta["zed/title"]` as a template — happy
to follow up with that if the team prefers an opt-in mechanism, but
wanted to start with something that works out of the box for every
existing MCP server.
## Tests
Added 10 unit tests in the existing `mod tests` block covering: happy
path, no args, null input, multi-field fallback, non-string fallback,
truncation, markdown escaping, multibyte chars, and empty-string
preservation.
`cargo check -p agent --tests` passes locally. I couldn't run the full
test binary on my machine because `wasmtime-c-api-impl` (a transitive
test-dep) needs `cmake`, but the new code is pure string-manipulation
with no wasm/runtime touch — CI should cover.
## Scope
One file, +127/-3. No behavior change for any tool shape other than
single-string-input MCP tools.
## Per CONTRIBUTING.md
Happy to convert to a discussion first if the team prefers — didn't see
a tracking issue for this. Also filed under CLA (signed).
Release Notes:
- Show MCP tool primary argument in tool header if space allows
---------
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
Allowing the settings UI to shrink smaller than that size can easily
cause UI states where the whole window becomes unusable. The previously
defined 900px size was defined so that those states did not happen. I
appreciate how having such minimum size can be a bit of a hassle when
the settings window is used with window managers, but given it's such a
transient window (i.e., one which you won't always have open all the
time) I think it's better to stay on the trade-off side of safety here.
As a quick example, it doesn't make sense to me to allow the UI to reach
this state:
<img width="300" alt="Screenshot 2026-07-13 at 9 26@2x"
src="https://github.com/user-attachments/assets/f2aebe21-293b-468f-b03e-37cd7305a9c5"
/>
---
Release Notes:
- N/A
Users can now Cmd+click multiple files in the file picker and press
Enter to open them all at once. Tab can also be used to select items
without clicking, advancing the cursor automatically.
# Objective
Currently, when opening the file picker (Cmd+P), users can only open one
file at a time. This adds multi-select support so users can select
multiple files and open them all at once.
Fixes#59818
## Solution
Added a `selected_indices` set to `Picker` to track which items the user
has toggled into a multi-selection. Regular clicks still open a file
immediately (unchanged behavior).
Cmd+clicking adds a file to the selection without opening it, and
pressing Enter opens all selected files at once. A `confirm_multi`
method was added to the delegate trait so individual delegates (like the
file finder) can handle opening multiple files with a safe fallback for
delegates that don't support it. Multi-selection is cleared when the
picker
is dismissed or the search query changes. Selected items show a
background highlight and a focused left border so the user always knows
what's selected.
## How to use it
1. Open the file or test picker.
2. Search and either Cmd+click or tab it to add it to the selection (the
file will not open yet).
3. Repeat for any other files you want to open.
4. To deselect a file, Cmd+click it again.
5. Alternatively, hover over an item and press Tab to select it with the
keyboard, the cursor automatically moves to the next item so you can
keep selecting quickly.
6. Once you have all the files you want, press Enter to open them all at
once.
## Testing
Tested manually on macOS.
- **Single select:** Clicking on a file opens it directly, which is the
existing behavior and remains unchanged.
- **Multi-select via Cmd+Click:** Holding Cmd and clicking multiple
items adds them to the selection. Cmd+clicking an already-selected item
deselects it. Pressing Enter opens all selected files at once.
- **Multi-select via Tab:** Hovering over an item and pressing Tab
selects it without clicking or opening it, allowing keyboard-driven
multi-selection.
## Showcase
**Single select:**
<img width="1512" height="982" alt="Screenshot 2026-06-25 at 6 45 33 PM"
src="https://github.com/user-attachments/assets/8f9d4408-0688-4619-807a-affd6dc66f21"
/>
Opened single file
<img width="1512" height="982" alt="Screenshot 2026-06-25 at 6 45 38 PM"
src="https://github.com/user-attachments/assets/34ffacfd-b8ed-4898-beaa-bd5e47ebf682"
/>
- **Multi-select:**
- Selecting multiple files
<img width="1512" height="982" alt="Screenshot 2026-06-25 at 6 49 22 PM"
src="https://github.com/user-attachments/assets/a7562fe8-9bd2-40ba-8bb4-12909ccefed7"
/>
Opened multiple files
<img width="1512" height="982" alt="Screenshot 2026-06-25 at 6 49 42 PM"
src="https://github.com/user-attachments/assets/c0c9e24c-86b7-45bf-898d-05068d5d7e3a"
/>
## Release Notes:
- Added multi-select to the file and text picker: Cmd+click or tab to
select multiple files, then open them all at once.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Yara <git@yara.blue>
# Objective
Fix errors in Windows when trashing files from the Git Panel. Closes
#60716.
## Solution
The solution and discussion is available at
https://github.com/zed-industries/trash-rs/pull/3 , seeing as the fix
was fully done on the `trash` crate. Original discussion of this issue
can be found at https://github.com/zed-industries/zed/pull/59595 .
## Testing
Testing was performed manually on a Windows machine by updating Zed's
`fs` crate dependencies to point at the updated code and then building
from source and testing out the same exact path, namely:
1. Create a new untracked file
2. Trash the file from the Git Panel's context menu
3. Confirm that, after confirming that you wish to trash the file, the
file is trash and no error is shown
Since this whole trash-tracking logic was implemented in the context of
the project panel's undo system, I also confirmed that the changes in
the crate's code didn't affect trashing and restoring on Windows.
## Self-Review Checklist:
N/A
## Showcase
<details>
<summary>Before</summary>
https://github.com/user-attachments/assets/120ab3ec-d631-4243-a21e-c510c27ed518
</details>
<details>
<summary>After</summary>
https://github.com/user-attachments/assets/7ff1e373-b56d-431f-aad5-d4c5bb301e02
</details>
---
Release Notes:
- Fixed issue when trashing untracked files in Git Panel on Windows
Map OpenAI's context_length_exceeded errors (both the in-stream error
events sent by the Responses API / ChatGPT Codex backend and HTTP 400
responses carrying the code) to
LanguageModelCompletionError::PromptTooLarge. This stops pointless
retries and surfaces the dedicated token-limit UI instead of a raw error
string.
Also record a synthetic request token usage when a completion fails with
PromptTooLarge, so the context indicator reports Exceeded rather than
the stale usage of the last successful request, and the next prompt
qualifies for auto-compaction.
Ought to help a bit with
https://github.com/zed-industries/zed/issues/59600
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Release Notes:
- On agent notifications, the corresponding zed window will now mark
itself for OS level attention
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
# Objective
Fixes#54250
`editor: copy file location` copies the row you're on in the
multi-buffer, not the row in the actual file. In a git diff view with
collapsed lines it copies the wrong line number.
## Solution
It read the rows straight off the selection, which is in multi-buffer
coordinates. `ClipboardSelection::for_buffer` already handles this with
`range_to_buffer_range`, so I used the same thing. Path and line now
come from the same buffer.
`range_to_buffer_range` returns nothing when the selection ends in a
different buffer than it starts in, which you can do in a git diff view.
Rather than copy nothing, it falls back to the cursor's buffer.
## Testing
Three tests: a multi-buffer excerpt, a selection dragged across two
files, and a plain single-file editor. The multi-buffer ones fail on
main; the singleton one passes either way, so normal editors are
unaffected.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed `editor: copy file location` copying the wrong line number in
multibuffers
([#54250](https://github.com/zed-industries/zed/issues/54250)).
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
# Objective
- Fixes#53650
- Possibly also fixes#57956 (needs confirmation)
## Solution
- Replace the direct `DisplayPoint::new(row, col)` construction with a
proper buffer-point-to-display-point
- This goes through the full inlay → fold → tab → wrap → block pipeline
and correctly accounts for any inlay hints on the target line.
## Testing
- Added a regression test for multi-cursors with inlay hints in helix
mode
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed `Shift+C cursor` position with inlay hints in helix mode
This hardens the Windows text rendering path in gpui_windows against
undefined behavior and out-of-bounds access. DirectWrite hands back
glyph-run arrays (glyph indices, advances, offsets) and cluster maps as
raw pointers that may be null; these are now interpreted through a
shared `slice_from_nullable` helper that treats a null pointer with zero
length as an empty slice and returns `E_INVALIDARG` when a null pointer
arrives with a nonzero length, instead of constructing a slice from a
null pointer. It also fixes a provenance bug: the renderer context
passed to `IDWriteTextLayout::Draw` was derived via `&raw const` from a
non-mut binding, but the `DrawGlyphRun` callback recovers that pointer
and writes through it, which is undefined behavior under Stacked/Tree
Borrows; the binding is now `mut` and the pointer is derived from `&raw
mut` so its provenance matches the write (codegen is unchanged).
On the DirectX side, the atlas upload is now bounded by the source slice
length so a mismatched destination region cannot read past the end of
the source, and the color-glyph staging texture is unmapped after
readback so the mapping is no longer leaked and the resource pinned. The
color-glyph rasterizer drives the shared, non-thread-safe D3D11
immediate context that `DirectXRenderer` and `DirectXAtlas` also use, so
it must stay on the main UI thread — which it always is today; a comment
documents that invariant.
Since gpui_windows is a Windows-only crate, it cannot be compiled on
non-Windows hosts, so Windows CI is the compile gate for these changes.
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#18112
Release Notes:
- Added support for pasting images from clipboard into Markdown files
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
Fixes#60261
Nothing under a `case` gets indented in C or C++, and the next `case`
doesn't come back out. It stays flat until you hit `editor: format`.
## Solution
The indent queries had no rule for case labels. Added the same pair
`cpp/indents.scm` uses for `access_specifier`: open an indent range at
the label, close it at the switch's `}`, outdent on the next label.
The part that got me: `@start` uses the *end* of the node you capture.
Fine for `access_specifier`, which is just `public:`. But a
`case_statement` swallows the statements under it, so capturing the node
starts the range after the last one. Capture the `:` instead. `default:`
is a `case_statement` too, so it comes along free.
Only affects what happens after a label, so existing `case` alignment
doesn't move.
## Testing
`test_c_autoindent_switch_case` and `test_cpp_autoindent_switch_case`
cover a plain case, fall-through labels and `default`. Both fail on
main. The `access_specifier` tests still pass.
Not mine, but worth knowing: `typescript::tests::test_outline` and
`test_generator_function_outline` are flaky on main, failing about half
my full `cargo test -p languages --lib` runs with or without this
change.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed statements under a `case` label not being indented in C and C++
([#60261](https://github.com/zed-industries/zed/issues/60261)).
Closes https://github.com/zed-industries/zed/issues/60595
cc Anthony-Eid since you did an initial pass on this.
# Objective
Currenly on macOs there is no way right now after the following
regression to use window management short keys to move them around. This
worked before, but was regressed initially in
https://github.com/zed-industries/zed/pull/59836 that tried fixing a
macos 27 clicking delay issue on the titlebar. That accidentally set the
`native_window.setMovable_(is_movable as BOOL)` to false. Because of
this mocos detects this and disables the window managements actions
because it thinks the window can/should not be able to move.
## Solution
The macOS 27 click delay actually comes from AppKit's native titlebar
dragging, not from `NSWindow.isMovable`. The problem is that
`is_movable` is also what enables the Window menu's tiling options, and
#59836 used it to turn off dragging, which disabled the tiling menu as a
side effect.
To fix this, I restored `is_movable` to its real meaning so the tiling
menu works again, and added a separate
`WindowOptions::app_owns_titlebar_drag` flag for windows that draw their
own titlebar and handle dragging via `Window::start_window_move`. On
macOS this tells AppKit to stop owning titlebar drags (removing the
click delay) without affecting `is_movable`. Zed's main window now sets
both `is_movable: true` and `app_owns_titlebar_drag: true`, so the
tiling menu stays enabled, the click delay is gone. I also added a
`window_movable` gpui example to make this behavior easy to test
manually.
## Testing
I added a gpui test example that helps testing this bug. You can run the
newly added gpui example with 4 different window configurations that
should confirm that this change is the right one for all of the window
types that we have.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
**After** (note this now shows the window managements entries as they
were greyed out.)
https://github.com/user-attachments/assets/192cc0e1-15d8-486f-b788-a92bb51fb7d1
**GPUI** (test examples with different window configurations.)
https://github.com/user-attachments/assets/c9e0f4d3-606b-4cd7-b4d8-a5bb16508164
---
Release Notes:
- Fix macos window management controlls were grayed out/not working
# Objective
Fixes#51967
Destructured JS/TS/TSX parameters with defaults were not highlighted
consistently as parameters when using themes that distinguish arguments
from variables/properties, such as Catppuccin.
For example, in:
```js
function a({ argument = true }) {}
```
`argument` was parsed under a default assignment pattern and did not
receive the same `@variable.parameter` capture as a destructured
parameter without a default.
This also affected array binding patterns with defaults, such as:
```js
function b([argument = true]) {}
```
## Solution
Updated the JS/TS/TSX highlight queries to capture destructured
parameters with default values as `@variable.parameter`.
This covers both:
- Object binding patterns with defaults, such as `{ argument = true }`
- Array binding patterns with defaults, such as `[argument = true]`
As a result, destructured parameters are highlighted consistently
whether or not they provide a default value.
## Testing
- Verified the highlight query changes for JavaScript/TypeScript
destructured parameters with defaults.
- Tested examples include:
```js
function a({ argument }) {}
function a({ argument = true }) {}
function a({ argument = true }?) {} //optional
function b([argument]) {}
function b([argument = true]) {}
function b([argument = true]?) {} // optional
```
- These cases should be easiest to visually confirm with a theme that
distinguishes parameters from variables/properties, such as Catppuccin.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
## Showcase
Before this change,
<img width="1600" height="332" alt="图片"
src="https://github.com/user-attachments/assets/fbacb22b-f0e4-490d-8f94-6059e66d3ae0"
/>
After this change:
<img width="1599" height="353" alt="图片"
src="https://github.com/user-attachments/assets/3eae692b-391e-4c53-9925-1ca2f5774038"
/>
Release Notes:
- Fixed inconsistent syntax highlighting for JS/TS/TSX destructured
parameters with default values.
# Objective
- Fix ignored file search in nested Git directories (even just empty
`.git` directories, not real git repositories)
- Fixes#52328
## Solution
Keep parent ignore rules when rebuilding a nested repository's ignore
stack. This hides root-ignored files again after excluded-file search is
turned off, without breaking global ignore handling.
For example:
```ascii
project/
├── .git/
├── .gitignore # log/
├── app/
│ └── a.txt # hello
└── log/
├── .git/ # nested repository marker
└── b.txt # hello
```
Both `a.txt` and `b.txt` have string `hello`.
Initially, searching for `hello` returns only `a.txt`. Enabling `Also
search files ignored by configuration` rescans `log/` and returns both
files.
Before this change, disabling the option still
returned both files because the rescan dropped the parent `.gitignore`
and marked `b.txt` as included.
## Testing
- Did you test these changes? If so, how?
To test changes in this pull request create a simple project with the
following dir structure:
```
.git
.gitignore
a/a.txt
b/b.txt
b/.git # this is an empty directory
```
Add `b` folder as an ignore entry to the `.gitignore` file: `b/`
- Are there any parts that need more testing?
No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Use the test scenario above
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
macOS
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
By using the structure above here is how it works before changes here:
https://github.com/user-attachments/assets/2028123e-388e-4390-b131-ddf4642ab5f3
Notice that `hello` string from file `b.txt` is listed in search results
regardless of the option `Include excluded files`
And here is after:
https://github.com/user-attachments/assets/99c627a2-e16a-4fdd-979b-2e0bacbd827d
Notice that `hello` string from file `b.txt` is **not** listed in search
results when the option `Include excluded files` is disabled.
Release Notes:
- Fixed ignored file search in nested Git directories
# Objective
- Fix npm v12 output deserialization
- Fixes#60705
## Solution
Initially I was thinking about checking the `npm` version and then
parsing its output accordingly but that would
include a call to `npm --version`. Zed's mojo is to be blazingly fast so
just checking the structure of the output should be enough:
1. `npm info --json` in v12 produces an array with 1 object: `[ {
"name": "something" } ]`
2. `npm info --json` in v11 and older produces an object: `{ "name":
"something" }`
So the trick is to check the output: if it's an array, we have npm v12,
otherwise npm v11.
## Testing
- Did you test these changes? If so, how?
1. Ensure you have `npm` v12 installed.
2. Install a Node.js based language server, for example, `markdownlint`
or `oxfmt`
3. Open a project and trigger start of a language server
- Are there any parts that need more testing?
no
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Use steps above
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
I've tested this on macOS and Linux.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
N/A
---
Release Notes:
- Fixed npm v12 output deserialization
Toggle Markdown Preview with the Existing Preview Shortcut
## Context
Markdown files already expose actions for opening a rendered preview in
the current pane or to the side. The current-pane preview action focuses
the preview, but there was no matching keyboard path from the preview
back to the source editor.
Users expect the existing preview shortcut to behave like a mode toggle:
press it from the editor to preview, then press it again from the
preview to return to editing. The existing preview view keeps a handle
to its source editor, so the preview can return focus to that editor
without adding a broader workspace-level toggle.
## Feature
Add a markdown-preview-scoped action,
`markdown::CloseAndReturnToEditor`, and bind the existing preview
shortcut to complementary actions:
- In a markdown editor, `ctrl-shift-v` on Linux and Windows, or
`cmd-shift-v` on macOS, dispatches `markdown::OpenPreview`.
- In a markdown preview, the same platform shortcut dispatches
`markdown::CloseAndReturnToEditor`.
The close action first activates and focuses the source editor. If the
source editor entity is no longer open in any pane, the action adds it
back to the active pane before closing the preview. The preview is
closed with `SaveIntent::Skip` because the preview is not the owner of
source-buffer changes.
Existing markdown preview shortcuts remain available.
## Alternatives
- Bind `escape` to close the preview. This is easy to discover, but it
does not provide a symmetric editor/preview toggle and can overlap with
transient UI such as search.
- Add a new dedicated toggle chord, such as `ctrl-alt-v` / `cmd-alt-v`.
This avoids changing the preview shortcut's meaning in the preview
context, but it makes users learn a second shortcut for the same
preview/edit workflow.
- Teach `markdown::OpenPreview` to toggle based on the active item. That
would mix editor-scoped preview creation with preview-scoped close
behavior and make the action depend on more workspace state.
## Consequences
- The toggle behavior is implemented by context-specific keybindings
rather than one action that changes meaning globally.
- Returning to edit mode works even when the original editor tab has
been closed while the preview remains open.
- The preview close path has focused GPUI tests because it relies on
pane activation, focus restoration, and asynchronous item closing.
Release Notes:
- Add a markdown action to close the current preview and focus the
related source file
# Objective
Right now the minimum width of the settings window is 900px, this makes
it so that when I open it with my window manager (aerospace), it goes
off the screen on the right side.
https://github.com/user-attachments/assets/e47c1f13-0b5c-49e1-9a1e-4d3b494eca8d
## Solution
There is a comment, that says:
```
// Don't make the settings window thinner than this,
// otherwise, it gets unusable. Users with smaller res monitors
// can customize the height, but not the width.
width: px(900.0),
height: px(240.0),
```
the comment and limit was added in #44505, which added the edit
prediction provider ui. Now in the past, in #51878 I fixed a bug with
the way that the edit prediction provider and some of the other sub menu
type pages in the settings menu displayed. There isn't really any record
of what specifically made the window unusable below 900px besides the
issue that I fixed in #51878.
## Testing
I tested it by just sort of poking around the different settings pages,
especially the ones I fixed in #51878, and every thing seems totally
fine to me. That said I haven't exhaustively checked every page and if
there was any more information on what that comment was referring to
that would be awesome.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
How it looks after the change:
https://github.com/user-attachments/assets/9258f51f-5da5-4f4c-997d-7f09a3448e4b
---
Release Notes:
- settings_ui: Allowed window widths below 900px
in a plain text file, cursor before a closing bracket, type an opening
one and nothing autocloses. `anything|)` + `[` gives `anything[|)` not
`anything[]|)`. fine in js/css/py.
autoclose checks the language's `autoclose_before` set. every language
sets one, plain text didn't, so a closing bracket ahead of the cursor
killed it. gave it `)]}`.
went `)]}` not the usual `;:.,=}])>` since plain text only has brackets.
`.typ` (Typst) is a separate extension, needs the same fix there.
Fixes#60560.
Release Notes:
- Fixed nested brackets not auto-closing in plain text files
# Objective
Fixes#60812
Previously, double-clicking in the preview updated the source editor
selection/cursor position, moved focus to the source editor, and stopped
the event from propagating. This prevented normal text selection in the
preview. When the source editor was in the same pane but not the active
tab, focus was then restored back to the preview, causing the tab/tab
bar to flicker.
## Solution
Update the source editor selection/cursor position on single-click
instead of double-click, while keeping focus in the Markdown preview.
This leaves double-click behavior available for normal text selection in
the preview.
- This approach keeps Markdown preview interactions consistent with
common text behavior: double-clicking text should select the word/text
under the cursor..
- The source editor selection/cursor position is still updated on
single-click so the preview can continue to keep the source editor in
sync with the location the user is inspecting.
## Testing
Manually tested the Markdown preview click behavior.
I also tried adding a regression test using `simulate_event` to simulate
mouse events, but I could not find a reliable API for locating the
rendered text position inside the Markdown preview. Because of that,
this was validated manually.
Manual test steps:
1. Open a Markdown file.
2. Open the Markdown preview for that file.
3. Keep the source editor and Markdown preview as separate tabs in the
same pane.
4. Activate the Markdown preview tab.
5. Single-click text in the Markdown preview.
- Confirm the source editor selection/cursor position is updated.
- Confirm focus remains in the Markdown preview.
- Confirm the tab bar does not flicker.
6. Double-click text in the Markdown preview.
- Confirm the text in the preview is selected.
- Confirm focus remains in the Markdown preview.
- Confirm the tab bar does not flicker.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
## Showcase
after change:
[录屏 2026-07-11
23-44-16.webm](https://github.com/user-attachments/assets/616d1ed3-5802-402f-8499-4864b149c550)
---
Release Notes:
- Fixed double-click text selection and tab bar flicker in Markdown
preview.
# Objective
Make branch filtering consistent and more flexible across the title bar
and Git panel branch pickers.
## Solution
- Replace the remote-only filter toggle with a dropdown for all, local,
and remote branches.
- Preserve the selected filter across branch picker instances.
- Add a ListFilter icon and active-filter indicator.
- Prevent nested filter-menu interactions from dismissing the parent
picker.
- Cycle through all, local, and remote filters with the existing
keyboard shortcut.
## Testing
- Ran `cargo check -p git_ui --tests --no-default-features`.
- Verified formatting with `cargo fmt -p git_ui`.
- Manually checked the filter dropdown from the title bar and Git panel.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
- Filters: All, Local, Remote
- "Cmd + Shift + I" to cycle over the filters
<details>
<summary>New Branch Picker Filter Dropdown</summary>
<img width="1624" height="1030" alt="Screenshot 2026-07-12 at 3 53
30 PM"
src="https://github.com/user-attachments/assets/1323d9c9-f4b9-41ee-ba93-841299872c02"
/>
<img width="1624" height="1030" alt="Screenshot 2026-07-12 at 3 54
35 PM"
src="https://github.com/user-attachments/assets/839345ff-de3b-48f0-b4e7-0f8d27e94204"
/>
</details>
Release Notes:
- Improved branch filtering with local, remote, and all-branch options
in the branch picker.
# Objective
`GitPanel::entry_label` builds file-name labels directly from `git
status` output without calling `.single_line()`. A raw newline in a file
name splits its row across multiple visual lines in the Changes panel.
## Solution
- Add the missing `.single_line()` call in `entry_label`, matching the
behavior in `project_panel.rs`.
## Testing
- Created a git repo with an untracked file whose name contains a
literal newline byte and confirmed the Changes panel now renders it on
one line, collapsing the newline to `⏎` like the project panel already
does.
## 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 adheres to Zed's UI standards
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
# Showcase
Before:
<img width="441" height="216" alt="image"
src="https://github.com/user-attachments/assets/921e5aad-01f9-49fd-89b1-f7270e2d203c"
/>
After:
<img width="447" height="206" alt="image"
src="https://github.com/user-attachments/assets/1c09af36-ccf1-434a-be20-0ea2c5d232d5"
/>
Release Notes:
- Fixed file names containing newlines rendering across multiple
lines in the Git Panel.
## Objective
Fix Git Graph showing `0 Changed Files` for commits that modify
submodules.
This happened because submodule entries are gitlinks rather than regular
blobs, so the existing commit diff loading path could not resolve them
correctly.
I ran into this issue previously, and it was confusing because the
commit clearly contained changes, but the UI did not reflect them. If a
commit included many file changes plus a submodule update, the submodule
change was effectively hidden and the UI could still show `0 Changed
Files` for that entry. Since submodules are not used in every
repository, the bug is easy to miss and may go unnoticed for a long
time.
## Solution
- Switched commit diff loading to use Git's raw diff output so submodule
entries are represented explicitly.
- Added parsing for gitlink entries alongside regular file changes.
- Render submodule changes as `Subproject commit <oid>` so they show up
in commit diffs instead of being dropped.
## Testing
- Added a repository test covering commit diffs that include submodule
changes.
- Ran the `git` crate test suite.
- Ran formatting and lint checks.
- Verified the Git UI crate still builds.
- Ran and tested it locally on MacOS.
Reviewer notes:
- The change is limited to commit diff loading and should not affect
normal blob diffs.
- Submodule changes now appear as explicit entries instead of being
counted as zero files.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and [icon](https://github.com/zed-
industries/zed/blob/main/crates/icons/README.md) guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
Before:
<img width="200" alt="Screenshot 2026-07-06 at 19 22 57"
src="https://github.com/user-attachments/assets/16efc348-5909-4cb0-8589-b0662923df56"
/>
After:
<img width="200" alt="Screenshot 2026-07-06 at 20 20 11"
src="https://github.com/user-attachments/assets/3201b264-6e61-45de-a9fc-c585f3b54e09"
/>
<img width="200" alt="Screenshot 2026-07-06 at 20 37 57"
src="https://github.com/user-attachments/assets/182ed4e1-9e90-4e33-9136-7626aba31153"
/>
---
Release Notes:
- Fixed Git Graph showing `0 Changed Files` for commits that update
submodules.
# Objective
Fix file header context menu actions in multi-file Git history diffs.
Previously, `Open File in Project` worked for the first file but did
nothing for subsequent files.
Fixes#60790
## Solution
Include the buffer ID in each file header context menu's GPUI element
ID. This prevents multiple file headers in split diff views from sharing
the same menu state.
## Testing
- Ran `cargo check -p editor --lib`.
- Ran `cargo fmt --package editor -- --check`.
- Reviewers can test by opening a multi-file commit from Git Panel →
History in split diff mode, then using `Open File in Project` on the
second and subsequent file headers.
https://github.com/user-attachments/assets/46fa4e15-60ac-4ae3-9a73-a89c7f107cb0
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed opening project files from context menus in multi-file Git
history diffs.
Co-authored-by: peakxy <2465549609@qq.com>
The unstaged diff view introduced in the partially staged changes commit
only had a Stage button but no Restore option. This adds:
- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action
Release Notes:
- Added restore buttons to the unstaged diff view for discarding
unstaged changes.
# Objective
New unstaged and staged diffs were added in #46541 . However for
unstaged changes, only option available is to stage a change. It would
also be a common use case to restore the changes. (Like how it is done
in uncommitted changes).
## Solution
- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action
## Testing
Tested in locally and ensured both features work
## Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
## Showcase
<img width="1141" height="635" alt="Screenshot 2026-07-09 at 9 00 47 AM"
src="https://github.com/user-attachments/assets/b1d3f091-9f1d-49c6-87e6-9efad25e62dd"
/>
## Note
I am still learning rust bit by bit. Please let me know if something is
massively wrong. This is assisted by AI but reviewed by me with best of
my knowledge.
---
Release Notes:
- Added restore buttons to the unstaged diff view for discarding
unstaged changes.
---------
Signed-off-by: Pranav <pranav10121@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Adds a `container_query` element to GPUI, in the spirit of CSS container
queries: the element's own size is determined solely by its style and
the space offered by its parent, and once that size is known the
provided closure is called with the measured size to build the contents.
```rust
container_query(|size, _window, _cx| {
if size.width < px(240.) {
div().child("Narrow layout")
} else {
div().child("Wide layout")
}
});
```
Implementation notes:
- Defaults to filling its parent (`size_full()` semantics), overridable
via `Styled` since contents can't influence the container's size (the
same constraint CSS container queries impose).
- Reworks the `grid_layout` example (the Holy Grail layout) to
demonstrate it: the three-column grid collapses to a stacked column when
the window is narrower than 400px, and the header shows the live
measured width.
Release Notes:
- N/A
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Window roots whose size is `auto` now stretch to fill the window, the
way the root element on the web fills the initial containing block.
Previously a window root with no explicit size shrink-wrapped its
content (flex/grid roots collapsed to content size in both axes), which
is why every root view needed `size_full()`.
Mechanically: `draw_roots` requests layout for the window root (and
prompt roots), then `TaffyLayoutEngine::stretch_auto_size_to_fill`
rewrites any `auto` dimension on the root node to the viewport size
before layout runs. Explicitly styled root dimensions are preserved, and
tooltips, drags, and anchored/deferred draws keep their shrink-wrap
semantics.
Includes regression tests covering both the auto-fill and explicit-size
cases (the auto case collapses to 0×0 without the fix).
Release Notes:
- N/A
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
TODO:
- [ ] Remove slop comments
- [ ] Review APIs in detail
# Objective
- This PR aims to add official mobile API surfaces to GPUI
## Solution
- This PR cross references several internal experiments to come up with
a general cross-platform abstraction for core input mechanisms, but
defers actual implementations to later. These are intended to be a
common base to build off of.
## Testing
- Yes, as mentioned above with external experiments
## Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [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
Closes#55934
Release Notes:
- Fixed terminal jitter when resizing vertically with content that
doesn't fill the available height.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
# Objective
- Add a view option for group by staging.
## Solution
- Add a new option for group_by under git_panel view options, with 2
sections "Staged" and "Unstaged", with buttons (+/-) to stage and
unstage
## Testing
- cargo check -p git_ui
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<img width="1679" height="1140" alt="Screenshot 2026-06-25 at 2 09
44 PM"
src="https://github.com/user-attachments/assets/1b605cad-7792-4823-983c-ada41be25504"
/>
---
Release Notes:
- Added group by staging view option
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Closes security loopholes and updates docs:
- installs seccomp filter for blocking naughty syscalls
- tightens macos seatbelt profile
- fetch tool responses that redirect are now constrained by allowed
domains list
Also adds a few "Learn More" buttons that link to the new docs.
Also fixes a bug where the agent would try to create a
`~/.config/zed/AGENTS.md` directory
Also adds unicode confusable detection to URL/path privilege escalation
prompts.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
The `edit_file` tool re-indents `new_text` by computing a single indent
delta from the first line of `old_text` versus the matched buffer line,
then applying that delta to every line of the replacement. When a model
omits the leading indentation on only the first line of
`old_text`/`new_text` (a common pattern when copying from mid-line
context), the delta computed from the first line was wrongly applied to
the remaining, already-correctly-indented lines, doubling their
indentation.
This PR:
- Tracks the `(query_row, buffer_row)` line pairs aligned by the
streaming fuzzy matcher so the indent of each `old_text` line can be
compared against the buffer line it actually matched.
- Computes a separate indent delta for the lines after the first: when
those lines agree on a consistent delta, it's used for the rest of the
replacement; otherwise the previous uniform behavior is preserved.
- Keeps `query_lines`/line pairs in sync when `finish()` extends a match
with a trailing incomplete line.
- Adds an end-to-end regression test reproducing the issue, plus unit
tests for the new re-indentation logic.
Closes https://github.com/zed-industries/zed/issues/60302
Release Notes:
- Fixed the agent's `edit_file` tool corrupting indentation when a
replacement omitted leading whitespace on only its first line.
On Linux and FreeBSD the native file watcher is non-recursive, so a
watch on the .git directory itself does not report changes to files
nested below it. Loose refs live in nested directories under refs, so
external git commit, fetch, branch, and update-ref operations that don't
also touch a direct child of .git (like the index) went entirely
unnoticed.
Watch every directory in the refs tree when a repository is inserted,
and watch directories subsequently created under refs (new remotes,
slash-named branches) as their creation events arrive. On platforms with
recursive watchers these registrations dedupe against the existing
recursive watch, making them free.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
# Objective
Fixes#59820.
## Solution
At a high level, I approached this by conditionally rendering a `Below`
preview layout only when the preview was at or below the min width of
the `Right` when the layout is `Right`. Since there's one breakpoint at
`SizeBounds::min_width()` and hitting that breakpoint only changes
rendering (and doesn't change the state), there's no need to persist to
storage or memory that the view is forced to be Below.
I toggled between the two rendering modes by defining
`Picker::preview_layout_rendered()` that would return `Below` if the
window was equal to or smaller than its min width. Then I replaced all
calls of `preview_layout()` that used the response purely for rendering
purposes with `preview_layout_rendered()`. I avoided replacing
`preview_layout()` calls that were responsible for persisting the
current layout and window dimensions to disk to ensure that changes to
the window dimensions were properly synced to the correct layout. This
way changes to the window while in the `BelowAuto` rendering mode edit
the `Right` window dimensions on disk.
## Testing
I tested these changes manually with the following actions on my local
machine (an Apple Silicon Macbook Pro):
- resizing the popover
- resizing the window
- adjusting the split
- making sure the popover size and split percent remains the same after:
- closing and re-opening the popover
- closing and re-opening the application and making sure the window size
and split percent remains the same
Reviewers can test my changes by performing the same manual actions.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
## Showcase
### Before
https://github.com/user-attachments/assets/a4524065-d1a3-4595-bc9e-50c9715b4e66
### After
https://github.com/user-attachments/assets/fede7eb0-5d73-423c-8df0-8192caee8d26
---
Release Notes:
- fix(picker): Automatically switch from Right split to Down split when
picker gets too narrow
LM Studio doesn't show the context token wheel (#53790) because token
usage is
never reported in streaming responses.
Causes:
1. `stream_options` was missing from the request. Without
`stream_options: { include_usage: true }`, the LM Studio API omits
`usage`
from every streaming chunk entirely.
2. The event mapper discarded usage data in the final chunk.
OpenAI-compatible
servers send the usage summary in a trailing chunk that has an empty
`choices`
array. The old guard treated that as an error, so even when usage was
present
it was thrown away before emitting a `UsageUpdate` event.
Fix:
- Add `StreamOptions { include_usage: bool }` and `stream_options` to
`ChatCompletionRequest`, and always set it to `true` for streaming
requests.
- Move usage handling in `LmStudioEventMapper::map_event` to run
*before* the
empty-choices guard, mirroring the OpenAI provider's approach.
- Add four unit tests for `map_event` covering the fixed behavior.
Release Notes:
- Fixed LM Studio not showing the context window usage wheel.
<img width="1184" height="1080" alt="Screenshot_20260527_130449"
src="https://github.com/user-attachments/assets/97eb8500-39dd-4824-aaf8-f0422b62119d"
/>
---------
Co-authored-by: Gabriele Ancillai <gabriele.ancillai@sofka.com.co>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Adds support for enabling Anthropic fast mode on configured models.
Previously, Anthropic models configured through
`language_models.anthropic.available_models` were always marked as not
supporting fast mode, so `speed: "fast"` would be stripped before
sending requests even when the configured model supported Anthropic fast
mode.
This adds an optional `supports_fast_mode` field to configured Anthropic
models. When enabled, the model is marked as supporting fast mode and
the required Anthropic beta header is added automatically. Built-in
fast-mode model detection remains the fallback when the setting is
omitted.
Testing:
- `cargo fmt --package anthropic --package language_models --package
settings_content`
- `cargo test -p language_models available_model --lib`
- `cargo test -p anthropic from_listed_enables_fast_mode --lib`
- `cargo check -p language_models`
- Manual: verified in a local build that a configured Anthropic model
can send fast mode requests correctly.
Release Notes:
- agent: Allow specifying if fast mode is supported for custom anthropic
models
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This passes the `include_remote_name` flag through the remote
`GetDefaultBranch` RPC instead of dropping it at the client/host
boundary. That lets remote repositories resolve default branches as
`origin/main` when needed, so worktree creation uses a valid remote
branch name instead of falling back to `main`.
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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#59121
Release Notes:
- Fixed remote worktree creation from the default branch when the
default branch requires its remote name.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes#21822
The issue is closed already, but it was requested to provide the
`hard_tabs` boolean param.
Follow-up to #52175
Reviewed by @maxdeviant (it already bumped the settings path to v0.8.0,
so this `hard_tabs` change only needs 2 files, 2-3 lines of code
additions).
## Context
Exposes `hard_tabs` from `AllLanguageSettings` to the Extension
API's `LanguageSettings` struct. Currently, only `tab_size` and
`preferred_line_length` are available to extensions, which prevents
language extensions (e.g., Go, C++) from reading the user's hard tabs
preference and forwarding it to their language server or formatter
(e.g., as rustfmt.hard_tabs or clang-format.UseTab).
Related:
https://github.com/zed-industries/zed/issues/21822#issuecomment-4139809956
## How to Review
Small change — follow how `tab_size` is plumbed through:
1. WIT definition (`language-settings` record)
2. `extension_api` Rust struct
3. Host-side bridge conversion
The new field follows the exact same pattern.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [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
- Compile-time verified via WIT bindings; no runtime behavior change
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Extends the existing ECMAScript comment-label injection system to
support GLSL and WGSL shader languages inside JS/TS strings and template
literals.
The pattern `/* language */` before a string is already used for `html`,
`sql`, `graphql`, and `css`. This adds the same support for two shader
languages commonly embedded as strings in WebGL/WebGPU code:
before:
<img width="460" height="300" alt="Screenshot 2026-04-30 at 23 07 05"
src="https://github.com/user-attachments/assets/8952eddc-2f53-42ea-b086-7a0b63dceb10"
/>
after:
<img width="460" height="300" alt="Screenshot 2026-04-30 at 23 07 39"
src="https://github.com/user-attachments/assets/93bf536a-9df4-438b-af7b-382efda196ca"
/>
Syntax highlighting activates when the corresponding extension is
installed:
- GLSL: the built-in `glsl` extension
- WGSL: the community extension
[`wgsl-wesl-zed`](https://github.com/lucascompython/wgsl-wesl-zed)
(language name `WGSL/WESL`)
Both `/*glsl*/` and `/* glsl */` forms are accepted (same behavior as
the existing patterns).
Release Notes:
- Added `/*glsl*/` and `/*wgsl*/` comment-label syntax injection for
JavaScript and TypeScript template literals
Turns out I only tested it with all tabs closed, the keybinding would
only work when all tabs were closed and you focused the agent panel. If
a file was opened in the center pane, cmd-f would open a search in that
file instead of searching in the agent panel, even if the thread view as
focused.
Closes#60686
Release Notes:
- agent: Fixed an issue where cmd-f would not work if file is open in
center pane
## Context
On Linux, `ctrl-q` is globally bound to `zed::Quit`. When a
`TerminalView` is focused, pressing `ctrl-q` quit the application
instead of forwarding the keycode to the shell, breaking programs like
`ftp`, `tig`, and any app that uses XON/XOFF flow control.
Windows already had the fix: its `Terminal` keymap context overrides
`ctrl-q` with `["terminal::SendKeystroke", "ctrl-q"]`. The Linux keymap
was simply missing that override.
Closes#58809
Manual test after fix below :
[Screencast from 2026-06-09
00-46-37.webm](https://github.com/user-attachments/assets/3d103b2a-bff1-4559-af1d-2a52d57a6b18)
## How to Review
- **`assets/keymaps/default-linux.json`** : One-line addition in the
`Terminal` context under the "Overrides for conflicting keybindings"
comment, mirroring the existing Windows entry.
- **`crates/terminal_view/src/terminal_view.rs`** : Regression test
`ctrl_q_is_forwarded_to_terminal_not_quit` (Linux-only, `#[cfg(target_os
= "linux")]`): loads the default keymap, focuses a display-only
terminal, simulates `ctrl-q`, and asserts the PTY receives byte `0x11`
instead of the quit action firing.
## 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
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed `ctrl-q` quitting Zed instead of being forwarded to the shell
when a terminal is focused on Linux
Removes the feature flag. The RFD is in Preview and I am confident it
will be stable without major changes by the time this hits Zed Stable.
Release Notes:
- acp: Allow ACP agents to use Elicitation capturing structure user
input.
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#57174
Release Notes:
- Open non-writeable files in Capability::Read mode
Co-authored-by: Lukas Wirth <lukas@zed.dev>
# Objective
- Fixes#58097.
- Opening a new project and clicking `+` in the agent panel to start a
terminal thread creates two terminals instead of one. I am able to
replicate the issue on version 1.8.0 on macOS 27
## Solution
The new-thread action creates the terminal and then focuses the agent
panel. Focusing re-activates the panel (`Panel::set_active` then
`ensure_thread_initialized`) before the terminal, which is spawned
asynchronously, has registered. The panel still looks uninitialized at
that moment, so it spawns its own "initial" terminal too, and that is
the duplicate.
`spawn_terminal` now marks the spawn as in-flight
(`pending_terminal_spawn`) the moment it starts, the same way the
restore and initial-terminal paths already do, so the existing guard in
`ensure_thread_initialized` skips the redundant terminal.
This only affected new (unrestored) projects, since existing ones
restore their previous entry instead of auto-creating one. The auto-init
behavior was introduced in #57150.
## Testing
- Verified in a local dev build on macOS: opening a fresh project and
clicking `+` now creates one terminal, and clicking `+` again creates a
second, as expected. Reopening an existing project still restores a
single terminal.
- Added `test_explicit_terminal_blocks_redundant_auto_init`, which fails
without the fix.
- The change is platform-agnostic (no platform-specific code); I wasn't
able to test on Linux/Windows.
## 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 adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed a duplicate terminal being created when starting an agent
terminal thread in a new project