Commit Graph
38823 Commits
Author SHA1 Message Date
Danilo Leal d97bbf3369 agent_ui: Use a callout for the sandbox warning (#60386)
Just a small tweak to use an existing component where the UI is a bit
tidier.

Release Notes:

- N/A
2026-07-04 09:15:51 +00:00
Kirill Bulatov 1a99eba192 Do not redownload same Nightly updates over and over (#59994)
If one gets a Nightly update but does not restart and rather dismisses
the notification, the next update check will do the update again.

This is caused by the fact that the version check is done based on
semver, but Nightly has the very same version that differs by the SHA
only.
Adjust the Nightly update check to skip re-downloads if SHA parts of the
version match also.

https://github.com/zed-industries/zed/pull/59852 does more changes, this
PR extracts the part I am sure about.

Release Notes:

- N/A
2026-07-03 23:29:01 +00:00
Miguel Raz Guzmán Macedo 4b7369481d Add dylint lint library for Zed-specific patterns (#58496)
Adds a dylint library under tooling/lints that flags Zed-specific
anti-patterns:

* shared_string_from_str_literal, 
* async_block_without_await, 
* entity_update_in_render, 
* notify_in_render, 
* owned_string_into_shared, 
* len_in_loop_condition, and 
* blocking_io_on_foreground. 

Includes UI tests, a single-lint helper, and workspace.metadata.dylint
registration so cargo dylint --all discovers it. The library pins its
own nightly toolchain (kept out of the main workspace) and tracks dylint
6.

Release Notes:

- N/A

Self-Review Checklist:

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

Closes #ISSUE

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-07-03 22:05:34 +00:00
Lukas Geigeranddino 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>
2026-07-03 20:43:32 +00:00
Gavin Luo c56646ffdf terminal: Fix IME candidate window not following cursor in TUI apps (#59911)
# Objective

Fix IME candidate window not following cursor position in the integrated
terminal when running fullscreen TUI applications like opencode.

When using IME (Input Method Editor) in Zed's terminal with fullscreen
TUI applications (e.g., opencode), the candidate window does not follow
the cursor position. This issue does not occur in normal terminal usage
(e.g., bash shell).

# Solution

The root cause was three-layer blocking preventing IME position updates
in ALT_SCREEN mode:

1. **ALT_SCREEN blocking**: `selected_text_range()` returned `None` in
ALT_SCREEN mode, causing `selected_bounds()` to return `None`
2. **Missing trigger**: `Event::Wakeup` did not call
`invalidate_character_coordinates()`, so cursor movement did not trigger
IME position updates
3. **Composition blocking**: `update_ime_position()` skipped updates
when `state.composing` was true

Fixes:
- Remove ALT_SCREEN check in `selected_text_range()` so IME position
updates work in fullscreen TUI apps
- Add `window.invalidate_character_coordinates()` in `Event::Wakeup` to
trigger IME position updates when terminal cursor moves
- Remove `state.composing` check in `update_ime_position()` to allow IME
position updates during text-input-v3 composition
- Remove unused `terminal` field from `TerminalInputHandler` struct

# Testing

**Did you test these changes? If so, how?**
- Yes, tested on Linux GNOME Wayland with iBus input method
- Verified IME candidate window correctly follows cursor in opencode
- Verified normal terminal usage with IME still works correctly

**Are there any parts that need more testing?**
- Other IMEs (fcitx, etc.) may need testing

**How can other people (reviewers) test your changes?**
1. Open Zed's integrated terminal
2. Run a fullscreen TUI application like `opencode`
3. Activate IME (e.g., iBus with Chinese input)
4. Type text and observe the IME candidate window follows the cursor

**What platforms did you test these changes on?**
- Linux (GNOME Wayland) - tested
- macOS - not tested (may have different IME behavior)
- Windows - not tested (different code path)

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

# Showcase

<details>
  <summary>Before</summary>
<video
src="https://github.com/user-attachments/assets/ee2fac4e-801b-49af-a57e-32ce25e01db5"
width="320" height="180" />
</details>

<details>
  <summary>After</summary>
<video
src="https://github.com/user-attachments/assets/c669ea99-2ffc-4179-b587-a47873e33e70"
width="320" height="180" />
</details>

---

Release Notes:

- Fixed IME candidate window not following cursor in terminal TUI apps
2026-07-03 20:25:16 +00:00
ArtinandSmit Barmase 5aa6e8a0b3 Reduce OAuth scope to avoid Windows credential size limit (#58541)
I encountered an issue where I couldn't sign in to ChatGPT Subscription
on Windows:

```
ChatGPT subscription sign-in failed to persist credentials: 
Failed to write credentials to Windows Credential Manager: 
占位程序接收到错误数据。 (0x800706F7)
```

Interestingly, only one of my three ChatGPT accounts had this problem —
the other two signed in successfully.

## What I Found

After investigating, I noticed that the OAuth scope in
`openai_subscribed.rs` requests 6 permissions:

```
openid profile email offline_access api.connectors.read api.connectors.invoke
```

I wrote a test script to measure token sizes and found that:
- With 6 scopes: my problematic account's token was **2578 bytes**
- With 4 scopes (removing `api.connectors.read` and
`api.connectors.invoke`): the same token was **2516 bytes**

Since Windows Credential Manager has a 2560-byte limit
(`CRED_MAX_CREDENTIAL_BLOB_SIZE`), this could explain why some accounts
fail while others succeed — it depends on the base token size.

## My Hypothesis

The issue seems to be that:
- Error code `0x800706F7` = `RPC_X_BAD_STUB_DATA` (size limit, not
format)
- Accounts with larger base tokens exceed the limit when the extra 48
chars are added
- Accounts with smaller base tokens still fit, which is why this isn't
universally reproducible

I'm not 100% certain this is the root cause, but the evidence seems to
point in this direction.

## Proposed Fix

I removed `api.connectors.read` and `api.connectors.invoke` from the
OAuth scope, since:
- These scopes don't appear to be used by Zed's current ChatGPT
integration
- OpenCode (another tool using the same OAuth provider) successfully
uses only 4 scopes
- This fix allowed my problematic account to sign in

However, I'd like to ask the maintainers:
- Are there plans to use OpenAI Connectors API in the future?
- Are there security or compliance reasons for requesting these extra
scopes?

If the answer is yes to either, we'd need a different approach (e.g.,
splitting credentials, using encrypted file storage, or checking token
size before storage).

## Testing

- [x] Verified my problematic account now signs in successfully
- [x] Verified my other accounts still work
- [x] Ran `cargo check -p language_models` (compilation successful)
- [ ] Would appreciate help testing on macOS/Linux

## Questions

1. Does this analysis make sense?
2. Are there any other considerations I'm missing?
3. Would it be helpful to add a size check with a clearer error message
for future cases?

I'm happy to adjust this approach based on your feedback.

Release Notes:

- Fixed ChatGPT Subscription sign-in failing on Windows for some
accounts by removing unused OAuth scopes (`api.connectors.read`,
`api.connectors.invoke`) that pushed JWT tokens over Windows Credential
Manager's limit.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-03 19:38:42 +00:00
Tautik Agrahari ea3d0f7abe keymap: Avoid format-vs-rules collision in JetBrains overlay (#55364)
the jetbrains overlay binds `ctrl-alt-l` (linux) / `cmd-alt-l` (macos)
to `editor::Format` (jetbrains "reformat code"), which collides with the
default `agent::OpenRulesLibrary` binding. the agent panel shows the
conflicting key as the rules tooltip but pressing it formats the buffer
instead of opening rules. mirrors the windows keymap by switching the
linux/macos overlays to `shift-alt-l` in the AgentPanel context (with
the colliding key explicitly null-ed), so the hint and the action stay
in sync.

closes #49764.

Release Notes:

- Fixed the JetBrains keymap so the agent panel "Rules" entry uses
`shift-alt-l` and no longer flickers a non-functional `ctrl-alt-l` /
`cmd-alt-l` shortcut.
2026-07-03 18:54:42 +00:00
Yara 🏳️‍⚧️andzed-zippy[bot] 5a823cf70e docs: Add new text finder (#60189)
Mention the text finder in the docs. 

Release Notes:

- N/A

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-07-03 18:46:05 +00:00
Ben Brandt fa8540ff62 Update Wasmtime dependencies (#60341)
Brings in the latest LTS security and bug fixes

Release Notes:

- N/A
2026-07-03 18:44:17 +00:00
KyleBartonandMartin Ye 9eb8a7c0ad Handle cases where Dockerfile aliases are chained (#57552)
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 #56189

Release Notes:

- Fixed bug to handle dev container Dockerfiles with chained aliases

---------

Co-authored-by: Martin Ye <martin@zed.dev>
2026-07-03 18:37:06 +00:00
Zak Nesler 2f1caadd38 Fix expanded commit editor (#60368)
This is a simple follow-up to #60331, the commit message in the expanded
view got messed up and was being shrunken and centered instead of taking
up the full height of the git panel.

All it needed was a `.h_full()`:

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

### Before
<img width="652" height="758"
alt="file-6d7f3fd7a5de8cff5ea44c0dfbaf0ac5"
src="https://github.com/user-attachments/assets/85dca75c-7528-4876-9154-0145272c5029"
/>

### After
<img width="662" height="761"
alt="file-268420a52e7b967fc09d10007d6aa1e5"
src="https://github.com/user-attachments/assets/f39ea70b-d0a9-40e6-bb20-20cd3508ad66"
/>

</details>

@danilo-leal 

## Self-Review Checklist:

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

---

Release Notes:

- N/A
2026-07-03 18:26:14 +00:00
bgfraserandTom Houlé 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
Anthony Eidandzed-zippy[bot] 262fb9ba2a Show per-file diff stat in multibuffer headers (#60299)
Renders the per-file added/removed line counts (already tracked per
buffer by the multibuffer) in each diff multibuffer header, matching the
overall stat shown in the branch diff toolbar.

### Before
<img width="1624" height="1061" alt="Screenshot 2026-07-02 at 11 50 42
AM"
src="https://github.com/user-attachments/assets/3e46a90c-a4e1-4b72-8ec9-80931a7e4a9a"
/>

### After
<img width="1624" height="1061" alt="Screenshot 2026-07-02 at 12 03 58
PM"
src="https://github.com/user-attachments/assets/25900790-82f5-44e9-9a3b-731a3090f23e"
/>


Release Notes:

- Improved diff multibuffer headers to show per-file added/removed line
counts

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-07-03 17:55:24 +00:00
Yi LiuandSmit Barmase 6eaad52c29 language_models: Avoid sending Bedrock cache-point-only messages (#59436)
When prompt caching is enabled, `into_bedrock` pushes a `CachePoint`
block
onto a message's content whenever `message.cache && supports_caching` is
true.
This push happens before the `if bedrock_message_content.is_empty() {
continue; }`
guard. As a result, a message whose content filters down to empty (for
example,
a message that contained only content stripped during conversion) still
gets
appended to the request carrying nothing but a `cachePoint`. Bedrock
rejects such
a message with a `ValidationException`, breaking the whole request.

The Anthropic path is already internally consistent here: in
`crates/language_models/src/provider/anthropic.rs` (around the message
assembly
in `completion.rs`) the empty-content check runs first, so an empty
message is
dropped before any cache marker is attached. The Bedrock path should
behave the
same way.

This change gates the `CachePoint` push on non-empty content
(`&& !bedrock_message_content.is_empty()`), so an empty message is left
empty and
then skipped by the existing `continue`, exactly mirroring the Anthropic
ordering.
The fix is minimal and touches only the cache-point condition.

Release Notes:

- Fixed Bedrock requests failing with ValidationException when the last
message filtered to empty content while prompt caching was enabled.

---------

Signed-off-by: Yi LIU <yi@quantstamp.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-03 16:41:58 +00:00
NeelandDavid Irvine 814b152a0f bedrock: Add Claude Sonnet 5 (#60360)
Also orders the Claude models from most to least capable.

Release Notes:

- Added Sonnet 5 to Bedrock provider

Co-authored-by: David Irvine <aviddiviner@gmail.com>
2026-07-03 15:26:15 +00:00
Hamza ParachaandSmit Barmase 53552b29a4 docs: Clarify agent notification placement (#54032)
## Summary
- describe agent notifications as OS desktop notifications instead of
claiming a fixed screen position
- keep the agent panel docs accurate across platforms and desktop
environments

Fixes #53588

Release Notes:

- N/A

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-03 15:21:52 +00:00
Jakub Konka f4364d870e gpui_linux: Add support for open_window in headless client (#60359)
This actually makes it possible for Linux headless client to have
working windows for computation (well, we are in headless mode after
all). This also matches macOS headless client behaviour.

Release Notes:

- N/A
2026-07-03 15:20:09 +00:00
aabcd71690 Improve commit container at larger font sizes (#60331)
At larger font sizes (e.g. I have profiles that increase the font sizes
when screen sharing) the commit button in the git panel editor does not
stay aligned to the bottom-right of the screen, and overlaps the other
elements:

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


https://github.com/user-attachments/assets/e73034db-07a6-42d7-b993-9d8091e50b70

Notice the extra clipping of the commit message editor element:

<img width="500" alt="image"
src="https://github.com/user-attachments/assets/67d59405-57e2-4547-87c2-1c4728515c26"
/>

</details>

This was happening because the floating icons on the right and the
footer containing the commit button were positioned absolutely, used
pixels instead of responsive rems, and had an offset that was calculated
and did not account for changes in user rem size.

So I've moved things around to be more "flexy"... basically just
removing the absolute positioning and making the elements flush against
one another.

## Testing

I have tested this manually on macOS 27 beta 2 and Windows 11, both
using various light/dark themes, window sizes, commit text, etc.

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

Here's a demo at different zoom levels, with and without text, when
expanding the commit window, etc.

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


https://github.com/user-attachments/assets/bea82da1-0c7f-4d51-a73b-d4bc4581a2b7

And here's another demo with debug colors for the different elements to
see what's going on:


https://github.com/user-attachments/assets/12fd3e95-5089-4e34-a84c-c352219ee197

</details>
---

Release Notes:

- Git Panel: Fixed overlapping elements in commit message container

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2026-07-03 15:19:49 +00:00
Edvard HøibyandNeel b497e2024a Add Claude Fable 5 to Amazon Bedrock (#59016)
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

What:
<img width="644" height="445" alt="image"
src="https://github.com/user-attachments/assets/b1b01f7d-8ee9-448c-a8c7-ae80c16326e4"
/>

Tested towards EU region off AWS. Makes Claude Fabel 5 accessible
through bedrock.
To enable Fable you need to opt in to `provider_data_share` in AWS.
[AWS
Docs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-anthropic-claude-fable-5.html)

Release Notes:

- Added Claude Fable 5 to the Amazon Bedrock provider.

---------

Co-authored-by: Neel <neel@zed.dev>
2026-07-03 15:10:39 +00:00
María CraigandDanilo Leal 4da73e1970 git_ui: Add configure and docs links to commit message tooltip (#60357)
When no LLM provider is configured, hovering the disabled "Generate
Commit Message" button in the git panel/commit modal previously showed a
plain, non-interactive tooltip with no way to act on it.

This tooltip now includes two links:
- **Configure Provider** — jumps directly to the "LLM Providers"
settings sub-page.
- **See Docs** — opens `https://zed.dev/docs/ai/llm-providers`.

Also adds `IconButton::hoverable_tooltip`, mirroring the existing
`.tooltip(...)` forwarding, since `IconButton` didn't previously expose
the underlying `ButtonLike::hoverable_tooltip` capability needed for
interactive tooltip content.

Release Notes:

- Improved the commit message tooltip to link directly to LLM provider
settings and documentation when no provider is configured.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2026-07-03 14:56:37 +00:00
di404andSmit Barmase be7e5b0338 terminal_view: Show terminal inline assist keybinding in tooltip (#55903)
## Summary

- Fixed the terminal inline assist tab bar tooltip so it resolves the
keybinding from the active terminal view.
- The bug happened when the initial terminal was closed and a new
terminal was opened: the tab bar button kept a cached focus handle for
the old terminal, so tooltip keybinding lookup could no longer find the
terminal key context.
- The button is now created while rendering the tab bar with the current
terminal view's focus handle, avoiding stale focus handles as terminals
are closed and recreated.

## Validation

- `cargo fmt --package terminal_view --check`
- `cargo check -p terminal_view --message-format short`

Release Notes:

- Fixed the terminal inline assist toolbar tooltip not showing its
keybinding after reopening terminals.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-03 13:48:03 +00:00
Maja BackmanandBennet Bo Fenner 7ed553b391 acp_thread: Shrink ACP terminal scrollback to used on exit (#60019)
# Objective

ACP agents (Cursor, Claude Code, Codex, etc.) start a display-only
`terminal::Terminal` for each bash tool call. After the call exits, the
terminal stays alive so that its output stays visible. But the
`alacritty` `Grid` keeps a `Storage` cache that's never reclaimed.
Across a long session this memory adds up.

Partially fixes #57099

## Solution

Added `Terminal::shrink_to_used`, called from the `Exit` branch of
`on_terminal_provider_event`. This calls `Grid::truncate()` on the
alacritty grid, shrinking the `Storage` cache portion while leaving
user-visible scrollback.

## Testing

- `cargo nextest run -p terminal
shrink_to_used_preserves_user_visible_scrollback` passes — exercises the
path with >10K rows of scrollback.
- `./script/clippy` clean.
- Manually verified: ran a noisy bash tool call via an ACP agent,
observed exit, then scrolled back through the output, no regression.

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

- Improved memory usage of ACP terminals after the tool call exits

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2026-07-03 11:41:48 +00:00
augustandYara 9448417157 project_symbols: Add preview to project symbols picker (#59863)
Candidate fix for #59822.

Adds a live preview pane to the project symbols picker, matching the
file finder and project search pickers. When the selection moves, the
selected symbol's file is shown in the preview with its declaration line
highlighted and vertically centered.

## Changes
- `project_symbols`: construct the picker with
`uniform_list_with_preview`; asynchronously open the buffer for the
selected symbol (cached by candidate id, cleared on each new query) and
implement `try_get_preview_data_for_match` to return the buffer plus the
symbol's anchor range.
- `picker`: add a public `refresh_preview` so a delegate can push
preview data once a buffer finishes opening asynchronously (the symbol
buffer is not available synchronously, unlike text search which already
holds open buffers).


#### Before
<img width="1725" height="712" alt="image"
src="https://github.com/user-attachments/assets/21dcd7d6-7cc4-4de8-ab7d-2f1ce143e814"
/>

##### After
<img width="1725" height="712" alt="image"
src="https://github.com/user-attachments/assets/db981db8-0a61-43bc-9838-c01b7bdbbf78"
/>

Can turn preview pane off by clicking at the bottom button!

## AI disclosure
AI was used for understanding the codebase and formatting this PR.

Release Notes:

- Added a preview pane to the project symbols picker

---------

Co-authored-by: Yara <git@yara.blue>
2026-07-03 10:48:15 +00:00
Ben Brandt 616b76cd59 Update Danger to 13.0.8 (#60346)
Release Notes:

- N/A
2026-07-03 10:10:41 +00:00
Richard Feldman 59185f5a70 livekit_api: Fix LiveKit token revocation timestamps (#60157)
LiveKit Cloud rejects room-join tokens as revoked when their `nbf`
predates a participant revocation. Zed generated those LiveKit JWTs with
`nbf: 0`, so a fresh participant token minted after stale connection
cleanup could still appear older than the cleanup and leave a user
joined at the collab layer without audio or screen sharing. This sets
`nbf` to the issuance time for room-join tokens while leaving admin/API
tokens unchanged, and adds regression coverage at the token, mock
LiveKit, and channel rejoin layers.

Closes FR-83

Release Notes:

- Fixed calls getting stuck without audio or screen sharing after
restarting Zed and rejoining a channel.
2026-07-03 09:50:42 +00:00
Ben Brandt 98ddc3ae2e Update openssl dependencies (#60342)
Release Notes:

- N/A
2026-07-03 09:38:07 +00:00
Finn Evers a91c8aa7d7 Remove more storybook leftovers (#60337)
Release Notes:

- N/A
2026-07-03 08:27:48 +00:00
Chiel RobbenandSmit Barmase 4a3b763518 Add progress bar to "Downloading Zed Update..." button (#60294)
# Objective

On a few occasions I have been wondering if the Zed update download had
stalled, when in fact it's just taking a while. This PR adds a progress
bar to the "Downloading Zed Update..." button to give users feedback
that the download is indeed progressing.

## Solution

Add a custom progress bar inside the button. I tried reusing the
existing ProgressBar component but that has a fixed height of 8px which
caused the button to become taller.

## Testing

- Tested manually using the command palette `collab: simulate update
available` and stepping through the different UI states.
- Added unit test

## 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="1350" height="748" alt="Image 02-07-2026 at 17 23"
src="https://github.com/user-attachments/assets/ed23c97a-01b8-446b-9693-0c53a69b419d"
/>

Release Notes:

- Added a download progress indicator to the update button.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-03 08:23:06 +00:00
Kirill Bulatov f961889ad4 Fix excluded language servers starting nonetheless (#60000)
Despite the default Zed settings containing an exclusion for
`typescript-language-server`


https://github.com/zed-industries/zed/blob/632dcae287b799975b1518b2c4914509e90a5c90/assets/settings/default.json#L2372-L2377

it actually starts every time I open the `*.ts` file which is wrong.

Seems that the settings merging malfunctions hence the fix, but I have
some doubts as I do not recall seeing this bad thing before?

Before:
<img width="1728" height="1084" alt="before"
src="https://github.com/user-attachments/assets/89659cee-c83c-4c87-8977-d53fec11662e"
/>

After:
<img width="1728" height="1084" alt="after"
src="https://github.com/user-attachments/assets/69747fa8-f3ab-454c-90de-b81d1778c5c2"
/>

Release Notes:

- Fixed excluded language servers starting nonetheless
2026-07-03 08:22:48 +00:00
Miguel Raz Guzmán Macedo 0346a17d09 Add zed: get merch command palette action (#60330)
Adds a `zed: get merch` command palette action that opens
https://merch.zed.dev/ in the system browser.

Just thought it'd be fun!

Release Notes:

- Added a `zed: get merch` action that opens the Zed merch store.
2026-07-03 05:59:13 +00:00
Ben KunkleandMarshall 552fc9f3c3 reqwest_client: Fix streamed request bodies being truncated (#60314)
StreamReader::poll_next dropped the reader it take()s whenever the read
returned Poll::Pending, so the next poll reported end-of-stream. And
poll_read_buf measured bytes via ReadBuf::filled(), which never advances
when the reader writes through initialize_unfilled(), so every read
counted as zero bytes. Together these made any AsyncBody::from_reader
request body (e.g. one backed by async_fs::File, which returns Pending
on its first read) upload as an empty or truncated body.

Keep the reader across Pending polls and use the byte count that
futures::AsyncRead::poll_read returns.



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

Co-authored-by: Marshall <marshall@zed.dev>
2026-07-03 01:00:54 +00:00
Marshall Bowers b5c2d8a13f Revert "Fix hanging updates after system sleep (#60301)" (#60321)
This reverts commit 2882636c06.

This was causing Zed to crash immediately on startup with the following
error:

```
thread 'main' (74835290) panicked at /Users/maxdeviant/.cargo/git/checkouts/reqwest-dc13ba947e7b959e/c156624/src/async_impl/body.rs:365:33:
there is no reactor running, must be called from the context of a Tokio 1.x runtime
```

Closes FR-118.

Release Notes:

- Reverted https://github.com/zed-industries/zed/pull/60301
2026-07-02 23:54:11 +00:00
Ben Kunkle bb48a42983 keymap_editor: Fix deleting and editing bindings that use deprecated action names (#60300)
# Objective

In the keymap editor, bindings whose `keymap.json` entries use a
deprecated action alias (e.g. `"editor::CopyRelativePath"` for
`workspace::CopyRelativePath`) could not be deleted or edited. Aliases
resolve to the canonical action on load, so the row displays normally,
but file updates searched for the canonical name and never matched the
alias entry. Deleting failed ("Failed to find keybinding to remove"),
and editing silently fell back to appending a new binding — leaving the
user with duplicate identical-looking rows they couldn't remove.

## Solution

- Thread gpui's deprecated-alias map
(`App::deprecated_actions_to_preferred_actions`) into
`KeymapFile::update_keybinding`, and resolve aliases in file entries
when matching bindings.
- As a side effect, editing an alias-based binding now rewrites the
entry with the canonical action name instead of duplicating it.

## Testing

- Unit tests in `settings` for removing and replacing alias-based
entries.
- End-to-end keymap editor tests (fake fs → keymap load → `KeymapEditor`
→ delete) covering both the alias case and plain duplicate bindings.

## 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 the keymap editor failing to delete or edit key bindings whose
keymap file entries use deprecated action names
2026-07-02 19:24:34 +00:00
Anthony Eid 2882636c06 Fix hanging updates after system sleep (#60301)
When Zed was downloading an update and the machine went to sleep, the
download would hang indefinitely on wake because the in-flight TCP
connection had silently died and nothing ever timed it out or retried.
This adds an inactivity `read_timeout` to the HTTP client so a stalled
response body errors out instead of hanging forever
(slow-but-progressing downloads are unaffected, since the timeout resets
on each chunk). It also promotes `App::on_system_wake` to a
multi-subscriber `Subscription` API and uses it in the auto-updater to
cancel an interrupted check/download on wake and start a fresh attempt.

## Self-Review Checklist:

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

Release Notes:

- Fix hanging Zed update downloads after system sleep
2026-07-02 19:13:08 +00:00
Bennet Bo Fenner 4aa8ad9742 agent: Make terminal threads searchable (#60292)
Makes cmd-f work for terminal threads.

Since the agent panel is not part of the normal pane system we have to
manually hook up the search bar.

Closes #57309

Release Notes:

- agent: Added support for searching (cmd-f) inside of terminal threads
2026-07-02 18:38:37 +00:00
Anant GoelandAnthony Eid 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
justinschmitz97anddino 31fc9d5f47 project_panel: Continue batch delete when individual entries fail (#59595)
## Summary

On Windows, `trash::delete_with_info` can return an error even when the
file was successfully moved to the Recycle Bin.

This is caused by a race condition in the `trash` crate: after
`IFileOperation::PerformOperations` completes, it re-binds the trashed
item via `SHCreateItemFromParsingName` to read its metadata, but the
shell's virtual namespace cache may not yet reflect the new item,
producing an error. Previously, the delete loop propagated this error
and aborted the entire batch. The outer `detach_and_log_err` swallowed
the error, so the user received no feedback.

This PR handles each entry independently: entries that fail to delete
are skipped, the loop continues, and undo history is recorded for the
entries that succeeded.

The upstream root cause (the post-operation re-bind race in
`zed-industries/trash-rs`) will be addressed separately.

Before:


https://github.com/user-attachments/assets/59a95ac5-098b-42dc-bffb-f3240c6b966d

After:


https://github.com/user-attachments/assets/0cd6c0b3-2ee3-4bf2-a243-3e8a83d05dd7



## Test plan

- [ ] Select multiple files in the project panel on Windows
- [ ] Trash them (right-click > Move to Trash, or `Delete` key)
- [ ] Confirm all selected files are deleted, even if one triggers the
trash-crate race
- [ ] Undo restores the files that were successfully trashed

Release Notes:

- Improved handling of failed trash or delete operations in the Project
Panel in order to display a toast informing the user that some files
could not be trashed or deleted

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-07-02 16:04:53 +00:00
Ibrahim Khananddino 27a9e2057b vim: Fix Helix cursor position when deleting to end of line (#59987)
## Why / What

Fixes #58702.

In Helix mode the block cursor is a one-character selection that can
rest on the
trailing newline at the end of a line. When you select to the end of a
line
(excluding the newline) and press `d`, Helix leaves the cursor on the
newline.
Zed instead clamped the cursor onto the character immediately to the
left of the
deleted selection.

The shared `visual_delete` always re-clipped the post-deletion cursor at
line
ends (`set_clip_at_line_ends(true)`), which is correct for Vim normal
mode but
contradicts Helix mode, where `Vim::clip_at_line_ends()` is `false`.
This also
made Helix inconsistent with itself: deleting a whole line left the
cursor on the
newline, but deleting to the end of a non-empty line clamped it onto the
previous
character. The fix honors the active mode's clip policy, so Helix keeps
the
cursor on the newline.

## Testing

- Added `test_delete_to_end_of_line_keeps_cursor_on_newline` reproducing
#58702.
- Corrected `test_helix_select_end_of_line`; its mid-line assertion had
captured
the pre-fix (clamped) cursor position. Its whole-line assertion already
expected the cursor on the newline, so the test is now internally
consistent.
- `cargo test -p vim`: 540 passed, 0 failed.
- Vim visual-mode delete is unchanged (`is_helix()` is false for Vim
modes).

Release Notes:

- Fixed Helix mode placing the cursor on the wrong character after
deleting a selection that ends at the end of a line.

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-07-02 15:38:22 +00:00
saberoueslatiandDanilo Leal e1ec575d3f editor: Update gutter hover tooltip on modifier changes (#58880)
## Context

The gutter hover button can represent either adding a breakpoint or
adding a bookmark depending on whether the secondary modifier is
pressed. Previously, the visible tooltip did not update when the
modifier changed while the popover was already open. This moves the
gutter hover intent into a shared state used by both the button and
tooltip, so the label, metadata, icon, color, click action, and
displayed keybinding all stay in sync.

Closes #58821

## How to Review

`crates/editor/src/editor.rs` adds a shared gutter hover intent type and
a custom tooltip view that reads the current modifier state while
rendering. Review that bookmark and breakpoint behavior map consistently
across the button icon/color, click action, tooltip label, metadata, and
keybinding.

`crates/editor/src/editor_tests.rs` adds a regression test covering the
tooltip intent selection with and without the secondary modifier.

Manual test after the fix below :

[Screencast from 2026-06-09
01-30-23.webm](https://github.com/user-attachments/assets/ef465eb9-e659-44da-93a6-a511c84e9401)

## Self-Review Checklist

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

Release Notes:

- Fixed the breakpoint/bookmark gutter popover not updating when
modifier keys change.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2026-07-02 14:38:04 +00:00
Bennet Bo Fenner 4ff55d09e5 Refactor agent settings UI code (#60274)
This PR removes/simplifies some APIs that were leftover after moving the
agent settings from the agent panel into the agent settings UI.
Behavior/UI should be identical.

- Removed `ConfigurationViewTargetAgent` since only a single variant was
used
- Removed `configuration_view` and `configuration_view_v2` and replaced
it with `settings_view`
- Removed all the custom configuration views that were replaced by the
API key view abstraction
- Removed `intitial_title` and `initial_description` and moved it to
`ProviderSettingsView`

Release Notes:

- N/A
2026-07-02 14:32:34 +00:00
17090674b3 text_finder: Add collapsible file groups (#60193)
## Summary

Add a chevron (`Disclosure`) to each file group header in Text Finder,
letting you fold/unfold that file's matches. Fold state is cleared
whenever a new search starts.

## Test plan

- [x] Open Text Finder, run a search with matches in multiple files
- [x] Click a header's chevron, confirm its matches hide/show and
selection lands on a visible row
- [x] Start a new search, confirm folded state doesn't carry over

Release Notes:

- Added the ability to collapse per-file match groups in Text Finder

---------

Co-authored-by: ozacod <ozacod@users.noreply.github.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2026-07-02 13:49:41 +00:00
Xiaobo Liu 78b6bf2fbe command_palette: Show scrollbar in command palette (#60239)
Enable the command palette picker scrollbar while preserving the
one-shot reopen behavior.

---

Release Notes:

- N/A or Added/Fixed/Improved ...

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
2026-07-02 13:23:17 +00:00
Smit Barmase 7eb4cb2bfa workspace: Fix panic when discarding a draft workspace (#60279)
To reproduce:

1. Open a git project with the agent sidebar, ideally with no other
threads in the sidebar.
2. Create a thread in a new git worktree and type into it without
sending.
3. While still in that worktree workspace, hit New Thread. The parked
draft must now be the last activatable entry in the sidebar.
4. Hover the parked draft → click Discard Draft
5. 💥

Release Notes:

- Fixed a panic when discarding a draft workspace.
2026-07-02 13:13:46 +00:00
Neel 969c6c719c editor: Fix panic when restoring empty selections on undo/redo (#59372)
Closes FR-81.

Also updates the error log, as the linked issue is closed.

Release Notes:

- Fixed panic when restoring empty selections on undo/redo
2026-07-02 13:07:42 +00:00
Neel 2ec0e6c2d7 editor: Fix panic when confirming completion across buffers (#59471)
In multi-buffer context, `do_completion` resolved the completion's
replace range anchors against whichever buffer currently held the newest
selection. If that selection had moved into a different file's excerpt
(while the menu remained open), the anchors belonged to a different
buffer and caused a panic.

This PR adds a guard to confirm the completion buffer and selection
buffer is the same.

Closes FR-76.

---

Release Notes:

- Fixed a panic that could occur when confirming a completion in a
multibuffer if the cursor had moved into a different file
2026-07-02 13:07:34 +00:00
Marco Grootanddino 442a3476bc Fix crash when trashing all untracked files (#60235)
# Objective

Fixes a crash when trashing a large number of untracked files from the
Git Panel, caused by unbounded OS thread spawning (thread explosion).

## Solution

`GitPanel::clean_all()` builds one deletion task per untracked file and
then awaits them one by one. Since GPUI tasks start executing as soon as
they are spawned, not when they are awaited, all deletions run
concurrently. Each of them called `RealFs::trash`, which spawned a
dedicated OS thread per call, so a large enough batch exceeded the OS
per-process thread limit and panicked at the `.expect("The os can spawn
threads")` in `RealFs::trash`.

This PR replaces the dedicated thread with `smol::unblock`, which runs
the blocking `trash::delete_with_info` call on a shared thread pool that
is capped and queues additional work instead of spawning more. This is
the same idiom already used elsewhere in the file (e.g. `atomic_write`)
for blocking filesystem work.

## Testing

- Did you test these changes? If so, how?
yes, reproduced using steps in the issue before and after and confirmed
fix works.


https://github.com/user-attachments/assets/d3bcd049-485a-486f-877a-0e5c21b7917c

Reproduction steps here:
https://github.com/zed-industries/zed/issues/60216

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

Closes #60216

---

Release Notes:

- Fixed a crash caused by spawning one thread per file when trashing a
large number of untracked files from the Git Panel.

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-07-02 13:01:57 +00:00
Bennet Bo Fenner 52b61cf424 zed: Respect default_open_behavior when opening file from Finder (#59661)
Follow up to #59551 so that it also works when opening a single file,
e.g. from finder

See #59950

Release Notes:

- N/A
2026-07-02 12:56:04 +00:00
Marshall Bowers c55693876e cloud_api_types: Remove unused AcceptTermsOfServiceResponse type (#60226)
This PR removes the `AcceptTermsOfServiceResponse` struct, as it is no
longer used.

Release Notes:

- N/A
2026-07-02 12:38:43 +00:00
Bennet Bo Fenner 21d66eb9d5 settings: Remove unused message_editor setting (#60260)
Used this at one point when we still had chat in Collab, but now it's
unused.

Release Notes:

- N/A
2026-07-02 11:45:37 +00:00
Ankan MisraandPiotr Osiewicz 4a1cb2b1e2 lsp_button: Fix missing server metadata after restart (#55162)
Restarting an LSP from the picker drops the server's metadata (version,
memory, "View Logs") even though the new server is healthy. Reproduces
with `vtsls`, `eslint`, `rust-analyzer`, and others; `vlsls` doesn't.

The button kept id-keyed state in
[`health_statuses`](https://github.com/zed-industries/zed/blob/main/crates/language_tools/src/lsp_button.rs#L159)
and
[`servers_per_buffer_abs_path`](https://github.com/zed-industries/zed/blob/main/crates/language_tools/src/lsp_button.rs#L161),
but never handled
[`LspStoreEvent::LanguageServerRemoved`](https://github.com/zed-industries/zed/blob/main/crates/project/src/lsp_store.rs#L4066)
— there was even a [stale
TODO](https://github.com/zed-industries/zed/blob/main/crates/language_tools/src/lsp_button.rs#L860)
claiming the event wasn't emitted (it's emitted from [five
sites](https://github.com/zed-industries/zed/blob/main/crates/project/src/lsp_store.rs#L11190)
in `lsp_store`). On restart the dead id lingered next to the new one in
both maps, and rendering picked the wrong entry.

Fix: handle `LanguageServerRemoved` and evict the dead id from both
maps. `binary_statuses` is left alone — it's name-keyed and shared
across restart cycles to drive the "Downloading… → Starting…" UX.

The cleanup is extracted to `LanguageServers::remove_server` so it's
directly unit-testable. Added four tests covering health eviction,
per-buffer eviction with empty-entry pruning, `binary_statuses`
preservation, and the full restart sequence.

[PR #50417](https://github.com/zed-industries/zed/pull/50417) attempted
this earlier with a `LanguageServerAdded` handler. @SomeoneToIgnore
flagged that as the wrong hook ([buffer
registration](https://github.com/zed-industries/zed/blob/main/crates/language_tools/src/lsp_button.rs#L919-L948)
is what populates state, not startup) and asked for tests. Handling
`LanguageServerRemoved` is a cleaner fit — it's the natural counterpart
to registration, and it also fixes the related case where stopping a
server (without restart) leaks state.

## Verification

Reproduced on `main` and verified the fix on this branch with `vtsls`
and `eslint` against a small TypeScript project.

| Before restart | After restart on `main` (bug) | After restart on this
branch (fix) |
|---|---|---|
| <img width="588" alt="vtsls row before restart — version, memory, View
Logs all visible"
src="https://github.com/user-attachments/assets/bdd2610b-cf8f-4ea1-bc45-f363b098c146"
/> | <img width="536" alt="vtsls row after restart on main — metadata
gone"
src="https://github.com/user-attachments/assets/66b3eefd-f801-4bfd-8b80-5f0e20fb3bc6"
/> | <img width="554" alt="vtsls row after restart on fix branch —
metadata persists"
src="https://github.com/user-attachments/assets/51d4df48-1223-4b21-856f-72d4c1eb2a6a"
/> |

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

Release Notes:

- Fixed missing language server metadata in the LSP menu after restart.
</content>

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2026-07-02 11:00:16 +00:00