2e2fb0a21811ce2dbaca5bb738b0be8f94de051e
3305
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
a0dc9fd13b |
acp: Validate registry agent checksums (#61334)
The registry now has optional checksums that we can use. Release Notes: - N/A |
||
|
|
a9a7cdd54c |
branch_picker: Add remote icons and fix edge cases (#61215)
# Objective Make the branch picker easier to scan and ensure branch creation and remote icons behave consistently across All, Local, and Remote filters. ## Solution - Group local and remote branches under their own headers in the All filter. - Place the create-branch option above branch sections when there is no exact branch-name match. - Resolve each remote's hosting provider from its URL and show the provider icon for branches from that remote. - Include remote URLs in remote-workspace repository responses so arbitrary remote names work without hardcoding `origin` or `upstream`. ## Edge Cases Fixed - An exact branch can exist outside the active Local or Remote filter. The picker now checks all branches before offering to create a duplicate branch. - A non-exact search can return fuzzy branch matches and a create action. The create action now stays at the top, before the Local and Remote section headers. - When a filtered search has no branch matches, the create action is shown without incorrectly placing it under a Local Branches or Remote Branches header. - Repositories can use any remote name, not only `origin` and `upstream`. Provider icons are resolved independently for every configured remote. - Remotes hosted on an unknown or unsupported forge use the generic server icon instead of implying a desktop or a specific provider. - Remote-workspace repositories carry the same remote-name-to-URL data as local repositories, so their branch icons follow the same provider-resolution path. ## Testing - `cargo check -p git_ui --no-default-features` - Branch picker test suite (17 tests) - `git diff --check` Tested on macOS. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase <img width="560" height="522" alt="Screenshot 2026-07-17 at 11 19 27 PM" src="https://github.com/user-attachments/assets/28d57315-b859-4a8d-86ca-53f9fb513bf5" /> The updated branch picker groups local and remote branches, keeps the create-branch action above those sections, and shows forge-specific icons for remote branches. --- Release Notes: - Improved branch picker filtering, grouping, branch creation suggestions, and remote-provider icons. |
||
|
|
f14fea9bf3 |
zed: Log worktree info when memory jumps unexpectedly (#61283)
Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
edeaf598c7 |
project: Add remote support for adding paths to .gitignore (#56368)
Release Notes: - Fixed remote support for adding paths to .gitignore The problem solved by this PR is: when opening a remote project, right-clicking a new file in the git panel and clicking "Add to .gitignore" does not work. --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
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 |
||
|
|
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> |
||
|
|
c9e8e611db |
lsp: Set workspace folder names (#60938)
# Objective Fixes #60518. Zed sends an empty `name` for entries in `initialize.params.workspaceFolders`. Language servers such as basedpyright use this field to identify workspace service instances, resulting in an unnamed instance. ## Solution Derive each workspace folder name from its URI, preferring the decoded filesystem basename. For basename-less URIs, fall back to a non-empty path, URI path segment, or the full URI. Use the same construction for initialization parameters, dynamic workspace-folder notifications, and `workspace/workspaceFolders` responses so all LSP messages remain consistent. ## Testing - `cargo fmt --all -- --check` - `cargo test -p lsp` - `cargo check -p project --all-targets --all-features` - `./script/clippy -p lsp` - `./script/clippy -p project` Reproduced with basedpyright 1.39.9 over an LSP stdio session. Before this change it logged: ```text Starting service instance "" ``` With a derived workspace folder name it logged: ```text Starting service instance "zed-60518-project" ``` Tested on macOS. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed language servers receiving empty workspace folder names. |
||
|
|
858d3172a8 |
debugger: Don't eagerly fetch variables for expensive DAP scopes (#61144)
# Objective Zed eagerly fetches variables for every scope returned by a DAP `scopes` response, including scopes the adapter marked `expensive: true`. Per the [DAP spec](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Scope), `expensive` means "the number of variables in this scope is large or expensive to retrieve... recommended for UIs to not automatically expand and evaluate the scope. Some debug adapters (e.g. `vscode-js-debug`, used for JavaScript/Chrome debugging) mark scopes like "Global" as expensive because resolving them can hang forever. VS Code honors this and leaves the scope collapsed until the user opts in by expanding it; Zed did not, so any session with a hanging expensive scope would freeze the entire debug session (including Resume) with no user action at all. Fixes #61105 ## Solution - `Session::scopes()` in `crates/project/src/debugger/session.rs` [unconditionally called `this.variables(...)`](https://github.com/zed-industries/zed/blob/058f01fa93503491a735bfded53e77bfaa276148/crates/project/src/debugger/session.rs#L2538) for every scope in the `scopes` response. - `VariableList::build_entries()` in `crates/debugger_ui/src/session/running/variable_list.rs` also called `session.variables(...)` [on every scope](https://github.com/zed-industries/zed/blob/058f01fa93503491a735bfded53e77bfaa276148/crates/debugger_ui/src/session/running/variable_list.rs#L291-L304), as a side effect of checking whether it was empty (used to decide whether to hide it from the tree). Fixing only the first call site wasn't enough, since this one would still trigger the fetch on the very next render. Both now skip the fetch for `expensive` scopes. Expensive scopes still show up in the variable list, collapsed, so the user can expand them manually (which fetches lazily via the existing on-toggle path). Also hardened the auto-expand heuristic (e.g. "expand the only scope if it's not Locals") to never auto-expand an expensive scope, even in adapters where it happens to be the sole or "Locals"-named scope. ## Testing - Added `test_expensive_scope_is_not_eagerly_fetched` in `crates/debugger_ui/src/tests/variable_list.rs`, asserting the DAP `variables` request is never sent for an `expensive: true` scope until the user expands it, and that expanding it does trigger the fetch. Verified this test fails on the old code and passes with the fix. - Ran the full `debugger_ui` test suite, all pass, no regressions. - Manually reproduced and verified the fix using the minimal repro at https://github.com/jasonwilliams/zed-dap-repro ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase Before: https://github.com/user-attachments/assets/7a3ead7e-aece-4726-883d-d60d49c83b7c Here you can see that once the break has happened Zed has crashed, resuming doesn't help, i effectively need to kill the whole debug session. After: https://github.com/user-attachments/assets/7a36cbb0-f22b-4782-9326-9ccab9297fc7 Here you can see the Global scope is closed and clicking resume carries on without any crashes Release Notes: - Fixed debugger eagerly fetching expensive variable scopes --------- Co-authored-by: Anthony Eid <anthony@zed.dev> |
||
|
|
2a983bca86 |
git: Fix operations timing out and commit-msg hook being skipped (#61185)
Closes #44926 Closes #43157 Closes #29903 We have an askpass 17s timeout that races against Git operations and results in "Connecting to host timed out". It came along in #25953 when we extracted askpass out of remoting, where it was used for SSH. I think, for SSH connection, no prompt and no connection after 17 seconds means the host is unreachable, so the timeout is a reliable signal there. But for Git, silence is pretty normal. Cases like hook running, pack transferring, an ssh-agent waiting on a fingerprint are all senarios where we should not be dependent on timeout which kills these healthy operations. #43285 worked around this for commits by running the pre-commit hook manually and passing `--no-verify` to `git commit`. But, there are more problems to address, which I reproduced on my machine: 1. A slow `post-commit` hook fails, since `--no-verify` doesn't skip it. 2. A slow `pre-push` hook fails too, and a workaround like #43285 needs a lot more handling. See https://github.com/zed-industries/zed/pull/42946#issuecomment-3550570438. 3. This is the tough one: due to `--no-verify`, we are also skipping the `commit-msg` hook. There is no direct way to call that hook since, Git hands this hook its in-progress message file, commits whatever the hook leaves in it, and aborts if the hook exits non-zero. Reproducing that outside `git commit` means reimplementing that. 4. An ssh-agent waiting for user approval fails after the timeout, like if you have 1Password set up. 5. It doesn't solve large fetches. Fetching `git@github.com:torvalds/linux.git` just dies at the 17s timeout mid-download. This PR fix keep the timeout only on the SSH transport and drop it for Git, which is less of a behavior change and more of a restoring its original scope. If Git in a terminal doesn't time out, we shouldn't either. This way, we let Git handle all types of hooks, which solves the hooks issue along with the timeout issue. _This follows how VS Code does it. It does not have any kind of timeout on git child process, and hooks are handled by Git itself._ Edit: I also think working towards way to cancel long going operations is better way forward. See https://github.com/microsoft/vscode/issues/171353. Hooks still don't run for untrusted repositories, the existing `core.hooksPath=/dev/null` clamp covers that. The `RunGitHook` proto handler is kept for compatibility with older remote clients. Release Notes: - Fixed git operations failing with a misleading "Connecting to host timed out" error when they took longer than 17 seconds (large fetches, slow hooks, or waiting on agent-based authentication like 1Password Touch ID). - Fixed `commit-msg` hooks being silently skipped on commit. |
||
|
|
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 |
||
|
|
b562439e93 |
project_panel: Add remote support for undo/redo system (#59709)
# Objective Add remote (SSH) and collaboration support for trashing and restoring files in the project panel, which in turn enables undo/redo of trash operations against remote and collab projects. Relates to #5039. ## Solution - Updated the project panel undo system to carry `TrashId` instead of `TrashedEntry`. - Using `TrashedEntry` could get hairy, as it includes paths, which wouldn't play too nicely when using, for exapmle, macOS as the client and Windows as the host. Using a simple identifier is much easier in this regard and simplifies implementation. - Enabled the Trash action and context-menu entry on remote projects, and removed the command palette filter in `ProjectPanel::new` that was still hiding the action on remote. - As far as I can tell, there isn't a reliable way to detect whether a given remote actually supports the OS trash, so we expose the action everywhere rather than guessing. On a remote without trash support the action will fail when invoked but this is a conscious tradeoff until we find a better way to handle this. - `fs` now tracks trashed files in a `SlotMap<TrashId, TrashedEntry>` on each `Fs` implementation. Trashed files are referenced by an opaque `TrashId` instead of passing a `TrashedEntry` around, which avoids serializing filesystem paths in remote messages. - Split the old `delete_entry(trash: bool)` API into distinct `trash_entry`/`trash_file` (returning a `TrashId`) and `delete_entry`/`delete_file` across `Project`, `Worktree`, `LocalWorktree` and `RemoteWorktree`. - This lets us drop the optional trash result (`Option<TrashedEntry>`) from the delete path and require a `TrashId` from the trash path. - Added new proto messages (`TrashProjectEntry`, `TrashProjectEntryResponse`, `RestoreProjectEntry`, `RestoreProjectEntryResponse`) to let clients request the host to trash or restore entries. - This deprecates `DeleteProjectEntry::use_trash`, but the host still honors it. An older collab peer may request trashing via that flag instead of the newer `TrashProjectEntry`. If the host ignored it, a newer host would permanently delete a file the user meant to send to the trash. The field will be removed in a later PR once all supported peers use `TrashProjectEntry`. ## Testing The following tests were introduced to ensure the new behavior is correctly tested: * `remote_server::remote_editing_tests::test_remote_trash_restore` – Tests trashing a project entry in remote * `remote_server::remote_editing_tests::test_remote_delete_project_entry_with_trash` – Test to ensure we continue respecting `DeleteProjectEntry::use_trash` until it is fully removed * `project_panel::tests::undo::trash_directory_undo_redo` – Not related to these changes but a nice to have as we were missing a test ensuring that trashing and then undoing and redoing it for a directory works as expected Besides these, the following scenarios were manually tested against a remote session on the same machine (macOS): - Trashing → Undo (Restore) → Redo (Trashing) - Batch Trashing → Undo (Batch Restore) → Redo (Batch Trashing) - Rename → Undo (Rename) → Redo (Rename) - Move → Undo (Move) → Redo (Move) - Batch Move → Undo (Batch Move) → Redo (Batch Move) ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [ ] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: Yara <git@yara.blue> |
||
|
|
1e22d1a83f |
project: Fix include filters being ignored for non-ASCII search in multi-worktree projects (#60538)
`SearchQuery::text()` drops the `match_full_paths` parameter when falling back to `escaped_regex` for non-ASCII queries, causing include filters to match against wrong path formats in multi-worktree projects. search works correctly after the fix <img width="1465" height="329" alt="截屏2026-07-07 21 32 34" src="https://github.com/user-attachments/assets/039640e6-22ae-4eb5-a9da-909fd8498b77" /> Fixes #60513 --- Release Notes: - Fixed project search with non-ASCII queries incorrectly ignoring include filters in multi-worktree projects. |
||
|
|
0bfd2d7cf0 |
language_core: Remove lsp-types dependency (#61041)
Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
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: https://github.com/zed-industries/zed/blob/8372eb1b131ab3b8c0622e930e985f15eb970687/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. |
||
|
|
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 ... |
||
|
|
4a3e0af532 |
Add a bespoke LSP request path for edit prediction context (#60947)
Closes EP-193
Edit prediction context collection previously reused the editor
goto-definition / goto-type-definition path, which resolves every LSP
result into a `LocationLink` — opening a buffer per target (worktree
creation, buffer registration, anchor conversion) before edit prediction
gets a chance to filter. On remote projects the host additionally
created a peer-visible buffer per link and the client waited on each
one.
This adds a bespoke request path that returns raw results first and only
does the expensive work for results that survive filtering:
- New `EditPredictionDefinition { path: ProjectPath, range:
Range<Unclipped<PointUtf16>> }` boundary type. LSP wire types never
leave `lsp_command.rs`; the workspace-only filter and URI→`ProjectPath`
resolution happen while normalizing the LSP response, before any buffer
exists, so the type encodes the workspace-only invariant.
- New `GetEditPredictionDefinitions` /
`GetEditPredictionTypeDefinitions` LSP commands and proto messages.
Responses carry only path + UTF-16 range — the host never calls
`create_buffer_for_peer` and the client never waits on remote buffers.
- One public API: `Project::edit_prediction_definitions(buffer,
position, include_type_definitions, cx)` fires both LSP requests
concurrently and returns a merged, deduped list ("not capable" = empty).
The definition/type-definition split was never used downstream, so
`CacheEntry` now holds a single list and the fetch pipeline runs one
task per identifier.
- `edit_prediction_context` dedupes raw results before opening buffers;
survivors open via `project.open_buffer(ProjectPath)` (skipping the
invisible-worktree/yarn machinery of `open_local_buffer_via_lsp`, and
working identically on remote projects), then clip → anchor →
`MAX_TARGET_LEN`.
- Removes the `workspace_only` flag from `GetDefinitions` /
`GetTypeDefinitions`: edit prediction was its only user. The editor path
always sent `false`, which proto3 doesn't encode, so normal
goto-definition requests are wire-identical; old peers still sending
`true` get unfiltered results (graceful degradation). The proto field
numbers are `reserved`.
Tested with a local test proving filtering precedes buffer opening (an
out-of-workspace target never spawns a worktree, an oversized target is
excluded from related files) and a collab test proving the remote
round-trip returns correct paths/ranges without opening buffers on the
client.
Release Notes:
- N/A
|
||
|
|
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: - |
||
|
|
97110fd5a1 |
Show tag names in git blame tooltips (#60757)
Fetch tag names for commits included in blame data and pass them through the blame rendering path. Render tag names as chips in the blame hover tooltip and expanded blame popover. Tag lookup is best-effort, so blame still renders if tag lookup fails. > Note: Tag names are currently only fetched for local repositories. For remote projects (SSH) and collab sessions, blame data travels over the `BlameBufferResponse` proto message, which doesn't carry tag names yet. ## Testing - `cargo test -p git test_parse_tag_names_for_lightweight_and_annotated_tags` - `cargo check -p git_ui` - `cargo check -p editor` - `cargo check -p project` Manual testing: - Opened `git: blame` on a file with a tagged commit. - Verified tag chips are shown in the blame hover tooltip and expanded popover. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon] (https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase Before: <img width="1655" height="660" alt="before" src="https://github.com/user-attachments/assets/dbefd729-f8df-48a9-8249-83c93518fe76" /> After: <img width="1655" height="660" alt="after" src="https://github.com/user-attachments/assets/2c1097de-b268-45d9-9d13-0f3e06058603" /> --- Release Notes: - Git: Made tags visible in Git blame tooltips. --------- Co-authored-by: Danilo Leal <daniloleal09@gmail.com> |
||
|
|
56ab1c4825 |
project: Report formatter failures in the status bar again (#60839)
set a formatter that fails (`"formatter": {"external": {"command":
"false"}}`), save, and you get nothing. it just goes to the log, the
"Formatting failed" indicator never shows.
#51605 made the formatter loop log-and-continue instead of bailing (so
unrelated edits don't get reverted, #51490). downside was the pipeline
always returned Ok after that, so the failure flag the indicator reads
always got wiped. this brings back failures from formatters you actually
configured. auto ones stay quiet when they're not around, so no prettier
installed = still a no-op.
only explicit failures show up, bit narrower than before #51605. can
widen it to auto ones too if you want, one line.
Fixes #59988.
Release Notes:
- Fixed formatter failures not showing the "Formatting failed" status
bar indicator
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
|
||
|
|
a21e87c077 |
git_ui: Fix remote branches missing from branch diff base picker (#60765)
The branch picker collapses remote branches that are tracked by a local branch (e.g. `origin/main` when local `main` tracks it). That makes sense for checkout, where the remote ref is redundant, but it was also applied to the branch diff base picker, where `main` and `origin/main` can point to different commits. As a result, once you switched the diff base from `origin/main` to `main`, there was no way to switch back. The tracked-remote collapsing is now only applied in checkout mode (no changed here). The select (diff base) picker lists both local branches and their remote upstreams. Release Notes: - Fixed remote branches (e.g. `origin/main`) not appearing in the branch diff base picker, making it impossible to switch back after changing the base to another branch. |
||
|
|
503292376e |
Fix remote worktree picker hides "Create from origin/main" option (#59134)
This passes the `include_remote_name` flag through the remote `GetDefaultBranch` RPC instead of dropping it at the client/host boundary. That lets remote repositories resolve default branches as `origin/main` when needed, so worktree creation uses a valid remote branch name instead of falling back to `main`. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #59121 Release Notes: - Fixed remote worktree creation from the default branch when the default branch requires its remote name. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 |
||
|
|
b9f3396b68 |
Add support for format_on_save only changed lines (#49964)
## Summary Introduces `format_on_save` variants that format only modified lines, limiting formatting to lines changed since the last commit. This prevents massive diffs when editing legacy codebases. Aligns with VS Code's `editor.formatOnSaveMode` naming: - `"modifications"` — formats only git-diffed lines. Requires source control; skips formatting if no diff is available. - `"modifications_if_available"` — formats only git-diffed lines, falling back to full-file formatting for untracked files, when source control is unavailable, or when the LSP does not support range formatting. Also supports importing equivalent VS Code settings (`formatOnSaveMode`). This PR uses the range-based whitespace/newline infrastructure from the dependency PR above. ## Changes <details> <summary><b>New settings, modified ranges computation, VS Code import</b></summary> ### New settings (`language.rs`, `default.json`, `all-settings.md`) Two new `FormatOnSave` variants: `Modifications` and `ModificationsIfAvailable`. ### Modified ranges computation (`items.rs`) - `compute_format_decision()` — reads `format_on_save` setting across all buffers, determines whether to use ranged formatting (`Ranges`), full formatting (`Full`), or skip (`Skip`). - `compute_modified_ranges()` — extracts modified line ranges from git diff hunks via `BufferDiffSnapshot`. - `is_empty_range()` — helper to detect deletion-only hunks that produce no formatable content. The `save()` method calls `compute_format_decision()` and dispatches accordingly. ### Modifications mode in `lsp_store.rs` - Adds `FormatOnSave::Modifications | FormatOnSave::ModificationsIfAvailable` to the formatter selection match arm. - `ModificationsIfAvailable` falls back to full-file formatting when ranged formatting produces no results. ### VS Code settings import (`vscode_import.rs`, `settings_store.rs`) Imports `editor.formatOnSaveMode` mapping: - `"modifications"` → `FormatOnSave::Modifications` - `"modificationsIfAvailable"` → `FormatOnSave::ModificationsIfAvailable` - `"file"` → `FormatOnSave::On` </details> ## Tests - `test_modifications_format_on_save` — basic modifications mode formatting with dirty buffer - `test_modifications_format_no_changes` — clean buffer triggers no formatting - `test_modifications_format_lsp_no_range_support` — LSP without range formatting skips entirely for `Modifications` - `test_modifications_format_lsp_returns_empty_edits` — empty edits handled gracefully - `test_modifications_format_multiple_hunks` — two non-adjacent edits produce two separate range formatting requests --- 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 #16509 Depends on #53942 Release Notes: - Added `modifications` and `modifications_if_available` options to `format_on_save`, which format only git-changed lines instead of the entire file - When using modifications mode, `remove_trailing_whitespace_on_save` and `ensure_final_newline_on_save` are also scoped to changed lines, preventing unwanted diff jitter in legacy codebases - Added support for importing VS Code's `editor.formatOnSaveMode` setting --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
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 |
||
|
|
01235732e6 |
Fix should_log_lsp_request_failure logic inversion (#57554)
Was trying to debug an r-a issue and ran into this. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliabilityx - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #ISSUE Release Notes: - N/A or Added/Fixed/Improved ... Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
bc29bcfe72 |
git: Load buffer git diff bases with a single batched git process (#59357)
# Objective Whenever the git repository state is updated on disk (e.g., via staging, committing, branch switching, or stashing), `reload_buffer_diff_bases` is scheduled to reload the diff for all active buffers. This causes 2 git processes to be spawned for each open file which can become noticeable when many files are open https://github.com/zed-industries/zed/blob/5e32405669d0470baec345073dafffb552a18bae/crates/project/src/git_store.rs#L5179 ## Solution This PR introduces `load_revisions` which uses a single `git cat-file --batch` command to compute the diff for all files in the same git process. This prevents the need to sequentially schedule 2 git subprocesses per open buffer. I also changed `load_index_text` and `load_commited_text` to rely on `load_revisions` which simplifies the code. ## Testing I added a unittest and manually verified that Zed now only runs a single `git cat-file --batch` command instead of 2 `git show` processes per open buffer. On macOS I viewed the currently running git processes using: ```shell sudo eslogger exec | jq --unbuffered -r ' select(.event.exec?.target?.executable?.path? | strings | contains("git")) | (.event.exec?.args? // []) | join(" ") ' ``` ## 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 /cc @Veykril Release Notes: - Reduced number of git processes for calculating diff of open buffers when the repo state changes on disk |
||
|
|
f360136f19 |
project: Create LSP file watcher on the background (#60530)
Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
001bda1a46 |
project: Fix ref-match rust completions dropping the leading & (#60521)
Closes #56973, Follow-up for https://github.com/zed-industries/zed/pull/56976 When a completion's `additionalTextEdits` contained a zero-width insertion touching the edge of the primary edit, the overlap check treated it as overlapping and silently skipped it. This broke rust-analyzer's ref-match completions (`&foo`), which deliver the `&` as a zero-width additional edit at the primary edit's start (#56973). The same root cause previously broke auto-imports at the very start of a file (#26136), which was worked around in #37746 with a special case for edits at position (0, 0). This PR replaces that special case with a general rule: a zero-width additional edit only overlaps the primary edit when it falls strictly inside it. i.e. touching the boundary is fine. This one check handles both the file-start auto-import case and the `&` ref-match case, so the (0, 0) workaround from #37746 is removed. Non-insertion edits still go through the original overlap check from #1871. Added three regression tests: - the file-start auto-import (#26136) - the `&` insertion at the primary edit's start (#56973) - overlapping edits being skipped while non-overlapping ones apply (general skip case) Release Notes: - Fixed rust-analyzer completions like `&some_var` inserting only the variable name and dropping the leading `&` when accepted. |
||
|
|
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> |
||
|
|
e58a02d974 |
Fix text finder crash from unbounded memory use (#60377)
- Fixes #60238. - The text finder could spike memory into the tens of gigabytes and crash the app. The finder was copying the full matched line into every match it kept, so memory grew with the number of matches times the size of each line. Enough matches carrying enough text and the process runs out of memory. ## Solution - Stop storing line text on matches. Each match now keeps only its position and column, and the text shown in a row is built lazily for the visible rows, using a bounded slice around the match rather than the whole line. Line boundaries come from the buffer's line index instead of re-scanning the content per match. - Cap the number of matches the finder builds while streaming results, using the same ceiling project search already applies. This keeps the finder from ever assembling an unbounded match list on the UI thread. - Behavior is unchanged: every occurrence is still its own row, jumping to a match lands on the exact line and column, and the rendered text and highlighting look the same. The finder just no longer holds text proportional to the match count. ## Testing - Added tests covering the new behavior: the match count is capped while streaming, every occurrence below the ceiling still becomes its own match at the correct line and column, and the rendered slice around a match stays bounded on a huge line while still covering a whole short line. - Verified by hand with the reproduction from the issue. The screenshot below shows the memory usage and the matching against the issue data: <img width="1277" height="1053" alt="Screenshot 2026-07-03 at 17 43 11" src="https://github.com/user-attachments/assets/71c0aa3b-2423-427d-91ba-792951d9ba31" /> ## 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 crash and high memory usage in the text finder. |
||
|
|
b77ec90b2e |
git: Do not recompute git_access on every file change (#59521)
# Objective As mentioned in #59514, the git panel currently runs a full `git status` for checking whether `git` has access to the repository. This was introduced in #43693 and currently runs on every file save which is problematic for large repos where `git status` runs a lot of computation. ## Solution This PR caches the `git_access` on the git panel such that we don't need re-check for git access on every file save. ## Testing I manually verified that the git panel doesn't trigger anymore unnecessary git status commands. **main:** ``` 2026-06-18T00:04:24+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967643 2026-06-18T00:04:24+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967643 2026-06-18T00:04:24+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967643 2026-06-18T00:04:24+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967643 2026-06-18T00:04:24+01:00 DEBUG [project.format.local] formatting buffer '"/Users/lgeiger/code/zed/CONTRIBUTING.md"' 2026-06-18T00:04:24+01:00 DEBUG [project.format.local] no changes made while formatting 2026-06-18T00:04:24+01:00 DEBUG [git::repository] Checking for git status in ["CONTRIBUTING.md"] 2026-06-18T00:04:25+01:00 DEBUG [git::repository] Checking for git status in [] ``` ``` /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z -- CONTRIBUTING.md /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager diff --numstat --no-renames HEAD -- CONTRIBUTING.md /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager config --get commit.template /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z -- ``` **This PR:** ``` 2026-06-18T02:47:54+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967656 2026-06-18T02:47:54+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967656 2026-06-18T02:47:55+01:00 DEBUG [project.format.local] formatting buffer '"/Users/lgeiger/code/zed/CONTRIBUTING.md"' 2026-06-18T02:47:55+01:00 DEBUG [project.format.local] no changes made while formatting 2026-06-18T02:47:55+01:00 DEBUG [git::repository] Checking for git status in ["CONTRIBUTING.md"] ``` ``` /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager diff --numstat --no-renames HEAD -- CONTRIBUTING.md /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z -- CONTRIBUTING.md /opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager config --get commit.template ``` ## 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 /cc @dinocosta --- Release Notes: - Improved Git Panel performance by no longer re-checking repository access on every file change --------- Co-authored-by: dino <dinojoaocosta@gmail.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
9375695626 |
Project/use line hint for search (#58871)
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 This PR makes two changes: 1. detect() now returns the line number of the first match instead of just a boolean. 2. This line number (line_hint) is threaded through the pipeline and passed as a subrange to query.search in full buffer scan, so the full buffer scan starts from where the first match was already found instead of the beginning of the file. ## Scope - This optimization only applies to **local search** (not remote). - It is only effective for **single-line text and single-line regex** queries. For multiline queries, `detect()` returns `line_hint = 0`, so the full buffer is scanned from the beginning as before. - It does not apply to already-open buffers, which always receive `line_hint = 0`. ## Test i tried to search the word "typeably" in the file "pkgs/development/haskell-modules/hackage-packages.nix" of the repo [nixpkgs](https://github.com/NixOS/nixpkgs) given in the comment: [comment](https://github.com/zed-industries/zed/issues/38799#issuecomment-4088491295). Result seems promising: **with line_hint: search: 45.21ms** **without line_hint: search: 508.05ms** I measured the time within the function: "handle_find_all_matches" ## Assumption The core assumption is: if the search query is long enough (after 4 or 5 chars), the probability of finding multiple matches in a single file is low. In that case, re-scanning the content before line_hint is unnecessary — detect() function already confirmed there is no match there. Changes maybe can make an improvement on issues #38799 and #58905 --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> |
||
|
|
d1e8c0b50f |
git_store: Avoid redundant work in worktree git repository update (#60205)
## Objective While profiling https://github.com/zed-industries/zed/issues/60102 I noticed `GitStore::update_repositories_from_worktree` does unneeded work. It fires on every `WorktreeUpdatedGitRepositories` event, which under filesystem pressure (`rescan: user dropped`) repeats roughly once per second and can fire more frequently in a large monorepo with many repositories, since the redundant work scales with the number of repositories. ## Solution In `crates/project/src/git_store.rs`: - Drop the per-iteration `Arc<Path>` clone in the repo lookup; compare the borrowed reference instead. - Hoist the `is_trusted` (`can_trust`) computation out of the loop since it only depends on `worktree_id`. No behavior change is intended; this is purely reducing redundant work per event. ## Notes The *frequency* of these events originates upstream in `LocalWorktree::changed_repos` (`crates/worktree/src/worktree.rs`), which re-emits an `UpdatedGitRepository` whenever `git_dir_scan_id` changes on a full rescan. That path is intentionally left untouched here since it involves scan semantics; this PR only addresses the redundant work on the consumer side. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - N/A |
||
|
|
b206841b4b |
Add range-based whitespace and newline removal to buffer formatting (#53942)
## Summary When formatting specific ranges (e.g. via Format Selections), trailing whitespace removal and final newline enforcement currently operate on the entire file. This PR makes these operations range-aware, so they only affect lines within the target ranges. As noted in #16509, users want `remove_trailing_whitespace_on_save` and `ensure_final_newline_on_save` to suppress jitter by only touching changed lines. This PR provides the foundational infrastructure for that — range-based whitespace and newline operations — which a follow-up PR will wire into the `format_on_save` modifications mode. ## Changes - Added `remove_trailing_whitespace_in_ranges` and `ensure_final_newline_in_range` to `Buffer` - When a `FormattableBuffer` has ranges set, whitespace and newline operations now use the range-based variants - `format_ranges_via_lsp` returns `Ok(None)` instead of an error when the LSP doesn't support range formatting - Extracted `anchor_ranges_to_row_ranges` helper to deduplicate conversion logic <details><summary>Tests (4)</summary> - `test_trailing_whitespace_in_ranges` — only modified lines have whitespace removed - `test_trailing_whitespace_empty_ranges` — empty ranges → no changes - `test_final_newline_modified_last_line` — newline added when last line is in range - `test_final_newline_unmodified_last_line` — newline not added when last line is outside range </details> --- Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved Format Selection to scope trailing whitespace removal and final newline enforcement to the selected range instead of the entire file - Improved handling of LSP servers that do not support range formatting by gracefully skipping instead of producing an error --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
df33d78661 |
cli: Always open new window when cli_default_open_behavior=new_window (#59415)
This makes sure that the behaviour of the CLI matches that of the UI. In Zed itself we always open a new window (e.g. when clicking on Open Project in new window in the recent projects picker), but in the CLI we where re-using existing windows even when specifying "cli_default_open_behavior": "new_window". This caused confusion, so this PR ensures that we always open a new window, even if that folder is already open. We still focus the active window in the case where the path is a subpath of a project that is already open. Can be tested with ``` cd crates/cli cargo run -- --zed ../../target/debug/zed somefolder ``` Release Notes: - cli: Ensure `zed somefolder` always opens a new window, even when `cli_default_open_behavior` is set to `new_window` and the project is already open |
||
|
|
45015f89d7 |
acp: Support boolean ACP config options (#59698)
Still behind a feature flag until the RFD is completed. Release Notes: - N/A --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com> |
||
|
|
f2006b20ac |
git: Allow showing inline blame in the status bar (#59696)
# Add status bar location for inline git blame ## Objective - Closes #12133 by implementing the VS Code-like behavior for status bar git blame ## Solution Adds a VS Code–style option to render the current-line git blame in the status bar instead of inline at the cursor. Whats new - A new location setting: Under the inline_blame configuration, you can now choose between two options: - `inline` (Default) — Keeps things exactly as they are, showing the blame details at the end of your current line. - `status_bar` — Moves the blame info down to the bottom status bar. - The Status Bar Item: When you choose the status bar option, a clean new button appears at the bottom left of your window. It features a Git icon, the author's name, how long ago the change was made, and the commit summary - Behaves as it does before, but displayed at a different location - Clicking the status bar item will instantly open up the full Git commit details like at vscode - Settings UI: - The "Location" control is now a `DynamicItem` nested under "Enabled", so it only appears when inline blame is enabled. - Registers a dropdown renderer for `InlineBlameLocation`. - Updates `all-settings.md` and `visual-customization.md` for the new option. ## Testing - Manually tested both modes by toggling `git.inline_blame.location` between `inline` and `status_bar`: - `inline` keeps the existing behavior unchanged. - `status_bar` shows the blame for the focused line in the status bar, hides the inline blame, updates on cursor movement, clears when no editor is focused, and opens the blame commit on click. - Verified the settings UI shows the "Location" dropdown only when inline blame is enabled. - Tested with `show_commit_summary` toggled when location is `status_bar` (for inline location, nothing is changed) Areas that could use more testing: - Remote (collab) editors ? Reviewers can test by setting the following in `settings.json` and moving the cursor across blamed lines: ```json { "git": { "inline_blame": { "enabled": true, "location": "status_bar" } } } ``` ## Showcase <details> <summary>Click to view showcase</summary> ### Video https://github.com/user-attachments/assets/6d9f490d-7bf3-473c-9562-8351546dfaf9 ### Screenshots <img width="894" height="749" alt="image" src="https://github.com/user-attachments/assets/c6a49008-899d-4a0c-9098-1ffb9e28252b" /> </details> Release Notes: - Added a `git.inline_blame.location` setting to render current-line git blame in the status bar instead of inline. |
||
|
|
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 |
||
|
|
7582bf7434 |
Allow empty values in .editorconfig (#60026)
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 |
||
|
|
0deb6c0dea |
Fix code lens not being resolved in remote workflows (#59999)
Follow-up to https://github.com/zed-industries/zed/pull/54100 Closes https://github.com/zed-industries/zed/issues/59122 Original PR overlooked that the resolve was not handled from the remote hosts at all... Also, fixes the re-fetch of code lens not taking new language servers into account: before, it exit early whilst now it actually re-fetches the lens for the new servers. Before: <img width="1728" height="1084" alt="before" src="https://github.com/user-attachments/assets/9ee8205b-084b-4409-9abc-18c4ddb9c4e9" /> After: <img width="1728" height="1084" alt="after" src="https://github.com/user-attachments/assets/16ad76dc-25e1-4257-80dc-b5aeabc9a4ef" /> Release Notes: - Fixed code lens not being resolved in remote workflows |
||
|
|
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> |
||
|
|
73b235aeb4 |
Refresh code lens after dynamic registration (#60009)
Follow-up to https://github.com/zed-industries/zed/pull/54100 Closes https://github.com/zed-industries/zed/issues/58864 Release Notes: - Fixed code lens not being refresh after the corresponding capability was dynamically registered --------- Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
bfe0d7c8f6 |
git_ui: Preserve in-progress commit message across reconnect (#58180)
Losing the connection on a remote project, or restarting Zed, while editing a git commit message cleared the in-progress text, because the Git panel rebuilds the commit buffer from the repository and discards unsent input. This persists the draft, scoped to the active repository's work directory, in the panel's serialized state and restores it when the panel is rebuilt from that state: at construction when the active repository already matches, and again in `reopen_commit_buffer` once the commit buffer loads. The restore only applies to an empty target buffer whose work directory matches the active repository, so it never replays committed or cleared text and never leaks a draft across repositories. The persisted draft is cleared after a successful commit. 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 #47864 Release Notes: - Fixed in-progress git commit messages being cleared when a remote project reconnects or Zed restarts --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
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> |
||
|
|
479bce0995 |
Implement telemetry for the remote server (#59692)
# Objective Telemetry events generated **on a remote server** were silently dropped, and all remote telemetry that *was* reported got attributed to the local client's OS. ## Solution This PR makes server-originated events flow to the telemetry pipeline and attributes them to the actual remote host (connection type, OS, version, architecture), plus adds a transport-agnostic connection event. ## Additional Notes This removes the "SSH Project Opened" event and replaces it with a "Remote Connection Established" one that has more structured info and is also more useful in where it gets invoked. The server unconditionally sends back telemetry to the client, the client is then responsible for filtering on whether telemetry is enabled by the user or not as the server does not have knowledge of those settings itself. Release Notes: - N/A |