Skip to content

fuzzy_nucleo: Add strings module and route several pickers through it - #1

Closed
feitreim wants to merge 250 commits into
feat-fuzzy-paths-optimizationfrom
feat-fuzzy-strings-module
Closed

fuzzy_nucleo: Add strings module and route several pickers through it#1
feitreim wants to merge 250 commits into
feat-fuzzy-paths-optimizationfrom
feat-fuzzy-strings-module

Conversation

@feitreim

Copy link
Copy Markdown
Owner

Stacked on top of zed-industries#54112
This is part 2 of 3 towards zed-industries#51197
More details from the original PR zed-industries#53551

Changes

In this PR I added a more general string matching functionality to fuzzy_nucleo, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up.

The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old fuzzy crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass CaseMatching::Ignore to nucleo and implement the same score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs.

Benchmark:

Benchmark Size Nucleo Fuzzy Nucleo/Fuzzy
1-word 100 10.18 µs 11.54 µs 0.88x
1-word 1,000 94.26 µs 97.54 µs 0.97x
1-word 10,000 822.99 µs 857.25 µs 0.96x
2-word 100 5.23 µs 2.99 µs 1.75x
2-word 1,000 34.69 µs 11.31 µs 3.07x
2-word 10,000 265.73 µs 56.02 µs 4.74x
4-word 100 2.39 µs 2.35 µs 1.02x
4-word 1,000 8.46 µs 5.89 µs 1.44x
4-word 10,000 36.75 µs 12.08 µs 3.04x

When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case.

Video:

picker_demo_down.mov

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
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries.

eholk and others added 30 commits April 9, 2026 14:20
…ries#53556)

Also indicates if the multiworkspace and the worspace disagree on the
right key.

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:

- [ ] 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
…stries#53566)

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: Eric Holk <eric@zed.dev>
…rkspace (zed-industries#53575)

When the sidebar opens a remote SSH project, it shows a
`RemoteConnectionModal` on the currently active (local) workspace. After
the connection succeeds and a new remote workspace is created and
activated, the modal on the local workspace was never dismissed.
Switching back to the local workspace (e.g. by activating a thread)
would re-render the local workspace's modal layer, revealing the stale
"Starting proxy..." modal.

Other code paths that show this modal (`recent_projects`, `git_ui`)
already call `modal.finished(cx)` after the connection completes. The
sidebar and agent panel paths were missing this cleanup.

## Changes

- **`remote_connection`**: Added `dismiss_connection_modal()`, a public
utility that finds and dismisses any active `RemoteConnectionModal` on a
given workspace.
- **`sidebar`**: Fixed two call sites (`open_workspace_for_group` and
`open_workspace_and_activate_thread`) to dismiss the modal after the
connection task completes, regardless of success or failure.
- **`agent_ui`**: Fixed `open_worktree_workspace_and_start_thread` to
dismiss the modal after workspace creation completes.

Release Notes:

- (Preview only) Fixed a spurious "Starting proxy..." modal appearing
and hanging when switching back to a local project after opening a
remote SSH project in a multi-project workspace.
…s#53484)

Thanks to Dario Weißer for the suggestion

Release Notes:

- Fixed some potential edge cases when paths in a project started
  with `-`.
…d-industries#53550)

This PR adds remote connection data to the threads metadata database.
This fixes an issue where threads ran on separate projects with the same
remote/local path list would show up in the sidebar in both workspaces,
instead of only the workspace they were originally created in.

I added a migrator that uses the workspace persistence database to add
remote connection argument to threads that only have path list matches
with a remote project. If a path list matches with both local/remote
workspaces, we default to setting it as local.

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 or Added/Fixed/Improved ...

---------

Co-authored-by: Eric Holk <eric@zed.dev>
Removed 'Text Threads' option from the mode dropdown for AI issues,
since zed-industries#52757 removed the feature

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
…es#53552)

Fixes a UI regression introduced in
zed-industries#48467, which prevented
automatic update statuses from being shown in the title bar unless the
update was checked for manually by the user, causing some users to
unknowingly cancel updates in progress by closing the application, since
there was no indication.


https://github.com/user-attachments/assets/ea16a600-3db4-49dc-bca5-11c8fcfff619

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 zed-industries#50162

Release Notes:

- Fixed missing indication that an update was currently being downloaded
or installed in the title bar
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [wasmtime](https://github.com/bytecodealliance/wasmtime) |
workspace.dependencies | patch | `36.0.6` → `36.0.7` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](..zed-industries/issues/15138) for more information.

### GitHub Vulnerability Alerts

####
[CVE-2026-34941](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-hx6p-xpx3-jvvv)

### Summary

Wasmtime contains a vulnerability where when transcoding a UTF-16 string
to the latin1+utf16 component-model encoding it would incorrectly
validate the byte length of the input string when performing a bounds
check. Specifically the number of code units were checked instead of the
byte length, which is twice the size of the code units.

This vulnerability can cause the host to read beyond the end of a
WebAssembly's linear memory in an attempt to transcode nonexistent
bytes. In Wasmtime's default configuration this will read unmapped
memory on a guard page, terminating the process with a segfault.
Wasmtime can be configured, however, without guard pages which would
mean that host memory beyond the end of linear memory may be read and
interpreted as UTF-16.

A host segfault is a denial-of-service vulnerability in Wasmtime, and
possibly being able to read beyond the end of linear memory is
additionally a vulnerability. Note that reading beyond the end of linear
memory requires nonstandard configuration of Wasmtime, specifically with
guard pages disabled.

### Impact

This is an out-of-bounds memory access. Any user running untrusted wasm
components that use cross-component string passing (with UTF-16 source
and latin1+utf16 destination encodings) is affected.

- With guard pages: Denial of service. The host process crashes with
SIGBUS/SIGSEGV.
- Without guard pages: Potential information disclosure. The guest can
read host memory beyond its linear memory allocation.

Patches

Wasmtime 24.0.7, 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this
bug. Users are recommended to update to these patched versions of
Wasmtime.
Workarounds

There is no workaround for this bug. Hosts are recommended to updated to
a patched version of Wasmtime.

####
[CVE-2026-34942](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-jxhv-7h78-9775)

### Impact

Wasmtime's implementation of transcoding strings into the Component
Model's `utf16` or `latin1+utf16` encodings improperly verified the
alignment of reallocated strings. This meant that unaligned pointers
could be passed to the host for transcoding which would trigger a host
panic. This panic is possible to trigger from malicious guests which
transfer very specific strings across components with specific
addresses.

Host panics are considered a DoS vector in Wasmtime as the panic
conditions are controlled by the guest in this situation.

### Patches

Wasmtime 24.0.7, 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this
bug. Users are recommended to update to these patched versions of
Wasmtime.

### Workarounds

There is no workaround for this bug. Hosts are recommended to updated to
a patched version of Wasmtime.

####
[CVE-2026-34943](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-m758-wjhj-p3jq)

### Impact

Wasmtime contains a possible panic which can happen when a `flags`-typed
component model value is lifted with the `Val` type. If bits are set
outside of the set of flags the component model specifies that these
bits should be ignored but Wasmtime will panic when this value is
lifted. This panic only affects wasmtime's implementation of lifting
into `Val`, not when using the `flags!` macro. This additionally only
affects `flags`-typed values which are part of a WIT interface.

This has the risk of being a guest-controlled panic within the host
which Wasmtime considers a DoS vector.

### Patches

Wasmtime 24.0.7, 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this
bug. Users are recommended to update to these patched versions of
Wasmtime.

### Workarounds

There is no workaround for this bug if a host meets the criteria to be
affected. To be affected a host must be using `wasmtime::component::Val`
and possibly work with a `flags` type in the component model.

####
[CVE-2026-34944](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-qqfj-4vcm-26hv)

On x86-64 platforms with SSE3 disabled Wasmtime's compilation of the
`f64x2.splat` WebAssembly instruction with Cranelift may load 8 more
bytes than is necessary. When
[signals-based-traps](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.signals_based_traps)
are disabled this can result in a uncaught segfault due to loading from
unmapped guard pages. With guard pages disabled it's possible for
out-of-sandbox data to be loaded, but this data is not visible to
WebAssembly guests.

### Details

The `f64x2.splat` operator, when operating on a value loaded from a
memory (for example with f64.load), compiles with Cranelift to code on
x86-64 without SSE3 that loads 128 bits (16 bytes) rather than the
expected 64 bits (8 bytes) from memory. When the address is in-bounds
for a (correct) 8-byte load but not an (incorrect) 16-byte load, this
can load beyond memory by up to 8 bytes. This can result in three
different behaviors depending on Wasmtime's configuration:

1. If guard pages are disabled then this extra data will be loaded. The
extra data is present in the upper bits of a register, but the upper
bits are not visible to WebAssembly guests. Actually witnessing this
data would require a different bug in Cranelift, of which none are
known. Thus in this situation while it's something we're patching in
Cranelift it's not a security issue.
2. If guard pages are enabled, and
[signals-based-traps](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.signals_based_traps)
are enabled, then this operation will result in a safe WebAssembly trap.
The trap is incorrect because the load is not out-of-bounds as defined
by WebAssembly, but this mistakenly widened load will load bytes from an
unmapped guard page, causing a segfault which is caught and handled as a
Wasm trap. In this situation this is not a security issue, but we're
patching Cranelift to fix the WebAssembly behavior.
3. If guard pages are enabled, and
[signals-based-traps](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.signals_based_traps)
are disabled, then this operation results in an uncaught segfault. Like
the previous case with guard pages enabled this will load from an
unmapped guard page. Unlike before, however, signals-based-traps are
disabled meaning that signal handlers aren't configured. The resulting
segfault will, by default, terminate the process. This is a security
issue from a DoS perspective, but does not represent an arbitrary read
or write from WebAssembly, for example.

Wasmtime's default configuration is case (2) in this case. That means
that Wasmtime, by default, incorrectly executes this
WebAssembly instruction but does not have insecure behavior.

### Impact

If
[signals-based-traps](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.signals_based_traps)
are disabled and guard pages are enabled then guests can trigger an
uncaught segfault in the host, likely aborting the host process. This
represents, for example, a DoS vector for WebAssembly guests.

This bug does not affect Wasmtime's default configuration and requires
[signals-based-traps](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.signals_based_traps)
to be disabled. This bug only affects the x86-64 target with the SSE3
feature disabled and the Cranelift backend (Wasmtime's default backend).

### Patches

Wasmtime 24.0.7, 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this
bug. Users are recommended to update to these patched versions of
Wasmtime.

### Workarounds

This bug only affects x86-64 hosts where SSE3 is disabled. If SSE3 is
enabled or if a non-x86-64 host is used then hosts are not affect.
Otherwise there are no known workarounds to this issue.

####
[CVE-2026-34945](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-m9w2-8782-2946)

### Impact

Wasmtime's Winch compiler contains a bug where a 64-bit table, part of
the memory64 proposal of WebAssembly, incorrectly translated the
`table.size` instruction. This bug could lead to disclosing data on the
host's stack to WebAssembly guests. The host's stack can possibly
contain sensitive data related to other host-originating operations
which is not intended to be disclosed to guests.

This bug specifically arose from a mistake where the return value of
`table.size` was statically typed as a 32-bit integer, as opposed to
consulting the table's index type to see how large the returned register
could be. When combined with details about Wnich's ABI, such as
multi-value returns, this can be combined to read stack data from the
host, within a guest. This information disclosure should not be possible
in WebAssembly, violates spec semantics, and is a vulnerability in
Wasmtime.

### Patches

Wasmtime 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this bug.
Users are recommended to update to these patched versions of Wasmtime.

### Workarounds

Users of Cranelift are not affected by this issue, but users of Winch
have no workarounds other than disabling the `Config::wasm_memory64`
proposal.

####
[CVE-2026-34946](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-q49f-xg75-m9xw)

### Impact

Wasmtime's Winch compiler contains a vulnerability where the compilation
of the `table.fill` instruction can result in a host panic. This means
that a valid guest can be compiled with Winch, on any architecture, and
cause the host to panic. This represents a denial-of-service
vulnerability in Wasmtime due to guests being able to trigger a panic.

The specific issue is that a historical refactoring, #&zed-industries#8203;11254,
changed how compiled code referenced tables within the `table.*`
instructions. This refactoring forgot to update the Winch code paths
associated as well, meaning that Winch was using the wrong indexing
scheme. Due to the feature support of Winch the only problem that can
result is tables being mixed up or nonexistent tables being used,
meaning that the guest is limited to panicking the host (using a
nonexistent table), or executing spec-incorrect behavior and modifying
the wrong table.

### Patches

Wasmtime 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this bug.
Users are recommended to update to these patched versions of Wasmtime.

### Workarounds

Users of Cranelift are not affected by this issue, but for users of
Winch there is no workaround for this bug. Hosts are recommended to
updated to a patched version of Wasmtime.

####
[CVE-2026-34971](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-jhxm-h53p-jm7w)

### Impact

Wasmtime's Cranelift compilation backend contains a bug on aarch64 when
performing a certain shape of heap accesses which means that the wrong
address is accessed. When combined with explicit bounds checks a guest
WebAssembly module this can create a situation where there are two
diverging computations for the same address: one for the address to
bounds-check and one for the address to load. This difference in address
being operated on means that a guest module can pass a bounds check but
then load a different address. Combined together this enables an
arbitrary read/write primitive for guest WebAssembly when accesssing
host memory. This is a sandbox escape as guests are able to read/write
arbitrary host memory.

This vulnerability has a few ingredients, all of which must be met, for
this situation to occur and bypass the sandbox restrictions:

* This miscompiled shape of load only occurs on 64-bit WebAssembly
linear memories, or when `Config::wasm_memory64` is enabled. 32-bit
WebAssembly is not affected.
* Spectre mitigations or signals-based-traps must be disabled. When
spectre mitigations are enabled then the offending shape of load is not
generated. When signals-based-traps are disabled then spectre
mitigations are also automatically disabled.

The specific bug in Cranelift is a miscompile of a load of the shape
`load(iadd(base, ishl(index, amt)))` where `amt` is a constant. The
`amt` value is masked incorrectly to test if it's a certain value, and
this incorrect mask means that Cranelift can pattern-match this lowering
rule during instruction selection erroneously, diverging from
WebAssembly's and Cranelift's semantics. This incorrect lowering would,
for example, load an address much further away than intended as the
correct address's computation would have wrapped around to a smaller
value insetad.

### Patches

Wasmtime 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this bug.
Users are recommended to update to these patched versions of Wasmtime.

### Workarounds

This bug only affects users of Cranelift on aarch64. Cranelift on other
platforms is not affected. Additionally this only affects 64-bit
WebAssembly linear memories, so if `Config::wasm_memory64` is disabled
then hosts are not affected. Note that `Config::wasm_memory64` is
enabled by default. If spectre mitigations are enabled, which are
enabled by default, then hosts are not affected by this issue.

####
[CVE-2026-34988](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-6wgr-89rj-399p)

### Impact

Wasmtime's implementation of its pooling allocator contains a bug where
in certain configurations the contents of linear memory can be leaked
from one instance to the next. The implementation of resetting the
virtual memory permissions for linear memory used the wrong predicate to
determine if resetting was necessary, where the compilation process used
a different predicate. This divergence meant that the pooling allocator
incorrectly deduced at runtime that resetting virtual memory permissions
was not necessary while compile-time determine that virtual memory could
be relied upon.

Exposing this bug requires specific configuration values to be used. If
any of these configurations are not applicable then this bug does not
happen:

* The pooling allocator must be in use.
* The `Config::memory_guard_size` configuration option must be 0.
* The `Config::memory_reservation` configuration must be less than 4GiB.
* The pooling allocator must be configured with `max_memory_size` the
same as the `memory_reservation` value.

If all of these conditions are applicable then when a linear memory is
reused the VM permissions of the previous iteration are not reset. This
means that the compiled code, which is assuming out-of-bounds loads will
segfault, will not actually segfault and can read the previous contents
of linear memory if it was previously mapped.

This represents a data leakage vulnerability between guest WebAssembly
instances which breaks WebAssembly's semantics and additionally breaks
the sandbox that Wasmtime provides. Wasmtime is not vulnerable to this
issue with its default settings, nor with the default settings of the
pooling allocator, but embeddings are still allowed to configure these
values to cause this vulnerability.

### Patches

Wasmtime 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this bug.
Users are recommended to update to these patched versions of Wasmtime.

### Workarounds

All four conditions above must be met to be vulnerable to this bug, and
users can work around this bug by adjusting any of the above conditions.
For example it is strongly recommended that guard pages are configured
for linear memories which would make this bug not applicable.

####
[CVE-2026-35195](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-394w-hwhg-8vgm)

### Impact

Wasmtime's implementation of transcoding strings between components
contains a bug where the return value of a guest component's `realloc`
is not validated before the host attempts to write through the pointer.
This enables a guest to cause the host to write arbitrary transcoded
string bytes to an arbitrary location up to 4GiB away from the base of
linear memory. These writes on the host could hit unmapped memory or
could corrupt host data structures depending on Wasmtime's
configuration.

Wasmtime by default reserves 4GiB of virtual memory for a guest's linear
memory meaning that this bug will by default on hosts cause the host to
hit unmapped memory and abort the process due to an unhandled fault.
Wasmtime can be configured, however, to reserve less memory for a guest
and to remove all guard pages, so some configurations of Wasmtime may
lead to corruption of data outside of a guest's linear memory, such as
host data structures or other guests's linear memories.

### Patches

Wasmtime 24.0.7, 36.0.7, 42.0.2, and 43.0.1 have been issued to fix this
bug. Users are recommended to update to these patched versions of
Wasmtime.

### Workarounds

There is no known workaround for this issue and affected
hosts/embeddings are recommended to upgrade.

---

### Release Notes

<details>
<summary>bytecodealliance/wasmtime (wasmtime)</summary>

###
[`v36.0.7`](https://github.com/bytecodealliance/wasmtime/releases/tag/v36.0.7)

[Compare
Source](https://github.com/bytecodealliance/wasmtime/compare/v36.0.6...v36.0.7)

#### 36.0.7

Released 2026-04-09.

##### Fixed

- Miscompiled guest heap access enables sandbox escape on aarch64
Cranelift.

[GHSA-jhxm-h53p-jm7w](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-jhxm-h53p-jm7w)

- Wasmtime with Winch compiler backend may allow a sandbox-escaping
memory
  access.

[GHSA-xx5w-cvp6-jv83](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-xx5w-cvp6-jv83)

- Out-of-bounds write or crash when transcoding component model strings.

[GHSA-394w-hwhg-8vgm](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-394w-hwhg-8vgm)

- Host panic when Winch compiler executes `table.fill`.

[GHSA-q49f-xg75-m9xw](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-q49f-xg75-m9xw)

- Wasmtime segfault or unused out-of-sandbox load with `f64x2.splat`
operator
  on x86-64.

[GHSA-qqfj-4vcm-26hv](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-qqfj-4vcm-26hv)

- Improperly masked return value from `table.grow` with Winch compiler
backend.

[GHSA-f984-pcp8-v2p7](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-f984-pcp8-v2p7)

- Panic when transcoding misaligned utf-16 strings.

[GHSA-jxhv-7h78-9775](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-jxhv-7h78-9775)

- Panic when lifting `flags` component value.

[GHSA-m758-wjhj-p3jq](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-m758-wjhj-p3jq)

- Heap OOB read in component model UTF-16 to latin1+utf16 string
transcoding.

[GHSA-hx6p-xpx3-jvvv](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-hx6p-xpx3-jvvv)

- Data leakage between pooling allocator instances.

[GHSA-6wgr-89rj-399p](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-6wgr-89rj-399p)

- Host data leakage with 64-bit tables and Winch.

[GHSA-m9w2-8782-2946](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-m9w2-8782-2946)

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/New_York)

- Branch creation
  - ""
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjExMC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Continuation of zed-industries#53566, now
with proper thread root mutation.

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
…-industries#53510)

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 or Added/Fixed/Improved ...
…ndustries#53582)

## Summary

- Fix crash on startup when the X11 server supports XInput < 2.4 (e.g.
XInput 2.3)
- Gesture event mask bits (pinch begin/update/end) are now only
requested when the server advertises XInput >= 2.4
- Zed previously failed to open any window on affected systems, printing
`Zed failed to open a window: X11 XiSelectEvents failed`

## 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









## Problem

On X11 systems where the XInput extension version is older than 2.4, Zed
crashes immediately on startup with:

```
Zed failed to open a window: X11 XiSelectEvents failed.

Caused by:
    X11 error X11Error { error_kind: Value, error_code: 2, sequence: 277,
    bad_value: 27, minor_opcode: 46, major_opcode: 131,
    extension_name: Some("XInputExtension"),
    request_name: Some("XISelectEvents") }
```

This makes Zed completely unusable on any X11 display server that only
supports XInput 2.3 or earlier, which includes many current Ubuntu
20.04/22.04 systems, remote X11 sessions, and VNC/Xvfb setups.

### Root cause

During window creation, `X11WindowState::new` calls `XISelectEvents`
with an event mask that unconditionally includes gesture event bits
(`GESTURE_PINCH_BEGIN`, `GESTURE_PINCH_UPDATE`, `GESTURE_PINCH_END`).
These gesture events were introduced in **XInput 2.4**.

When the X server only supports XInput 2.3 (or older), it does not
recognize these mask bits and rejects the entire `XISelectEvents`
request with a `BadValue` error. This is fatal because the error is
propagated up and prevents the window from being created.

A comment in the original code stated:

> If the server only supports an older version, gesture events simply
won't be delivered.

This is incorrect. The X11 protocol does **not** silently ignore unknown
mask bits in `XISelectEvents` — it rejects the whole request.

### How XInput version negotiation works

The client calls `XIQueryVersion(2, 4)` to announce the highest version
it supports. The server responds with the highest version **it**
supports (e.g. `2.3`). The client is then responsible for not using
features beyond the negotiated version. The existing code ignored the
server's response and used 2.4 features unconditionally.

## Fix

### Approach

Check the XInput version returned by the server. Only include gesture
event mask bits in `XISelectEvents` when the negotiated version is >=
2.4. On older servers, basic input events (motion, button press/release,
enter, leave) still work normally — only touchpad pinch gestures are
unavailable.

### Changed files

**`crates/gpui_linux/src/linux/x11/client.rs`**

1. Added `supports_xinput_gestures: bool` field to `X11ClientState`.
2. After the existing `xinput_xi_query_version(2, 4)` call, compute
whether the server version is >= 2.4:
   ```rust
   let supports_xinput_gestures = xinput_version.major_version > 2
|| (xinput_version.major_version == 2 && xinput_version.minor_version >=
4);
   ```
3. Added an `info!` log line reporting the detected XInput version and
gesture support status.
4. Pass `supports_xinput_gestures` through `open_window` into
`X11Window::new`.

**`crates/gpui_linux/src/linux/x11/window.rs`**

1. Added `supports_xinput_gestures: bool` parameter to both
`X11Window::new` and `X11WindowState::new`.
2. The `XISelectEvents` call now builds the event mask conditionally:
- Always includes: `MOTION`, `BUTTON_PRESS`, `BUTTON_RELEASE`, `ENTER`,
`LEAVE`
- Only when `supports_xinput_gestures` is true: `GESTURE_PINCH_BEGIN`,
`GESTURE_PINCH_UPDATE`, `GESTURE_PINCH_END`

### What is NOT changed

- The gesture event **handlers** in `client.rs`
(`XinputGesturePinchBegin`, `XinputGesturePinchUpdate`,
`XinputGesturePinchEnd`) are left as-is. They simply won't be triggered
on servers without gesture support, since the events are never
registered.
- No behavioral change on systems with XInput >= 2.4 — gesture events
continue to work exactly as before.

## Testing

| Test | Before fix | After fix |
|------|-----------|-----------|
| `./target/release/zed .` on XInput 2.3 | Immediate crash (exit code 1)
| Window opens successfully (runs until killed) |
| XInput version detection | Version queried but response ignored |
Version checked and logged |

Verified on an X11 system with XInput 2.3 (X.Org 1.20.13, Ubuntu 20.04).

## Test plan

- [x] Build succeeds (`cargo build --release`)
- [x] Zed launches and opens a window on XInput 2.3 system
- [x] No regression on the basic input event path (motion, clicks,
enter/leave still registered)
- [ ] Verify gesture pinch events still work on a system with XInput >=
2.4

Release Notes:

- Fixed Zed failing to start on X11 systems with XInput version older
than 2.4, which includes many Linux distributions and remote desktop
setups.
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
Follow-up of zed-industries#53452

* disables mouse wheel zooming in agent, debugger, keymap editor, dev
inspector and repl-related editors
* adjusts the code to call for theme changes directly instead of sending
the events, so that agent following does not capture the events and
changes its font size

Release Notes:

- N/A
Re-building the tool on CI every time is pointless when can just install
the binary itself

Release Notes:

- N/A or Added/Fixed/Improved ...
…tkey (zed-industries#53127)

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 zed-industries#53056.

Release Notes:

- Fixed terminal tabs losing keyboard focus after switching tabs on Linux X11
Release Notes:

- N/A or Added/Fixed/Improved ...
Related to zed-industries#53484. 

This PR fixes a `--` file being created when staging a hunk.

Release Notes:

- N/A
## What does this PR changed

Adds footnote rendering and navigation to Zed's markdown preview.

- **Footnote references**: (`[^1]`) render inline as `[1]` with link
styling (color + underline)
- **Footnote definitions**: (`[^1]: ...`) render at the bottom with a
horizontal separator, smaller text (85% size), and a label prefix
- **Click-to-navigate**: clicking a footnote reference scrolls to its
definition


https://github.com/user-attachments/assets/a79a0136-f22d-40ac-8b53-cfefa8573d21

## OOS/ Need discussion

- **Display style**: Since currently the gpui crate does not provide a
superscript style, in this PR we publish the feature with using
[`[1]`]() instead of aligning to the GFM styled[^1]
- **Footnote definition placement**: GFM renders the footnote at the
bottom of the content no matter where the user place the footnote
definition, but the `pulldown_cmark` renders the footnote just at where
user place it, for this PR I'll keep the footnote where `pulldown_cmark`
renders it, and we may have some more discuss on if we need to move them
to the bottom of the markdown preview

[^1]: GitHub-flavoured markdown

## What to test

- [ ] Open a markdown file with footnotes (e.g. `Text[^1]\n\n[^1]:
Definition`)
- [ ] Verify reference renders as `[1]` with link color
- [ ] Verify definition renders below a separator with smaller text
- [ ] Verify pointer cursor appears on hover over `[1]`
- [ ] Verify clicking `[1]` scrolls to the definition
- [ ] Verify normal links still work as before
- [ ] `cargo test -p markdown` passes (46 tests)

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

Closes zed-industries#13603

Release Notes:

- Added support for footnotes in Markdown Preview.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
…ed-industries#53567)

This PR makes it so the Collab panel can be disabled by the
organization's configuration:

<img width="239" height="191" alt="Screenshot 2026-04-09 at 2 38 35 PM"
src="https://github.com/user-attachments/assets/48216c00-85cd-441a-b613-7468db2b25bd"
/>

Depends on zed-industries/cloud#2247.

Closes CLO-638.

Release Notes:

- N/A
…rray (zed-industries#53557)

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

## Details

- The [devcontainer CLI writes the `devcontainer.metadata` label as a
bare JSON object](devcontainers/cli#1054) when
there is only one metadata entry (e.g. docker-compose devcontainer with
a Dockerfile and no features)
- Zed's `deserialize_metadata` only accepted a JSON array, causing
deserialization to fail with `invalid type: map, expected a sequence`
- This made it impossible to attach to existing docker-compose
devcontainers created by the devcontainer CLI or VS Code

The fix tries parsing as an array first, then falls back to parsing as a
single object wrapped in a vec. This mirrors how the [devcontainer CLI
itself reads the
label](https://github.com/devcontainers/cli/blob/main/src/spec-node/imageMetadata.ts#L476-L493).

An upstream fix has also been submitted:
devcontainers/cli#1199

## Reproduction

1. Create a docker-compose devcontainer with a Dockerfile and no
features:

`.devcontainer/devcontainer.json`:
```json
{
  "name": "repro",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "remoteUser": "root"
}
```

`.devcontainer/docker-compose.yml`:
```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    command: sleep infinity
    volumes:
      - ..:/workspace
```

`.devcontainer/Dockerfile`:
```dockerfile
FROM ubuntu:24.04
```

2. `devcontainer up --workspace-folder .`
3. Open the folder in Zed, fails with metadata deserialization error

Release Notes:

- Fixed attaching to a devcontainer that has a single metadata element
which was started with `devcontainer-cli`
This PR adds the `correctly_deleted_chars` field and updates `kept_rate`
to account for it, not just inserted chars.

It also adds `recall_rate` to measure coverage of reference
insertions/deletions.

Finally, it renames "final" to "reference" and "prediction" to
"candidate".

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
…ies#53515)

This will ensure we do not post a second Slack message in case the first
check was successful. We still _run_ the second check, but do not notify

Release Notes:

- N/A
…industries#53640)

We hope this fixes an issue with permissions

Release Notes:

- N/A
…on configuration (zed-industries#53639)

This PR makes it so we disable training data collection for Edit
Prediction based on the organization's configuration.

Closes CLO-641.

Release Notes:

- N/A
…es#53642)

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 #ISSUE

Release Notes:

- N/A
…nu (zed-industries#53645)

This changes the behavior of the recent project picker in multi-folder
projects, so that when you select a folder that is a repository, it sets
the active repository in the Git panel as well.

Release Notes:

- N/A
…gent panel (zed-industries#53099)

Replaces raw provider error strings in the agent panel with specific,
user-friendly error callouts. Each error now has a clear title,
actionable copy, and appropriate buttons instead of the generic "An
Error Happened" fallback.

Error variants added:

Variant | Title | Body | Trigger |
|---|---|---|---|
| `RateLimitExceeded` | Rate Limit Reached | {Provider}'s rate limit was
reached. Zed will retry automatically. You can also wait a moment and
try again. | Provider rate limit exhausted after retries |
| `ServerOverloaded` | Provider Unavailable | {Provider}'s servers are
temporarily unavailable. Zed will retry automatically. If the problem
persists, check the provider's status page. | Provider server overloaded
or internal server error |
| `PromptTooLarge` | Context Too Large | This conversation is too long
for the model's context window. Start a new thread or remove some
attached files to continue. | Conversation exceeds model's context
window |
| `NoApiKey` | API Key Missing | No API key is configured for
{Provider}. Add your key via the Agent Panel settings to continue. | No
API key configured for a direct provider |
| `StreamError` | Connection Interrupted | The connection to
{Provider}'s API was interrupted. Zed will retry automatically. If the
problem persists, check your network connection. | Stream dropped or I/O
error during generation |
| `InvalidApiKey` | Invalid API Key | The API key for {Provider} is
invalid or has expired. Update your key via the Agent Panel settings to
continue. | API key present but invalid or expired |
| `PermissionDenied` | Permission Denied | {Provider}'s API rejected the
request due to insufficient permissions. Check that your API key has
access to this model. | API key lacks access to the requested model |
| `RequestFailed` | Request Failed | The request could not be completed
after multiple attempts. Try again in a moment. | Upstream provider
unreachable after retries |
| `MaxOutputTokens` | Output Limit Reached | The model stopped because
it reached its maximum output length. You can ask it to continue where
it left off. | Model hit its maximum output token budget |
| `NoModelSelected` | No Model Selected | Select a model from the model
picker below to get started. | No model configured when a message is
sent |
| `ApiError` | API Error | {Provider}'s API returned an unexpected
error. If the problem persists, try switching models or restarting Zed.
## Approach

- Added typed errors (`NoModelConfiguredError`, `MaxOutputTokensError`)
where previously raw strings were used, so they can be reliably downcast
- Extended `From<anyhow::Error> for ThreadError` to downcast
`LanguageModelCompletionError` variants before falling through to the
generic `Other` case
- Each variant has a dedicated `render_*` function with appropriate
buttons (retry icon, New Thread, or none)
- Telemetry events updated with specific `kind` labels for each new
variant

Release Notes:

- Improved error messages in the agent panel to show specific,
actionable copy instead of raw provider error strings

Self-Review Checklist:

- [ x] I've reviewed my own diff for quality, security, and reliability
- [n/a] 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)
- [n/a ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable


Release Notes:

Improved error messages in the agent panel to show specific, actionable
copy instead of raw provider error strings
probably-neb and others added 2 commits April 17, 2026 10:43
Hit a flake in this test in
https://github.com/zed-industries/zed/actions/runs/24555985980/job/71792549618.
Ran for 1000 iterations and hit a second race, now also hopefully fixed.

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 or Added/Fixed/Improved ...
The inlines are within the noise floor for the benches but they make
sense to me to have.
@yara-blue
yara-blue force-pushed the feat-fuzzy-strings-module branch from c084aae to e5c2d72 Compare April 17, 2026 15:53
smitbarmase and others added 19 commits April 17, 2026 22:52
)

Closes zed-industries#49568

Read more: zed-industries/lsp-types#14

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 YAML language server settings (like `customTags`) being ignored,
causing valid tags to show as errors.
…s#54205)

This is a follow up to: zed-industries#54202 

`thread_worktree_archive.rs` had its own
walk-up-and-remove-empty-parents pass that ran after archiving a Zed
managed git worktree. It duplicated logic that zed-industries#54202 moved into
`Repository::remove_worktree` (which also adds remote support for this)

This PR deletes the dead code path and its associated tests.

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
We had an internal report of soft wrap not working in git panel's commit
editor. Given the following settings:
```json
{
  "languages": {
    "Git Commit": {
      "preferred_line_length": 80,
      "soft_wrap": "preferred_line_length",
    },
  },
}
```
We would not soft-wrap in narrow viewports. As it turned out, the
problem was that we were always prefering a `preferred_line_length` as
our soft wrap boundary over the actual width of the editor.

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 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 #ISSUE

Release Notes:

- Fixed git commits editor not respecting soft wrap boundaries.
- settings: Removed `"soft_wrap": "preferred_line_length"` in favour of
`"soft_wrap": "bounded"`. Soft wrap now always respects editor width
when it's enabled.
## Context

Fixes a bug on Windows where the Alt modifier key becomes stuck in the
pressed state after using Alt-Tab to switch away from and back to the
Zed application.

### Root Cause
In `crates/gpui_windows/src/events.rs`, when the window loses focus
during Alt-Tab, the WM_KEYUP event for the Alt key is never delivered to
the application. The pending modifier state in GPUI remains as
`alt=true`. When the window regains focus, there is no synchronization
point to reset this stale state.

## How to Review

In `handle_activate_msg()` (WM_ACTIVATE handler), when the window is
activated:
1. Reset the cached modifier tracking state (`last_reported_modifiers`
and `last_reported_capslock` set to `None`)
2. Query the actual current modifier state from Windows using
`GetKeyState()` APIs
3. Dispatch a `ModifiersChanged` event with the true state to
synchronize GPUI

## 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
- [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

I think it's difficult to add tests for this because it's
platform-dependent, but I recorded a video for comparison — sorry I only
have an anime‑style app to show the key presses.

<details>
  <summary>Video</summary>
  


https://github.com/user-attachments/assets/b545178c-b360-4e2b-8d60-d6f95a0b4b79



https://github.com/user-attachments/assets/bc4d41eb-6f42-4040-a588-0fc46c576db7


</details>

Closes zed-industries#45485

Release Notes: 

- Fixed Alt modifier key stuck after Alt-Tab on Windows. Modifier state
is now synchronized when the window regains focus, ensuring correct key
interpretation after window switching.
…ed-industries#54207)

This adds a list of open workspaces to the project group dropdown menu,
to make sure it's possible to understand what workspaces are open, might
be running language servers, etc. It also allows you to close a specific
workspace.

Single folder project:
<img width="229" height="170" alt="Screenshot 2026-04-17 at 4 13 39 PM"
src="https://github.com/user-attachments/assets/86fca86a-73f1-4295-97b0-e97951102139"
/>

Multi folder project:
<img width="381" height="193" alt="Screenshot 2026-04-17 at 2 26 14 PM"
src="https://github.com/user-attachments/assets/b3c0c299-adf9-45d1-a314-feee8a993ea8"
/>

Release Notes:


- N/A
This PR revamps our feature flag system, to enable richer iteration. 

Feature flags can now:
- Support enum values, for richer configuration
- Be manually set via the settings file
- Be manually set via the settings UI

This PR also adds a feature flag to demonstrate this behavior, a
`agent-thread-worktree-label`, which controls which how the worktree tag
UI displays.

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
Bumps the `lsp-types` rev which contains patch for breaking change
introduced by upstream `typescript-go` repo

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:
- Fixed tsgo LSP
…dustries#53714)

Remove statements that imply that `subtle` edit prediction mode can only
be used if Zed is set as an edit provider, despite this not being the
case.

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 zed-industries#53207 

Release Notes:

- N/A

---------

Co-authored-by: morgankrey <morgan@zed.dev>
…stries#52162)

## Context

Red and blue have inherently low perceptual luminance in APCA — pure
default Lc 45 threshold. This caused ensure_minimum_contrast to lighten
them, washing out the color to pink/lavender.

When an application explicitly specifies an RGB value via
ESC[38;2;R;G;Bm,
that color should be rendered as-is. Named and indexed colors continue
to be contrast-adjusted since they come from theme mappings



[zed-colors-before.webm](https://github.com/user-attachments/assets/1adb8c95-5dec-4744-b6f8-38f085602ef4)


[zed-colors-after.webm](https://github.com/user-attachments/assets/1968db26-9c02-48cf-9542-86a6c39899c0)


Closes: zed-industries#50396 

<!-- 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 zed-industries#456)
     if one exists — helps with traceability. -->

## 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
- [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 true-color render in terminal
…popover is shown (zed-industries#53168)

Hover popovers aren't immediately dismissed when the hover ends, but
this delay mechanism is currently causing popovers to sometimes still
briefly appear when the hover lasted too short to have triggered it.
Fixed by immediately cancelling the popover task when the hover ends
before the popover is displayed.

Most easily reproduced when setting the hover popover delay to a value
lower than the default 300ms (but it still happens sometimes with the
default value), because the popover hide delay is also 300ms. Here's it
with `"hover_popover_delay": 200`:


https://github.com/user-attachments/assets/6415d112-d8e0-4a87-9a79-a7ab559f20f2

After the fix:


https://github.com/user-attachments/assets/34782389-de4c-4a25-bd6e-4858b55028de

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 hover popovers sometimes briefly appearing after the hover
already ended.

---------

Co-authored-by: Lukas Wirth <lukas@zed.dev>
…zed-industries#53781)

Closes zed-industries#47926

  ## Summary

When using a uv (or Poetry/PDM) workspace with multiple subprojects,
Python LSP servers (Pyright, Ruff, ty, etc.) are initialized with the
subproject directory as their workspace folder instead of the workspace
root. This happens because `PyprojectTomlManifestProvider::search()`
returns the first (innermost)
  `pyproject.toml` found walking up the directory tree.

  For example, in a uv workspace like:

  main-project/
  ├── pyproject.toml       # workspace root with [tool.uv.workspace]
  ├── uv.lock
  ├── packages/
  │   └── project-api/
  │       └── pyproject.toml   # subpackage
  └── projects/
      └── project-a/
          └── pyproject.toml   # subpackage

Opening a file in `packages/project-api/` would register
`packages/project-api/` as the LSP workspace folder instead of
`main-project/`.

  ## Approach

The fix uses lockfile existence as a heuristic to detect workspace
roots. The updated `search()` method walks all ancestors (similar to
`CargoManifestProvider`) and:

  - Tracks the **innermost** `pyproject.toml` as a fallback
- Tracks the **outermost** `pyproject.toml` that has a sibling lockfile
(`uv.lock`, `poetry.lock`, `pdm.lock`, or `Pipfile.lock`)
- Returns the outermost workspace root if found, otherwise falls back to
the innermost

This works within the existing `ManifestDelegate` interface (existence
checks only, no file content reading).

  | Scenario | Result |
  |---|---|
| uv workspace (root `pyproject.toml` + `uv.lock`) | Returns workspace
root |
| Poetry workspace (root `pyproject.toml` + `poetry.lock`) | Returns
workspace root |
| Simple project (single `pyproject.toml`, no lockfile) | Returns
project dir (unchanged) |
| Independent subprojects (no lockfile at any level) | Returns each
project's own dir (unchanged) |

Since the manifest provider is set at the Python **language** level,
this fix applies to all Python LSP servers (Pyright, Ruff, ty, etc.).

  ## Test plan

- [x] Added unit tests for `PyprojectTomlManifestProvider` covering all
scenarios above
- [x] Existing integration test
`test_running_multiple_instances_of_a_single_server_in_one_worktree`
passes (independent subprojects without lockfiles)
  - [x] `cargo check -p languages` compiles cleanly
- [x] Manual testing with a real uv workspace (Pyright and Ruff both
receive correct workspace root)

Release Notes:

- Fixed Python LSP servers (Pyright, Ruff, etc.) using the wrong
workspace folder in uv/Poetry/PDM workspaces with multiple subprojects.
…zed-industries#52706)

### 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
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

#### Closes zed-industries#52702

### Video 

[Screencast from 2026-03-30
13-17-08.webm](https://github.com/user-attachments/assets/8b0f6927-04d2-406b-b7fd-064a730b2f86)

Release Notes:

- Fixed the Inline Assist button showing in the Project Diagnostics
toolbar when the agent is disabled.
…ed-industries#53100)

Fixes zed-industries#42787

## Summary

- When "Go to Definition" navigates into a dependency (e.g. `.venv/`,
`node_modules/`), the save dialog for new files defaulted to that
directory
- `most_recent_active_path` now checks the `read_only_files` setting and
skips matching paths, falling back to the next eligible path, the
worktree root, or the home directory

## Design tradeoffs

We considered three approaches:

1. **Filter by `is_ignored`/`is_hidden`/`is_external` on worktree
entries** — catches `.venv` when gitignored or when it's a dotfile, but
also false-positives on directories like `.github/workflows/` that users
intentionally edit.

2. **Use preview tab status** — "Go to Definition" opens files as
preview tabs, so skipping preview paths targets the right intent. But it
doesn't work when preview tabs are disabled, and the signal is transient
(preview status changes as you interact with tabs).

3. **Use `read_only_files` setting** (this PR) — an explicit user
declaration of "I never want to edit files here." If you can't edit
them, you don't want to save new files next to them either. This is the
clearest signal of intent and respects user configuration. The tradeoff
is that `read_only_files` is empty by default, so users need to
configure it. But the kind of user bothered by the save dialog
defaulting to a dependency directory is the same kind of user who
already configures `read_only_files` (see
[zed-industries#46827](zed-industries#46827) for an
example).

## Test plan

- [x] Manual test: configured `read_only_files: ["**/.venv/**"]`, opened
project, Go to Definition into `.venv`, created new file — save dialog
defaults to project root
- [x] Added `test_most_recent_active_path_skips_read_only_paths`
- [x] All existing workspace tests pass

Release Notes:

- Fixed save dialog defaulting to dependency directories (e.g. `.venv/`,
`node_modules/`) after using Go to Definition, when those directories
are configured as `read_only_files`.

---------

Co-authored-by: Lukas Wirth <lukas@zed.dev>
Super small update changing two instances where
`DiagnosticSeverity::HINT` was set to use the color for "info".

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 zed-industries#45637

Release Notes:

- Fixed various instances of hint level diagnostics using the color
designated for info
…ed-industries#54183)

This PR makes Zed only have one worktree picker, as opposed to a flavor
of it in the title bar and another in the agent panel. It then moves it
to the title bar, making it always present, so that its trigger is
separate from the branch picker (which now contains only two views:
branches and stashes). For the worktree picker, I'm mostly favoring the
behavior we've introduced in the agent-panel-flavored version.

It also updates the title bar settings migration to use the JSON
`migrate_settings` helper instead of a shallow Tree-sitter rewrite, so
old `show_branch_icon = true` values are promoted to
`show_branch_status_icon = true` across root, platform, release-channel,
and profile settings scopes.

- [x] Move worktree creation logic to the `git_ui` crate to make this
more generic and less agent-specific
- [x] Double-check the remote use case and ensure nothing broke there
- [x] Improve the UX for the detached HEAD state; better invite people
to create a branch
- [x] Migrate `show_branch_icon = true` to `show_branch_status_icon =
true` across nested settings scopes

Suggested .rules additions

When migrating renamed settings keys that can appear in platform
overrides, release-channel overrides, or profiles, prefer the JSON
`migrations::migrate_settings` helper over shallow Tree-sitter key
rewrites unless tests explicitly cover every nested scope that can
contain the key.

Release Notes:

- Improved migration of the title bar branch status icon setting.

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
…cation (zed-industries#54297)

Closes zed-industries#52587

Release Notes:

- Improved the Dev Container suggestion notification to include the
project name, with the full path shown as a tooltip.
yara-blue added a commit to zed-industries/zed that referenced this pull request Apr 20, 2026
…#54123)

Stacked on top of #54112
This is part 2 of 3 towards #51197
More details from the original PR #53551

This PR includes the changes from #54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim#1

## Changes

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:


https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
@feitreim feitreim closed this Apr 22, 2026
@feitreim
feitreim deleted the feat-fuzzy-strings-module branch April 22, 2026 21:02
kathbigra pushed a commit to kathbigra/zed that referenced this pull request May 10, 2026
…zed-industries#54123)

Stacked on top of zed-industries#54112
This is part 2 of 3 towards zed-industries#51197
More details from the original PR zed-industries#53551

This PR includes the changes from zed-industries#54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim#1

## Changes

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
zed-industries#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:


https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
jasonsmithio pushed a commit to paddleboarddev/paddleboard that referenced this pull request May 31, 2026
… (#54123)

Stacked on top of #54112
This is part 2 of 3 towards #51197
More details from the original PR #53551

This PR includes the changes from #54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim/zed#1

## Changes

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
zed-industries/zed#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:


https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
jiayun pushed a commit to jiayun/superzent that referenced this pull request Jun 30, 2026
… (#54123)

Stacked on top of #54112
This is part 2 of 3 towards #51197
More details from the original PR #53551

This PR includes the changes from #54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim/zed#1

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
zed-industries/zed#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:

https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
(cherry picked from commit 68541960a7c41548060fcfcb1c644c56a1b31166)
Zenor27 pushed a commit to Zenor27/zed that referenced this pull request Jul 4, 2026
…zed-industries#54123)

Stacked on top of zed-industries#54112
This is part 2 of 3 towards zed-industries#51197
More details from the original PR zed-industries#53551

This PR includes the changes from zed-industries#54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim#1

## Changes

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
zed-industries#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:


https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
jonx pushed a commit to jonx/zed-aros that referenced this pull request Jul 17, 2026
…zed-industries#54123)

Stacked on top of zed-industries#54112
This is part 2 of 3 towards zed-industries#51197
More details from the original PR zed-industries#53551

This PR includes the changes from zed-industries#54112 , im not sure how to avoid
that, my understanding is that after that one is merged, this PR can be
rebased onto main and everything will be correct. You can also view the
version of this that does reflect the changes more directly here:
feitreim#1

## Changes

In this PR I added a more general string matching functionality to
`fuzzy_nucleo`, in order to have proper testing for this, I also changed
the command palette, tab switching picker, branch picker, and recent
projects picker to use this new implementation. I think the command
palette change in particular is awesome, just super nice to vaguely
gesture at the command i want and have it pop right up.

The main change here and departure from
zed-industries#37123 is realizing that the
primary reason for the regressions is actually how nucleo handles smart
case, the old `fuzzy` crate only uses the smart case argument to score
things differently, while nucleo actually filters on the case, eg. with
smart case query "Apple" wouldnt match "apple". To get around this we
always pass `CaseMatching::Ignore` to nucleo and implement the same
score modifications from fuzzy in our code.

There is a performance cost to that, of course, but from my testing it
is fairly static, not growing as the size increases, so maybe a query
takes 35 µs instead of 25 µs, but a query that takes 800 µs will only
take 820 µs.

Benchmark:
| kind | query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---|---:|---:|---:|---:|
  | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× |
  | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× |
  | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× |
  | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× |
  | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× |
  | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× |
  | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× |
  | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× |
  | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× |

When I added the 4-word queries to the benchmarks I was actually really
concerned that the performance would be awful, making it unsuitable for
the command palette especially. However, I think due to the CharBag
pre-filtering when the query is longer, the performance is actually way
better than the 2 word case.

Video:


https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3

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:

- Improved fuzzy matching in the command palette, branch picker, tab
switcher, and recent projects picker to support multi-word queries.

---------

Co-authored-by: Yara <git@yara.blue>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.