Commit graph

135 commits

Author SHA1 Message Date
Xin Zhao
fa00dccc42
Fix project path handling when connecting from Unix to Windows remotes (#62038)
# Objective

Follow-up of #61374.

Zed now supports Windows as a remote target, but when connecting from a
Unix platform to Windows, some path handling still uses the native
client's path style (Unix) to construct paths, which causes weird path
displays in different areas.

One of them is the project path stored in the `settings.json` file,
which is related to the open path picker in the codebase:

5e1fd392f6/crates/open_path_prompt/src/open_path_prompt.rs (L668-L679)
For example, if I have a remote project at `D:\code\test_python` and
want to open it in remote development, I usually use path completions,
with `D:\code\` as the parent path and `test_python` as the selected
candidate. Zed directly joins them using `Path::join` on the Unix
platform, which results in `D:\code\/test_python`.

A second thing I found is the displayed name for the git repo. The
related source code is:

5e1fd392f6/crates/title_bar/src/title_bar.rs (L262-L268)
Also taking `D:\code\test_python` as an example: the passed-in
`common_dir_abs_path` is `D:\code\test_python\.git`, and
`repo_identity_path()` directly uses `Path::file_name()` and
`Path::parent()` from the standard library to handle this:

5e1fd392f6/crates/project/src/git_store.rs (L9956-L9965)
Ideally, this function should return `D:\code\test_python`. But due to
the platform mismatch, `D:\code\test_python\.git` is returned; after
further processing in the title bar, we get `D:\code\test_python\` as
the displayed name, while the expected display name is `test_python`.

In the past, only Unix-like systems could serve as remote servers, and
their path separator (`/`) is valid on Windows, so everything looked
fine. But Unix does not support `\` as a valid separator — that's the
root cause. We need to use `PathStyle`, which is designed for processing
paths across platforms, to deal with these cases.

## Solution

- Added new APIs `PathStyle::parent()` and `PathStyle::file_name()`,
which serve as replacements for `Path::parent()` and `Path::file_name()`
to process paths cross-platform.
- Adopted the new APIs in `repo_identity_path()`, and updated the
relevant call sites.
- For the open path picker, use `PathStyle::join_path()` instead of
`Path::join`.

## Testing

The added `PathStyle::parent()` and `PathStyle::file_name()` are covered
by detailed unit tests. These tests verify that the behavior matches the
corresponding methods in `Path`, just independent of the host platform.

For the path display issues, I built and tested manually; a comparison
is attached in the Showcase section.

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

<details>
  <summary>Click to view showcase</summary>

| Content | Before | After |
|:--:|:--:|:--:|
|title bar|<img width="486" height="272" alt="title_bar_before"
src="https://github.com/user-attachments/assets/d14d0e37-a1b8-43ab-b51b-fe9dd1b977eb"
/> | <img width="406" height="274" alt="title_bar_after"
src="https://github.com/user-attachments/assets/fc9193f4-d42c-47a8-a254-4ed08c806a11"
/> |
|path storage| <img width="337" height="264" alt="project_path_before"
src="https://github.com/user-attachments/assets/3352add3-20df-43b9-8a20-10ee7d96e703"
/>| <img width="319" height="262" alt="project_path_after"
src="https://github.com/user-attachments/assets/fa3d7feb-f393-416a-868d-85eb0af5cfb8"
/>|
|open remote| <img width="554" height="135" alt="open_remote_before"
src="https://github.com/user-attachments/assets/62983eca-22ad-472f-8333-8561cfc17357"
/>|<img width="562" height="176" alt="open_remote_after"
src="https://github.com/user-attachments/assets/22528a6b-0e73-4a12-a825-673ba57a63da"
/> |
</details>


## Other things to note
This PR also did a little refactoring: it moved the `PathStyle`-related
tests from the `util` crate to the `path` crate, and updated the
documentation to reflect that Windows can serve as a remote platform.

The recent project picker also suffers from the same cross-platform bug,
but it is not fixed here, because a clean fix requires dealing with
database storage, unlike the direct API changes made here. I will
address it in a follow-up PR.

This PR looks very large, but most of the changes are the test migration
and the new API implementation. I hope the unit tests and comments can
offload some of the burden for reviewers.

---

Release Notes:

- Fixed project paths being built incorrectly when connecting from Unix
machines to Windows remote servers.
2026-08-19 12:16:37 +00:00
Ali
00c0e96e76
Make opening large files use less peak memory (#62748)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
# Objective
Opening a file laods it twice. `decode_file_text` builds the whole file
as a `String`, and that `String` stays alive alongside the finished rope
while `text::Buffer::new` copies it in. The `Vec` behind it grows by
doubling, so it also commits up to nearly the file's size again in
capacity it never uses.

Partially addresses #27283.

## Solution

Add `decode_file_text_to_rope`, which streams the file in 1 MB blocks
straight into a `Rope`, validating UTF-8 and normalizing line endings as
it goes. The file is never fully held as a `String`.

`LoadedFile::text` becomes a `Rope` carrying the `LineEnding` detected
before normalizing, so `buffer_store` calls `Buffer::new_normalized`.

## Testing

On a 729 MB SQL dump, peak memory fell 25% and CPU fell around 28%.
tested on 5950x, win11.

Release Notes:

- Improved memory use when opening large files, reducing peak memory
during load by roughly the size of the file itself.
2026-08-18 16:59:08 +00:00
Buyun Xu
3624a5bfda
project: Anchor diagnostic related information that points into the buffer (#62805)
Closes #62796. Follow-up to #62110.

# Objective

The range of a diagnostic entry is anchored when it is ingested, so it
follows edits. The ranges in the related information kept on the
diagnostic were the ones the server published. A code action request
carried both and reported the same note at two different lines: the
entry Zed flattened that note into had followed the edit, the related
information had not.

The distance does not correct itself either. When diagnostics are merged
rather than replaced, the existing entries are re-collected from their
anchors while the payload is cloned as it is, so the two positions drift
further apart with every edit that passes.

`mlir-lsp-server` shows what this costs. `MLIRTextFile::getCodeActions`
takes the line number out of `relatedInformation`, and
`getCodeActionForDiagnostic` resolves it against its own current
document, reading that line to copy its indentation before inserting the
`expected-note` check.

## Solution

The related information moves from `Diagnostic` onto
`DiagnosticEntry<T>`, next to the range it belongs with. The locations
of the diagnostic's own file are then in the same coordinate space as
that range: anchors inside the buffer, points in the worktree's store.
`Diagnostic` carries no coordinates again, so nothing that is only
meaningful inside one buffer travels with a payload that outlives it.

Every transition goes through `DiagnosticEntry::map_coordinates`: the
unsaved-edit adjustment and the clipping when diagnostics are ingested,
the anchoring in `DiagnosticSet::new`, and the conversion back to points
in `merge_diagnostic_entries`. Only the diagnostic's own range is
widened when it is empty, since that is for how it is rendered, while
the related locations are reported back as the server framed them.

Locations in another file have nothing here to anchor to and are kept as
published, which is also what `mlir-lsp-server` expects, since it skips
them.

`DiagnosticEntryRef` is left alone. It is what the rendering path
iterates, down to the scrollbar markers that walk every diagnostic of
the buffer on each frame, so nothing there converts or allocates. The
entries are read through `diagnostic_entries_in_range` where the request
is built, and `diagnostics_in_range` is now implemented on top of it.

The field is an `Option`, as an empty `Arc<[_]>` still allocates and
most diagnostics carry no related information.

`data` has the same staleness and cannot be anchored, as it is opaque.

## Commits

The third commit is mechanical: it introduces `DiagnosticEntry::new` and
rewrites the literals at its call sites, so that the last commit holds
only the change of behaviour.

## Testing

Three tests, all failing before this change. The first two are added as
separate commits, so that they can be run against `main`:

- `test_code_actions_related_information_follows_edits` edits above the
note and requests code actions, where the two positions for it used to
disagree.
- `test_code_actions_related_information_drifts_across_merges` edits and
pulls diagnostics twice, where the distance used to be every line
inserted since the diagnostic was published rather than the last edit
alone.
- `test_code_actions_related_information_of_disk_based_diagnostics`
publishes a diagnostic computed against the file on disk while the
buffer holds an unsaved edit, covering the adjustment the two positions
share.

- `cargo test -p project`
- `cargo test -p language -p diagnostics -p editor`
- `cargo fmt --all -- --check`
- `./script/clippy -p project -p language`

## 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 language servers receiving outdated positions for the related
information of a diagnostic when code actions are requested.
2026-08-18 15:06:02 +00:00
Dom Porada
cf08569e82
Add support for the "..." entry in file_scan_exclusions (#62769)
## Objective

`file_scan_exclusions` replaces the defaults instead of adding to them,
so excluding one extra directory means restating all eleven default
globs and never picking up defaults added in later Zed releases.

## Solution

`file_scan_exclusions` now accepts the `"..."` entry, which expands to
the value it overrides, so `["**/node_modules", "..."]` adds to the
inherited globs instead of replacing them. Entries listed by name keep
their position, and leaving `"..."` out still replaces the list
outright, so existing settings behave exactly as they do today.

## Testing

- Four unit tests in `crates/settings_content/src/project.rs` cover
splicing versus replacing, accumulation across successive layers, and
edge cases: a repeated `"..."`, an empty list clearing the value, and a
bare `["..."]` leaving it unchanged.
- To check by hand: set `"file_scan_exclusions": ["**/node_modules",
"..."]` in user settings and confirm `node_modules` disappears from the
project panel and file finder while `.git` and `.DS_Store` stay
excluded. Remove `"..."` and confirm only `node_modules` is excluded.
Repeat in a project's `.zed/settings.json` to confirm it splices the
resolved user settings rather than the defaults.
- Tested on macOS. This is platform-independent settings-merge logic
with no OS-specific code paths, so I did not test Linux or 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:

- Added support for the `"..."` entry in `file_scan_exclusions`. Custom
exclusions can now extend the defaults instead of replacing them.
2026-08-18 09:57:38 +00:00
Xiaobo Liu
fd90c0af7f
project: Deduplicate identical language server hover responses (#62266)
Closes https://github.com/zed-industries/zed/issues/62262

## Solution

Identical hover responses from multiple language servers should be
displayed only once.

Different hover responses should still all be preserved, since multiple
language servers may provide complementary information.


## Showcase



https://github.com/user-attachments/assets/67246d9f-ed1c-4f5a-98f5-f10548b7fc6d



---

Release Notes:

- Deduplicated identical language server hover responses

---------

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-17 22:47:34 +00:00
Buyun Xu
6dee3fc755
project: Send diagnostic related information in code action requests (#62110)
Closes #62560.
Supersedes #62108, which was a subset of this one.
Overlaps #62400, see comments.

# Objective

Zed flattens the `relatedInformation` of a diagnostic into non-primary
entries of the same diagnostic group. Before this change it did not
retain the original related information on the primary diagnostic, so
code action requests were built from the entries intersecting the
requested range, with the primary diagnostic carrying no
`relatedInformation`.

This caused incomplete code actions from servers such as
`mlir-lsp-server`, which generates `expected-note` edits by walking the
related information of an error or warning diagnostic.

## Solution

Keep the related information the server published on the primary
diagnostic when the diagnostic comes in, next to `data`, and pass it
back when building the code action request.

Nothing is removed from `context.diagnostics`: the flattened entries are
still sent as before, so a diagnostic the server published on its own
and that Zed merged into a group as supporting information keeps being
sent with the severity the server gave it. What it does not recover is
that diagnostic's own `relatedInformation`: ingestion keeps only its
severity. Unchanged from `main`.

Reassembling it from the flattened entries instead, which is what the
first revision of this PR did, is neither faithful — ingestion trims
messages and drops entries with an empty message or pointing at another
file — nor cheap: diagnostics are not indexed by group, so every request
would scan all diagnostics of the buffer, once per server, on every
selection change.

One caveat: the stored ranges are the ones the server published rather
than anchors, so they do not follow edits made after the diagnostic
arrived, while the primary's range does. An edit in that window can put
a resolved insertion a few lines off — `mlir-lsp-server` places the
`expected-note` line at the note's own position. `data` has the same
property today. Anchoring them would mean carrying related information
through the anchor conversion, which I would rather do as a follow-up if
you consider it worth it.

The field is not carried over the proto conversion, as LSP requests are
only built by the peer that received the diagnostics from the language
server.

## Testing

New tests for:

- related information sent verbatim, including the cross-file and empty
entries that flattening drops;
- no related information;
- a flattened entry whose primary is outside the requested range;
- a server-published supporting diagnostic;
- two servers on the same buffer.

Verified on the repro from #62560 that `mlir-lsp-server` inserts both
the `expected-error` and the `expected-note` check
([screenshot](https://github.com/zed-industries/zed/issues/62560#issuecomment-5278476460)).

- `cargo test -p project`
- `cargo test -p language -p editor -p diagnostics`
- `cargo fmt --all -- --check`
- `./script/clippy -p project -p language`

## 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 incomplete code actions from language servers that rely on the
related information of a diagnostic.
2026-08-17 16:40:29 +00:00
hvck
8968bf7808
git: Decode non-UTF-8 blobs for project diffs (#60821)
## Summary

Fixes #56449.
Related to #16965.

Zed’s Git panel and Project Diff build UI diffs from `language::Buffer`
diff bases loaded through the Git backend. Git blob loading previously
converted bytes with `String::from_utf8(...).ok()`, so legacy-encoded
blobs were treated as missing and the whole worktree file appeared newly
added.

This follows the same encoding path used for worktree buffers:

- move shared byte decoding and encoding into `language`
- keep Git blob, revision, and index APIs byte-oriented with `Vec<u8>`
- decode diff bases and index contents in `GitStore`, where
`language::Buffer`s are created
- encode index writes using the open buffer’s encoding and BOM so
partial staging does not rewrite the file as UTF-8
- keep worktree loading and saving on the same shared implementation

Regression coverage includes Windows-1251 decoding/encoding,
UTF-8/UTF-16 BOM preservation, raw Windows-1251 Git blob loading, and a
`BufferDiffSnapshot` assertion that a one-line CP1251 edit produces one
modified-line hunk instead of a full-file rewrite.

This does not run Git `textconv` commands. It fixes the reported
legacy-encoding case without executing repository-configured commands or
modifying working files on disk.

## Testing

- `cargo test -p language file_content::tests --locked`
- `cargo test -p git repository::tests::test_load_revisions --locked`
- `CARGO_INCREMENTAL=0 cargo test -p project
git_store::tests::test_decode_git_text_windows_1251_one_line_change
--locked`
- `CARGO_INCREMENTAL=0 cargo test -p project --test integration
test_restaging_hunk_after_optimistic_unstage --locked`
- `CARGO_INCREMENTAL=0 cargo check -p project --tests --locked`
- `CARGO_INCREMENTAL=0 cargo check -p git_ui --tests --locked`
- `cargo fmt --all --check`
- `git diff --check`

## Suggested .rules additions

- N/A

Release Notes:

- Fixed Git panel and Project Diff rendering for legacy-encoded text
files whose Git blobs are not valid UTF-8.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2026-08-17 01:47:11 +00:00
Kirill Bulatov
b47d8ac455
Merge array settings from extension contributions instead of overwriting (#62686)
Closes https://github.com/zed-industries/zed/issues/62572

Reworks https://github.com/zed-industries/zed/pull/54950 — instead of
unconditionally replacing the array with a different one, now does the
replacement only when the user settings are set.
The rest now merges into the array.


Release Notes:

- Fixed array merging for extensions case
2026-08-16 21:10:59 +00:00
Kirill Bulatov
18be72fd68
Make file scanner less eager in non-git-tracked directory trees (#62583)
Fixes https://github.com/zed-industries/zed/issues/35780
Collab schema migration PR:
https://github.com/zed-industries/cloud/pull/3422
The corresponding database schema migration has been created in the
Cloud repo and applied to the production database.

Before, Zed scanned each and every entry in the tree down from the
directory it was opened in, except gitignored files and scan exclusions.
The approach is unchanged, if Zed detects it was open inside a git
repository: e.g. the directory open in Zed contains `.git` directory.

For the rest of the projects, 2 optimizations are made:

* Limit the depth of file scan traversal.
Now, `file_scan_depth` (default `5`) restricts Zed from traversing any
directory that has same number or more segments in its file path.


Such directories behave similar to gitignored directories: their
contents is not available in file finder, project search and project
panel, but can be lazily traversed when the directory is expanded (e.g.
project panel expands it or a nested file is open by path via terminal,
etc.)

To indicate that to the users, a status entry is shown firs time the
limitation is hit in the project:

<img width="858" height="133" alt="image"
src="https://github.com/user-attachments/assets/7da6cfbb-98b4-4cc3-bf2a-8902a9597a15"
/>

* During the scan, any git repositories that are not direct children of
the directory open in Zed (depth >= 2), are traversed and indexed
normally, but their git metadata is never fetched eagerly.

Only when Zed opens a buffer from that repo the git metadata is fetched
and applied.

All that combined now uses a way more moderate amount of CPU and RAM
when opening `~`:

<img width="1717" height="368" alt="Screenshot 2026-08-13 at 17 43 53"
src="https://github.com/user-attachments/assets/ec83e2a9-f7cc-452b-8eb7-af158284ca4e"
/>

File scan inclusions and exclusions are considered still for such
projects.
Set `file_scan_depth` to `0` to enable old behavior.
The setting is supported in the project settings, so custom values can
be set based on the project's structure.

---

Release Notes:

- Fixed Zed using a lot of memory and CPU in large, non-git-tracked,
directory trees
2026-08-13 17:07:06 +00:00
Kirill Bulatov
4efba7161f
Unify non-Unicode file detection code (#62581)
Closes https://github.com/zed-industries/zed/issues/62464
Closes https://github.com/zed-industries/zed/issues/62212

As a bonus, fixes the project search not working in BOM'd UTF-16 files.

Release Notes:

- Fixed project search not working in some non-Unicode files
2026-08-13 16:49:32 +00:00
Michael Thomas
bc463bc205
Send correct line endings to language servers (#59941)
# Objective

Zed normalizes all buffer text to `LF` internally, but was sending that
`LF`-normalized text to language servers even for `CRLF` files. This
caused servers such as ESLint (with a `linebreak-style` rule) to report
a false error on every line.

Fixes #38453

## Solution

Send the buffer's actual line endings to the language server instead:

- `didOpen` and full-document `didChange` now send
`text_with_line_endings()`, and incremental changes apply the buffer's
line ending to each edit.
- Normalize the line endings returning from the LSP before computing
changed regions
- This effectively incorporates the fix from #59151, which happens to be
the reason this change was [originally
reverted](1b6cde7032).
As such, that PR should likely be integrated first.
- Detect when a buffer's line ending differs from what a server was last
sent and force a full-document resync, without this the server would
keep stale line endings, as the incremental change tracking does not
consider line ending differences.
- Route the `UpdateLineEnding` operation to `on_buffer_edited` so
toggling line endings via the status bar notifies the server immediately
rather than waiting for the file to be edited or reopened.



## Testing

- Did you test these changes? If so, how?
Yes, in addition to new unit test coverage, I used a test project with
ESLint configured with the `linebreak-style` rule set to enforce CRLF
line endings to verify that the LSP integration worked as expected.

- Are there any parts that need more testing?
The original reversion seems to have been due to a regression in which
LSP formatting would cause the editor to scroll to the bottom. I'm not
seeing this in my reproduction, and I believe this was due to a failure
to normalize line endings coming back from the LSP, but I don't know the
exact circumstances that led to the original reversion, so there might
be some additional things to test there.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Not really! As mentioned above, configuring ESLint with the
`linebreak-style` rule is probably the easiest way to test.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  I tested on Linux, but I don't believe it's relevant.

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



https://github.com/user-attachments/assets/881c5758-a5de-433c-8fd6-3cad7478aa90



---

Release Notes:

- Fixed an issue where language servers received incorrect line endings
for `CRLF` files, causing linters and formatters to report false errors.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-12 18:14:22 +00:00
Toru Nayuki
a034d87024
project: Don't let a canceled caller leak a loading worktree forever (#61009)
# Objective

`WorktreeStore::find_or_create_worktree` inserts the shared
worktree-creation task into `loading_worktrees` and relies on the task
it returns to each caller to remove that entry once creation resolves.
But the creation task keeps running through the clone the map itself
holds, while the map cleanup lives only in the callers' returned tasks.

If every caller is cancelled before creation resolves, the resolved task
stays in `loading_worktrees` forever, retaining the `Entity<Worktree>`
captured in its result (a `Shared` task memoizes its output). Such a
worktree can never be released: `remove_worktree` only unlists it, so
its background scan keeps running and its snapshot keeps growing for the
lifetime of the window. The stale entry also keeps
`initial_scan_complete` permanently `false` (that flag is
`loading_worktrees.is_empty() && …`).

Callers are cancelled routinely — worktree creation is async and can
take seconds on a large tree, while the tasks awaiting it are owned by
UI that the user can close at any time (a tab or pane, a debugger panel
resolving a path, an agent session, or the whole window). See the
existing note in `crates/zed/src/zed.rs` that external-file worktrees
are "released on file close".

Observed in the wild: a home-directory worktree removed from the project
kept scanning for hours and grew Zed past 45 GB; neither removing the
folder nor ending the agent session freed it — only quitting Zed. (The
scan-amplification half of that incident is #60988.)

## Solution

Spawn the map cleanup as its own detached task, next to the map
insertion, so a loading entry always leaves `loading_worktrees` when
loading resolves regardless of what happens to the callers. The returned
per-caller task is unchanged apart from no longer owning that cleanup.

## Testing

- Added `test_worktree_released_when_creation_caller_is_cancelled`: it
requests a worktree, drops the returned task immediately (as a cancelled
caller would), lets creation complete, removes the worktree, and asserts
the entity is released. It fails on `main` and passes with this change.
- Full worktree-related project integration suite is green (45/45).

## 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 memory leak where a worktree whose creation was requested by a
since-cancelled task (e.g. a folder opened as its owning
tab/panel/window closed) could never be released, leaving its background
scan running and its snapshot growing for the lifetime of the window.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-12 18:13:37 +00:00
Toru Nayuki
fdf5de99c6
project: Keep the buffer associated after an LSP rename also renames the file (#61142)
# Objective

`test_rename_that_also_renames_file` (added in #59104) is
order-dependent: it passes at seed 0, which CI runs, but fails on many
others (e.g. 11, 15, 17). Any unrelated change that schedules one extra
task shifts the deterministic test scheduler enough to flip it at seed 0
too — which is how it surfaced, while working on #61009. The bug it
exposes is real and pre-existing:

#59104 stopped the content swap, but the open buffer still relied on the
filesystem watcher to follow the file to its new path. Depending on the
order the watcher reports the old path's deletion and the new path's
creation, the entry id isn't carried over, and the buffer is stranded at
the now-deleted old path (shown as saved) and never re-associates.

## Solution

Move the worktree entry explicitly after the rename, preserving its id,
the same way `rename_entry` (project panel renames) already does.

## Testing

- `test_rename_that_also_renames_file` now runs 30 seeds to cover both
orderings.

## 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 symbol rename that also renames the file leaving the open
buffer on the old path
2026-08-12 11:01:18 +00:00
Kirill Bulatov
1271f8b0e8
Bump rustc to 1.97 (#62395)
Some checks failed
extension_auto_bump / detect_changed_extensions (push) Has been cancelled
extension_auto_bump / bump_extension_versions (push) Has been cancelled
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
Release Notes:

- N/A
2026-08-09 22:29:52 +00:00
Shuhei Kadowaki
3b90a9be7c
lsp: Separate timed RPC log groups (#61452)
RPC log grouping only tracked whether consecutive messages had the same
transport direction. This made an untimed request appear beneath the
duration header of an unrelated response when both were sent in the same
direction.

Before:

    // Send (took 53.0ms):
    {"jsonrpc":"2.0","id":"##CodeLensRefreshRequest#1226","result":null}
    {"jsonrpc":"2.0","id":53,"method":"textDocument/diagnostic"}

After:

    // Send (took 53.0ms):
    {"jsonrpc":"2.0","id":"##CodeLensRefreshRequest#1226","result":null}

    // Send:
    {"jsonrpc":"2.0","id":53,"method":"textDocument/diagnostic"}

Apply the same boundary handling to received messages while continuing
to group consecutive untimed messages.

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-08-08 13:01:16 +00:00
Piotr Osiewicz
1ade7854f2
Respect regex assertions more faithfully with search (#62158)
- **project_search: Add failing test for regex searches with
assertions**
- **project_search: Improve handling of regex assertions**

# Objective

Fixes #55995 by removing a faulty optimization path for regex searches.


## Solution

## Testing

We've added 3 extra tests for the changed behavior.

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

> This section is optional. If this PR does not include a visual change
or does not add a new user-facing feature, you can delete this section.

- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
- A before/after comparison is very useful for changes to existing
features!

While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:

<details>
  <summary>Click to view showcase</summary>

My super cool demos here

</details>

---

Release Notes:

- Improved handling of regexes in project/buffer searches

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-08-04 11:23:39 +00:00
Ben Kunkle
b5764581d2
project: Refresh MCP settings after worktree changes (#62026)
# Objective

Prevent MCP servers from remaining unavailable when a project is created
before its first worktree.

## Solution

Refresh effective MCP settings before maintaining servers after worktree
additions or removals.

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

- Agent: Fixed MCP servers missing from new project threads after a
worktree opens.
2026-08-03 20:33:31 +00:00
Kirill Bulatov
410a8a06ed
Do not drop other servers' data on semantic token refresh (#61795)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
Closes https://github.com/zed-industries/zed/issues/60825

Release Notes:

- Fixed semantic tokens overly invalidated on
`workspace/semanticTokens/refresh`
2026-07-30 08:36:31 +00:00
Kirill Bulatov
1efdc3e63e
Instantly acknowledge workspace/diagnostic/refresh (#61772)
Closes https://github.com/zed-industries/zed/issues/61692

Makes no sense to wait for anything at all when receiving such requests,
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic_refresh
does not imply anything either.

Release Notes:

- Fixed diagnostics refresh deadlocking certain language servers
2026-07-28 12:32:28 +00:00
Jiby Jose
137c981cb0
Refresh git state on bare .git events (#59876)
# Objective

Fix stale Git state in Zed when repository metadata changes are reported
only as a bare `.git` directory event.

On macOS, file watcher events can be coalesced such that Git operations
only surface as a `Changed` event for the `.git` directory itself,
rather than individual events for files like `.git/index` or
`.git/HEAD`. Zed previously ignored bare `.git` directory events before
scheduling a Git metadata refresh, which could leave the Git panel
showing stale changes or an outdated history even though `git status` /
`git log` reflected the latest state.

## Solution

Treat meaningful bare `.git` directory events as Git repository updates
before skipping them from normal worktree scanning.

This preserves the existing behavior of not scanning `.git` as regular
project content, while still notifying the Git repository tracking path
that repository metadata may have changed. As a result, Git state such
as `HEAD` and file statuses are refreshed when `.git` itself is the only
watcher event.

Updated the existing worktree test expectations so bare `.git` events
now trigger `UpdatedGitRepositories`, while skipped files like
`.git/index.lock` still do not.

Added a test covering the full project/Git path:

- repo initially has old `HEAD` and a modified file status
- fake Git state is updated to represent a commit
- only a bare `.git Changed` event is emitted
- Zed refreshes the repository snapshot, observes the new `HEAD`, and
clears the stale file status

## Testing

The new tests cover the full project/Git path scenario described above.
It fails without the fix and passes with the fix. Unfortunately, i was
unable to reproduce the issue deterministically enough to test it end to
end.

## 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 stale Git panel state after repository metadata changes.

Co-authored-by: Eric Holk <eric@zed.dev>
2026-07-23 23:41:43 +00:00
Finn Evers
e49d280094
language: Refactor available_languages into its own struct (#61388)
This adds a dedicated `AvailableLanguages` struct in preparation for a
more cabable language matching based on a given language config. No
functional changes, just shuffling some code around for this round.

Also made the LanguageMatcher non-cloneable in favor of wrapping it in
an Arc, since cloning is rather expensive for this and having a
reference is sufficient in all cases right now.

Release Notes:

- N/A

---------

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
2026-07-23 11:22:43 +00:00
qrzychu
d87dfaa4b3
Fix cursor going to the end of file when LSP formatter uses CRLF line endings (#59151)
I got super annoyed when using Zed with F#, so I fixed it. This also
fixes other LSPs on Windows

Fix is super simple, the test fails if the fix is commented out

Closes #48367 (and probably others)


Release Notes:

- fix cursor jumping to the end of file when LSP formats the file using
CLRF line endings
2026-07-23 07:54:28 +00:00
Tautik Agrahari
b64e5dc886
project: Track inlay hint / code lens / document symbol registrations by ID (#55340)
extends the precedent set by #43703 (thanks @reflectronic) so that
`textDocument/inlayHint`, `textDocument/codeLens`, and
`textDocument/documentSymbol` correctly track multiple dynamic
registrations by id. previously each register call overwrote the slot on
`ServerCapabilities`, and unregister either silently did nothing
(inlayHint, documentSymbol — no match arm) or wiped the entire
capability (codeLens). now each method keeps its own id-keyed map on
`DynamicRegistrations`; the field on `ServerCapabilities` is cleared
only when the last registration is removed.

textDocument-sync notifications (`didChange`/`didSave`/`willSave`) are
deliberately out of scope — their fan-out semantics are ambiguous in the
spec and were flagged on @smitbarmase's earlier exploration in #36876.

verified with `cargo check -p project -p lsp -p editor`, `cargo test -p
project --test integration -- multi_registration` (3/3 passing), and
`cargo fmt -p project`.

closes part of #37838.

Release Notes:

- Improved support for language servers that dynamically register inlay
hints, code lens, or document symbols multiple times.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-23 07:53:30 +00:00
Benjamin Ye
d61edb0825
Fix incorrect array merging in LSP initialization_options (#54950)
In lsp_store, user's lsp initialization_options are merged into the
adapter's
defaults using `merge_json_value_into`; this merges by concatenating
arrays,
which can produce duplicate entries.

Adds merge_json_value_into_replacing_arrays, a variant that replaces
arrays instead of merging; uses it for LSP initialization options.
`merge_json_value_into` is kept since some callers intentionally
use array concatenation (extending rust-analyzer's
experimental.commands.commands list).

Closes #54892


Release Notes:

- Fixed duplicated or extra array values in LSP `initialization_options`
when user settings override LSP defaults with an array

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-23 07:53:27 +00:00
Mohit Goyal
94792bdbfc
Respect disabled trailing whitespace removal (#58776)
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 #58686

Release Notes:

- Fixed `.editorconfig` re-enabling trailing whitespace removal when Zed
settings disable it.

---------

Co-authored-by: Martin Ye <martin@zed.dev>
2026-07-22 21:10:32 +00:00
Apoorva Verma
ac44e9f5df
project: Restart context servers when their working directory changes (#61365)
# Objective

Fixes #60879

Open Zed from Finder/Dock and the agent's MCP servers run from `/`
instead of your project. They get spawned before any worktree exists, so
there's no root to give them and they grab Zed's own cwd. The worktree
shows up right after, but `maintain_servers` only restarts on a config
change and the working dir isn't part of the config, so nothing kicks
it.

## Solution

Track each server's working dir and restart when it changes. Direction 1
from @SomeoneToIgnore's triage. Could also defer startup until the first
worktree lands, happy to switch if you'd rather.

## Testing

Added a test: file-only worktree (root is `None`) → start server → add a
real worktree → server restarts. Fails without the fix.
- Fixed agent MCP servers running from the wrong directory when started
before a worktree was available
2026-07-22 19:45:18 +00:00
Lukas Wirth
54c5db8346
Disable LSP for files with very long lines (#61447)
Release Notes:

- Fixed ui stutters when opening large single line files like minified
javascript due to running LSP requests against them
2026-07-22 13:25:49 +00:00
Shuhei Kadowaki
4ba5dc0d2c
lsp: Show request durations in RPC messages (#61018)
Language server performance issues can be difficult to diagnose because
request timings are not shown alongside the corresponding JSON-RPC
traffic. Annotate responses in the "LSP Logs / RPC Messages" view with
their end-to-end duration, making it easier to identify slow methods,
latency outliers, and cancellation behavior in the language server
process launched by Zed.

Capture timestamps at the transport boundary, correlate decoded request
IDs separately by direction, preserve timing across cancellation, bound
stale request tracking, and forward host-measured durations to remote
clients.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and relxability
- [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

<details>
<summary>Example trace</summary>

```
// Send:
{"jsonrpc":"2.0","id":61,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":378,"character":3}}}

// Receive (took 7.698042ms):
{"jsonrpc":"2.0","id":61,"result":[]}

// Send:
{"jsonrpc":"2.0","id":62,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":378,"character":3},"end":{"line":378,"character":3}},"context":{"diagnostics":[]}}}

// Receive (took 5.632167ms):
{"jsonrpc":"2.0","id":62,"result":[{"title":"Show macro expansion for `@static`","command":{"title":"Show macro expansion for `@static`","command":"jetls.openMacroExpansion","arguments":["jetls-macro-expansion:/macro-expanded.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609"]}},{"title":"Expand all macros in this top-level form","command":{"title":"Expand all macros in this top-level form","command":"jetls.openMacroExpansion","arguments":["jetls-macro-expansion:/macro-expanded.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609&mode=toplevel"]}},{"title":"Show inferred type annotations","command":{"title":"Show inferred type annotations","command":"jetls.openTypeAnnotation","arguments":["jetls-type-annotation:/type-annotated.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609"]}}]}

// Send:
{"jsonrpc":"2.0","id":63,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":379,"character":3}}}

// Receive (took 3.473792ms):
{"jsonrpc":"2.0","id":63,"result":[]}

// Send:
{"jsonrpc":"2.0","id":64,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":379,"character":3},"end":{"line":379,"character":3}},"context":{"diagnostics":[]}}}

// Receive (took 4.472375ms):
{"jsonrpc":"2.0","id":64,"result":[{"title":"Show macro expansion for `@static`","command":{"title":"Show macro expansion for `@static`","command":"jetls.openMacroExpansion","arguments":["jetls-macro-expansion:/macro-expanded.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609"]}},{"title":"Expand all macros in this top-level form","command":{"title":"Expand all macros in this top-level form","command":"jetls.openMacroExpansion","arguments":["jetls-macro-expansion:/macro-expanded.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609&mode=toplevel"]}},{"title":"Show inferred type annotations","command":{"title":"Show inferred type annotations","command":"jetls.openTypeAnnotation","arguments":["jetls-type-annotation:/type-annotated.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=14278&stop=15609"]}}]}

// Send:
{"jsonrpc":"2.0","id":65,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":380,"character":0}}}

// Receive (took 1.186541ms):
{"jsonrpc":"2.0","id":65,"result":[]}

// Send:
{"jsonrpc":"2.0","id":66,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":380,"character":0},"end":{"line":380,"character":0}},"context":{"diagnostics":[]}}}

// Receive (took 2.552708ms):
{"jsonrpc":"2.0","id":66,"result":[]}

// Send:
{"jsonrpc":"2.0","id":67,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":401,"character":0}}}

// Receive (took 1.490084ms):
{"jsonrpc":"2.0","id":67,"result":[]}

// Send:
{"jsonrpc":"2.0","id":68,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":401,"character":0},"end":{"line":401,"character":0}},"context":{"diagnostics":[]}}}

// Receive (took 2.819125ms):
{"jsonrpc":"2.0","id":68,"result":[]}

// Send:
{"jsonrpc":"2.0","id":69,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":400,"character":0}}}

// Receive (took 3.501375ms):
{"jsonrpc":"2.0","id":69,"result":[]}

// Send:
{"jsonrpc":"2.0","id":70,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":399,"character":0}}}

// Receive (took 2.903333ms):
{"jsonrpc":"2.0","id":70,"result":[]}

// Send:
{"jsonrpc":"2.0","id":71,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":399,"character":14}}}

// Receive (took 3.166ms):
{"jsonrpc":"2.0","id":71,"result":[{"range":{"start":{"line":389,"character":19},"end":{"line":389,"character":22}},"kind":3},{"range":{"start":{"line":399,"character":11},"end":{"line":399,"character":14}},"kind":2}]}

// Send:
{"jsonrpc":"2.0","id":72,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":399,"character":14},"end":{"line":399,"character":14}},"context":{"diagnostics":[]}}}

// Receive (took 3.169625ms):
{"jsonrpc":"2.0","id":72,"result":[{"title":"Show inferred type annotations","command":{"title":"Show inferred type annotations","command":"jetls.openTypeAnnotation","arguments":["jetls-type-annotation:/type-annotated.jl?source=file%253A%252F%252F%252FUsers%252Faviatesk%252Fjulia%252Fpackages%252Fworktrees%252FJETLS%252Fplacid-wren%252FJETLS%252Fsrc%252Fanalysis%252FAnalyzer.jl&start=15676&stop=16556"]}}]}

// Send:
{"jsonrpc":"2.0","id":73,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":399,"character":14}}}

// Receive (took 1.234396208s):
{"jsonrpc":"2.0","id":73,"result":{"contents":{"kind":"markdown","value":"```julia\n(local) ret :: Compiler.RTEffects  # Core.PartialStruct(Compiler.RTEffects, Any[Any, Any, Compiler.Effects, Core.Const(nothing)])\n```\n"},"range":{"start":{"line":399,"character":11},"end":{"line":399,"character":14}}}}

// Send:
{"jsonrpc":"2.0","id":74,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":399,"character":14}}}

// Receive (took 11.429875ms):
{"jsonrpc":"2.0","id":74,"result":{"contents":{"kind":"markdown","value":"```julia\n(local) ret :: Compiler.RTEffects  # Core.PartialStruct(Compiler.RTEffects, Any[Any, Any, Compiler.Effects, Core.Const(nothing)])\n```\n"},"range":{"start":{"line":399,"character":11},"end":{"line":399,"character":14}}}}

// Send:
{"jsonrpc":"2.0","id":75,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"position":{"line":401,"character":0}}}

// Receive (took 1.098667ms):
{"jsonrpc":"2.0","id":75,"result":[]}

// Send:
{"jsonrpc":"2.0","id":76,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///Users/aviatesk/julia/packages/worktrees/JETLS/placid-wren/JETLS/src/analysis/Analyzer.jl"},"range":{"start":{"line":401,"character":0},"end":{"line":401,"character":0}},"context":{"diagnostics":[]}}}

// Receive (took 4.117459ms):
{"jsonrpc":"2.0","id":76,"result":[]}
```

</details>

---

Release Notes:

- Improved LSP Logs by showing request durations alongside RPC
responses, making slow language server behavior easier to diagnose.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-21 16:55:55 +00:00
counterfactual5
604221dbc7
settings_ui: Fix MCP server toggle not updating in UI (#60552)
Fixes an issue where toggling an MCP server on/off in Settings → AI →
MCP Servers does not update the toggle state in the UI immediately.

## Root Cause

There were two issues:

1. `ContextServerStore::update_server_state()` and `remove_server()`
emitted `ServerStatusChangedEvent` but did not call `cx.notify()`, so
Settings UI observers were not informed to re-render.

2. `render_toggle_switch()` was bound to `is_running` (runtime status)
instead of `is_enabled` (settings state).

## Solution

- Add `cx.notify()` in both methods after emitting the status event.
- Change toggle to read `settings.enabled()` and rename parameter from
`is_running` to `is_enabled`.

## Testing

- `cargo check -p settings_ui -p project` passes.
- `cargo fmt --check` passes.
- Manual verification: open Settings → AI → MCP Servers, toggle a
server, observe immediate UI update.

---

Release Notes:

- Fixed MCP server toggle not updating immediately in Settings UI.

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-07-20 17:08:32 +00:00
Ben Brandt
a0dc9fd13b
acp: Validate registry agent checksums (#61334)
The registry now has optional checksums that we can use.

Release Notes:

- N/A
2026-07-20 13:21:18 +00:00
Sathwik Chirivelli
54fdf58d3a
git_panel: Show staged and unstaged diff stats (#60815)
# Objective

- Show accurate diff stats for each staged and unstaged projection of a
partially staged file in the Git panel.
- This was originally considered for
https://github.com/zed-industries/zed/pull/59884, but was scoped out of
that already-large PR and is being submitted separately as discussed
there.

## Solution

- Collect HEAD-to-index and index-to-worktree diff stats alongside the
existing combined HEAD-to-worktree stats.
- Carry the staged and unstaged stats through repository status
snapshots and remote status serialization.
- Use the stat matching the projected Git panel section while preserving
the combined stat for the other grouping modes.
- Update the fake Git repository and add regression coverage with
deliberately different staged and unstaged counts.

## Testing

- `cargo check -p git_ui`
- `cargo check -p collab`
- `cargo test -p git_ui
test_group_by_staging_section_membership_and_order --lib`
- `cargo test -p project --lib --no-run`
- `cargo fmt --all -- --check`
- `git diff --check`

## 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 diff stats for partially staged files in the Git panel
2026-07-18 19:02:25 +00:00
Jake Abendroth
eb962794a3
buffer_diff: Canonicalize ambiguous hunk placement to fix staging corruption (#60584)
Closes #60424

## Problem

With the repro from #60424, staging the first deletion hunk marked the
second deletion as staged in the UI even though git still had it
unstaged, and clicking the (incorrectly shown) Unstage button inserted a
duplicate copy of the hunk's contents into the git index on every click.

The root cause is ambiguous hunk placement. The committed text contains
repeated `end\n\n` line runs, so the deletion hunks can "slide": more
than one placement produces a minimal diff. The uncommitted diff (HEAD
vs worktree) anchored the remaining deletion at one row while the
unstaged diff (index vs worktree), recomputed after the partial stage,
anchored the same logical deletion at a different row. Everything that
correlates hunks across those two diffs assumes they agree on positions:

- the secondary-status matching in `hunks_intersecting_range_impl` found
no unstaged hunk at the uncommitted hunk's rows and reported it as
staged (`NoSecondaryHunk`);
- the worktree→index projection in `compute_uncommitted_index_edits`
treated the hunk's position as unchanged text and, on unstage, inserted
the hunk's HEAD content at an index position that already contained it,
duplicating it on every request.

## Fix

Upgrade `imara-diff` from 0.1.8 to 0.2.0 and run
`Diff::postprocess_lines` (imara-diff's port of git's xdiff
slider/indent heuristic) after computing hunks in `buffer_diff`. This
canonicalizes the placement of ambiguous hunks based only on their local
content, so diffs of the same buffer against different base texts anchor
the same logical change at the same rows. A bonus is that Zed's hunk
placement now matches `git diff`'s output for such cases (git has used
the indent heuristic by default since 2.11).

As defense in depth, `compute_uncommitted_index_edits` now drops a
pure-insertion index edit whose content is already present at the target
position, so a stale secondary status can no longer duplicate index
content.

The imara-diff 0.2 API removed the `Sink` trait and the top-level
`diff()` function, so the other call sites (`language/text_diff.rs`,
`zeta_prompt/udiff.rs`, `edit_prediction_metrics/reversal.rs`) are
migrated mechanically to `Diff::compute` + `hunks()` with unchanged
behavior (0.2 also renamed `lines_with_terminator` to `lines` and
changed the default `&str` tokenization to include terminators; the
unified-diff builders keep terminator-less tokens via `str::lines()`).

## Testing

- New regression test `test_staging_hunks_with_ambiguous_placement`
replays the exact repro from #60424 (same file contents): stages the
first deletion, asserts the remaining hunks keep their unstaged status
and the index matches exactly, then issues repeated unstage requests for
the unstaged hunk and asserts the index is unchanged. Before the fix
this test showed the second hunk flipping to staged and the index
growing by one copy of the deleted block per unstage request.
- `buffer_diff`, `language`, `zeta_prompt`, `edit_prediction_metrics`,
`multi_buffer`, `git_ui`, `editor`, and the `project` integration suite
pass.
- One test expectation updated: `editor::test_fold_function_bodies`
asserted the old placement of an ambiguous deletion (blank line before
comment); the canonicalized placement (comment before blank line)
matches what `git diff` produces for the same texts.

Release Notes:

- Fixed staging a hunk sometimes marking a different hunk as staged (and
subsequent unstaging corrupting the git index) when the diff contained
repeated lines
([#60424](https://github.com/zed-industries/zed/issues/60424)).

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-18 18:48:49 +00:00
Lukas Wirth
c7148c8190
project: Fix agent hanging indefinitely when pulling workspace diagnostics (#61176)
The agent's diagnostics tool waits on pull_workspace_diagnostics_once,
which enqueues a completion signal into the background workspace
diagnostics refresh loop. When a language server failed to answer
workspace/diagnostic requests, that signal could be stranded, leaving
the agent stuck on 'Check project diagnostics' (reported with logs full
of 'Timeout during workspace diagnostics pull' and requests cancelled
after 120s).

Three hang paths in lsp_workspace_diagnostics_refresh:

1. Timeouts never resolved the completion signal. On
ConnectionResult::Timeout the loop just retried, holding the waiter
through up to 50 attempts x 120s each (~100 minutes) before the sender
was finally dropped.

2. Waiters could queue behind an already-hanging request. The refresh
channel has capacity 1; if the loop was mid-retry (e.g. the initial pull
at server startup was timing out), a newly enqueued waiter sat
unreceived until the entire retry cycle ended.

3. The request timeout was permanently disabled after the first partial
result. The timer raced progress_rx.recv() once and became pending()
forever if progress won, so a server that streamed one chunk and then
stalled hung the request indefinitely.

Fixes:

- On timeout, release all pending waiters (including ones that queued
mid-flight) with refreshed = false, so callers fall back to cached
diagnostics after at most one timeout period while the background loop
keeps retrying.

- Carry waiters as a Vec and absorb refresh requests queued during
backoff/in-flight requests into the current attempt instead of
serializing them behind it.

- Restart the timeout whenever a partial result arrives, turning it into
an inactivity timeout: streaming servers get unlimited total time while
they keep making progress, but a stalled stream now times out instead of
hanging forever.

Adds a regression test with a fake server that never answers workspace
diagnostic pulls, verifying the waiter resolves after the timeout; it
fails with 'Parking forbidden' (infinite hang) without the fix.

Closes FR-124

Release Notes:

- Fixed agents hanging indefinitely if an LSP server never responds to
diagnostics requests
2026-07-17 08:45:02 +00:00
Xin Zhao
c7b43b20b4
project: Persist workspace diagnostics when closing buffer (#59875)
# Objective

Closes #50739

Many language servers have settings for their diagnostic mode, typically
supporting either "single file" mode or "workspace" mode.

In single file mode, the language server only generates diagnostics for
files that the user has open. When a file is closed, those diagnostics
are cleared. This is the behavior currently implemented in Zed.

However, when a language server runs in workspace mode, we should retain
all diagnostics regardless of whether the corresponding file is open or
closed. As reported in #50739, Zed currently discards these diagnostics
when a buffer is closed, just like in single file mode.

When a buffer is completely closed, Zed triggers a diagnostics update to
perform cleanup:

8372eb1b13/crates/project/src/lsp_store.rs (L4747-L4773)
and the Pulled diagnostics are all cleaned, that's why when closing a
buffer, the diagnostic summary disappeared. This process aggressively
clears all `Pulled` diagnostics, causing the diagnostic summary for the
closed file to disappear.

## Solution

Filter the target language servers when updating diagnostics on buffer
close. If a language server has workspace diagnostics enabled, we skip
clearing its diagnostics.

## Testing

Added two new integration tests in
`crates/project/tests/integration/project_tests.rs`:
1.
`test_diagnostic_summaries_cleared_on_buffer_close_without_workspace_diagnostics`:
Verifies that diagnostics are cleared on buffer close when workspace
diagnostics is disabled.
2.
`test_diagnostic_summaries_retained_on_buffer_close_with_workspace_diagnostics`:
Verifies that diagnostics are retained when workspace diagnostics are
enabled. (This test fails on the current `main` branch).

I have also verified this functionality locally. Both local and remote
development environments work as expected.

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

<details>
  <summary>Click to view showcase</summary>

My super cool demos here

</details>

---

Release Notes:

- Fixed workspace diagnostics being cleared when closing a buffer.
2026-07-15 08:43:47 +00:00
Lukas Wirth
f181a2f47b
Split out RelPath into a separate crate (#61029)
This is necessary to remove some `util` dependencies from crates, as
well as better sharing for our projects. This also includes the WIP
AbsPath abstraction as well as some bug fixes from internal tooling.


Release Notes:

- N/A or Added/Fixed/Improved ...
2026-07-15 08:33:25 +00:00
Mikayla Maki
e9d6cd2f05
Open gitignored subdirectories as their own workspace (#60918)
# Objective

Let's git ignored directories be opened as their own project


## Solution

- Add an "ignored dir" carve out when checking project collision

## Testing

- Added tests

## Self-Review Checklist:

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

---

Release Notes:

-
2026-07-14 15:34:30 +00:00
David Wu
60314a7416
Open non-writeable files in Capability::Read mode (#57202)
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>
2026-07-10 09:50:19 +00:00
Om Chillure
b2db24e58a
Fix MCP servers in multi root workspaces (#52849)
### Closes #51951

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

#### Note : Reopens previous work from closed PR
https://github.com/zed-industries/zed/pull/52161 (fork was deleted)

## Video 

[Screencast from 2026-03-22
23-26-06.webm](https://github.com/user-attachments/assets/ab68e47a-7e74-4f1e-991d-8ca4fed7952c)


## Release Notes:

- Fixed MCP servers from `.zed/settings.json` not being discovered when
multiple project folders are open in a workspace.

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
2026-07-10 09:13:45 +00:00
Keith Hall
6b733d1058
search: Bump fancy-regex dependency and enable CRLF mode (#55471)
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 #43396

Release Notes:

- Project search now supports CRLF line endings correctly, as well as
other regex features like subroutine calls
2026-07-08 16:56:45 +00:00
Ibrahim Khan
2243c13b9b
project: Fix content swap when an LSP rename also renames the file (#59104)
A "rename symbol" whose workspace edit also renames the file (a
`TextDocumentEdit` followed by a `RenameFile` resource operation) only
applied the text edit to the in-memory buffer. The on-disk file still
held the pre-edit content, so the blind `fs.rename` moved stale bytes to
the new path while the edited buffer was stranded at the old path,
swapping the two files' contents.

This persists a dirty buffer for the rename source before renaming, so
the new file receives the edited content and the now-clean buffer can't
be saved back to the old path.

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

Closes #59077

Release Notes:

- Fixed a symbol rename that also renames the file swapping the contents
of the old and new files
2026-07-08 12:21:10 +00:00
drbh
c31b2b0dc7
Git partially staged changes (#46541)
This PR explores the addition of a new feature and UI to improve
visibility into partially staged commits.

Currently, the Git panel shows tracked and untracked changes, but it
does not clearly distinguish between staged and unstaged changes.

As a result, it’s difficult to quickly see which changes are not staged
in the current UI. Both staged and unstaged changes are combined into
the `Uncommitted Changes` multibuffer. This developer experience differs
from other editors, most notably VS Code; which presents separate Staged
Changes and Changes lists.

### Staged and unstaged diffs in multibuffers

This PR introduces an alternative UI for unstaged changes that aligns
with the overall Zed experience. Instead of showing changes on a
per-file basis, staged and unstaged diffs are each displayed in their
own multibuffers, similar to how `Uncommitted Changes` currently works.

For example the following screenshot shows the current `Uncommitted
Changes` on the left, the `Staged Changes` in the middle and the
`Unstaged Changes` buffer on the right for comparison

<img width="1408" height="859"
src="https://github.com/user-attachments/assets/aa709f7a-041d-4cb1-95d6-84c0f5fff688"
/>

### Indicators/interactions

The new multibuffers can be opened in two ways:

1. Via a new `U` chip, which appears when a file has unstaged changes
2. Via new menu options

(See screenshots below for both interaction paths.)


<table>
  <tr>
    <td style="text-align: center; vertical-align: top;">
      <p>via the chip</p>
      <img
        height="400"

src="https://github.com/user-attachments/assets/3ef69f02-b787-499c-959a-25f50b3728e8"
        alt="Via the chip"
      />
    </td>
    <td style="text-align: center; vertical-align: top;">
      <p>via the menu</p>
      <img
        height="400"

src="https://github.com/user-attachments/assets/f5be8b6d-ccdc-4420-bd29-75570b558016"
        alt="Via the menu"
      />
    </td>
  </tr>
</table>

### Design goals
- minimally intrusive UI changes (small new badge and menu items)
- adhere by Zed'ism (use multibuffer where possible)
- avoid disabling any current interactions (Uncommitted Changes ui is
unchanged)
- avoid introducing an app level view mode (no new settings needed)

### Experience goals
- make it easy to see what changes are not staged
- make it easy to see that a file has unstaged changes (avoid developers
accidently leaving out changes in a commit; a personal issue that I have
when using Zed)
- elegantly handle large file's unstaged changes (follows the same
collapse and expanding seen in `Uncommitted Changes`)

### How to try

- Clone the repo and run `cargo run`
- Make a change to a file and stage it
- Make another change to the file (the `U` indicator will appear)
- Click the `U` to see the unstaged view

### Open questions/rough edges
- [ ] determine if this user experience is useful for others
- [ ] ensure all interactions work as expected (response to all update
cases)

In general I'm really interested in hearing the community's feedback
about this interface, more than happy to make any changes or explore a
different solution!

### Related issue:
- https://github.com/zed-industries/zed/pull/36646
- https://github.com/zed-industries/zed/issues/26560

Release Notes:

- Support partially staged commit multibuffers via a staged and unstaged
changes view.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-07 06:55:29 +00:00
bgfraser
12e1e24434
Initiate MCP OAuth flow on post-initialize 401 responses (#60236)
MCP servers may accept `initialize` unauthenticated but return `401`
with a `WWW-Authenticate` challenge only on a later request such as
`tools/list` or `tools/call`. Previously Zed only started the Auth flow
when `initialize` itself was challenged, so these servers failed
opaquely and stayed stuck in `Running` with a dead client.

`ContextServerStore` now handles `TransportError::AuthRequired` returned
from any request, not just startup: it runs Auth discovery and
transitions the server into `AuthRequired` so the UI offers to
authenticate. The discovery logic is shared with the startup path, and
the tool/prompt request sites route their errors through it.

Release Notes:

- Fixed MCP servers that require auth only on tool calls (not on
`initialize`) failing to prompt for authentication.

---------

Co-authored-by: Tom Houlé <tom@tomhoule.com>
2026-07-03 18:24:54 +00:00
Anant Goel
ea87b05794
Fix worktree grouping for bare checkouts (#59968)
Summary

- Track whether a worktree root is itself a linked Git worktree.
- Use that metadata when computing project group keys so bare checkout
worktrees group under the repository identity path.
- Propagate the metadata through remote worktree protocols and add
local/remote regression coverage.

Background

Bare checkout layouts can place linked worktrees under the repository
identity directory, e.g. `/monty/.bare` with worktrees like
`/monty/feature-a`. We were treating those linked worktree paths as
separate project identities, which caused the sidebar to move agent
threads under the active worktree instead of the shared repository
group.
We also exclude adding this to collab intentionally, we can open a
different PR for that if we need to.

Closes #59910
Closes AI-431

Test Plan

- `cargo fmt --package project --package worktree --package
remote_server --package workspace --package collab --package proto`
- `git --no-pager diff --check`
- `cargo test -p project test_project_group_key -- --nocapture`
- `cargo test -p remote_server test_remote_root_repo_common_dir --
--nocapture`
- `cargo test -p worktree remote_worktree -- --nocapture`
- `cargo test -p workspace
test_remote_project_root_dir_changes_update_groups -- --nocapture`
- `cargo check -p collab`

Self-Review Checklist:

 I've reviewed my own diff for quality, security, and reliability
 Unsafe blocks (if any) have justifying comments
The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
 Tests cover the new/changed behavior
 Performance impact has been considered and is acceptable

Release Notes:

- Fixed agent thread/sidebar grouping for Git worktrees backed by bare
checkouts.

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
2026-07-02 18:14:11 +00:00
Bing Wang
33473c1cd3
git_panel: Fix stale Git status entries for moved directories (#59934)
# Objective

Fix stale Git status entries for moved directories

## Solution

Coalesce changed paths before scanning and remove cached descendant
statuses when a directory disappears from the current status set.



## 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 stale Git status entries for moved directories
2026-06-29 02:54:40 +00:00
Kirill Bulatov
7582bf7434
Allow empty values in .editorconfig (#60026)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
Closes https://github.com/zed-industries/zed/pull/59559
Closes https://github.com/zed-industries/zed/issues/59466

Release Notes:

- Fixed incorrect parsing of .editorconfig with empty values
2026-06-28 16:15:20 +00:00
Artem Kalytiuk
2a93ca53fd
Handle dynamic registration of semantic tokens capability (#60015)
In C# files nothing gets semantic highlighting — class fields and other
identifiers are colored by tree-sitter only, so a private field looks
the same as a plain local variable.

The reason: Roslyn (the C# language server) doesn't declare
`semanticTokensProvider` statically in its `initialize` response. It
registers it **dynamically** (`client/registerCapability`), and only
when the client advertises
`textDocument.semanticTokens.dynamicRegistration = true`. Zed advertised
`false` and didn't handle such a registration, so Roslyn never offered
semantic tokens at all. (rust-analyzer/gopls are unaffected — they
declare the capability statically.)

This is the first of two PRs. This one makes Roslyn actually **send**
semantic tokens. The companion PR (#60027) maps Roslyn's C#-specific
token types to theme styles — without it the tokens arrive but most are
dropped, since their types aren't in Zed's default rules.

## Solution

- Advertise `textDocument.semanticTokens.dynamicRegistration = true`.
- Handle the `textDocument/semanticTokens` registration and
unregistration so the capability is stored, following the existing arms
for `documentLink`, diagnostics, etc.

## Testing

- Added a test that dynamically registers and unregisters
`textDocument/semanticTokens` and checks the stored capability appears
and is cleared.
- Verified manually against Roslyn on a C# project: Zed now sends
`textDocument/semanticTokens/full` and gets tokens back; before this
change there was no semantic-token traffic at all.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Support dynamic registration of the `textDocument/semanticTokens`
capability.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 13:48:10 +00:00
Kunall Banerjee
438070b1cf
languages: Fix Debug Test for Go subtests (#53680)
The `go-subtest` task template wrapped the `-run` arg in single quotes
for shell safety. This works for Run Test (terminal strips quotes), but
Debug Test sends the arg through Delve’s DAP protocol with no shell
involved, so the literal quote characters ended up in the regex and
prevented any match.

All other Go task templates (`go-test`, `go-testify-suite`,
`go-table-test-case`) use the backslash-escaped format which `GoLocator`
already knows how to handle. Align the `go-subtest` template to the same
format.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #53230.

Release Notes:

- Fixed Debug Test for Go subtests

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-06-23 11:10:05 +00:00
guopenghui
f6bfa0915f
Add named bookmark support (#57491)
Adds support for named bookmarks while preserving the existing unnamed
bookmark workflow.

Main changes:
- Keeps `ToggleBookmark` as the quick unnamed bookmark action.
- Adds `ToggleNamedBookmark`, which prompts for a bookmark name when
adding a new bookmark and removes an existing bookmark on the same line,
including unnamed ones.
- Adds `EditBookmark` support for renaming existing bookmarks.
- Persists bookmark names in workspace storage.
- Adds a project bookmarks picker that supports filtering by bookmark
name and relative path, with highlighted matches.
- Updates bookmark storage and tests to carry bookmark names through
serialization, restoration, navigation, and project-level listing.

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

Video
toggle:


https://github.com/user-attachments/assets/a725b9cf-ac37-4ebc-85cc-ee820452c043

rename:


https://github.com/user-attachments/assets/a6d0d0c1-511b-4fb7-ae5d-22c55d1a075f


Release Notes:

- Add named bookmark support

---------

Co-authored-by: Yara 🏳️‍⚧️ <git@yara.blue>
2026-06-22 20:47:44 +00:00
Dan Dascalescu
10628c3d2c
agent_ui: Add in-thread search bar (#57231)
This is a narrower alternative to #54816, scoped to search only the
currently-loaded thread, excluding tool output or thinking blocks (happy
to follow up on those, see next). It uses a custom bar confined to
`agent_ui` rather than `BufferSearchBar` + `SearchableItem`, avoiding
the cross-crate plumbing that #54816 reached. Open as draft pending
direction from @benbrandt on what scope/approach would be acceptable for
in-thread search.

<img width="959" height="609" alt="image"
src="https://github.com/user-attachments/assets/8971e432-61d3-46db-a6a4-2bbd355089e7"
/>


## What this PR does

Adds a search bar to the agent panel, triggered by Ctrl+F (Cmd+F on
macOS), that lets users grep the currently-loaded thread without leaving
the agent panel; not cross-thread or cross-agent.

- Searches visible content only: user messages, assistant message
chunks, and tool-call labels. Thought blocks and rendered tool-call
content (collapsed by default) are intentionally skipped so that:
  1. The visible match count matches what the user sees.
2. The search experience is consistent between tool output blocks in the
current Zed session, ans tool output blocks from past sessions, which
are not rendered - see issue #57230
- Highlights matches inline via `Markdown::set_search_highlights` for
markdown-rendered content and
`Editor::highlight_background(HighlightKey::BufferSearchHighlights, …)`
for past user messages (rendered through `MessageEditor`'s inner
`Editor`, not through markdown).
- Next/prev navigation, case/whole-word/regex toggles (same UI as
`BufferSearchBar`).
- Returns focus to the message editor on dismiss so the user can keep
typing immediately.

<details><summary>Commits (authored by Claude 4.7 Opus, max)</summary>

### Seven logical commits

1. **`agent_ui: Add in-thread search bar`** — initial implementation:
bar UI, keymap bindings under `AcpThreadSearchBar` context, markdown
highlight plumbing, focus-restore on dismiss.
2. **`agent_ui: Add unit tests for in-thread search`** — coverage of the
matcher across entry kinds and the dismiss-clears-highlights path.
3. **`agent_ui: Limit search to visible tool-call text`** — UX fixes
from manual testing: `track_focus` so `AcpThreadSearchBar` context lands
in the editor's dispatch chain; red border on zero-match query; skip
tool-call content (only search labels).
4. **`agent_ui: Fix Esc dispatch, smart toggle, error message, skip
Thought blocks`** — round 2 of UX fixes: contribute `AcpThreadSearchBar`
context from `ThreadView` when bar is visible, smart Ctrl/Cmd+F
outside-the-bar focuses instead of closing, regex error message row,
skip `AssistantMessageChunk::Thought`.
5. **`agent_ui: Polish thread search bar — Esc routing, user-message
highlights, action forwarding`** — `search::*` action forwarders on
`ThreadView`; `cx.defer` around the activate callback (fixes a
double-borrow panic); `editor::actions::Cancel` interception so Esc
dismisses our bar instead of escaping to the workspace's
`BufferSearchBar`; user-message highlights via the inner `Editor`; muted
zero-match counter; three new gpui regression tests.
6. **agent_ui: Fix Shift+Enter shadowing in thread search bar`** —
capture-phase intercept of `editor::Newline*` on the bar's `bar_row`
element so a base keymap binding `shift-enter` at the `Editor` context
(e.g. JetBrains → `editor::NewlineBelow`) can't shadow the bar's
`agent::SelectPreviousThreadMatch`. Adds a regression test that loads
`default-linux.json` + `linux/jetbrains.json` and asserts `shift-enter`
navigates instead of inserting a newline.
7. `agent_ui: Debounce thread search, refresh on thread changes,
highlight user messages`** — last round before maintainer review: 150 ms
debounce on the match rescan; subscribe to `AcpThread` updates so
results/highlights/counter follow a streaming conversation live;
navigate the list to the entry owning the active match; `.ok()` instead
of `let _ =`; assorted cleanups; two new regression tests
(`test_thread_search_refreshes_on_new_thread_entry`,
`test_thread_search_scrolls_to_later_user_message_match`).
</details>

8 gpui tests cover the load-bearing logic (`cargo test -p agent_ui --lib
-- thread_search`). All pass.

## Manual testing

Verified on Linux against `upstream/main` `13e7c11768` (full `release`
profile, with LTO and `codegen-units=1` built and tested at that
commit). Branch since merged with `upstream/main` `a6780a5`. Of the 100
intervening upstream commits, several touch files in this diff; one
produced a real conflict in `crates/agent_ui/src/conversation_view.rs`
(`gpui::{...}` import block — both sides added new, non-overlapping
symbols; resolved by union).

- Bar opens / dismisses via Ctrl+F and Esc
- Next/prev navigation via Enter / Shift+Enter / F3 / Shift+F3 / chevron
buttons
- Case / whole-word / regex toggles via buttons and via Alt+C / Alt+W /
Alt+R (Linux)
- Highlights inside past user messages render correctly on the
`MessageEditor`'s inner `Editor`
- query text turns red on no-match; bad regex shows error message;
zero-match counter stays muted (not red)
- `search::*` actions fire from outside the bar (focus in message
editor) via the `ThreadView`-level forwarders
- Workspace pane `BufferSearchBar` is unaffected; the two bars hold
independent state
- Feature looks great in light mode and dark mode, and with various
themes
- Navigating to a match in a past user message scrolls that message into
view (its top to the viewport top)
- Results update live as the agent streams new messages while the bar is
open (debounced ~150 ms, same for typing)

[Zed agent thread search subscribe to thread
updates.webm](https://github.com/user-attachments/assets/75585fee-ba25-42ac-9dde-16c8e152fb06)

<details><summary>Full manual test plan</summary>

### Setup (preconditions for every test below unless otherwise noted)

1. Launch the dev binary: `./target/release-fast/zed --user-data-dir
~/.local/share/zed-dev-feat`
2. Open the agent panel, start a thread, send 2–3 prompts so the thread
contains:
- At least one user prompt with a distinctive substring (e.g.
`watermelon`)
   - At least one assistant message with a distinctive substring
   - At least one tool call with a known label substring
   - At least one collapsed Thinking block
3. In parallel: have at least one code editor open in a workspace pane
(some tests cross-check that path).

### Core matching

#### T-001 — Ctrl+F opens the bar with focus in query

**Status:**  PASS 2026-05-15 15:30

**Repro:** With focus in the agent panel's message editor, press Ctrl+F
(Linux) / Cmd+F (macOS). The search bar appears at the top of the thread
view and the query input is focused.

#### T-002a — Active match visually distinct from inactive matches

**Status:**  PASS 2026-05-15 15:30

**Repro:** Type a query that produces ≥3 matches. The current ("active")
match must be visually different from the others — different highlight
color, not just position. If they look identical, this may be a theme
issue (`search_active_match_background` vs `search_match_background` too
close on the entry's background); note the theme.

#### T-002b — User-prompt text gets inline highlight, not just match
count

**Status:**  PASS 2026-05-15 17:15 (fix shipped 2026-05-15 16:15;
regression-guarded by
`test_thread_search_highlights_user_message_editor`)

**Repro:** Send a user prompt containing a distinctive substring. Then
search that substring. The user prompt text **must** show yellow
highlight, not just be counted. The bar's matcher reads from
`message.content.markdown()` but the on-screen render goes through a
`MessageEditor`; the current code only highlights via
`Markdown::set_search_highlights`, which misses the editor.

**Notes:** Fix routes user-message matches through
`Editor::highlight_background(HighlightKey::BufferSearchHighlights, …)`
— the same path `Editor`'s own `SearchableItem` impl uses.
`collect_markdowns` no longer pulls the user message's markdown
(avoiding double-counting). The bar now maintains separate
`highlighted_markdowns` and `highlighted_editors` lists for clean-up.
Match-target enum (`MatchTarget::Markdown` vs `MatchTarget::Editor`)
tags each match so active-vs-inactive re-paint can dispatch correctly.
Pending runtime verification on next `release-fast` build.

#### T-003 — Enter / Shift+Enter in bar navigates matches

**Status:**  PASS 2026-05-25 14:00 (verified on `release` build)

**Repro:** With focus in the query, type a query with ≥3 matches. Press
Enter → counter `1/N → 2/N → 3/N`. Press Shift+Enter → reverses (and no
`\n`s are output in the search box). F3 / Shift+F3 same.

### Option toggles

#### T-004 — Alt+C toggles case sensitivity from inside bar

**Status:**  PASS 2026-05-15 07:50

**Repro:** With focus in query, press Alt+C. `Aa` button toggles state;
results re-filter.

#### T-005 — Alt+W toggles whole-word from inside bar

**Status:**  PASS 2026-05-15 15:30

**Repro:** Same as T-004, with Alt+W toggling `wd` button.

#### T-006 — Alt+R toggles regex from inside bar (Linux)

**Status:**  PASS 2026-05-15 15:30 (fix shipped 2026-05-15 06:35)

**Repro:** Press Alt+R. `.*` button toggles.

**Notes:** macOS keymap (`alt-cmd-x`) left unchanged in this session —
it matches the wider macOS Zed convention.

#### T-006a — Tooltips on toggle buttons show their hotkey

**Status:**  PASS 2026-05-15 15:30

**Repro:** Hover each toggle button (`Aa`, `wd`, `.*`). Tooltip shows
action name AND keybinding (e.g. "Toggle Case Sensitive · Alt+C").

### Error / empty states

#### T-007 — Empty matches: no red border on bar input

**Status:**  PASS 2026-05-15 15:30

**Repro:** Type `zzzzzzz`. Query text turns red. Counter shows `0/0`.
Bar input border stays **neutral**, no red box.

#### T-008 — Bad-regex error message

**Status:**  PASS 2026-05-15 15:30 (error renders aligned with the
input)

**Repro:** Switch to regex mode, type `[`. Error message appears below
bar, aligned with the input.

#### T-019 — Zero-match counter not colored red

**Status:**  PASS 2026-05-15 15:30 (fix shipped 2026-05-15 06:30)

**Repro:** Type a query with no matches. The counter (`0/0`) stays
muted, **not** red. MPS-parity.

### Dismissal & re-entry

#### T-009 — Esc doesn't interrupt agent generation

**Status:**  PASS 2026-05-15 15:30

**Repro:** Start a long prompt; while the agent is generating, open the
search bar and press Esc. Bar closes, generation continues.

#### T-010 — Close-X button position

**Status:**  PASS 2026-05-15 15:30

**Repro:** Look at the bar. Close (X) button is on the right side, after
the nav arrows (`<` `>` `1/N` `X`). NOT free-floating left of the input.

#### T-011 — Ctrl+F in bar selects all query text

**Status:**  PASS 2026-05-15 15:30

**Repro:** With bar open and query containing text, press Ctrl+F. All
query text becomes selected (next keystroke replaces).

#### T-012 — Ctrl+F outside the bar (bar already open) does not crash

**Status:**  PASS 2026-05-15 15:30 (fix shipped 2026-05-15 06:30;
regression-guarded by
`test_thread_search_select_next_from_thread_view_update_does_not_panic`)

**Repro:** Bar visible, focus in the message editor (not the bar). Press
Ctrl+F. Bar gets re-focused, query text is selected. **Must not crash.**

**Notes:** Original crash also reproducible from Enter / Shift+Enter
inside the bar after a search had matches. Fix wraps the
`on_activate_match` callback's `view.update` in `cx.defer`.

#### T-021 — Esc dismisses agent bar (not the unrelated workspace pane's
BufferSearchBar)

**Status:**  PASS 2026-05-15 15:30 (fix shipped 2026-05-15 14:40;
regression-guarded by `test_thread_search_editor_cancel_dismisses_bar`)

**Repro:** Open a file in a workspace pane editor (e.g.
`settings.json`). Open BufferSearchBar there. Switch focus to the agent
panel, open agent search bar, type a query. Press Esc. **The agent bar
must dismiss; the workspace pane's BufferSearchBar must remain.**

**Notes:** Root cause: `Editor::cancel` in single-line mode calls
`cx.propagate()`. The propagated `editor::actions::Cancel` walked past
our bar all the way to `Workspace`, where `BufferSearchBar::register`
had registered a workspace-wide handler that dismissed the active pane's
bar. Fix: `ThreadView` now catches `editor::actions::Cancel` when the
bar is visible.

### Action routing while bar is open, focus is in the message editor

#### T-013 — F3 / Shift+F3 from outside the bar

**Status:**  PASS 2026-05-15 15:30 (Enter from outside is *expected*
not to work — message editor's `enter` binding outranks. F3 is the
canonical out-of-bar nav key.)

**Repro:** Bar open with matches, focus in message editor. Press F3 →
next match. Shift+F3 → previous.

#### T-014 — Alt+C / Alt+W / Alt+R from outside the bar

**Status:**  PASS 2026-05-15 15:30 (fix shipped 2026-05-15 02:30;
`ThreadView` forwarders for `search::ToggleCaseSensitive`,
`ToggleWholeWord`, `ToggleRegex`, `FocusSearch`)

**Repro:** Bar visible, focus in message editor. Alt+C/W/R toggles the
bar's options and re-runs search.

### Nav buttons

#### T-022 — `<` / `>` chevron buttons in the bar advance match

**Status:**  PASS 2026-05-15 15:30

**Repro:** With ≥2 matches, click `<` → previous. Click `>` → next.
Wraps at ends.

### Coexistence with workspace-pane buffer search

#### T-015 — Ctrl+F in a workspace-pane editor still opens
`BufferSearchBar` (no agent-panel takeover)

**Status:**  PASS 2026-05-15 15:30

**Repro:** Focus a code editor in a workspace pane, press Ctrl+F. The
pane's `BufferSearchBar` opens as before; agent panel's bar does NOT
open.

#### T-016 — Independent bars: agent vs workspace pane

**Status:**  PASS 2026-05-15 15:30

**Repro:** Have both bars open simultaneously. They hold independent
state (different queries, different toggles, independent dismissal).

### Tool-call content (auto-expand on match)

#### T-017 — Auto-expand collapsed tool calls on match

**Status:** ⏸️ BLOCKED (not implemented; out of scope for current
session)

**Repro:** Have a tool call whose collapsed content contains a unique
substring. Search that substring. The tool call auto-expands so the
match is visible. After dismissal, the tool call collapses again unless
the user manually expanded it before.

#### T-018 — Auto-expand collapsed Thinking blocks on match

**Status:** ⏸️ BLOCKED (not implemented; out of scope for current
session)

**Repro:** Same shape as T-017 for a collapsed Thinking block.

#### T-019 — Streaming results automatically highlighted / live thread
search

**Status:**  PASS 2026-06-08

**Repro:** Send prompt "Write a 5-paragraph story about a researcher who
hated noise. The last paragraph should be a one-sentence: "So she moved
to <name of the quietest continent on Earth>" (replace that <name> with
the actual name)", then search for `Antarctica`.
</details>


## Known limitations

1. (pre-existing, not from this PR): search highlights inside markdown
table cells can be visually offset by a few characters in columns
starting with the second. The bug lives in `crates/markdown`'s render
layer - see issue #57229
2. (excluded vs. #54816 to keep the scope tight): raw tool-call
input/output JSON and terminal scrollback are not indexed.
3. Navigating to a search hit located **below the fold of a very long
user message** highlights the match but only scrolls the message's top
into view, so the hit can stay off-screen until you scroll manually.
Past user messages render through an `AutoHeight` `Editor` inside a
virtualized `List`, which can't reliably drive intra-entry autoscroll
the way markdown content does. User messages are usually shorter than a
viewport, so this is left unaddressed.
4. Plain-text search across triple-backtick fences does not match (the
fence characters live in the markdown source; regex search with explicit
fence handling does).
5. The literal text "Thinking" rendered as the thought-disclosure header
is not searchable (rendered chrome, not markdown source).



Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- No new `unsafe` introduced; no network, file-system, or process APIs
touched; only added dep is `search` (promoted from dev-dep to runtime),
already used by this crate's tests; `MessageEditor::editor()` accessor
widening is `pub(crate)` (in-crate only). Assessment: no new attack
surface.
- [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)
— partially; see "What I did NOT verify" above
- [ ] I did not verify **macOS and Windows**. Keymap entries exist for
all three platforms (`AcpThreadSearchBar` context bindings) but I only
verified Linux at runtime.
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable:
regexp-searching for "t.e" in a thread almost at the context limit (919k
tokens) felt instant, and navigation among the 2100+ results occurred at
the keyboard autorepeat rate.
   - [ ] Haven't measured against the 8ms / 120fps frame budget.

Partially closes #39338

Release Notes:

- Added in-thread search to the agent panel (Ctrl/Cmd+F)

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2026-06-18 13:00:24 +00:00
Alisina Bahadori
45afbac0a5
Fix project grouping for Git repo subdirectories (#57998)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
  - No unsafe blocks added.
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- No new UI components; behavior better matches user intent for opened
folders.
- [x] Tests cover the new/changed behavior
  - Added sibling-subdirectory project group regression coverage.
- Extended subfolder Git-status test to ensure Git still uses the parent
repo while project identity stays at the opened folder.
- [x] Performance impact has been considered and is acceptable
- Change adds one small enum/optional field check when computing
worktree paths; no meaningful performance impact expected.

Closes #57997

Release Notes:

- Fixed project grouping for opened subdirectories that share the same
parent Git repository.

## Screenshots

### Before
<img width="334" height="224" alt="Screenshot 2026-05-28 at 5 29 55 PM"
src="https://github.com/user-attachments/assets/ad5b13c5-11a7-4fa4-a074-a519521641da"
/>
<img width="485" height="201" alt="Screenshot 2026-05-28 at 5 28 36 PM"
src="https://github.com/user-attachments/assets/9cd2c138-92f5-4ff2-bf8f-21cdbeff0b79"
/>

### After

<img width="343" height="253" alt="Screenshot 2026-05-28 at 5 29 40 PM"
src="https://github.com/user-attachments/assets/56a4dca7-f0a1-4530-8c89-3c4773b90486"
/>
<img width="420" height="206" alt="Screenshot 2026-05-28 at 5 29 22 PM"
src="https://github.com/user-attachments/assets/d118340a-955e-4483-9888-4b566f59b931"
/>

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
2026-06-17 01:53:23 +00:00