Commit Graph
39931 Commits
Author SHA1 Message Date
Dom Porada b8aee8f9d7 Inherit file scan exclusions in project settings (#64092)
## Objective

Follow-up to #62769.

## Solution

Now that Zed Stable supports `"..."`, we can make the project settings
update [deferred from the original
PR](https://github.com/zed-industries/zed/pull/62769#discussion_r3799304949).

## Testing

Rust tests and in-app validation were not run for this
configuration-only 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

---

Release Notes:

- N/A
2026-09-11 17:23:09 +00:00
Lukas Wirth 8687b3f35d gpui: List only available font families in suggestions (#64095)
## Summary

Make GPUI's font suggestions reflect the platform text system's actual
font inventory, including fonts loaded by the application, rather than
appending hardcoded fallback candidates.

The appended names could be unavailable on the current platform.

The downside of this is that virtual aliases such as `.SystemUIFont`,
`.ZedMono`, and `.ZedSans` are no longer injected into suggestions;
existing settings using those aliases still resolve as before, they just
won't be shown in the settings UI anymore.

Release Notes:

- Fixed font suggestions listing unavailable fallback fonts and internal
font aliases.
2026-09-11 17:14:29 +00:00
Conrad Irwin 3cd117bb4c Fix Zed upgrade prompts for non-Zed payment errors (#64094)
## Summary

Fixes #63401.

Only payment errors originating from the Zed provider now use the Zed
free-usage-limit callout. Other providers use the existing Request
Failed display with their original message and no Zed upgrade button.
Telemetry follows the same distinction.

Rename the UI error variant to `ZedPaymentRequired` to make its scope
explicit. Add regression coverage for OpenRouter, OpenAI, and Anthropic
errors both with and without an HTTP status, plus the Zed upgrade path.

## Verification

- `cargo test -p agent_ui --lib conversation_view::tests`: 104 passed,
including both new regression tests.
- Rustfmt checks and `git diff --check` passed.
- Provided a temporary OpenCode payment-error override for manual
testing; the override has been removed and is not included in this PR.
- Corgi failed to link `clang_rt.osx`; the Cargo fallback succeeded.
Details were recorded in the requested local Corgi log.

Release Notes:

- Fixed payment errors from non-Zed model providers incorrectly
prompting users to upgrade to Zed Pro instead of displaying the original
provider error message.
2026-09-11 17:11:33 +00:00
Anton WieheandBen Kunkle ce88488f79 util: Raise open file soft limit at startup on Unix (#64034)
# Objective

Fixes #46470
Relates to #53901, #62486, #20806

Processes launched via GUI (such as `launchd`, Finder, Spotlight, or
Dock on macOS) inherit a default soft `RLIMIT_NOFILE` of only 256 open
files (lazily raised to 2,560 by Apple frameworks on first use of
certain APIs).

In active workspaces—especially those running multiple language servers,
MCP context servers, active filesystem watchers (`FSEventStream`), and
agent tool calls—baseline file descriptor consumption sits near 200–250.
During bursts of file activity or shell tool spawning, Zed quickly
exhausts this soft limit and fails with `EMFILE (os error 24: Too many
open files)`.

Similar desktop runtimes and editors (Chromium, VS Code, Node.js, Go,
JVM) raise their soft descriptor limit at startup for this exact reason.

## Solution

- Added `util::increase_open_file_limit()` called early in `main()`
right after tracing initialization.
- On macOS, query `getrlimit(RLIMIT_NOFILE)` and raise `rlim_cur` to
`limit.rlim_max.min(OPEN_MAX)`, where `OPEN_MAX = 10,240` (from
`<sys/syslimits.h>`). Note that macOS `setrlimit(2)` returns `EINVAL` if
`rlim_cur > 10240` even when `rlim_max` is `RLIM_INFINITY`.
- On other Unix platforms (Linux), raise `rlim_cur` to
`limit.rlim_max.min(65536)`.
- If the current limit is already at or above the target, it remains
untouched.
- Added a unit test in `crates/util/src/util.rs` verifying limit
querying and retention.

## Testing

- Added `test_increase_open_file_limit` in `crates/util/src/util.rs`.
- Ran `cargo test -p util` (134 passed, 0 failed).
- Ran `cargo check -p zed` (passed cleanly).

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

- Raised the default open file descriptor soft limit at startup on
Unix/macOS to prevent `EMFILE` (`Too many open files`) errors in large
workspaces.

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2026-09-11 15:39:49 +00:00
anciegandKirill Bulatov 1b0115048f Fix Linux mailto URI handling (#64088)
Fixes #64071

# Objective

Fix `Help → Email Us...` on Linux when using an affected version of
`ashpd`.

The `mailto:` URI generated by Zed is valid, but older `ashpd` versions
incorrectly reject URIs that contain a scheme without `://`, causing the
URI to fail before it can be opened.

## Solution

Update the `ashpd` dependency to `0.13.5`, which contains the upstream
fix for URI parsing
([ashpd#385](https://github.com/bilelmoussaoui/ashpd/issues/385),
[ashpd#386](https://github.com/bilelmoussaoui/ashpd/pull/386)).

Also update `Cargo.lock` to ensure the fixed version is used.

## Testing

Verified that `cargo tree -p ashpd` resolves to `ashpd v0.13.5` and that
the project builds successfully.

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

Not applicable. This PR does not introduce a visual change or new
user-facing UI.

---

Release Notes:

- Fixed Linux `mailto:` URI handling when using `Help → Email Us...`.

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-09-11 15:34:31 +00:00
Giorgio PoglianiandKirill Bulatov fde3e42be8 editor: Allow customizing CodeLens text color (#64084)
CodeLens text currently hardcodes `text.muted`, so changing its color
also changes unrelated muted UI text such as the sidebar.

This adds a dedicated `editor.code_lens.foreground` theme color. When
omitted, it falls back to `text.muted`, preserving the existing
appearance of themes while allowing CodeLens text to be customized
independently.

Release Notes:

- Added `editor.code_lens.foreground` for customizing CodeLens text
independently.

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-09-11 15:19:53 +00:00
Ben Brandt 1e6cc1f182 Upgrade ACP to 2.1 and futures to 0.3.34 (#64077)
Upgrade to ACP SDK 2.1 and futures 0.3.34. Remove the dedicated-thread
polling workaround introduced in #62259 now that the SDK bounds
dispatch-chain stack usage.

This is the first PR from the ACP integration work. First-class
tool-call names, context compaction support, and the independent native
elicitation ID fix are intentionally deferred to separate PRs.

- Upgrade the ACP SDK and derive crate to 2.1.0, with schema 1.7.0.
- Upgrade the nine futures-rs 0.3 components to 0.3.34, including the
[cloned-waker identity
fix](https://github.com/rust-lang/futures-rs/pull/3032) identified
through [ACP
rust-sdk#254](https://github.com/agentclientprotocol/rust-sdk/issues/254).
- Poll ACP connections on the normal GPUI background executor and remove
the now-unused ACP-specific dedicated-spawn wrapper. Keep the general
scheduler dedicated-executor APIs intact.
- Use the stable authentication metadata accessor and route first-class
terminal authentication without requiring ACP beta. Keep legacy
terminal-auth metadata as a fallback for other authentication methods.

Also upgrades a big fix release of the futures crates because there was
some polling issues with FuturesUnordered reported with the old
versions.

Release Notes:

- Improved ACP compatibility and async task wakeup handling.
2026-09-11 11:10:44 +00:00
Kirill Bulatov 4e693c3b6b Fix diagnostics batches stopping at paths without a worktree (#64017)
Closes https://github.com/zed-industries/zed/issues/62303

Based on the amazing find in
https://github.com/zed-industries/zed/issues/62303#issuecomment-5553387960

Release Notes:

- Fixed diagnostics batches stopping at paths without a worktree
2026-09-11 09:16:11 +00:00
tidely ba66199475 Bump Rust to 1.98.1 (#63010)
# Objective

- Bump Rust to 1.98.1

Release Notes:

- N/A
2026-09-11 09:13:44 +00:00
Cameron Mcloughlin 9eb022bd23 gpui: Long-press to activate tooltips (#63948)
Tooltips on web need long-press, rather than hover

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-11 05:25:06 +00:00
Conrad Irwin 85ad201397 Add a filesystem watching debug window (#64065)
## Summary

Add `dev: Debug Filesystem Watching`, which opens a singleton, app-wide
debug window for local filesystem watching.

- Capture native and polling notifications before filtering/coalescing,
including lost-sync/rescan markers and watcher initialization,
registration, and removal errors.
- Show Raw Events, Watch Roots, and Scan Exclusions in separate
read-only editors with normal selection and copying.
- Record only while the window is open, retain the latest 10,000 events,
and periodically compact editor buffers so deleted text/history does not
accumulate indefinitely.
- Display local timestamps and concise event names; export full raw
details, roots, exclusions, dropped-event counts, and Zed/OS version
information as JSON.
- Declare the renderer source that `gpui_apple`'s build script reads in
Corgi's sandbox configuration.

This is diagnostic tooling, not a change to watcher behavior. It
captures local watcher-level events; it does not yet trace worktree scan
start/completion or remote filesystems. Scan exclusions are labeled
separately from OS watch roots because excluded files can still generate
notifications.

## Related issues

These reports motivate the capture tooling; this PR does not claim to
fix them:

- [#63254: Project and Git panels stop updating when the macOS FSEvents
stream limit is
reached](https://github.com/zed-industries/zed/issues/63254)
- [#63174: Atomic file replacement leaves Linux buffers
stale](https://github.com/zed-industries/zed/issues/63174)
- [#58678: Worktree stops opening files/expanding folders after a
lost-sync rescan
storm](https://github.com/zed-industries/zed/issues/58678)
- [#53480: High CPU after watcher lost sync under low file-descriptor
limits](https://github.com/zed-industries/zed/issues/53480)

## Validation

- `corgi build -p zed`
- `corgi test -p fs --lib --features test-support fs_watcher` — 19 tests
passed
- `corgi test -p fs --features test-support --test integration
watcher_diagnostics` — 2 tests passed, including real OS notification
delivery
- `cargo test -p zed watcher_debug::tests` — 7 tests passed, covering
formatting, singleton lifetime, tab layout, copying/read-only behavior,
selection preservation, compaction and retained storage, JSON metadata,
cancellation, and save failures
- Rust formatting and `git diff --check`
- Manual UI smoke testing on macOS during development

The UI tests use Cargo because the installed Corgi version omits
`CARGO_BIN_NAME` when compiling the binary test target. Normal Corgi
builds pass.

## Reviewer note

The required README review acknowledgment is intentionally left for the
author to remove manually after review.

## Suggested .rules additions

For bounded diagnostic logs backed by an editor, trimming visible rows
does not bound memory: the text buffer retains deleted text and edit
history. Periodically replace the buffer/editor while preserving
selection and scroll state, and test retained storage rather than only
visible row count.

Release Notes:

- Added `dev: Debug Filesystem Watching` to inspect local watcher
events, watch roots, and scan exclusions, and export diagnostic captures
as JSON.
2026-09-11 04:13:07 +00:00
Maurício R Duarte d66b5d2050 agent_ui: Enable terminal thread renaming from the Agent Panel (#63660)
## Summary

- Follow up on #63578 by extending the existing
`agent::RenameSelectedThread` action to the active Terminal Thread in
the Agent Panel.
- Preserve the existing Threads Sidebar behavior and default
keybindings.
- Document custom keymap assignment and add focused Agent Panel
regression coverage.

## Testing

- `cargo test -p agent_ui
agent_panel::tests::test_rename_selected_thread_action --lib`
- `cargo test -p sidebar rename_selected_thread --lib`
- `cargo fmt --package agent_ui -- --check`
- `npx prettier --check src/ai/terminal-threads.md`
- Manually tested locally with a custom `AgentPanel > Terminal` keymap
binding.

Release Notes:

- Added support for custom keybindings to rename Terminal Thread titles
from the Agent Panel.

### screenshots
<img width="921" height="205" alt="Screenshot 2026-09-02 at 18 40 31"
src="https://github.com/user-attachments/assets/b1edabfc-35f9-42ef-b368-486003202349"
/>
2026-09-11 01:07:36 +00:00
tidelyandKirill Bulatov 5a74e0b423 project_panel: Fix dragged folders remaining highlighted even after the drag has ended (#64038)
# Objective

When dragging a folder outside of Zed, it is considered a platform drag,
instead of a GPUI native drag event. Currently when this platform drag
finishes, the selected folder remains highlighted, until unhighlighted
by initiating a GPUI native drag event.

Found this while testing #64033, I did not find an issue related to this
bug.

## Solution

- Clear the drag state when no gpui **or** platform drag event is
active.

## Testing

- Added asserts to relevant parts of previous tests
- Tested this locally

I can record a showcase if requested, skipping it for now since its
quite time consuming

## 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 folders remaining highlighted even after dragging the folder has
stopped

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-10 21:42:22 +00:00
Counterfeit IQanddino b9364a77e9 recent_projects: Fix built-in prompt not capturing focus when removing remote servers (#60965)
Fixes the issues where using the zed builtin prompt when removing
wsl/ssh remote servers did not capture focus and caused input to be
passed to the existing picker/editor.

Closes #60840.

# Objective

The objective of this fix was to make the remote server removal prompts
work correctly, capture focus, when using keyboard navigation to remove
a server or wsl distro. The fix was created directly to address #60840.

## Solution

The solution here is quite simple, we remove the forced, focus lines,
that attempt for the context to capture the new prompt window. The
oringal additional call to `cx.focus` was entirely unnecessary and was
duplicated from the original ssh remote server addition, into the wsl
distro addition. This behaviour and the correct deferal is handled by
the receivers invocation upon the execution of the listitem.

## Testing

I tested these changes manually, however this is incredibly easy to
reproduce, and is entirely platform agnostic. Simply add a testing
distro to the list, and then attempt to remove that distro by going into
its settings and removing the sever/distro. Then use the keybinds to
attempt to navigate. Prior to this PR, this would cause you to interact
with the editor behind the prompt, but now correclty directs
actions/inputs to the prompt window.

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

---

Release Notes:

- Fixed remote server removal prompts not capturing keyboard focus.

Signed-off-by: Counterfit IQ <logicye@proton.me>
Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-09-10 17:54:38 +00:00
Cameron Mcloughlin a55d12e05a gpui_web: Disable autoscroll (#64041)
Autoscroll causes weird jank in delta web on mobile sometimes

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-10 16:28:39 +00:00
Conrad Irwin 996971b6c4 Fix Python interpreter discovery crashes on non-UTF-8 output (#64040)
## Summary

Pin all PET dependencies to [our fork at
5aad716](https://github.com/zed-industries/python-environment-tools/commit/5aad7164bfc2a58977b103c8ef8fdd7302ed2e9f),
fixing ZED-BGV: non-UTF-8 interpreter stdout could panic discovery.

Refs https://github.com/microsoft/python-environment-tools/issues/525.

The bump also includes upstream’s Windows Conda alias-deduplication fix
(#519 in PET) and CI-only changes. No unrelated lockfile changes.

## Validation

- `corgi check -p languages` passed on macOS.
- PET’s regression test failed with the original code and passed with
the fix; all 51 `pet-python-utils` tests passed in the PET checkout.
- Verified all seven direct dependencies and 27 lockfile entries point
to the fork.
- `git diff --check` passed.

Release Notes:

- Fixed a crash during Python interpreter discovery when an executable
emits non-UTF-8 output.
2026-09-10 16:24:26 +00:00
tidelyandKirill Bulatov c70724205d gpui_macos: Migrate start_external_drag to objc2 (#64033)
# Objective

Get rid of instances of the `block` crate, as it will not compile in a
future version of Rust.

## Solution

Migrate an independent code block to the `objc2` crate family.

## Testing

Tested dragging/dropping files & folders from Zed into Finder. There
seems to be some highlighting bug with folders, but that existed
previously as well.

Release Notes:

- N/A

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-09-10 14:52:46 +00:00
Conrad Irwin 7556e307d2 anthropic: Classify exhausted credits as payment required (#63988)
Anthropic reports exhausted credits as `invalid_request_error` rather
than the documented `billing_error`. Recognize the specific
credit-balance message when converting Anthropic API errors to
`PaymentRequired`.

This preserves the original status, code, and message, handles errors
with or without an HTTP status, and leaves other invalid requests
unchanged. The comment links to Anthropic's error documentation.

Closes DELTA-77

Validation: the existing Anthropic billing-error test and package
formatting check pass. A temporary classification test also passed for
exhausted credits and malformed requests, with and without HTTP status;
it is not included in this PR.

Release Notes:

- Fixed Anthropic credit exhaustion being classified as a malformed
request instead of a payment issue.
2026-09-10 14:33:24 +00:00
UdeshyaandKirill Bulatov aac4829c4d Add action parameter comment_empty_lines for editor::ToggleComments (#63961)
# Objective

- Fixes: https://github.com/zed-industries/zed/issues/60738
- Re-iteration of https://github.com/zed-industries/zed/pull/63918 with
suggested changes

## Solution

- Added the parameter `comment_empty_lines` to `editor::ToggleComments`
set to `false` by default.

## Testing

- Tested manually. See showcase below.
- Added two automated tests for the added feature.
- Tested on MacOS.

## Self-Review Checklist:

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

## References
The action's behavior was observed across Emacs, VSCode, and Intellij,
and the corresponding keymaps were set accordingly.


https://github.com/user-attachments/assets/36c1a27a-357c-468a-b56b-59ef31265329

https://github.com/user-attachments/assets/de755753-9de1-4771-980f-177810fb85ef

https://github.com/user-attachments/assets/c8ecd261-2bba-4345-89f4-c1d708d8b6d2

## Showcase

Below is the screen recording of these three tests:

1. Behavior of toggling comments when `comment_empty_lines` is `true`.
2. Switching the parameter value to true after commenting a block and
un-commenting the same block does not re-comment the block due to an
empty line in between.
3. Menu bar item is still present, albeit it's behavior is mapped to the
default value of the parameters of the bound action, instead of what is
inside the keybindings file. This (bug?) was present even before. See
the attached clip below.

1.
https://github.com/user-attachments/assets/a9cd2a2c-437b-41a3-bd8e-c4c3a1f350cd
2.
https://github.com/user-attachments/assets/4bbfb77c-9019-410e-9d0a-952d4438d2a7
3.
https://github.com/user-attachments/assets/ca300e2d-2106-4bb7-865b-5d2ab89cd0f2


https://github.com/user-attachments/assets/ec1e47b6-ff99-461e-93af-af925be4d914

---

Release Notes:

- Added `comment_empty_lines` parameter to `editor::ToggleComments` for
multiline selections.
Use `["editor::ToggleComments", {"comment_empty_lines": true}]` to
comment blank lines too (default for Zed keymap now), or
`["editor::ToggleComments", {"comment_empty_lines": false}]` to skip
them (default for VSCode keymap).

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-10 13:39:44 +00:00
tidely 00365ad222 gpui_macos: Migrate get_sources to objc2 (#64031)
# Objective

Get rid of instances of the `block` crate, as it will not compile in a
future version of Rust.

## Solution

Migrate an independent code block to the `objc2` crate family.

## Testing

I tested screen sharing inside of a Zed channel

Release Notes:

- N/A
2026-09-10 12:02:06 +00:00
Henrique FerreiroandSmit Barmase e58da8753e Fix inline assistant fallback model selection (#63963)
Use the registry's default_model() accessor so inline assist can use the
same automatically selected fallback model as agent sessions when no
configured default model resolves. Keep explicit inline model selection
as the first choice.

Related to #59309.

Release Notes:

- Fixed Inline Assistant failing to select an available fallback model
when no default model is configured.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-09-10 10:53:30 +00:00
Cameron Mcloughlin 42626fe94e gpui_web: Simplify keyboard focus model (#63989)
Simplifies the mobile web virtual keyboard implementation in the
following ways:
- assumes that GPUI web apps will set
`interactive-widget=resizes-visual`. This means that GPUI's window will
not change viewport size when the keyboard appears
- Exposes `Window::fully_visible_bounds`, which returns a rectangle
which is fully visible (pixels outside these bounds *may* be visible but
may not be)
- These two changes together mean that keyboard visibility is more
reliably detectable (though not fully), and also makes it easier to have
a stable scroll position when the keyboard is animating in/out
- tweaks the focus model so that:
- transitions into/out of the state "GPUI focus is in a text input, and
that text input is in an editable range" will change keyboard visibility
- manually-dismissed keyboards are preserved by not synchronizing unless
a tap event (or similar, or a programmatic request) on that input
happens
- there is a new `Window::{request,dismiss}_virtual_keyboard()` method
that allows programmatically controlling keyboard visibility (without
interacting with GPUI focus). This allows for patterns like "pressing
button A focuses text field B, *and opens the keyboard*

This PR also fixes a bug in non-touch web that caused text fields to
lose IME mirror focus when they entered non-editable regions, which
could prevent keyboard input from being detected by GPUI properly.

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-10 09:49:08 +00:00
xiaoffandKirill Bulatov 1d7ff1d2ee buffer_store: Fix path_to_buffer_id never update when move action occurs in remote mode (#64005)
# Objective
Fix an issue in SSH remote mode where reopening a newly created file at
a path that was previously renamed could incorrectly reuse the buffer
for the renamed file.

## Solution

When handling UpdateBufferFile, remove the buffer's previous path from
path_to_buffer_id when the file path changes.

## Testing

Tested manually on Linux using SSH remote mode.

Reproduction before the fix:

touch A
Open A from the project panel

mv A B
touch A

Open the new A from the project panel

Before the fix, opening A reused the buffer for B.

After the fix:

B continues to use the original buffer.
The recreated A opens as a separate buffer.
Renaming an opened remote file still updates the existing buffer to the
new path correctly.

## 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 an issue in SSH remote mode where reopening a newly created file
at a path that was previously renamed could incorrectly reuse the buffer
for the renamed file.

---------

Signed-off-by: xiaoff <xiaoff0019@outlook.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-10 08:27:36 +00:00
tidely 2b56eae5a2 gpui_macos: Migrate prompt_for_path to objc2 (#63994)
# Objective

Get rid of instances of the `block` crate, as it will not compile in a
future version of Rust.

## Solution

Migrate to the `objc2` crate family.

This gets rid of `block` inside of `platform.rs` 🎉 

Release Notes:

- N/A
2026-09-10 07:28:42 +00:00
Kirill Bulatov b02587f47b Pin miri to the version that does not fail (#64013)
Seems that a few PRs' CI start to fail with unrelated errors, e.g.
https://github.com/zed-industries/zed/actions/runs/34428484649/job/102747668773?pr=63933

```
warning: integer-to-pointer cast
   --> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/parking_lot_core-0.9.12/src/word_lock.rs:320:9
    |
320 |         (self & QUEUE_MASK) as *const ThreadData
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
    = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
    = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
    = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
    = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
    = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
    = note: this is on thread `tests::test_non`
    = note: stack backtrace:
```

That used to be the case before too:
https://github.com/zed-industries/zed/actions/runs/34360850759/job/102497345024#step:9:402
but with the recent version bump it became a hard error ergo this for
now.

No new parking lot releases yet:
https://github.com/Amanieu/parking_lot/pull/502 hence pin Miri to
version that does not fail for now.

Release Notes:

- N/A
2026-09-10 06:50:03 +00:00
Lukas Wirth e81eff46c7 watch: Add snapshot-based channels (#63964)
Add an opt-in watch channel that atomically publishes immutable, owned
snapshots rather than holding a reader/writer lock. Readers can retain a
value without delaying publication.

Use independent atomic wakers for receivers while preserving
latest-value coalescing and channel closure semantics. Keep the existing
watch implementation unchanged and document when to choose each
implementation.

Release Notes:

- N/A
2026-09-10 06:33:43 +00:00
Kirill Bulatov 4d88c159f7 Normalize CRLF line breaks in completion labels too (#63920)
Part of
https://github.com/zed-industries/zed/issues/63273#issuecomment-5562451827



https://github.com/user-attachments/assets/ecaa1bd0-672b-4323-a67e-e1a7e3c428fb


Release Notes:

- Fixed CRLF line breaks not normalized in completion labels
2026-09-09 15:23:30 +00:00
Kamil JakubusandKirill Bulatov ab2e4601d2 extension: Bump wasi-sdk to version 34 (#63816)
# Objective

Bumps `wasi-sdk` to v34 that is based on LLVM 23.1 which includes [a
compile time and memory usage
fix](https://github.com/llvm/llvm-project/pull/181755) for tree-sitter
grammars. It speeds up every grammar's compile time and reduces compile
memory usage unlocking big grammars that were impossible to compile
before to be submitted to Zed extensions.

Drive-by added additional wasi-sdk targets for the rest of the supported
architectures (by wasi-sdk), if riscv is unwanted I can remove it but it
should not create any problems (I think).

Also noticed the `download-wasi-sdk` script had `OS=mingw` which wasn't
even in the artifact name on v25.

## Testing

Compiled, ran and compiled my [big
grammar](https://github.com/usagi-coffee/tree-sitter-abl) on it, that
wouldn't compile at all pre-llvm 23.

## Self-Review Checklist:

- [X] I've reviewed my own diff for quality, security, and reliability

---

Release Notes:

- Fixed compiling dev extensions with big Tree-sitter grammars.
- Fixed compiling dev extensions on Windows ARM64.
- Added wasi-sdk installation invalidation.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-09 15:16:15 +00:00
whitecat1331 1ff9082ced sqlez: Set a 5s SQLite busy timeout (#63923)
SQLite fails fast with `SQLITE_BUSY` when another process holds the
database lock. This database, and others like it, are shared between Zed
instances. SQLite allows multiple readers at once, but only one writer
at a time. Writes are short-lived, but if multiple Zed instances try to
write to the file at the same time, the default fail-fast behavior
throws `SQLITE_BUSY` and the write is dropped instead of retried. The
fix is to keep trying the write for up to five seconds, so transient
lock contention resolves and the write succeeds instead of erroring.

A concrete case is the agent threads database (`threads.db`), which
lives in the shared per-user data directory and is not namespaced by
release channel. Running two Zed instances side by side means both can
attempt to write to the same file at the same time, resulting in the
error mentioned previously.

Release Notes:

- Fixed intermittent "database is locked" errors when sharing a database
across Zed instances
2026-09-09 15:11:24 +00:00
4ee80bcbbb lsp: Handle dynamic registration of textDocument/documentHighlight (#63029)
Zed did not advertise document highlight dynamic registration support or
handle `textDocument/documentHighlight` registrations. Dynamically
registered providers therefore fell through to the unhandled-capability
path, while servers with a fallback had to advertise a static provider
for every attached document.

Advertise dynamic registration support and track document highlight
registrations and unregistrations alongside the other selector-aware
dynamic text document capabilities. Refresh editors whenever the
effective document highlight registration state changes, including
selector-only changes that leave the merged provider unchanged, so
runtime registrations take effect immediately and unregistrations clear
stale or in-flight highlights.

Add coverage for the client capability, registration lifecycle with
multiple selectors sharing identical provider options, and editor
refresh behavior when an applicable selector is added or removed.

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

---------

Co-authored-by: GPT-5.6 Sol <noreply@openai.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-09 14:55:56 +00:00
Katie Geer 797fa3b3d9 Update Zed trial copy for the $5 GPT Luna offer (#63969)
## Summary

Updates Zed trial copy for
[CLO-1373](https://linear.app/zed-industries/issue/CLO-1373/update-zed-to-show-the-dollar5-gpt-luna-trial).

- Show $5 of GPT Luna and unlimited edit predictions across pre-sign-in,
Free-plan, and active-trial onboarding.
- Clarify that the 14 days begin when the trial starts, rather than when
the welcome panel is viewed, and retain no-credit-card messaging.
- Update hosted-model trial descriptions and use "Start Free Trial" for
onboarding and AI configuration trial CTAs.
- Document GPT Luna-only trial hosted-model access and the shared
Zed/Delta $5 trial balance.

This is a copy-only change. Trial eligibility, subscription creation,
trial timing, billing, model-access enforcement, button actions, URLs,
and telemetry are unchanged. Paid, Student, Business, and VIP plan
descriptions are unchanged. This does not implement the offer on the
backend.

## Verification

- Rust formatting and `git diff --check` passed.
- Prettier check passed for the pricing documentation.
- Source checks confirmed the offer wording and unchanged callbacks,
URLs, telemetry, and other plan definitions.
- Katie built and launched Zed with `cargo run -p zed --bin zed`, then
reviewed Component Preview and requested the final CTA wording.
Formatting and diff checks were rerun after that wording adjustment; the
final adjustment has not been rebuilt.
- Confirmed the branch merges cleanly with the latest `main`.

Release Notes:

- Improved trial descriptions to show $5 of GPT Luna and unlimited edit
predictions for 14 days from trial start.
2026-09-09 14:50:23 +00:00
Kirill Bulatov 7265ff479a language: Cache buffer syntax highlighting per row chunk (#63145)
Closes https://github.com/zed-industries/zed/issues/63730
Related to #52340 and #43460
Based on https://github.com/zed-industries/zed/pull/63138 and needs it
to be merged first.

`BufferSnapshot::chunks` re-ran the tree-sitter highlight query over the
requested range on every call, so scrolling and cursor movement paid the
full query cost per frame.

Highlight runs are now computed once per 50-row chunk (the same
`RowChunks` that back bracket colorization), resolved against the
current `HighlightMap` at compute time, merged into `(Range<usize>,
HighlightId)` runs, and kept in a cost-budgeted per-buffer LRU (10MB).
Entries reuse the `ResolvedHighlights` representation from #63138: each
stores the grammars and maps it was resolved against and is served only
while every map is pointer-identical (`is_current`), so theme changes
and grammar reloads invalidate structurally, with no invalidation hooks
and no global state.
Edits and reparses drop the cache through the existing `TreeSitterData`
swap.
Chunks spanning more than 64KB bypass the cache and fall back to direct
querying, so files with giant lines behave as before.

## Benchmarks

`editor_render_highlighted` and `editor_render_highlighted_minimap`
benches (`cargo bench -p benchmarks --bench editor_render`) move the
cursor through a generated 10K-line Rust file with real tree-sitter
highlighting, with and without the minimap.
The benches are new in this PR, so the baseline is the same binary with
`ZED_DISABLE_HIGHLIGHT_CACHE=1`, which routes rendering through the
pre-existing direct-query path.

Run 1 — baseline, cache disabled:

```
editor_render_highlighted          time: [1.7164 ms 1.7377 ms 1.7604 ms]
editor_render_highlighted_minimap  time: [12.273 ms 12.407 ms 12.549 ms]
```

Run 2 — cache enabled:

```
editor_render_highlighted          time: [1.4572 ms 1.4597 ms 1.4627 ms]
                                   change: [-16.378% -14.944% -13.526%] (p = 0.00 < 0.05)
editor_render_highlighted_minimap  time: [9.2750 ms 9.3213 ms 9.3744 ms]
                                   change: [-25.800% -24.872% -23.930%] (p = 0.00 < 0.05)
```

Over the same runs, GPUI reports window draw mean 0.81 ms → 0.68 ms and
p99 1.06 ms → 0.76 ms without the minimap, and mean 5.14 ms → 4.12 ms,
p99 6.12 ms → 4.75 ms with it.
The relative deltas held across two independent sessions (-14.1…-14.9%
and -20.7…-24.9%), while absolute times drift a few percent with machine
state.

Release Notes:

- Improved editor rendering performance in syntax-highlighted files,
especially with the minimap enabled
2026-09-09 14:31:14 +00:00
Kirill Bulatov ed192bf4f1 markdown: Cache code block syntax highlighting at parse time instead of re-highlighting every frame (#63138)
Part of https://github.com/zed-industries/zed/issues/57349

`MarkdownElement` re-highlights every code block with tree-sitter on
every frame.
Each visible code block pays a full parse per frame, which makes agent
panel streaming and hover popovers janky once the content grows.

This PR computes code block highlights once, in the background parse
task, instead of at render time:

- Highlights are resolved into `(Range<usize>, HighlightId)` runs at
parse time; each entry stores the grammar and `HighlightMap` it was
resolved against and is served only while the grammar still holds the
pointer-identical map (`ResolvedHighlights::is_current`), so theme
changes need no invalidation hooks, and a block whose entry went stale
falls back to direct fragment highlighting at render until the next
parse.
- `Language::highlight_text_resolved` memoizes results in a
content-keyed LRU (4MB budget, 512KB per-entry cap), so the re-parses
triggered by streaming appends reuse the highlights of unchanged blocks
instead of re-running tree-sitter on them.
- Blocks larger than the per-entry cap bypass the cache and are
highlighted directly, as before.

`CostBudgetedLru` is generic rather than specialized because a follow-up
PR reuses it for per-buffer highlight caching in
`BufferSnapshot::chunks`; the capture flattening keyed by grammar index
(`HighlightCaptureRef`) is shared with that follow-up as well.

## Benchmarks

`cargo bench -p benchmarks --bench markdown_renderer` renders generated
documents that mix paragraphs, headings, tables, and Rust code blocks.

**Run 1 — baseline, `main` (`ee2366a395`):**

```
Markdown render/min_bytes/5000    time: [1.2956 ms 1.2974 ms 1.3016 ms]
Markdown render/min_bytes/10000   time: [1.7919 ms 1.7955 ms 1.8026 ms]
Markdown render/min_bytes/50000   time: [6.5510 ms 6.6241 ms 6.6671 ms]
Markdown render/min_bytes/250000  time: [37.644 µs 2.4819 ms 4.3791 ms]   <- bimodal already on main
```

**Run 2 — this branch:**

```
Markdown render/min_bytes/5000    time: [940.11 µs 945.28 µs 948.79 µs]
                                  change: [-29.317% -28.385% -27.607%] (p = 0.00 < 0.05)
Markdown render/min_bytes/10000   time: [1.1162 ms 1.1331 ms 1.1407 ms]
                                  change: [-40.859% -39.151% -37.719%] (p = 0.00 < 0.05)
Markdown render/min_bytes/50000   time: [2.4943 ms 2.9225 ms 3.1051 ms]
                                  change: [-80.088% -67.885% -58.058%] (p = 0.00 < 0.05)
Markdown render/min_bytes/250000  time: [43.442 µs 44.661 µs 45.514 µs]
                                  change: [-98.210% -95.806% +5.5167%] (p = 0.17 > 0.05)
```

Over the same runs, GPUI reports window draw mean 2.22 ms → 1.26 ms, p99
31.2 ms → 16.0 ms, and the share of frames that blow the frame budget
drops from 3.9% to 2.0%.

Note: at the 250,000-byte case root blocks render lazily, which makes
the measurement bimodal and inconclusive in both configurations.

Release Notes:

- Improved rendering performance of markdown code blocks (agent panel,
hover popovers, markdown preview)
2026-09-09 14:31:14 +00:00
tidelyandKirill Bulatov ded89e373b gpui_macos: Migrate register_url_scheme to objc2 (#63945)
# Objective

The `block` crate will no longer compile with some unspecified future
version of Rust. The long term goal is to get rid of the `block` crate
entirely, and this is one such step.

## Solution

Migrate a standalone function to the `objc2` crate family. Removes many
lines of unsafe code, and switches from `block` to `block2`.

## Testing

All of the calls to `objc2` are identical to the ones in the old code.

Release Notes:

- N/A

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-09-09 13:53:54 +00:00
Xiaobo LiuandKirill Bulatov 3d0649186f gpui: Prevent idle sleep during AI response streaming (#53130)
Release Notes:

- Added button tu prevent idle sleep during AI response streaming


**Context / Motivation:**
When an AI agent takes a long time to generate a response, the operating
system might enter an idle sleep (or display sleep) state if there is no
user interaction (mouse or keyboard). This can interrupt the workflow.
This PR aims to prevent the system from sleeping during an active AI
turn by invoking native OS APIs, and provides a UI toggle for users to
control this behavior.

**Key Changes:**

1. **Cross-Platform Idle Sleep Prevention in GPUI (`gpui`, `gpui_*`)**
- Added a new `prevent_idle_sleep` method to the `Platform` trait. It
returns a RAII-based `PreventIdleSleepToken`, which automatically
restores the original sleep policy when dropped.
- **macOS**: Utilizes `NSProcessInfo`'s `beginActivityWithOptions` with
`NSActivityIdleDisplaySleepDisabled`.
- **Windows**: Uses `SetThreadExecutionState` to prevent display and
system sleep, incorporating a reference counter to handle concurrent
requests safely.
- **Linux**: Uses `ashpd` to request `org.freedesktop.portal.Inhibit`
(inhibiting `Idle` and `Suspend` states) via D-Bus.

2. **AI Agent State Integration (`crates/acp_thread`)**
- Introduced idle sleep prevention logic in `AcpThread`: Acquires the
token at the beginning of `run_turn`, and automatically releases it when
the turn completes normally, errors out, or is explicitly canceled by
the user.
- Added comprehensive unit tests to ensure the token is correctly
acquired and released under various cancellation and concurrency
scenarios.

3. **Settings and UI (`crates/agent_settings`, `crates/agent_ui`)**
   - Added `AgentOutputIdleSleepControl` to global state.
- Added a new toggle button (screen icon) to the toolbar at the bottom
of the `ThreadView` (AI conversation panel). Users can hover to view the
tooltip and click to toggle the feature on or off.

<img width="419" height="132" alt="截屏2026-04-04 16 09 08"
src="https://github.com/user-attachments/assets/619da9ff-10f7-46e0-b959-d7c74b16b918"
/>

---------

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-09 13:49:13 +00:00
Toru NayukiandKirill Bulatov a6cf4032e6 Restore macOS windows to their original Space after restart (#58886)
Addresses #9640 (the Spaces part).

On macOS, Zed already restores each window's size, position, and
display, but not its Space (virtual desktop). So after a restart, all
windows open on whatever Space is active at launch, not the Space they
were on before. This is the most reported problem in #9640.

A window's Space is not part of the window bounds we save. It is handled
by AppKit's own window state restoration. So instead of tracking the
Space myself, this PR uses that AppKit feature:

- I mark `GPUIWindow` as restorable and encode its native state (frame +
Space) by calling `encodeRestorableStateWithCoder:` with an
`NSKeyedArchiver`. A delegate skips the `NSView`/`NSWindow` objects that
do not support `NSSecureCoding`.
- I save the blob per workspace in a new `restorable_window_states`
table.
- When a saved workspace is opened again, I create the window and then
replay the blob with `restoreStateWithCoder:`. AppKit then moves the
window back to its Space.

On other platforms, and when there is no saved blob, this does nothing.

Verification:

- Added a round-trip test for the database part (save / overwrite /
read, and `ON DELETE CASCADE`).
- The macOS encode/restore part calls into AppKit, so I could not
unit-test it. I checked it by hand: I put several windows on different
Spaces, quit with Cmd+Q, started Zed again, and each window came back on
the Space it was closed on. I also checked that the saved blob is a real
AppKit archive (it starts with `bplist00`).

For now this only works for local workspaces. Remote workspaces could
use the same way later.

Self-Review Checklist:

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

Release Notes:

- macOS: Restored windows now reopen on the Space (virtual desktop) they
were on, instead of all landing on the currently active Space.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-09 13:48:50 +00:00
Kirill Bulatov 3af83d6d0b Support commands in inlay hints (#63605)
Closes https://github.com/zed-industries/zed/discussions/51582

During testing, spotted that if I toggle off the hints with the modifier
keys, they are resurrected on scrolling — fixed that in a small commit
on top.

Release Notes:

- Supported commands in inlay hints
2026-09-09 13:47:39 +00:00
Kirill Bulatov 66a1d8d7cb Support LSP command executions and showDocument requests (#63607)
Closes https://github.com/zed-industries/zed/issues/13756
Closes https://github.com/zed-industries/zed/issues/61572

Last window client capability we were missing!
<img width="1557" height="159" alt="image"
src="https://github.com/user-attachments/assets/2cca5d92-a28e-4262-8f55-89f582782bbc"
/>

Two features are connected to each other, as most of the commands result
in opening a document:


https://github.com/user-attachments/assets/661aae88-7af9-4173-9f6a-2fd11dbec675


Release Notes:

- Added support for LSP command executions and showDocument requests
2026-09-09 13:47:28 +00:00
Kirill Bulatov 5697636cd5 Autosuggest Emmet extension (#63750)
Closes https://github.com/zed-industries/zed/issues/32713

<img width="507" height="160" alt="image"
src="https://github.com/user-attachments/assets/356973ce-51b8-43be-9b4c-700d0d5dd009"
/>


https://github.com/user-attachments/assets/eea030ba-7a40-406d-bf43-3ac9c6af70f1


Release Notes:

- Added Emmet extension autosuggestion
2026-09-09 12:27:32 +00:00
zed-zippy[bot] 5e25888c38 Bump Zed to v1.21.0 (#63960)
Release Notes:

- N/A

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-09-09 12:16:17 +00:00
Lukas Wirth 5849530017 gpui: Replace shared asset futures with owning cache entries (#63934)
## Summary

Replace GPUI's shared asset futures with owning cache entries. The
mutex-backed waiter collection in futures::future::Shared can contend
between a worker and the browser main thread, where blocking waits are
forbidden.

- Keep loading on the background executor, with one foreground task
publishing the cached result and notifying interested views.
- Deduplicate loads and view registrations; cancel pending work on
eviction without allowing completion to update a replacement entry.
- Change App::fetch_asset to return Option<A::Output>, remove
ImageLoadingTask, and make ImageCacheItem an opaque owning entry.
- Migrate the retain-all image cache and image gallery LRU example.
Repository-wide search found no further callers requiring migration.

Results become visible after the foreground completion task publishes
them. Entries expose neither cloneable nor awaitable task handles.

Release Notes:

- N/A
2026-09-09 09:30:38 +00:00
Om ChillureandPiotr Osiewicz 24b222a981 Fix tab switcher random jumps (#52671)
#### Fixes #52579

When quickly pressing and releasing Ctrl+Tab, the tab switcher popover
would briefly appear, and any mouse movement over it would select a
random tab instead of the intended recently-focused file.

### Fix : 
This adds a 300ms delay before showing the tab switcher UI when opened
via modifier keys. If the modifier is released before the delay elapses,
the selected item is confirmed directly without ever showing the
popover. This matches the behavior of system window switchers (e.g.
macOS Cmd+Tab), where quick presses never flash the UI.

- `visible` and `_show_task` fields track whether the popover should be
rendered
- When not yet visible, the picker is mounted in a zero-size
overflow-hidden container to preserve focus and keyboard state
- When modifiers are released before the popover is visible, `confirm()`
is called directly instead of dispatching `menu::Confirm`, avoiding any
mouse-hover-based selection

### Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — *N/A, no unsafe
blocks*
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
— *Matches system window switcher behavior (e.g. macOS Cmd+Tab); no
visual change for slow/held switches*
- [x] Tests cover the new/changed behavior — *Added
`test_quick_switch_before_popover_visible`*
- [x] Performance impact has been considered and is acceptable — *Only
adds a lightweight 300ms timer task; no extra allocations or rendering
cost*

### Video 

[Screencast from 2026-03-29
11-52-07.webm](https://github.com/user-attachments/assets/8e148a74-75ae-4c36-8d44-594c3c9097e6)



### Note : Reopens previous work from closed PR #52648 (fork was deleted
by mistake)


Release Notes:

- Fixed Ctrl+Tab jumping to random documents when the mouse is moved
during a quick tab switch

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2026-09-09 09:09:25 +00:00
5c1845ddb8 Fix language injections containing interpolations (#49265)
Release Notes:

- Fixed injected language highlighting for strings containing
interpolations

current             |  updated
:-------------------------:|:-------------------------:

![](https://github.com/user-attachments/assets/b1e609c4-f0cd-45af-9e11-abcc711a19ea)
|
![](https://github.com/user-attachments/assets/9d6eb37e-f476-4495-bcec-9792ad52d3d6)

<details>

<summary> test snippet  </summary>

```python
my_regex = r"[0-9]"
spark.sql(  # sql
    f"""
        SELECT
            col1,
            CASE WHEN col2 RLIKE '{my_regex}' THEN '1' ELSE '2' END col4,
            ROW_NUMBER() OVER(PARTITION BY col1, col2 ORDER BY col3) as rn
        FROM tbl
    """
)
```

</details>

## Summary
Strings with interpolations like `f"SELECT col1 FROM tbl WHERE col2 =
'{my_var}'"` in Python produce multiple `string_content` nodes. Without
grouping, each fragment gets its own injection layer which breaks syntax
highlighting.

This PR adds an `@injection.host` capture to group `@injection.content`
ranges by their host node. This was implemented by extending the
existing `combined_injection_ranges` hash map with a node key per host.
Added tests for this behavior covering simple strings, f-strings with
single/multiple interpolations, and multi-string isolation.

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 08:27:12 +00:00
Rani 5df18ff955 editor: Skip multi-cursor selection broadcast when unshared (#60605)
Resubmit of #59731, which got auto-closed when I accidentally deleted
its branch. It wasn't rejected, it had already been reviewed. This is
rebased onto latest `main`, and osiewicz's review feedback (using `_`
for the unused param in the trait default) is already in.

Follow-up to #58510. Profiling multi-cursor typing on current main
showed the per-keystroke `set_active_selections` broadcast does an
O(selections) multi-buffer anchor remap and runs even with zero
collaborators (about 0.9ms/call at 1k cursors, 8.4ms at 10k, fired ~3x
per edited iteration).

This skips the broadcast when the buffer has no audience, and
re-publishes on share so there's no regression:

- Add `CollaborationHub::should_broadcast_selections`, defaulting to
`true`. `Entity<Project>` overrides it to `Project::is_shared()`, which
is true for a host that shared the project and for a collab guest, and
stays correct before peer-join notifications have propagated locally
(unlike a live collaborator count). A purely local project has no
audience.
- Gate `set_active_selections` in `selections_did_change` on it.
Follow-mode is unaffected since it uses the separate
UpdateFollowers/UpdateView channel, and the focused user's own cursors
render from `editor.selections`, not `remote_selections`.
- When the project becomes (re)shared (`RemoteIdChanged(Some)`,
`Reshared`, `HostReshared`), the focused editor re-publishes its current
selections, so a peer joining after a share still sees the host's cursor
without waiting for the next selection change.
- Reuse the post-edit display snapshot in the `hard_wrap` branch instead
of taking a redundant fresh buffer snapshot.

Multi-cursor type+delete benchmark: about 5% faster at both 1k and 10k
cursors (615 to 583 ms at 10k, significant). All 773 editor tests pass
locally. Collab and channel-buffer integration tests need the test DB,
so they run on CI.

Discussion and profiling:
https://github.com/zed-industries/zed/issues/32051

Release Notes:

- Improved multi cursor editing performance
2026-09-09 08:20:26 +00:00
Nicolas Le CamandPiotr Osiewicz 63fc2ea501 node_runtime: Ignore package-lock.json files when installing internal tools (#52451)
## Context

This prevents tools with native bindings to fail installation, see:
- https://github.com/oxc-project/oxc-zed/issues/145
- https://github.com/napi-rs/napi-rs/pull/2707
- https://github.com/npm/cli/issues/4828

## How to Review

Fixes for https://github.com/oxc-project/oxc-zed/issues/145

## Self-Review Checklist

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

Release Notes:

- Fixed potential node tools failed/incomplete installation when having
native bindings as optional dependencies

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2026-09-08 21:44:06 +00:00
Ali 6870a68687 project: Stop sharing private files through project search (#63860)
# Objective

Files matching the `private_files` setting are meant not to be shared
with collaborators. That is true when a guest asks to open one directly,
`respond_to_open_buffer_request` refuses with `ErrorCode::UnsharedItem`.

Project search reaches the same `create_buffer_for_peer` without passing
through that check. In `handle_search_candidate_buffers`, every matching
buffer was shared with the requesting peer unconditionally, so a guest
searching for a string that happens to appear in a private file received
the buffer containing it.

## Solution

Check `is_private` before sharing a matched buffer with a peer

## Testing

added new test `test_project_search_excludes_private_files` in the
collab integration suite:"
The host configures `private_files: ["**/.env"]` and has two files
`.env` containing `API_KEY=secret` and `a.txt` containing `the secret is
out`. The guest joins the shared project and searches for `secret`.



---

Release Notes:
- Fixed private files being shared with collaborators through project
search.
2026-09-08 20:49:05 +00:00
Tim Vermeulen bcf8c7bee7 Fix crash in Editor::rotate_selections using cursors on nonconsecutive lines (#63937)
Crash repro:

```
A
1234567890
B
C
```
1. place cursors before `A`, `B`, and `C`
2. run `editor: rotate selections forward`

Caused by the current `Editor::rotate_selections` logic assuming that
the text between the end of one of the lines being rotated and the start
of the next one is just the newline:
```rs
let newline_len = line_ranges[1].start.0 - line_ranges[0].end.0;
```
which fails when those lines aren't consecutive in the editor.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [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 crash in `editor: rotate selections forward` and `editor: rotate
selections backward` using cursors on nonconsecutive lines.
2026-09-08 20:13:56 +00:00
Kirill Bulatov a6b3c5b33d Fix block-comment prefix stripping when joining lines (#63916)
Closes
https://github.com/zed-industries/zed/issues/63273#issuecomment-5580302020



https://github.com/user-attachments/assets/0945d43d-9a19-4af6-bc85-c3369d8babb3


Release Notes:

- Fixed block-comment prefix stripping when joining lines
2026-09-08 15:16:55 +00:00
Rusty Raven 3a904a7722 docs: Describe how preview tabs actually behave (#63875)
# Objective

- Fixes #33819
- The `preview_tabs` documentation says preview tabs "close
automatically when you switch to another file unless you explicitly pin
them". They do not close. Moving to another file leaves the preview tab
open — either still as the preview tab, or converted into a regular one.
Four people ran into this on the issue over the past year.
- The same section then lists the ways to turn a preview tab into a
regular tab, and two of them are missing, including the pinning that the
sentence above uses as its counter-example.

## Solution

Two corrections to the `Preview tabs` section of
`docs/src/reference/all-settings.md`. No behaviour was touched.

**The description.** A pane holds a single `preview_item_id`, so there
is at most one preview tab at a time. What happens to it when you move
to another file depends on the path:

- Opening a not-yet-open file in preview mode from the project panel or
file finder goes through `Pane::open_item`, which calls
`close_current_preview_item` — that really does close the old tab
(`remove_item`) and hands back its index, and the new file is inserted
there.
- Code navigation with the default
`enable_keep_preview_on_code_navigation: false` instead calls
`unpreview_item_if_preview` on the old item *before*
`replace_preview_item_id`, so the previous file stays open as a regular
tab.

A third path, the file finder with the default
`enable_preview_from_file_finder: false`, opens the new file as a
regular tab and leaves the existing preview tab alone entirely.

Rather than spell out every path in a settings description — the
`enable_preview_*` settings immediately below already cover them — the
new wording sticks to what holds in all of them: a pane keeps at most
one preview tab and opening another file in preview mode takes over that
slot, and switching to a file that is already open does not close the
preview tab. That second half is the case the issue actually reports.

**The list.** Two more ways to convert a preview tab into a regular tab:

- Pinning it — `change_tab_pin_state` calls `unpreview_item_if_preview`
on the `Pin` branch.
- `pane::TogglePreviewTab` — the action dedicated to exactly this,
registered whenever preview tabs are enabled.

## Testing

- Built a debug Zed and walked through the steps from the issue on a
scratch project of `a.txt` / `b.txt` / `c.txt`: with `a.txt` open as a
regular tab and `b.txt` opened as a preview tab, clicking back to
`a.txt` leaves the `b.txt` preview tab open, which is what the current
wording says should not happen. Single-clicking `c.txt` takes over the
same slot rather than adding a second preview tab, and pinning the
preview tab drops the italics.
- Ran the docs steps from `run_tests.yml` locally: `zed
--dump-all-actions > crates/docs_preprocessor/actions.json`, then
`mdbook build ./docs` on mdbook 0.4.37 to match CI. Exit 0 with no
preprocessor errors, and both new `{#action ...}` references resolve —
the rendered page reads "pane: toggle pin tab" and "pane: toggle preview
tab" in the same style as the existing "project panel: open permanent".
- `cargo test -p workspace --lib` — 272 passed, 0 failed, including
`test_close_other_items_unpreviews_active_item`,
`test_reopening_closed_item_after_unpreview`, and the proptest that
opens random paths with random `allow_preview` and asserts a pane never
holds more than one preview item.

## Notes for review

- Several people on the issue would rather the *behaviour* changed, so
that preview tabs close on any tab switch the way the docs currently
describe. I left that alone deliberately: the issue is typed `Docs`, so
this PR only makes the prose match the implementation. Happy to open a
discussion separately if it is worth pursuing.
- Saving a file also unpreviews it (`Pane::save_item`), but I left it
off the list as redundant — you have to edit a file before you can save
it, and editing is already there. Say the word if you would rather it
were explicit.
- The comment on `preview_tabs.enabled` in
`assets/settings/default.json` words this as "close automatically when
you open another preview tab". That is right for the project-panel path
and carries the same code-navigation caveat as above; I left it alone to
keep this diff to one file, and am happy to align it in a follow-up.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — N/A
- [x] The content adheres to Zed's UI standards — N/A, docs only
- [x] Tests cover the new/changed behavior — N/A, no behaviour change;
the docs build is verified locally
- [x] Performance impact has been considered and is acceptable — N/A

---

Release Notes:

- N/A
2026-09-08 12:24:20 +00:00
Kirill Bulatov 2e9b4fe596 Unify copy actions for agent panel and markdown (#63884)
Before, it was not possible at all to copy the text from the agent
panel, only its markdown.
The PR breaks the existing ctrl/cmd-c binding there by using the same
approach markdown preview does: copy as text by default, allow to copy
as markdown via the context menu.

Before:


https://github.com/user-attachments/assets/2014f363-5167-4700-be86-9c0774d7e4fd

After:


https://github.com/user-attachments/assets/1dad253c-7a3b-4ca7-99c8-e8df8b3c3fd6


Release Notes:

- Changed agent panel to copy text with cmd/ctrl-c, as markdown preview
does. `markdown::CopyAsMarkdown` action is available still and can be
bound if needed.
2026-09-08 11:21:20 +00:00