Commit Graph
39737 Commits
Author SHA1 Message Date
Kirill Bulatov 01acd0ee8e Improve outline fonts and colors (#63325)
Closes https://github.com/zed-industries/zed/issues/58580

* Outline modal and panel now use buffer fonts for the contents:

<img width="1728" height="1117" alt="modal"
src="https://github.com/user-attachments/assets/5e0ef6e3-be39-4949-bc32-7087a51a02ec"
/>
<img width="1728" height="1092" alt="panel"
src="https://github.com/user-attachments/assets/5cf9edbf-5ff3-402d-a2ca-bc915bd10e8e"
/>

* Gutter colors are now fall-backed to tree-sitter better, if no
semantic tokens could be retrieved due to multi buffer shenanigans:

<img width="1728" height="426" alt="gutter"
src="https://github.com/user-attachments/assets/a175b2c8-843e-4632-b030-3edfbd350982"
/>

Release Notes:

- Improved outline fonts and colors
2026-08-28 03:28:04 +00:00
John Tur 4c6c4750d3 Improve Windows shell discovery (#63339)
- Simplify PowerShell discovery, and add support for .NET global tool
installations.
- Fix Git Bash discovery in the case where Zed was launched from within
Git Bash. Git Bash prepends its internal `mingw64\bin` directory to
`PATH`, so `which git` returns a different `bash` executable that causes
the relative path lookup to fail.

Release Notes:

- N/A
2026-08-28 03:21:39 +00:00
Lukas Wirth fa8d0b7751 crashes: Abort after reporting Windows panics (#63157)
On Windows, the panic hook generated a minidump by calling
`simulate_exception`, but that function only invokes the crash callback
and then returns. Rust could therefore unwind a panicking background
thread while leaving the rest of the application running.

Abort unconditionally after minidump generation, matching the existing
Linux and macOS behavior. The Windows-specific simulation still runs
first so the crash sidecar can persist the exception context and panic
metadata before the process terminates.

Testing:

- `cargo fmt -p crashes --check`
- `cargo nextest run -p crashes`

Release Notes:

- Fixed Windows processes remaining alive after a background thread
panic.
2026-08-28 03:20:42 +00:00
Saber OueslatiandKirill Bulatov 797e5dc95c editor: Auto-refresh Bookmarks tab when bookmarks change (#56363)
[## Context

Fixes a bug where the Bookmarks tab, opened via `editor: view
bookmarks`, showed a stale snapshot and had to be reopened to display
bookmarks added or removed while it was open.

Closes #56268

`view_bookmarks` built a one-time multibuffer and never subscribed to
`BookmarkStore`. The store also calls `cx.notify()` while resolving
serialized bookmarks into anchors, even though that bookkeeping does not
represent a user-visible bookmark change. Observing all notifications
would therefore feed resolution notifications back into the refresh
mechanism and cause redundant cancellation and requeue work. The store
now emits a dedicated `BookmarkStoreEvent::BookmarksChanged` from
bookmark mutation paths, while `resolve_all` deliberately does not emit
it.

Refresh state lives on a `BookmarksView` entity that holds the tab's
multibuffer. Split editors already share that multibuffer, so they share
the view as well. Each store event drives one reconciliation regardless
of how many split editors display it. The view remains alive as long as
any split retains it, so closing the original tab does not stop the
remaining split from refreshing.

Each refresh reconciles excerpts per path instead of rebuilding the
multibuffer: `set_excerpts_for_path` updates files that still contain
bookmarks, while `remove_excerpts` removes files whose final bookmark
was deleted. This follows the per-path reconciliation pattern used by
project diff views.

`view_bookmarks` creates the tab synchronously and populates it
asynchronously, following the existing patterns in
`ProjectDiagnosticsEditor::deploy` and
`ProjectSearchView::existing_or_new_search`. Repeated invocations focus
the existing Bookmarks tab instead of opening duplicates.

Video of the manual test:

[Screencast from 2026-05-11
02-03-38.webm](https://github.com/user-attachments/assets/8ac97245-09ff-4a79-9634-20cb8dfbb7eb)

## How to Review

**`crates/project/src/bookmark_store.rs`**

Adds `BookmarkStoreEvent::BookmarksChanged`, emitted from bookmark
mutation paths such as toggle, label edit, file rename or deletion,
clear, and deserialization, but not from anchor resolution. It also adds
`BookmarkStore::is_empty`.

**`crates/editor/src/bookmarks.rs`**

Adds `BookmarksView`, which holds the multibuffer, store subscription,
and in-flight refresh task. It reconciles excerpts and emits
`BookmarksViewEvent::Populated(ranges)` for per-editor highlights and
cursor placement. It also caches the latest populated ranges and replays
them when an editor attaches, allowing a split created after population
to display bookmark highlights immediately.

**`crates/editor/src/editor.rs`**

Adds the shared `bookmark_view`, a per-editor subscription to its
population events, and `bookmark_initial_selection_pending` for initial
cursor placement. `Editor::clone` attaches the split to the shared view
instead of creating another store subscription and refresh task.

**`crates/editor/src/editor_tests.rs`**

Adds five tests covering automatic addition and removal across multiple
files, removal of a file's path after its final bookmark is deleted,
initial cursor placement, a bookmark change racing initial population,
splitting while population is pending, cached highlights in a
late-attaching split, and continued refreshing after the original tab
releases its view handle.

## 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 Bookmarks tab not updating when bookmarks are added or removed
while the tab is open](https://github.com/zed-industries/zed/pull/56363)

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-27 23:28:05 +00:00
Mikhail Pertsev 756c2b737c helix: Add m i m/m a m and preserve the selection after those actions (#59201)
# Objective

- Preserve Helix mode selections after surround-related commands such as
adding, deleting, and replacing surrounds.
- Add Helix-compatible closest-pair behavior for `m i m` / `m a m` and
surround commands that target `m`.
- Avoid long stalls in Helix text-object boundary scans by removing
repeated syntax-scope classification during textual scans.
- Keep workflows like selecting text with `m i w`, applying `m s`, and
continuing with `i`, `a`, or another surround command aligned with Helix
behavior.

## Solution

- Add selection anchors that preserve each pre-edit selection range and
direction through surround edits.
- Update Helix surround add so the resulting selection includes the
added delimiters, allowing surround commands to compose and
insert/append actions to land outside the pair.
- Apply preserved selections to Helix surround delete and replace so
non-empty selections are not collapsed to the cursor after the edit.
- Add Helix-specific text-object bindings so `m` selects the closest
surrounding pair, `t` selects types/classes, `c` selects comments, and
`x` selects XML/HTML elements in Helix mode.
- Match the current closest pair through language bracket queries, so
delimiters inside strings or comments do not count as surrounding pairs.
- Resolve the textual boundary scanner's `CharClassifier` once per scan
and pass it by reference instead of recomputing the same classifier for
every scanned character. Word and subword boundaries still clone it only
to apply the `ignore_punctuation` flag.

## Performance

The textual boundary scanner previously called
`char_classifier_at(from.0)` inside the per-character comparison
closures for the four `ImmediateBoundary` scan methods and
`FuzzyBoundary::to_boundary`. That lookup resolves the language scope
through the syntax layers, and the value was loop-invariant because
every iteration used the scan's starting offset.

Local debug benchmark, using `] m` in a roughly 540 KB buffer with no
pair characters so the scan runs to EOF across all pair boundaries:

|        | `] m` |
| ------ | -----: |
| Before | 36.3 s |
| After  | 210 ms |

This speeds up the remaining textual scanner paths, including `m i (` /
`m i "`-style pair objects, word/sentence/paragraph objects, `]` / `[`
text-object navigation, and `] m` / `[ m`. The current-pair `m i m`, `m
a m`, `m d m`, and `m r m` paths use the tree-sitter closest-pair path
instead.

## Testing

- Ran `cargo test -p vim test_helix_surround -- --nocapture`.
- The focused Helix surround test filter passed: 10 passed, 0 failed.
- Added coverage for closest-pair selection, Helix-specific text-object
keys, and surround selection preservation.

## Self-Review Checklist:

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

---

Release Notes:

- Added Helix mode support for closest-pair text objects with `m i m`
and `m a m`.
- Fixed Helix mode surround commands to preserve selections after edits
and avoid slow textual boundary scans.
2026-08-27 23:24:52 +00:00
DongandKirill Bulatov 8166e3d7b8 Add folder_indicator setting to show chevron and folder icon together (#62393)
# Objective

- Enable panels to show chevron and icon at the same time.
- Closes #8661

## Solution

- Replaces `folder_icon` with a new `folder_indicator` which converts
from a boolean to enum (`both`, `chevron`, `icon`) for the three display
cases

## Testing

- gpui and migration tests had been applied

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

### project panel

both | chevron | icon
--- | --- | ---
<img width="400" alt="both_project_panel"
src="https://github.com/user-attachments/assets/4c21e1a1-a7a4-4471-b7de-fe867373ddbd"
/> | <img width="400" alt="chevron_project_panel"
src="https://github.com/user-attachments/assets/a626a82e-e5b7-470d-9d93-ed5787dc83d6"
/> | <img width="400" alt="icon_project_panel"
src="https://github.com/user-attachments/assets/20f9c55e-87c4-477a-b4c9-b070d6e5a1db"
/>

### git panel

both | chevron | icon
--- | --- | ---
<img width="400" alt="both_git_panel"
src="https://github.com/user-attachments/assets/3dc166dd-9e63-4943-b803-df3f167876b6"
/> | <img width="400" alt="chevron_git_panel"
src="https://github.com/user-attachments/assets/8dfd2c10-3a68-439a-8019-4951b72e17d1"
/> | <img width="400" alt="icon_git_panel"
src="https://github.com/user-attachments/assets/d78a9938-91e7-4d39-a3c8-04647da67768"
/>

### outline panel

both | chevron | icon
--- | --- | ---
<img width="400" alt="both_outline_panel"
src="https://github.com/user-attachments/assets/1b58c679-0bea-4600-a8ac-e800b0e8d24c"
/> | <img width="400" alt="chevron_outline_panel"
src="https://github.com/user-attachments/assets/0a9358e4-ec89-40d8-8d5e-a53b784ed30a"
/> | <img width="400" alt="icon_outline_panel"
src="https://github.com/user-attachments/assets/d8bf5199-5a8c-4de0-b516-00247e6531a5"
/>



---

Release Notes:

- Added a `folder_indicator` setting that can show the disclosure
chevron and folder icon at the same time in the project, outline, and
git panels.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-27 20:11:28 +00:00
1e2e422c7b Fix settings schema missing extension-provided LSP settings on remote (#62355)
## Objective

Fixes an issue where language servers provided by extensions are not
included in the settings schemas served by remote servers. When
connecting to a remote server via the
`open_remote_project_with_existing_connection` flow (dev servers,
multi-workspace reopen, git worktree picker), setup-N servers never
received any extension sync, so their schemas omitted extension-provided
language servers, breaking language support for remote development.

## Solution

Three changes ensure that language servers provided by extensions are
included in the settings schemas served by remote servers:

1. **Register connections opened via
`open_remote_project_with_existing_connection` with the extension
store**: dev servers, multi-workspace reopen, and the git worktree
picker now register their connections with the extension store so that
extensions are synced to those servers. Previously only the
`open_remote_project` flow did this, so setup-N servers never received
any extension sync and their schemas omitted extension language servers.

2. **Emit `ExtensionsInstalledChanged` from `HeadlessExtensionStore`
after sync and install complete**: this allows the remote process to
invalidate its cached settings schemas. The local `ExtensionStore`
already emitted this event; without it, the remote schema cache stayed
stale for the lifetime of the server process.

3. **Include available LSP adapters in the project settings schema**:
this matches the user settings schema (this was fixed for `settings` in
#46766 but never applied to `project_settings`).

## Testing

- Manually verified that after connecting to a remote server via the
`open_remote_project_with_existing_connection` flow (including dev
servers and the git worktree picker), extension language servers appear
in the schema served by the remote server.
- Verified that `ExtensionsInstalledChanged` is emitted after sync and
install complete, and that the remote schema cache is correctly
invalidated and rebuilt.
- Verified that the `project_settings` schema includes the available LSP
adapters, matching the behavior of the user settings schema.
- Reviewers should focus on the multi-workspace reopen and git worktree
picker flows (the two previously unregistered flows) to confirm that
extension language servers are correctly synced and appear in the
schema.

## 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
- [x] Performance impact has been considered and is acceptable

## Showcase
**Server / Project** — before the fix
<img width="1061" height="749" alt="image"
src="https://github.com/user-attachments/assets/d6c5459f-58fb-4769-a701-f6fb317adc37"
/>
**Local**
<img width="1119" height="449" alt="image"
src="https://github.com/user-attachments/assets/fb30a1e2-74f0-4439-a25f-1022ed164074"
/>

---

Release Notes:

- Fixed an issue where language servers provided by extensions were
missing from settings schemas served by remote servers.

---------

Co-authored-by: vancez <vancez@users.noreply.github.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-27 17:09:28 +00:00
ec312b2701 Add LSP call hierarchy modal (#53239)
<img width="1128" height="953" alt="image"
src="https://github.com/user-attachments/assets/b2017c0a-e25a-49d7-9342-d074014d085c"
/>

Closes #14203

Release Notes:
- Initial Call Hierarchy support in Zed

---------

Co-authored-by: Alexey Olshanskiy <gh@aohoy.dev>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-27 16:21:41 +00:00
Cameron Mcloughlin 5218009a2d gpui: IME race condition bug (#63311)
When an IME makes a selection, but doesn't modify the text, there was a
race condition, where the GPUI->mirror sync could overwrite the
`selectionchanged` event, causing IME sessions to be discarded.

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-08-27 13:23:18 +00:00
12ef40c316 lsp: Add client support for LSP 3.18 markdown diagnostic messages (#61030)
LSP 3.18 allows servers to send [`MarkupContent` diagnostic
messages](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnostic),
guarded by the client capability
`textDocument.diagnostic.markupMessageSupport`.

- Advertise `markup_message_support` only while pull diagnostics are
enabled because `textDocument.diagnostic` is the pull-model capability.
  LSP 3.18 currently has no equivalent capability for push diagnostics:

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnosticClientCapabilities
  https://github.com/microsoft/language-server-protocol/issues/2246
- Handle `string | MarkupContent` messages in both push and pull
diagnostic paths: markdown-kind messages populate the existing
`Diagnostic::markdown` field (rendered in hover popovers and the
diagnostics panel), plaintext-kind markup remains plain text, and plain
string messages keep going through the adapter's
`diagnostic_message_to_markdown`.
- Preserve server-provided markup for code actions sent back to the
originating server, avoid forwarding markup diagnostics to other
servers, and render diagnostic metadata without altering the
server-provided markdown.
- Carry the markup kind over RPC via a new optional
`LspDiagnostic.markup_message_kind` proto field so remote/collab
projects round-trip `MarkupContent` messages.

Depends on the lsp-types change that turns `Diagnostic.message` into a
`DiagnosticMessage` enum (`string | MarkupContent`):
https://github.com/zed-industries/lsp-types/pull/15
Once merged, Cargo.toml can point to the upstream commit.

Note that Zed already rendered some plain-string diagnostics as Markdown
through language-specific adapter hooks, including `rust-analyzer`. This
adds protocol-level support for diagnostics explicitly sent as LSP 3.18
`MarkupContent`, while preserving the existing adapter fallbacks.

As a result, this does not introduce a new diagnostics rendering
pipeline.
Server-provided Markdown is routed through the existing
`Diagnostic::markdown` path, with small fixes to handle Markdown-only
updates and block content correctly.

## Showcase

Example from [JETLS.jl](github.com/aviatesk/JETLS.jl) (a Julia language
server):

> Before
<img width="924" height="160" alt="Screenshot 2026-07-15 at 16 05 40"
src="https://github.com/user-attachments/assets/b19fe9e3-50e3-44e4-9b4d-ac8bd438d3d6"
/>

> After
<img width="924" height="160" alt="Screenshot 2026-07-15 at 14 13 05"
src="https://github.com/user-attachments/assets/359c3382-118d-4fa6-aa91-6bd3661d3d28"
/>

---

Release Notes:

- Added support for rendering LSP 3.18 Markdown diagnostic messages from
language servers.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-08-27 12:55:42 +00:00
Cameron Mcloughlinandzed-zippy[bot] d84e5d4992 gpui: Add text_edit_editable_range API (#63294)
When syncing text to the browser IME mirror, we sometimes need to mark a
particular range as "editable". Native clients have a pull-based model,
so don't need this mechanism, but on the web we need to proactively push
content to the IME mirror `textarea`.

---

Release Notes:

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

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-27 10:13:49 +00:00
Pranav Bansal c8dfe26a7e Add support for Visual Line select in terminal vi mode (#63251)
# Objective

Add support for Visual Line Select in terminal vi mode.

## Solution

Add handling for "V" akin to Visual Line Select mode in vim.

## Testing

manually tested these changes by running locally (`cargo run`)

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


https://github.com/user-attachments/assets/a39636cd-a82e-444d-bdac-8f86d76f03f4



---

Release Notes:

- Added support for Visual Line Select in terminal vi mode
2026-08-27 06:40:50 +00:00
Miguel Raz Guzmán Macedo 6efd4950d6 Require clear sections in lint UI fixtures (#62659)
Add `// --- SHOULD FIRE ---- ` and `// ---- SHOULD NOT FIRE ---- ` to
the `/lint-creator` skill.

Release Notes:

- N/A
2026-08-27 05:53:18 +00:00
Miguel Raz Guzmán Macedo fe5b7cedc4 Remove wasted clones of loop-invariant values (#62763)
# Objective

Remove avoidable clones of loop-invariant values that pay a copy on
every loop iteration. These were found by running a prototype
`deep_clone_in_loop` dylint (modeled on the accidentally quadratic
project-search fix in #62658) across the workspace. None of these sites
are quadratic in practice — the loops are bounded — but each one does
strictly wasted work that a one-line change removes.

## Solution

- `collab/src/api/extensions.rs`: use `next_marker.take()` instead of
`next_marker.clone()` for the S3 pagination marker. The marker is either
overwritten via `clone_from` at the end of the iteration or the loop
breaks, so it is never read after the `take`.
- `project/src/manifest_tree/path_trie.rs`: build the trie key with
`Arc::from(path_so_far.as_rel_path())` instead of
`path_so_far.clone().into()`. The `From<RelPathBuf> for Arc<RelPath>`
impl copies the bytes into the `Arc` anyway, so the intermediate
`RelPathBuf` clone was a second, redundant copy.
- `context_server/src/client.rs`: in `notify`, split off the last
handler and move the `serde_json::Value` payload into it, cloning only
for the preceding handlers. Previously every handler received a clone
and the final one was always wasted.
- `editor/src/rewrap.rs`: use `std::mem::replace` to move the
comment-delimiter and rewrap-prefix accumulators into the pushed range
instead of cloning them and immediately reassigning.

## Testing

- `cargo check -p collab -p project -p context_server -p editor` —
clean.
- `cargo test -p editor rewrap` — 7/7 pass, including the
boundary-sensitive `test_rewrap*` editor tests.
- `cargo test -p context_server` — 97/97 pass.
- `cargo test -p project path_trie` — 2/2 pass.
- Re-ran the `deep_clone_in_loop` lint on the four crates: the
`extensions.rs`, `path_trie.rs`, and `rewrap.rs` hits are gone;
`client.rs` still (correctly) reports the remaining required per-handler
clone.
- Not tested platform-specifically; the changes are
platform-independent.

## 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
2026-08-27 05:35:30 +00:00
Miguel Raz Guzmán Macedo f595fd84cf Improve lint-creator skill (#60383)
Rewrote `.agents/skills/lint-creator/SKILL.md` to be more concrete and
concrete.

Release Notes:

- N/A
2026-08-27 05:34:16 +00:00
Smit Barmase f66ed399cd gpui: Fix stale pending input when a window is blurred (#63271)
This prepares for the keybinding hints PR.

To reproduce, press `ctrl-b` in a GPUI app with `ctrl-b h` and `ctrl-b
j` bindings, then call `window.blur()`. The live pending state clears,
but observers still report `ctrl-b`.

`Window::blur` now clears pending input and notifies observers after the
current effect cycle. I don't think we currently exercise this path in
Zed, and I was only able to reproduce it with an example GPUI app.

Release Notes:

- N/A
2026-08-26 21:36:59 +00:00
Jacob WolfandSmit Barmase fc9258b463 editor: Add file permalink support to tabs and the Project Panel (#62177)
# Objective

- Add file-level hyperlink support for opening and copying hyperlinks
for Git remote source control to project panel and tabs
- Unify the language for Git remote hyperlinks across blame, project
panels, and tabs to be similar to GitLens' definitions (which are
commonly used in VS Code)

## Solution

- Updated the Git crate to expose relevant metadata to surface new
options within the editor
- Added new options for `Open File on Remote` and `Copy Remote File URL`
to project panel/file explorer and file tabs
- Altered the blame UI options to be consistent with new labels / more
clear

## Testing

- Ran `cargo run` to boot app and manually smoke test (see proof below)
- Added unit tests for this change

## Self-Review Checklist:

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

## Showcase



https://github.com/user-attachments/assets/d600ca4f-47e7-438c-90e1-f40124a606b4

---

Release Notes:

- Added options to open or copy whole-file permalinks from file tabs and
the Project Panel.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-08-26 18:21:33 +00:00
Cameron Mcloughlin 8fc1a8a0c6 gpui: Text input configuration and web implementation (#63264)
Allows setting various attributes for the underlying mirror textarea on
the web. Allows GPUI app authors to specify things like "this element
should be auto-corrected"

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-08-26 17:57:23 +00:00
Grant HutchinsandKirill Bulatov 3b90a96830 agent: Release completed terminal PTY resources (#62978)
Closes #62972

Completed Agent terminal cards remain alive so conversation history can
render their output. Each retained terminal also kept its Alacritty PTY
sender alive, which retained a poller and one kqueue descriptor after
the command exited.

Terminal lifecycle state is now more strongly typed to prevent this
class of regression. Task terminals are created through a sealed
`TerminalMode` API that pairs their running state with the correct
completion channel, while PTY resources use explicit active and released
states. This makes invalid lifecycle combinations unrepresentable
instead of relying on callers to coordinate independent `Option` values
correctly.

- Release the live PTY sender after final terminal output is captured.
- Preserve PTY process metadata and working-directory behavior for
historical terminal cards.
- Represent PTY resources as explicit active or released lifecycle
states.
- Construct interactive and task terminals through typed modes so a task
cannot omit its running state or use a mismatched completion channel.
- Keep resource release idempotent for later ACP release and entity
destruction.
- Add a macOS regression test that retains the historical terminal
entity while exercising the complete sandboxed terminal tool path.

Release Notes:

- Fixed Agent terminal tool calls leaking file descriptors on macOS.

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-26 17:56:33 +00:00
a1cc2548f9 open_router: Support effort-based reasoning (#61308)
# Objective

- This PR adds support for effort-based reasoning for OpenRouter models
- This PR correctly configures whether OpenRouter models support
reasoning or not
- Fixes #58843 (already closed, was converted to #58848 )

## Solution

- The OpenRouter `/v1/models` endpoint includes data about supported
effort levels (see
[docs](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#discovering-per-model-reasoning-options))
and model capabilities
- This PR uses this data to populate the "effort" dropdown in the agent
panel (compare #56411 which added a similar feature for OpenAI) and to
provide better model metadata (`supports_thinking`,
`supports_disabling_thinking`).
- If a model supports `max_tokens`-based thinking, effort levels will
still be shown. OpenRouter automatically converts effort levels into an
appropriate `max_tokens` budget
([docs](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#reasoning-effort-level)).
This way users are not limited to a fixed `max_tokens` budget.
- Some models return `"supported_parameters": ["reasoning"]` with
`"reasoning": {"mandatory": false}`. From the docs I am not quite sure
what that's supposed to mean. The PR interprets these models with a
binary thinking on/off switch.

The PR also fixes the inverted logic where
`supports_parallel_tool_calls` would always return `false`, which would
then result in `parallel_tool_calls: None` for the actual API call
(which enables parallel tool calls by default). So the result of
`supports_parallel_tool_calls` was interpreted opposite to what I would
expect. The PR now returns `true` from `supports_parallel_tool_calls`
and adapts the corresponding call. There is no change in behavior
(`parallel_tool_calls` are always enabled in practice), it just fixes
the code logic.

## Testing

I tested the changes manually in an instance started via `cargo run`:
- I tested using GLM 5.2 and GPT 5.5. The reasoning effort is being
shown in the agent panel. Changing the effort level changes the amount
of thinking that the model does (e.g. on "Extra High" I consistently see
thinking blocks, on lower levels I sometimes do. I don't see thinking
blocks when thinking is disabled).
- Some models with `"reasoning": {"mandatory": false}` can be called
with effort levels. I am not sure if it actually makes a difference, but
the API doesn't reject it. Maybe there are configuration options that
are not currently exposed by this PR. I think the approach in this PR is
a safe default though.
- To test this PR:
  1. Build it via `cargo run`
  2. Set an OpenRouter API Key
3. Open the Agent panel and select different models. Notice that the
effort level selector and the thinking toggle is dynamically
shown/hidden/populated based on the model.

## Self-Review Checklist:

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

—

Release Notes:

- Added support for effort-based reasoning when using OpenRouter models

---------

Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2026-08-26 17:39:50 +00:00
Bennet Bo Fenner 5ed5bf95e5 Move language model stream mapping to background executors (#63241)
Language model event mappers run as part of lazy completion streams.
Because these streams are polled on the main thread, repairing and
parsing large streamed tool inputs can freeze the UI.

This moves completion stream mapping to background executors. A bounded
channel preserves event order and backpressure, while dropping the
stream cancels its background task. The change covers all providers that
perform this work.

Release Notes:

- Fixed UI hangs when language model providers stream large tool inputs.
2026-08-26 17:36:06 +00:00
7ecab315fb Fix project search holding a reference to closed unsaved files (#61677)
# Objective

Fixes #28398

## Solution

This issue was occurring because `ProjectSearch` stored
`Entity<MultiBuffer>` with has reference counted pointers to underlying
buffers
The function `remove_deleted_buffers` is renamed to
`remove_stale_buffers` and it now also checks for buffers which do not
have a file associated with them and are closed. Then, it removes them
from `Entity<MultiBuffer>` stored in ProjectSearch. This function is
also called in again when workspace is upgraded.

## Testing

Bug being fixed was manually verified. 

## Self-Review Checklist:

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


Release Notes:

- Fixed project search retaining results from closed untitled buffers.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-26 17:00:03 +00:00
zed-zippy[bot] ac099b4a80 Bump Zed to v1.19.0 (#63253)
Release Notes:

- N/A

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-26 14:53:52 +00:00
Yifeng Xu 4a9a863cee Improve auto indentation in situations with multiline comments present (#61669)
## Objective

Fix incorrect indentation after multiline comments and when pasting
multiline code immediately after a comment.

Fixes #61668 
Fixes #55597 

## Solution

- Calculate logical indentation from the opening line of block comments,
documentation comments, and multiline strings.
- Reuse the logical indentation for both newline handling and multiline
paste auto-indent.
- Preserve the relative indentation of pasted multiline content while
using the logical indentation of the surrounding code as its basis.

## Testing

- `cargo test -p editor --lib test_newline -- --nocapture`
- `cargo test -p editor --lib test_paste -- --nocapture`
- `cargo test -p language --lib test_autoindent -- --nocapture`
- `./script/clippy -p language`
- `./script/clippy -p editor`
- Regression coverage includes Go, TypeScript, and Python comment/string
indentation, plus Go multiline paste after a documentation comment.
- No platform-specific behavior is involved; the fix is implemented in
shared editor and language auto-indent logic.

The demonstration video is as follows:


https://github.com/user-attachments/assets/2a2ee494-d4ea-4b16-8644-f868b9f31272


https://github.com/user-attachments/assets/9487f893-e584-448d-a1c7-a94c76c03f5b


## 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 incorrect indentation after multiline comments and multiline
paste.
2026-08-26 14:33:25 +00:00
ProhectandKirill Bulatov ea701d40f3 agent: Coalesce thread saves into a single worker (#63053)
# Objective

- Reduce excessive RAM usage during long agent sessions. Previously
every
`Thread::notify` triggered a full serialization of the entire
conversation
(including any embedded base64 image) to JSON, so streaming bursts
queued
many large, redundant saves and ballooned memory into the multi-GB
range.
- Related to #57126.
- Related to #62133.

## Solution

- Replace the per-notification save task with a single coalescing save
worker
  per session in `crates/agent/src/agent.rs`.
- `save_thread` now writes the latest snapshot into an in-place buffer
and wakes
  the worker via a `watch` channel, instead of spawning a fresh
  full-conversation save on every notification.
- The worker drains the buffer in a loop, saving only the latest
snapshot per
burst (latest-wins coalescing), and preserves save-on-close by draining
the
  final snapshot before exiting.

## Testing

- `cargo check -p agent`
- `cargo test -p agent test_close_session_saves_thread`
- `cargo test -p agent test_save_load_thread`
- `cargo test -p agent test_threads_flushed_to_database_on_app_quit`

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

---

Release Notes:

- Improved memory usage during long agent sessions.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-26 14:33:17 +00:00
Kirill Bulatov 34241d5fc8 Reduce LLVM IR bloat (#63232)
Cuts serde monomorphization in settings_content: both parse entry points
now share one deserializer instantiation, and the flatten-heavy settings
structs deserialize through a small manual routing macro instead of
serde's Content buffering.
Parsed values seem to be unchanged; JSON schema and serialization
derives are untouched.

`cargo llvm-lines -p settings_content`:
Before (1ff7cb669b): 2716889 lines, 92801 copies
After: 1203744 lines (-55.7%), 47122 copies (-49.2%)

With sccache disabled, `cargo clean` and `cargo build -p zed`:
Before: 132.8s wall, 1440.6s CPU, zed binary 1241791992 bytes
After: 128.8s wall (-3.0%), 1400.0s CPU (-2.8%), zed binary 1204044312
bytes (-3.0%, -37.7MB)

Release Notes:

- N/A
2026-08-26 14:33:14 +00:00
Kirill Bulatov c595091b0a Bump dependencies to dedupe the crate graph (#63231)
Deduplicates crates with different versions from the graph, drops unused
features.

`cargo tree -d duplicate` listing: 160 -> 112 lines.

<details>
<summary>Deduplicated list</summary>

```
base64 (v0.22.1, v0.21.7 -> v0.22.1)
convert_case (v0.11.0, v0.10.0, v0.8.0 -> v0.11.0, v0.10.0)
core-foundation (v0.10.0, v0.9.4 -> v0.10.0)
cssparser (v0.36.0, v0.35.0 -> v0.37.0, v0.36.0)
fancy-regex (v0.18.0, v0.16.2 -> v0.19.0)
fixedbitset (v0.5.7, v0.4.2 -> v0.5.7)
h2 (v0.4.12, v0.3.27 -> v0.4.12)
heck (v0.5.0, v0.4.1, v0.3.3 -> v0.5.0, v0.4.1)
html5ever (v0.39.0, v0.35.0 -> v0.39.0)
hyper (v1.7.0, v0.14.32 -> v1.7.0)
hyper-rustls (v0.27.9, v0.24.2 -> v0.27.9)
mach2 (v0.6.0, v0.5.0, v0.4.3 -> v0.6.0, v0.5.0)
markup5ever (v0.39.0, v0.35.0 -> v0.39.0)
phf (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3)
phf_codegen (v0.13.1, v0.11.3 -> v0.13.1)
phf_generator (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3)
phf_macros (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3)
phf_shared (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3)
prost (v0.12.6, v0.9.0 -> v0.14.4)
prost-build (v0.12.6, v0.9.0 -> v0.14.4)
prost-derive (v0.12.6, v0.9.0 -> v0.14.4)
prost-types (v0.12.6, v0.9.0 -> v0.14.4)
rustix (v1.1.4, v0.38.44 -> v1.1.4)
rustls (v0.23.40, v0.21.12 -> v0.23.40)
rustls-native-certs (v0.8.3, v0.6.3 -> v0.8.3)
rustls-pemfile (v2.2.0, v1.0.4 -> v2.2.0)
rustls-webpki (v0.103.13, v0.101.7 -> v0.103.13)
security-framework (v3.5.1, v2.11.1 -> v3.5.1)
socket2 (v0.6.3, v0.5.10 -> v0.6.3)
string_cache (v0.9.0, v0.8.9 -> v0.9.0)
string_cache_codegen (v0.6.1, v0.5.4 -> v0.6.1)
strum (v0.28.0, v0.27.2 -> v0.28.0)
strum_macros (v0.28.0, v0.27.2 -> v0.28.0)
tendril (v0.5.1, v0.4.3 -> v0.5.1)
tokio-rustls (v0.26.4, v0.24.1 -> v0.26.4)
tungstenite (v0.28.0, v0.27.0 -> v0.28.0)
web_atoms (v0.2.6, v0.1.3 -> v0.2.6)
which (v6.0.3, v4.4.2 -> v8.0.5)
```

</details>


Release Notes:

- N/A
2026-08-26 14:33:13 +00:00
Kirill BulatovandKostia R 279da63882 Flush all persistence threads for the rest for various shutdown cases (#63213)
Follow-up to https://github.com/zed-industries/zed/pull/60477
Closes #25022

We have more places that need a similar synchronization before quitting
the app: restarts on update, reloading the workspace.

On top of it, two more findings:

* `on_app_will_quit` was redundant: the global `on_app_quit` hook
flushes a strict superset of the same tasks and runs before windows are
cleared, while the entity hook held only a weak handle and could never
flush the `Window`-dependent workspace state anyway.

* previously, shutdown was run as `cx.spawn`, yet main threads got
parked on app shutdown: now using `cx.background_spawn` instead

Release Notes:

- Improved data persistence during various app shutdown cases

---------

Co-authored-by: Kostia R <k-bx@k-bx.com>
2026-08-26 14:33:10 +00:00
Kirill BulatovandBennet Bo Fenner 839ab7a9f7 Fix shallow diffs causing a lot of computations (#63024)
For repositories with shallow mode enabled, before, Zed instantly loaded
diff changes which could be very large and CPU-demanding:


https://github.com/user-attachments/assets/5577730a-efef-424f-b749-501394a8b51f

Now, we show the following state instead of loading:

<img width="1728" height="1084" alt="after"
src="https://github.com/user-attachments/assets/03cc47fe-7074-4e8b-ba12-2fefa101377d"
/>

(the button allows to move on and do the load nonetheless)


Release Notes:

- Fixed shallow diffs causing a lot of computations

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2026-08-26 14:33:08 +00:00
Kirill Bulatov 1475887faf Enable project search on type by default (#62506)
Closes https://github.com/zed-industries/zed/issues/9318

Most of the diff is tests.

Notable behavior changes during this mode, compared to current mode:

* unsaved changes in multi buffer won't spawn any "save or not" pop-ups
during typing — submitting the query still does it, as before.
Unsaved files will stay so after being sorted out on typing: we cannot
save them by default as file-less buffers need a save modal; Zed should
already be able to persist and restore such changes on restart.

* gutter may jump during search, if new excerpts with large line numbers
appear during query input — yet it would not shrink back to avoid
excessive flickering and rewraps

Release Notes:

- Enabled project search on type by default (use `{ "search": {
"search_on_type": false } }` to restore the previous behavior)
2026-08-26 14:33:03 +00:00
HuaGu-Dragon 4ccbcabfee movement: Remove unused stop_at_soft_boundaries parameter from line_beginning (#63245)
# Objective

remove the entire `stop_at_soft_boundaries` parameter from
`line_beginning`, since it was never used

---

Release Notes:

- N/A
2026-08-26 14:28:43 +00:00
Anthony Eid fecc3273ed gpui_platform: Expose headless renderer through bench support (#63244)
GPUI's `bench-support` feature provides the benchmark context and
headless-renderer interface without enabling `test-support`, but the
platform implementation remained available only through
`gpui_platform/test-support`. As a result, consumers could not use
`#[gpui::bench]` with a fully isolated feature graph because the
generated benchmark harness calls
`gpui_platform::current_headless_renderer()`.

This threads `bench-support` through `gpui_platform`, `gpui_macos`, and
`gpui_apple`, exposing the existing Metal headless renderer without
widening unrelated test window or prompt APIs. The existing benchmark
package now requests the platform's canonical `bench-support` feature.
Its other test-backed fixtures are intentionally unchanged and remain
outside this focused dependency fix.

Validation:

- Confirmed `gpui_apple/bench-support`, `gpui_macos/bench-support`, and
`gpui_platform/bench-support` resolve no `test-support` feature with
`cargo tree --locked --no-default-features --features bench-support -e
no-dev,features`.
- Ran `cargo check --locked -p benchmarks --benches` to compile every
existing `#[gpui::bench]` target against the real platform headless
renderer.
- Ran `cargo nextest run --locked -p gpui_apple -p gpui_macos -p
gpui_platform`.
- Ran `./script/clippy` for each changed platform package with
`--no-default-features --features bench-support`.
- Ran `cargo fmt --check`.

Release Notes:

- N/A
2026-08-26 11:00:10 +00:00
Casey Avila 45cd77bba0 debugger: Update debug panel when breakpoint store changes (#63240)
# Objective

- There is currently a bug where toggling breakpoints would not be
immediately reflected in the breakpoint list of the debug panel
- For example, pressing `F9` to create a breakpoint would not
immediately add an entry to the breakpoints list in the debug panel,
instead requiring another event like mouse movement

## Solution

- Subscribe the debug panel to changes to the breakpoint store.

## Testing

- Manually tested

## Self-Review Checklist:

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

## Showcase


https://github.com/user-attachments/assets/d2b7efab-0131-491e-8339-3657edaf7fcd



https://github.com/user-attachments/assets/4161a435-c59e-4f6a-9387-31528c127c80





---

Release Notes:

- Fixed debugger panel not immediately reflecting changes in toggled
breakpoints
2026-08-26 10:17:48 +00:00
Anthony Eid 1f7eae7fb7 gpui: Separate benchmark support from test support (#63039)
`gpui::bench` previously required GPUI's full `test-support` feature.
Any benchmark using the supported GPUI harness therefore compiled
test-only APIs and fakes, even when the benchmark otherwise followed
production dependency paths.

This change introduces `bench-support` as GPUI's canonical benchmark
feature and keeps `bench` as a compatibility alias for existing
consumers. The benchmark feature now exposes only the existing GPUI
internals that `BenchAppContext` needs: the real threaded dispatcher,
profiler integration, and a headless platform surface. Benchmark HTTP
requests use the production `BlockedHttpClient`, so accidental network
access fails instead of silently entering a fake response path.

The current headless implementation reuses the cfg-stripped core of
`TestPlatform`. Test-only prompt state, simulation APIs, and test
executors remain unavailable under `bench-support`. Cargo feature-tree
checks confirm that both `bench-support` and the compatibility alias
remain independent of `test-support`.

This also adds a `gpui-bench` agent skill covering production-shaped
fixtures, frame and foreground responsiveness, macOS headless Metal
rendering, deterministic correctness guards, Criterion measurement,
Instruments symbolication, and the requirement that a benchmark's
complete dependency graph contain no `test-support` feature.

Two follow-ups are intentionally deferred to keep this feature-isolation
change reviewable:

- Extract the shared headless implementation into
`HeadlessPlatformCore`, with separate `BenchPlatform` and `TestPlatform`
wrappers. This will remove benchmark-related cfg branches from the
test-facing type and make their supported surfaces explicit.
- Add a shared scripted HTTP client that compiles independently under
either `http_client/test-support` or `http_client/bench-support`. Tests
and benchmarks could then serve predefined responses through the same
deterministic transport boundary without either support feature enabling
the other; the default benchmark context should remain network-blocked.

This PR only isolates GPUI itself. Migrating downstream benchmark
fixtures that explicitly request other crates' `test-support` features
remains separate work.

Testing performed:

- `cargo tree --offline --package gpui --no-default-features --features
bench-support --edges features --invert gpui`
- `cargo tree --offline --package gpui --no-default-features --features
bench --edges features --invert gpui`
- `cargo check -p gpui --no-default-features --features bench-support`
- `cargo check -p gpui --no-default-features --features bench`
- `git diff --check`

Release Notes:

- N/A
2026-08-26 09:51:50 +00:00
Gaauwe Rombouts 5f1f7e634b gpui_web: Improve mobile keyboard focus handling (#63220)
Prevent mobile browsers from dismissing the software keyboard during
touch handling, and only activate the keyboard when a touch targets an
editable text input. On iOS, the hidden IME element is made editable
before it receives focus so the keyboard can reopen after interacting
with non-editable controls or dismissing it manually.

Release Notes:
- N/A
2026-08-26 09:49:03 +00:00
Lena b415b5d447 Nudge contributors to allow maintainer edits (#63204)
Release Notes:

- N/A
2026-08-26 09:35:51 +00:00
Bennet Bo Fenner 764780249e open_ai: Classify additional overload errors (#63238)
OpenAI can return streamed overload errors with the codes
`server_is_overloaded` and `slow_down`. Zed previously only recognized
`overloaded_error`, so these responses fell through to
`ProviderErrorCategory::Other`. Downstream consumers could then treat a
routine provider-capacity failure as an unexpected error.

Classify all three codes as `ProviderErrorCategory::Overloaded`. This
lets existing retry and error-reporting behavior handle them
consistently without matching provider-specific messages outside the
OpenAI response parser.

This matches Codex’s handling. Codex classifies both
[`server_is_overloaded` and `slow_down` in streamed
responses](https://github.com/openai/codex/blob/a26f1806a4f4b8cfec2ea1be129963815a61e58c/codex-rs/codex-api/src/sse/responses.rs#L696-L699),
and performs the [same classification for HTTP 503 response
bodies](https://github.com/openai/codex/blob/a26f1806a4f4b8cfec2ea1be129963815a61e58c/codex-rs/codex-api/src/api_bridge.rs#L63-L74).

Release Notes:

- Improved OpenAI error handling
2026-08-26 08:55:34 +00:00
1d7e5f1d01 gpui_windows: Fix window placement on secondary monitor with different DPI scaling (#62859)
# Objective

Fixes #48927. On Windows, when monitors have different DPI scaling
factors, a new window opened on a secondary monitor can be positioned
partially off-screen, with the title bar unreachable.

## Solution

`WindowsWindow::new` calls `CreateWindowExW` with `CW_USEDEFAULT` for
the window's initial position, so Windows picks a starting spot
(typically based on where the previous window was, which is often the
primary monitor) before the window is explicitly moved to its intended
monitor via `SetWindowPlacement`.

`WindowsWindowState::new` immediately reads the window's scale factor
via `GetDpiForWindow(hwnd)` at that point — i.e. the DPI of wherever
Windows initially placed it, not necessarily the target monitor.
`retrieve_window_placement` then used that scale factor to convert the
target monitor's logical bounds into physical pixels. When the two
monitors have different scaling (e.g. 150% vs 100%, as in the linked
issue), this produces the wrong physical rect, leaving the window
off-screen.

The target `WindowsDisplay` already computes its own correct
`scale_factor` from the actual monitor (`get_scale_factor_for_monitor`)
— this is also what `check_given_bounds` already uses. This PR exposes
that value via `WindowsDisplay::scale_factor()` and uses it in
`retrieve_window_placement` instead of the transient window's scale
factor, since the bounds being converted are expressed in logical pixels
for that target display.

## Testing

- Verified the logic by tracing through `WindowsWindowState::new` →
`retrieve_window_placement` → `calculate_window_rect` and confirming the
target monitor's own DPI (not the temporarily-assigned window DPI) is
now used to compute the physical placement rect, matching the approach
`WindowsDisplay::check_given_bounds` already uses for the same
target/temporary-monitor mismatch.
- I wasn't able to build/run Zed locally in this environment (missing
Windows SDK components in the local toolchain, unrelated to this change)
to reproduce the original multi-monitor/mixed-DPI repro steps
first-hand. I'd appreciate a maintainer or anyone who can reproduce
#48927 double-checking on real mixed-DPI hardware.
- Platforms: Windows only (`gpui_windows` crate); no other platform code
touched.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments (no new unsafe
blocks added)
- [ ] The content adheres to Zed's UI standards (N/A, no UI change)
- [ ] Tests cover the new/changed behavior (no existing test harness for
Windows-specific placement logic; happy to add one if pointed at the
right pattern)
- [x] Performance impact has been considered and is acceptable (no
measurable impact; same number of DPI queries, just reading from the
already-computed `WindowsDisplay` instead of the window)

Release Notes:

- Fixed: new windows on Windows could open partially off-screen when
placed on a secondary monitor with a different DPI scaling factor than
the monitor Windows initially placed them on.

---------

Co-authored-by: Lukas Wirth <lukas@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-26 08:42:18 +00:00
Alistair SmithandLukas Wirth 4278ff36ef gpui: Don't start a wrapped line with closing punctuation or a slash (#62743)
# Objective

`LineWrapper` treats every punctuation character as a break opportunity,
so a wrap can land right before `!`, `?`, `/`, `)`, `]`, `}`, a closing
quote or an ellipsis. Text such as `please fix this plz!`, `8.0/8.0`,
`cli/install`, `(see)` or `“quoted”` then wraps with the closing mark
orphaned at the start of the next line.

## Solution

Add the "UAX 14 LB13 rule" to `LineWrapper::is_word_char`, which is to
not break before `! ? / ) ] } " ” » …`

## Testing

Added unit tests and manually tested myself with a long paragraph in a
gpui app.

## 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 (one
extra `matches!` per character in the wrap loop)

---

Release Notes:

- Fixed text wrapping so closing punctuation and slashes never begin a
wrapped line.

Co-authored-by: Lukas Wirth <lukas@zed.dev>
2026-08-26 08:19:39 +00:00
JKNandLukas Wirth 74490daced gpui_windows: Implement render_to_image for headless window capture (#63012)
# Objective

`gpui_macos` implements `PlatformWindow::render_to_image` — the
MetalRenderer samples an offscreen target, so a **hidden** window can be
captured. `gpui_windows` does not implement it, so the method falls
through to the trait default and returns `Err("render_to_image not
implemented for this platform")`.

That leaves Windows consumers (tests, headless screenshot harnesses) on
`PrintWindow`-style workarounds, which require the window to actually be
on screen: a DirectComposition swap chain that never presents has no
frame to read, so you get a visible flash — or an off-screen parking
trick — for every capture.

This closes the macOS/Windows gap. Linux (`gpui_linux`) still returns
the trait default; a Blade/wgpu readback is the obvious follow-up but is
not in this PR.

## Solution

The DirectX analogue of the Metal path:

- `DirectXRenderer::draw`'s clear, scene upload and batch encoding are
factored into a shared `render(scene, background_appearance)`. `draw` is
now `render` + `present`; `render_to_image` is `render` + readback.
Nothing about how a frame is produced is duplicated between them, so the
two cannot drift.
- `render_to_image` renders into the **existing** render target —
created at window construction, so no window need ever be shown — then
copies it into a `D3D11_USAGE_STAGING` texture, `Map`s it, and converts
BGRA → RGBA. `RowPitch` padding is honoured per row; the copy loop
carries a safety comment.
- It refuses to run while `skip_draws` is set. That flag marks a pending
device-lost recovery, where the atlas still holds tile references from
the previous device — drawing before the forced re-render rebuilds them
panics in `DirectXAtlasState::texture` (the case
`WindowState::force_render_pending` documents). Returning an error beats
panicking in a capture harness.
- Gated on `cfg(any(test, feature = "test-support"))` to match the trait
method. `gpui_platform`'s `test-support` now forwards to
`gpui_windows/test-support`, the way it already does for `gpui_macos`.

No behaviour change outside `test-support`/`cfg(test)` builds beyond the
`render` factoring, which is a pure code move.

## Testing

- **Windows, functional:** an earlier revision of this patch has been in
production use since June in the `--screenshot` harness of a GPUI app I
ship ([Ferail](https://github.com/jonx/Ferail)), capturing a hidden
window (`show: false`) with no flash. BGRA→RGBA output was verified
against the on-screen rendering.
- **This exact revision** has been cross-checked from macOS only: `cargo
clippy -p gpui_windows --no-default-features --features test-support
--target x86_64-pc-windows-msvc -- -D warnings` is clean, both with and
without `test-support` (clang-cl + `xwin`; `--no-default-features` skips
only the `windows-manifest` embed-resource step, which is irrelevant
here). I'm relying on CI for a native Windows build of this revision —
happy to report back from a Windows host if that's a blocker for review.
- **Not covered by an automated test.** The behaviour needs a live D3D11
device, so it can only be exercised by a Windows-hosted test. Happy to
add one under `gpui_windows` if you'd like it — say the word and I'll
push it rather than guess at the shape you want.
- **Reviewers:** the interesting part is the staging-texture readback in
`directx_renderer.rs`. Worth a second pair of eyes on the `skip_draws`
guard and on premultiplied alpha (the swap chain is
`DXGI_ALPHA_MODE_PREMULTIPLIED`, so non-opaque captures come back
premultiplied — same as the macOS path, but it does mean
semi-transparent regions are not straight-alpha).

## 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) — n/a, no UI surface
- [ ] Tests cover the new/changed behavior — see Testing; needs a
Windows host, happy to add
- [x] Performance impact has been considered and is acceptable — the
readback path is `test-support`-only; `draw` is unchanged apart from the
`render` factoring

## Showcase

<!-- TODO: drop in the headless Windows capture (and the macOS one
beside it) -->

---

Release Notes:

- N/A

Co-authored-by: Lukas Wirth <lukas@zed.dev>
2026-08-26 08:17:09 +00:00
david leeandLukas Wirth 5dd0666dfb Fix missing NUL terminator in X11 WM_CLASS (#62848)
## Objective

GPUI's X11 `WM_CLASS` property omits its final NUL terminator, so any
window
manager that relies on the terminator reads the class one byte short.

`WM_CLASS` is specified by [ICCCM
§4.1.2.5](https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.5)
as two consecutive NUL-**terminated** strings, `instance\0class\0`.
`set_app_id` writes the separator but not the final terminator:

```rust
let mut data = Vec::with_capacity(app_id.len() * 2 + 1);
data.extend(app_id.bytes()); // instance
data.push(b'\0');
data.extend(app_id.bytes()); // class   <- no trailing NUL
```

This affects Zed itself. `ReleaseChannel::app_id()` returns
`dev.zed.Zed` on
stable, so under X11 and XWayland the class is read as `dev.zed.Ze`. The
shipped
desktop file is `dev.zed.Zed.desktop`, so the association it depends on
is
exactly the string being truncated, and window-manager rules or taskbar
grouping
matching `dev.zed.Zed` silently fail to apply.

Wayland is unaffected, since the app id is set through `xdg_toplevel`
rather
than an X11 property.

## Solution

Append the missing terminator after the class string, and size the `Vec`
capacity to match (`* 2 + 2` rather than `* 2 + 1`).

## Testing

Tested manually on Arch Linux with Hyprland v0.56.2 (wlroots) via
XWayland.

**Reproducing the bug** — Zed 1.14.2, before the fix:

```
$ env -u WAYLAND_DISPLAY zeditor some-dir
$ hyprctl clients -j | jq '.[] | select(.xwayland) | .class'
"dev.zed.Zed\u0000dev.zed.Ze"
```

The same window read with `xprop`, which does not require the
terminator, shows
the intended value — confirming the property itself is malformed rather
than the
compositor misreading it:

```
$ xprop -id 0x800001 WM_CLASS
WM_CLASS(STRING) = "dev.zed.Zed", "dev.zed.Zed"
```

**Control** — on the same compositor and the same XWayland path,
Alacritty
(winit, which writes the trailing NUL) reports its class intact:

```
$ hyprctl clients -j | jq '.[] | select(.xwayland) | .class'
"Alacritty"
```

The same truncation was reproduced independently with a third-party GPUI
application using `app_id: Some("sprite")`, which reports
`sprite\u0000sprit`.

**Platforms:** verified on Linux/XWayland only. Wayland does not use
this code
path. macOS and Windows have their own `set_app_id` implementations and
are
unaffected by this change.

**Needs more testing:** confirmation on a bare X11 session (not
XWayland) and on
a non-wlroots window manager such as i3, KWin, or Mutter would be
welcome — the
malformed property is compositor-independent, but which readers visibly
truncate
it is not.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — *none added*
- [x] The content adheres to Zed's UI standards — *N/A, no UI change*
- [ ] Tests cover the new/changed behavior — *see note below*
- [x] Performance impact has been considered and is acceptable — *one
additional
      byte in a property set once per window*
      
"No automated test: asserting the property bytes requires a live X
server. Happy to add one if there's an existing pattern for X11 window
tests I've missed."

Co-authored-by: Lukas Wirth <lukas@zed.dev>
2026-08-26 08:15:17 +00:00
Bennet Bo FennerandYang Yang 081a45f6f8 x_ai: Add Grok 4.5 and Grok 4.6 models (#63234)
Release Notes:

- xAI: Add Grok 4.6 and Grok 4.5 models

Co-authored-by: Yang Yang <geraint0923@gmail.com>
2026-08-26 08:04:05 +00:00
Ali 7040aa5669 gpui_windows: Clear render target before compositing COLR emoji (#63225)
… layers

# Objective

olor emoji (COLR glyphs) are rasterized on the GPU by compositing each
glyph layer into a D3D11 render target that is created with
`pInitialData: None` and, until now, never cleared. The texture contents
are undefined: texels not covered by any layer quad retained garbage
(typically leftovers from previous rasterizations via the DXGI
allocation pool).

## Solution

- Clear the render target with `[0, 0, 0, 0]` (premultiplied
transparent) immediately after binding it and before drawing the layers.

## Testing

add test to test this specifically 


## Showcase

before : 
<img width="1634" height="754" alt="ezgif-1a339c7dea79f905"
src="https://github.com/user-attachments/assets/6e282c46-d2a4-4043-9c1c-7f4ee9232fcc"
/>


after : 

<img width="1677" height="690" alt="Screenshot 2026-08-26 015248"
src="https://github.com/user-attachments/assets/c922909e-c70b-49f0-88fd-5a0c7cbe574b"
/>

---

Release Notes:

- Windows: Fixed artifacts around color emoji glyphs
2026-08-26 07:49:12 +00:00
OscarandAnthony Eid d4cd310edb gpui: Use platform clock in action profiler (#63183)
# Objective

I’m building a component library with GPUI and ran into a panic when I
enabled the profiler feature for a `wasm32-unknown-unknown` build.
Dispatching an action calls std::time::Instant::now(), which has no
clock implementation on this target, and the browser reports time not
implemented on this platform. The panic then triggers RefCell already
borrowed errors and leaves the GPUI window unresponsive.

The current `main` fails to compile this feature combination because the
action profiler’s std::time::Instant does not match the scheduler-based
timestamps in the profiler journal. I want GPUI’s action profiler to use
the same cross-platform clock as the rest of the profiler and keep this
configuration covered by CI.

## Solution

Use `scheduler::Instant`, the scheduler crate's cross-platform instant
type, for action timings so they match the rest of the GPUI profiler.
Keep the existing downstream wasm check and add a separate
profiler-enabled GPUI wasm check so CI covers both feature
configurations.

## Testing

- `cargo check --target wasm32-unknown-unknown -p gpui
--no-default-features --features profiler`
- `cargo -Zbuild-std=std,panic_abort check --target
wasm32-unknown-unknown -p gpui_platform -p cloud_api_client --features
gpui/profiler`
- `cargo test -p gpui --no-default-features --features profiler
profiler::` (48 tests passed)
- `./script/clippy -p gpui`

I ran a wasm GPUI app in Edge with WebGPU. The app opens a window and
dispatches an action with `profiler` enabled. Before this change, the
action produced the clock panic and follow-on borrow errors. After the
fix change, the action completed and the window remained active.

I did not run the browser harness in Firefox or Safari, though the wasm
compile check covers the changed profiler configuration without
depending on a browser.

## 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); this PR has no UI changes
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed a crash when dispatching profiled GPUI actions in web
applications.

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
2026-08-26 07:46:31 +00:00
Oleksandr KholiavkoandAnthony Eid e0f913b07d tabular_data_preview: Move settings into popup (refine UI) (#62812)
# Objective

The settings panel rendered as a persistent bar above the table, always
taking up vertical space even though most of its controls (text
alignment, filter sort order, multiline rows, dev-only toggles) are
rarely touched. @Anthony-Eid suggested reworking it into popover

## Solution

Replaced the always-visible settings panel with a single settings icon
button (next to the row-identifier toggle) that opens a popover menu
with the same controls, grouped under headers:
- Text Alignment, Filter Sort, Display
- and (behind `dev-tools`) Rendering Mode / debug toggles.

Frees up the row of vertical space previously occupied by the panel.
Similarly how it's done in git pannel


## Testing

`cargo check -p tabular_data_preview` and `--features dev-tools` both
build clean; `./script/clippy` clean.
Manually opened the popover and toggled each setting (alignment, filter
sort, multiline rows) to confirm they still apply and persist while the
popover stays open.

## Demo

| Before | After |
| --- | --- |
| <img width="720" height="427" alt="image"
src="https://github.com/user-attachments/assets/0af2e7a5-ab70-4cb8-b106-6cecd5a5752d"
/> | <img width="721" height="384" alt="image"
src="https://github.com/user-attachments/assets/c2938156-938e-4f05-b842-08e599e4bcdd"
/> |

Line numbers vs Row number
<img width="572" height="253" alt="image"
src="https://github.com/user-attachments/assets/1ccc5e8b-ffa3-4a8f-9dcb-07cba340306c"
/>

<img width="571" height="412" alt="image"
src="https://github.com/user-attachments/assets/ecb3c686-cb4c-41e7-918c-b8a5e123a452"
/>


## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([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

---

~~# NOTE TO REVIEWER (release notes related)~~
~~This feature is still under feature flag, but I've head from
@Anthony-Eid few weeks ago that it's already good enough to go public.
Do we make it live and I keep release notes or should I remove release
notes due to some blockers?~~

Disabled feature flag in
https://github.com/zed-industries/zed/pull/62773

---

Release Notes:

- Refine tabular data preview setting UI

---------

Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
2026-08-26 05:32:15 +00:00
Anthony Eid 55007f518b gpui: Report average dirty-to-present frame timings (#63221)
Extends the existing GPUI frame-duration telemetry with the average time
from a window's first invalidation through presentation.

- Record dirty-to-present durations in each window profiler
- Include the declared root entity type name on window handles
- Add the average and root type to the existing five-minute `Frame
Duration Report` event

Testing:

- `cargo fmt --all -- --check`
- `cargo test -p gpui --features profiler
records_dirty_to_present_durations`
- `cargo check -p gpui --no-default-features`
- `cargo check -p input_latency_ui -p zed`

Release Notes:

- N/A
2026-08-25 23:21:19 +00:00
Jakub Konka 1ff7cb669b gpui_wgpu: Reuse glyph image after measuring bounds (#63209)
Release Notes:

- Improved rasterization performance on Linux by caching glyphs after
measuring bounds.
2026-08-25 17:56:09 +00:00
Cole Miller 3c2848e919 open_ai: Classify billing and content policy errors (#63208)
OpenAI can return structured provider failures either as Responses
stream events or as non-success HTTP responses. The streaming path
classified the provider's error code, while the HTTP path treated the
body as opaque and classified only its status. As a result, exhausted
credit could look like a retryable rate limit, and prompt policy
rejections looked like generic provider failures.

This change gives billing failures their existing payment-required
category and adds a content-policy category for `invalid_prompt` and
`cyber_policy`. It also parses OpenAI's standard HTTP error envelope and
sends both HTTP and stream failures through the same classifier while
preserving the original status, code, and message. Responses with
another body format retain the previous status-based fallback.

Release Notes:

- N/A
2026-08-25 17:33:00 +00:00
Miguel Raz Guzmán Macedo f42c6e873e Use unstable sorts before deduplication (#63199)
# Objective

Get some speedups by using unstable sortts.
Supersedes #58761 after rebasing onto current `main`.

## Solution

replace `.sort()` by `.unstable_sort()`.

## Testing

All tests pass in affected crates:

```
cargo test -p edit_prediction_context -p editor -p git -p language -p language_tools -p migrator
```

## 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
2026-08-25 15:46:41 +00:00
Cameron Mcloughlin 224373ab88 gpui: Web text input improvements (#63201)
GPUI's keyboard handling on the web was previously managed with a hidden
`<input>`, and raw key events from this element were forwarded to GPUI's
key handling code.

However, this approach had some issues:
- it's not sufficient for key handling on android - gboard (the default
keyboard) does not produce raw key events, and instead presents as an
IME. The existing code did handle IMEs, but the implementation was
minimal, and didn't support gboard
- there was a bug relating to how state mapped between GPUI elements and
the underlying `<input>` that allowed for edits to be applied to stale
element text
- gboard seems to be picky about exactly how events are reported back,
and would lose state if we naively pass events back as soon as they are
ready. Now, we coalesce edits to the underlying `<textinput>` to at most
1 per JS event loop cycle

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-08-25 15:23:50 +00:00