Commit Graph
39827 Commits
Author SHA1 Message Date
Dmitry IvanishkinandKirill Bulatov fad8515a7a git_graph: Show time in commit details (#62679)
# Objective

The Git Graph list shows the full commit timestamp in its constrained
date column, while the more spacious commit details view only shows the
calendar date. Include the time in the details view so it does not
provide less information than the graph itself.

## Solution

Reuse the existing `format_timestamp` helper from the Git Graph `Date`
column when rendering the selected commit details. This gives both views
the same local date and time format without a separate formatting path.

## Testing

- `cargo check -p git_ui`

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

- Improved Git Graph commit details to show the same full commit
timestamp as the `Date` column.

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-03 09:47:23 +00:00
Smit BarmaseandKirill Bulatov d4424eec68 which_key: Add a pending key binding indicator (#63343)
This PR makes Zed's one-second key binding delay visible.

Say both ctrl-w and ctrl-w left have bindings. After you press ctrl-w,
Zed waits to see whether left follows. The PR shows that wait in the
status bar with a countdown. Hovering the indicator shows which bindings
can still match.

It also adds a setting to hide the indicator. It does not change how Zed
resolves key bindings.

<img height="100" alt="dyn-db84a840272e2f6250a3f527a59b1efd"
src="https://github.com/user-attachments/assets/e42c6a6c-4677-499f-a1d3-835960ebb21a"
/>
<br/>
<img height="100" alt="dyn-8012278d030b41bc8ebfae1540504eff"
src="https://github.com/user-attachments/assets/250928d5-f913-40f0-9068-00ccb5cdf59f"
/>
<br/>
<img height="100" alt="file-5e6ffa90944faa294e7870f471b4e65b"
src="https://github.com/user-attachments/assets/c250e6eb-a269-4e2c-a5a0-0be9b5006f99"
/>

Release Notes:

- Added a status bar countdown for pending multi-stroke key bindings.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-03 09:35:53 +00:00
Smit Barmase a47324bb2b gpui: Add an option to keep hover listeners active after keyboard input (#63614)
While working on https://github.com/zed-industries/zed/pull/63343, I ran
into a problem with the pending key binding indicator. Hovering pauses
its countdown, but pressing the next key made `on_hover` report false
even though the mouse had not moved. The countdown then resumed while
the pointer was still over the indicator.

`on_hover` currently follows GPUI's normal hover rules. GPUI clears
hover after keyboard input so the item under a stationary mouse does not
interfere with keyboard navigation, for example list popover navigation
with keyboard.

This PR adds `HoverListenerMode` and `hover_listener_mode`. Callers that
need to track the pointer across key presses can opt in like this:

```rs
div()
    .hover_listener_mode(HoverListenerMode::InputModalityIndependent)
    .on_hover(|is_hovered, window, cx| {
          // ...
      })
```

`InputModalityAware` remains the default.

Release Notes:

- N/A
2026-09-03 09:35:52 +00:00
denizdogan 9441364cf1 Fix Keymap Editor "Search by Keystrokes" shortcut shadowed by the text finder (#63376)
# Objective

Fixes #62361.

In the Keymap Editor, focus lands on the "Filter action names" input,
which is wrapped in a `BufferSearchBar` key context
(`crates/keymap_editor/src/keymap_editor.rs`). Its `cmd-alt-f →
text_finder::Toggle` binding (added in #60677) shadows the
`KeymapEditor` context's `cmd-alt-f →
keymap_editor::ToggleKeystrokeSearch`, because `BufferSearchBar` sits
deeper in the focus stack — so `cmd-alt-f` in the filter opens the file
finder instead of toggling "Search by Keystrokes". Same collision on
Linux (`ctrl-alt-f`); Windows is unaffected (it uses `alt-f`).

## Solution

Add a `KeymapEditor > BufferSearchBar` binding mapping the chord back to
`keymap_editor::ToggleKeystrokeSearch`, in `default-macos.json` and
`default-linux.json`. It's more specific than the plain
`BufferSearchBar` binding and placed after the `KeymapEditor` block, so
it wins the same-depth tie-break (gpui precedence: depth, then
definition order) — restoring the shortcut inside the Keymap Editor
without affecting the global text finder.

I gave the `KeymapEditor` binding precedence rather than rebinding
"Search by Keystrokes" to a non-conflicting default (e.g. `cmd-alt-k`),
since it's less invasive and doesn't change a documented default. Happy
to switch to the rebind if the team prefers.

## Testing

Built and ran locally on macOS: opened the Keymap Editor (`cmd-k
cmd-s`), pressed `cmd-alt-f` with focus in the filter → "Search by
Keystrokes" toggles instead of opening the file finder; confirmed the
file finder still works normally in a regular editor. `cargo test -p zed
keymap` passes (validates the bundled keymaps parse and all actions
resolve).

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Tests cover the new/changed behavior (bundled-keymap validation
exercises the new binding; runtime behavior manually verified — no logic
to unit-test in a default-keymap change)

_Unsafe blocks / UI standards / performance: N/A for a keymap default
change._


Release Notes:

- Fixed the Keymap Editor's "Search by Keystrokes" shortcut (`cmd-alt-f`
/ `ctrl-alt-f`) being shadowed by the file finder.
2026-09-03 08:45:58 +00:00
Vlad GaevskyandMrSubidubi d0699ca1d6 gpui: Snap recomputed padding to the device pixel grid before clamping scroll (#62296)
# Objective

Follow-up to #62135, taking the approach suggested there: fix the error
at its
source in GPUI instead of hiding it in the scrollbar.

At fractional rem sizes (`py_1` at an odd UI font size), a container
whose
content fits becomes scrollable by a sub-pixel amount, and every
uniform-list
picker grows a full-height scrollbar thumb for that phantom range.

## Solution

Taffy lays boxes out with every authored length snapped to the device
pixel grid
(`to_taffy`), and the final bounds are snapped again after layout.
However,
`Interactivity::clamp_scroll_position` recomputed the padding from the
raw style
with no snapping at all, so the padded content size exceeded the snapped
bounds
by up to half a device pixel, far past the existing two-decimal
float-noise
rounding, and `scroll_max` came out positive.

The fix snaps the recomputed padding with the same `pixel_snap` helper
the rest
of the pipeline uses, so both operands of the subtraction sit on the
same grid
and the phantom range never comes into existence.

Two neighbouring cases are deliberately left out to keep this scoped,
both are
follow-up candidates: percentage-based padding resolves inside Taffy
without
pre-snapping, so a discrepancy is still theoretically possible there;
and
`ListState::max_scroll_offset` (the older `list()` element) has no
rounding
protection at all.

## Testing

- New regression test: a 50px container with `py(4.25)` padding and a
child that
fits exactly. It fails on main (`max_offset` comes out at 0.5px) and
passes
  with the fix; verified in both directions.
- Full gpui suite: 241 tests pass.
- Reviewers can see the original symptom by opening any picker at a UI
font
size that makes `py_1` fractional in device pixels: a spurious
full-height
scrollbar thumb appears on main and is gone with this change. The math
is
  logical-pixel only, so the behavior is 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
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable (one
pixel-snap
per padding edge per clamp, negligible against existing per-frame layout
work)

cc @MrSubidubi

Release Notes:

- Fixed containers becoming scrollable by a sub-pixel amount, with a
phantom
  full-height scrollbar thumb, at fractional UI font sizes.

Co-authored-by: MrSubidubi <finn@zed.dev>
2026-09-02 23:15:40 +00:00
Finn Evers 946dab8c11 extension_cli: Error on unrecognized files and queries in language directories (#63080)
This ensures that we do not copy over resources we do not need for
languages. We enforce this at this stage so that potential contributors
to these extensions do not think these files might be needed for the
given language.

Release Notes:

- N/A
2026-09-02 22:45:15 +00:00
kai-xlr 443318ef01 agent_ui: Hide manage skills command when AI is disabled (#63598)
# Objective

Fixes #63495

When `"disable_ai": true` is set, `agent: manage skills` still appears
in the command palette. The action was exposed by the `else` branch of
the `disable_ai` check in `update_command_palette_filter`, which called
`show_action_types` on it — overriding the `hide_namespace("agent")`
applied when AI is disabled.

## Solution

Moved `filter.hide_action_types(&manage_skills_action)` out of the
conditional so it applies regardless of the `disable_ai` setting. Skills
are surfaced through the settings UI now, so the command should never
appear in the palette.

Added test coverage in `test_agent_command_palette_visibility`:
- Asserts `ManageSkills` is hidden even when AI is enabled (the
invariant).
- Asserts `ManageSkills`, `OpenSkillCreator`, and `NewThread` are hidden
when AI is disabled.

## Testing

- `cargo test -p agent_ui` (398 passed)
- `./script/clippy -p agent_ui`
- `cargo fmt --check`
- Manual verification: set `"disable_ai": true`, open the command
palette, filter `agent` — `agent: manage skills` should be absent.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments (no unsafe blocks)
- [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 `agent: manage skills` still appearing in the command palette
when AI is disabled
2026-09-02 20:56:51 +00:00
Cameron Mcloughlin 81808cb5db gpui: Add TouchDragEvent API (#63645)
Adds `TouchDragEvent` and coresponding APIs. This allows web/touch-based
code to capture long press events without having to go through
scroll-like APIs

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-02 20:28:07 +00:00
Shuhei KadowakiandKirill Bulatov 8482496a16 lsp: Honor dynamic LSP document selectors (#59243)
Zed previously discarded the documentSelector from dynamically
registered textDocument capabilities and treated those capabilities as
applicable to every buffer attached to the server. This could route
requests for documents outside a registration selector.

Track dynamic textDocument registrations by method and registration ID,
and use their selectors when routing local requests, checking
capabilities, and deriving completion triggers. Static capabilities
continue to apply to every attached buffer. Language and URI scheme
matching are supported, while unsupported pattern matching remains
fail-open.

Keep document color, symbol, link, code lens, and folding range caches
aligned with the selector-aware server set so incapable or non-matching
servers do not leave caches perpetually incomplete.

Require an advertised diagnostic provider before sending pull diagnostic
requests, and add integration coverage for selector-aware dynamic
completion registration and trigger updates.

---

Release Notes:

- Improved language server request routing to respect dynamically
registered document selectors.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-02 19:54:04 +00:00
Kirill Bulatov 9be65a8dfe Strip local symbols from macOS and Linux release bundles (#63429)
Not sure if this PR is 100% good, since it removes symbols from local
traces, leaving addresses only — but this what Windows seem to do
already, and we have those symbols on Sentry to restore from, which were
needed to normally read Linux perf traces already (see `perf.zip` in
https://github.com/zed-industries/zed/issues/59689#issuecomment-5452720248)

On the upside, uncompressed binaries' are now ~100MB less, which is a
lot — hence decided to open the PR for the review

-------------------

Strips debug info and local symbols from shipped macOS and Linux
binaries, matching what Windows already does with PDBs: `bundle-mac` now
always runs `dsymutil` before a new `strip -x` step, and `bundle-linux`
adds `--discard-all` plus `zed.dbg`/`remote_server.dbg` extraction via
`--only-keep-debug`.

Sentry uploads are unchanged and precede stripping.

The macOS binary UUID and the GNU build id survive stripping, so
user-provided traces stay recoverable without rebuilding at the
reporter's commit: `sample` output resolves via `atos` against the
archived `zed.dwarf`, and `perf.data` via `perf buildid-cache` against
the Sentry-archived binary.

zed binary:
macOS (2026-08-29 nightly): 420478976 -> 316503984 bytes (-24.7%,
-104.0MB)
Linux (v1.17.2 aarch64): 439417448 -> 336967256 bytes (-23.3%, -102.5MB)
Downloads shrink far less, symbols compress ~7:1: the macOS DMG loses
only ~15MB.

Release Notes:

- Improved installed size on macOS and Linux by stripping debug symbols
from release binaries (roughly -25%)
2026-09-02 19:38:12 +00:00
Kirill Bulatov 8b32975a05 Fix workspace diagnostics polling (#63336)
Closes https://github.com/zed-industries/zed/issues/62391

Workspace diagnostics were polled incorrectly:

* Workspace pulls were cancelled and re-sent every 120s.
Pyright-family servers hold the request open forever and re-analyze the
whole workspace on every new one, so the retry loop leaked memory; the
request is now kept open (long-poll), as the spec recommends.

* No re-trigger after a server closed a workspace pull.
ty closes the request when diagnostics change and expects the client to
re-pull
 
* `ServerCancelled` / `retriggerRequest` was ignored.
The spec defaults cancellation data to `{ retriggerRequest: true }`, so
these errors now retrigger workspace pulls and retry document pulls
instead of failing them.

* LSP error codes were erased with `anyhow!(message)`
Errors now carry a typed `lsp::ResponseError` through the chain,
replacing four copies of `ends_with(...)` matching against
rust-analyzer's literal message texts.

* Workspace partial results were not tied to their request.
Stale or numeric-token `$/progress` reports were applied as current data
and could poison `previousResultIds` until a server restart; reports are
now matched against the exact in-flight token.

* `interFileDependencies` was never read.
Every edit re-pulled all other open buffers even for servers declaring
no inter-file dependencies (e.g. ruff); cross-buffer pulls are now gated
on that capability.

* Cross-buffer pulls were unpaced.
All open buffers were pulled back-to-back after each edit debounce; they
are now paced at one document per 500ms.

* The failure valve killed workspace pulls permanently.
51 hard errors over a server's lifetime silently stopped its workspace
pulls until restart

* Concurrent refresh waiters could be dropped instantly.
The capacity-1 refresh channel resolved a second concurrent waiter to
`false` immediately, and request errors dropped queued refreshes;
waiters now queue and carry over to the retried pull.

Release Notes:

- Fixed basedpyright memory leak caused by incorrect workspace
diagnostics polling
2026-09-02 19:12:35 +00:00
Finn Evers bfad3a6108 docs: Document focus_follows_mouse (#63646)
Release Notes:

- N/A
2026-09-02 18:54:48 +00:00
Kaj KowalskiandKirill Bulatov cdee8dd547 Properly clear diagnostics data for stopped servers (#63460)
# Objective

Diagnostics published by a language server survive the buffer being
detached from that server, so a file keeps showing errors from a server
that is no longer reading it.

To reproduce:

1. Install the [GitHub Actions
extension](https://zed.dev/extensions/github-actions).
2. Open a composite action definition,
`.github/actions/<name>/action.yml`.
3. Select the GitHub Actions language for it in the language selector.
That server validates the file as a workflow, so it reports `on` and
`jobs` as missing and `inputs`, `outputs` and `runs` as unexpected.
4. Select YAML again, since GitHub Actions was not what you wanted here.
5. The errors are still there. `editor: restart language servers` does
not clear them either. They go away only once the buffer is dropped, in
practice by switching to another project and back.

Two things keep them alive:

- `LocalLspStore::unregister_buffer_from_language_servers` drops the
snapshot bookkeeping and sends `didClose`, but never clears what that
server already published. `LspStore::set_language_for_buffer` calls it,
so a language change detaches the buffer while leaving the old verdict
on it.
- Restarting does not reach the server either.
`stop_local_language_servers_for_buffers` collects servers through
`language_server_ids_for_buffer`, evaluated against the language the
buffer has *now*. The old server no longer matches, so it is never
stopped, and it is typically still running legitimately for other files
in the project. Only `stop_local_language_server` clears diagnostics,
and it is never reached for that server.

## Solution

The first commit cleared the detached server's diagnostics inside
`unregister_buffer_from_language_servers`, on `didClose`. Review pointed
out that publishes are applied by path regardless of registration, so a
running server can legitimately describe a file that is no longer open
in it, and that this clearing also left `diagnostic_summaries` and the
worktree's per-path diagnostics stale.

The second commit reworks this. Detaching a buffer now only drops the
buffer's entry in `buffers_opened_in_servers` and the path's
pull-diagnostics result ids for the servers it left, two pieces of
per-server state that previously leaked. After the buffer is registered
with the servers of its new language, the server tree is rebuilt through
`refresh_server_tree`, the same pruning that runs on settings changes:
every server no registered buffer maps to any more is stopped through
`stop_local_language_server`, whose path already clears buffer
diagnostic sets, `diagnostic_summaries` and worktree diagnostics. A
detached server that other buffers still map to keeps running and keeps
everything it published. An earlier revision judged orphanhood by
`buffers_opened_in_servers`, which is only filled in once a server runs,
so it stopped servers that were still starting;
`test_context_completion_provider_mentions` caught that.

## Testing

Added `test_selecting_a_language_clears_the_old_servers_diagnostics`: a
Rust buffer gets a diagnostic from a fake server, the buffer is switched
to JavaScript, and afterwards both the buffer's diagnostics and the
project-level `diagnostic_summary` must be empty. It fails on `main`,
where the message survives the switch:

```text
< ["unused constant"]
> []
```

The test passes with the rework and fails without it. The `project` test
suite, `script/clippy` and style checks ran green on the reworked change
in CI. Tested on Linux; the change is 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

## Showcase

The buffer is back on YAML, as the status bar shows, while the workflow
schema's complaints from the GitHub Actions server are still on screen:
`on` and `jobs` reported missing, and `inputs`, `outputs` and `runs`
reported as unexpected values.

<img width="2514" height="2008" alt="Screenshot From 2026-08-30
21-52-12"
src="https://github.com/user-attachments/assets/040898a6-cc61-41b6-88c6-f346666e8e13"
/>

---

Release Notes:

- Fixed diagnostics from the previous language server staying on a file
after changing its language.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-09-02 18:23:56 +00:00
Cameron Mcloughlin bd46f70cfd gpui: Prevent touch mispredict jitter (#63638)
When scrolling, mispredicted touch events could cause scroll jitter. We
now ignore predictions that are "travelling the wrong direction".

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-02 18:23:32 +00:00
Shuhei Kadowaki e0c38940d5 lsp: Scope logs and status updates to their projects (#61221)
The language registry and LSP log store are shared by every workspace in
a Zed process. The LSP Logs selector enumerated the shared log store
without filtering by project, while each activity indicator consumed
global binary status updates. This exposed servers from other windows as
"Unknown worktree" entries and surfaced their startup failures or
timeouts in unrelated status bars.

Key each logged server by its owning project or LSP store together with
its process-local language server ID. Use that identity consistently
when adding, removing, streaming, selecting, opening, and reselecting
log entries so local, remote, SSH, and supplementary servers cannot
collide across ownership domains.

Model Copilot and other servers outside the project LSP store as
project-scoped supplementary servers, while matching SSH servers by
their owning LSP store.

Tag project-originated binary status updates with the owning LSP store
entity ID. Carry that source through extension worktree delegates and
every worktree-based WASM language-server call, then let each local LSP
store forward only statuses for its project. Activity indicators rely
solely on their project LSP store, and remote projects continue to
receive host statuses through the existing protocol path instead of
subscribing to local registry events.

Own each binary-status subscription task in its local LSP store and
unregister its broadcaster sender when the store is dropped, so closing
windows cannot leave detached status tasks or stale senders behind.

Add regression coverage for duplicate process-local server IDs across
ownership domains, filtering remote, supplementary, and SSH servers from
other projects, retaining servers owned by the current project or LSP
store, preserving extension status sources, and unregistering dropped
status subscriptions.

Release Notes:

- Fixed language servers from other projects appearing in the LSP Logs
view and their statuses showing in unrelated windows' status bars
2026-09-02 18:23:27 +00:00
Cameron Mcloughlin 1a1d00988e gpui_web: Drive IME mirror focus state from GPUI (#63629)
Previously, we manually synchronized the keyboard state in response to
tap events, but this meant that several common cases were unreliable.

Now, we use GPUI's focused element as the source of truth, and use
`sync_virtual_keyboard` in cases where they have gotten out of sync
(i.e. a user manually dismisses a keyboard while the input is still
focused).

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-02 18:23:07 +00:00
Kirill Bulatov b80f016f89 Bump more dependencies (#63379)
* 1st commit fixes bumps `quinn-proto` and `serde_with` to fix the
dependabot alerts

* 2nd commit deduplicates more dependencies

`cargo tree -d` listing: 194 -> 187 top-level entries on the host
target, 298 -> 287 unique duplicated crate-versions across all targets.

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

```
accesskit_consumer (v0.35.0, v0.37.0 -> v0.38.0)
bindgen (v0.71.1, v0.72.1 -> v0.72.1)
nix (v0.28.0, v0.29.0, v0.30.1 -> v0.28.0, v0.30.1)
ordered-float (v2.10.1, v4.6.0 -> v5.5.0)
quick-xml (v0.30.0, v0.37.5, v0.38.3, v0.39.3, v0.41.0 -> v0.30.0, v0.37.5, v0.39.3, v0.41.0)
sysinfo (v0.31.4, v0.37.2 -> v0.31.4, v0.39.6)
wasm-encoder (v0.252.0, v0.254.0 -> v0.254.0)
wasmparser (v0.252.0, v0.254.0 -> v0.254.0)
windows-registry (v0.4.0, v0.5.3, v0.6.1 -> v0.4.0, v0.6.1)
```

`ordered-float v4.6.0` remains in the lockfile only as an inactive
optional dependency of `sea-query`; the compiled graph is fully
deduplicated to v5.5.0.

</details>

Release Notes:

- N/A
2026-09-02 18:21:25 +00:00
Kirill Bulatov 74f3fa1454 Support Emmet's wrap with abbreviation (#63383)
Closes https://github.com/zed-industries/zed/issues/15588


https://github.com/user-attachments/assets/2813d235-6dac-4fe6-9ae0-2783e16270ac

Release Notes:

- Added Emmet's wrap with abbreviation support
2026-09-02 18:21:02 +00:00
Albert Bogusz 7e7087a589 Add on_new_window setting (#63522)
> [!NOTE]
> This is a remake of #63335 as it's unlikely to be reopened just from
my
[mention](https://github.com/zed-industries/zed/pull/63335#issuecomment-5452544138).
Apologies for the noise!

# Objective

Closes #59368, where users (including me) are asking for a way to show
the Launchpad instead of an empty tab when opening a new window. As per
advice from
https://github.com/zed-industries/zed/issues/60720#issuecomment-4936162420,
adding a separate setting from `restore_on_startup` is more ideal.

`on_new_window` allows for two values:
- `empty_tab`
- `launchpad` (default)

## Testing

Added a regression test which opens a new window with `on_new_window`
set to `launchpad` and asserts that no item gets opened in the window's
pane. I've verified it fails without the setting gate, and confirmed
configuring this setting works manually (see Showcase).

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

## Showcase


https://github.com/user-attachments/assets/bf339bd1-8c62-4243-ac9d-1045d1a14865

---

Release Notes:

- Added `on_new_window` setting to configure the opening of new windows.
2026-09-02 18:17:30 +00:00
Jakub Konka f15a5dac90 nix: Include corgi patches in build sources (#63644)
The local `scratch` override lives under `corgi-patches`, but the Nix
build source filter omitted that directory. As a result, `nix develop`
failed while loading the patched dependency.

Include `corgi-patches` in the filtered source and preserve the patch
implementation in Crane's dummy dependency source. The latter is
required because `cxx-build` calls `scratch::path` while dependency
artifacts are built.

## Testing

- `nix fmt -- --ci nix/build.nix`
- `nix develop --command true`
- `nix develop --command cargo fmt --check`

Release Notes:

- N/A
2026-09-02 18:13:59 +00:00
zed-zippy[bot] c784b96b33 Bump Zed to v1.20.0 (#63636)
Release Notes:

- N/A

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-09-02 17:53:30 +00:00
Jakub Konka 0d31bb3e06 ui: Allow hiding keybinding labels (#63616)
`KeyBinding` elements currently always render their shortcut labels.
Applications with a touch-oriented interface cannot remove those
keyboard-only visual affordances without changing each consumer or
unregistering the shortcuts themselves.

This adds an application-wide visibility policy to the reusable
`KeyBinding` component, so context menus and other consumers follow the
same setting. Registered keybindings and `aria-keyshortcuts` remain
intact, and labels remain visible by default.

## Testing

- `cargo nextest run -p ui --lib`
- `cargo fmt --check`
- The final unused-override cleanup was not rerun because `nix develop`
currently fails while building the existing `zed-editor-deps`
derivation: `corgi-patches/scratch/Cargo.toml` is absent from its Nix
source.

Release Notes:

- N/A
2026-09-02 17:46:50 +00:00
Finn EversandAnant Goel af2c5b36c7 Unify language model event stream handling (#63520)
Closes https://github.com/zed-industries/zed/issues/63314
Closes https://github.com/zed-industries/zed/issues/42584

Follow-up to https://github.com/zed-industries/zed/pull/62652

Removes a lot of duplicated code in favor of throwing it
into`language_core` as well as removing duplicate struct definitions
that were only different because of entirely unused fields.

Furthermore, improves error-messages so that these untagged enum errors
are no longer a thing in an effort to make this more maintainable in the
future.

Lastly, includes a small but nice improvement changing a `Value` to a
`RawValue` so that we don't have to clone for deserialization in that
specific case.

Release Notes:

- Improved streaming for OpenAI-compatible providers.

---------

Co-authored-by: Anant Goel <anant@zed.dev>
2026-09-02 15:41:05 +00:00
Reinier Millo Sánchez 73d8912639 git_ui: Fix 'Go Back' skipping the Git Graph view (#63597)
# Objective

- "Go back" behaved inconsistently when navigating from the Git Graph
view: opening a commit diff (double-click on a commit) and then using
"Go Back" would not return to the Git Graph — instead it jumped to
whatever file was open before the Git Graph was opened.
- Fixes #63293

## Solution

- `GitGraph`'s `Item` implementation never hooked into the pane's
navigation history (missing `deactivated` / `set_nav_history`), unlike
every sibling diff view (`CommitView`, `ProjectDiffEditor`,
`MultiDiffView`, `BranchDiff`). Because of this, when a commit diff was
opened on top of it, deactivating Git Graph never pushed an entry onto
the pane's back-stack, so "Go Back" skipped straight past it to the
previously active file.
- Added a `nav_history: Option<ItemNavHistory>` field to `GitGraph` and
implemented `set_nav_history`/`deactivated` to push a nav-history entry
when the Git Graph tab is deactivated, matching the pattern used by
other `git_ui` diff views.

## Testing

- Added `test_go_back_from_commit_view_returns_to_git_graph` in
`crates/git_ui/src/git_graph.rs`, which opens a file, then Git Graph,
then a commit diff, and asserts that `Pane::navigate_backward` returns
to the Git Graph view rather than the file.
- Verified the test actually catches the regression by temporarily
reverting the fix and confirming the test fails, then restoring the fix
and confirming it passes.
- `cargo test -p git_ui --lib git_graph::` — all 28 tests pass.
- `./script/clippy -p git_ui` — clean, no warnings.

## Self-Review Checklist:

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

## Showcase

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


Open the Git Graph and double click on any commit to see the details,
after that press go back button, it should return to the Git Graph
instead of previos opened file.



https://github.com/user-attachments/assets/15f659a7-a60b-4d43-ad59-8be69a94cb31

</details>

---

Release Notes:

- Fixed "Go Back" not returning to the Git Graph view after opening a
commit diff
2026-09-02 14:48:12 +00:00
Richard Feldman e75564a92a language_model_core: Classify Anthropic prompt-too-long 400s as context overflow (#63596)
Anthropic reports a context-window overflow with HTTP 400 and a message
of the form `prompt is too long: N tokens > M maximum`. The
`BAD_REQUEST` arm of `ProviderErrorCategory::from_http_status` only
recognized OpenAI's phrasings (`context_length_exceeded`, "exceeds the
context window"), and `parse_prompt_too_long` only ran for HTTP 413, so
these rejections were classified as `InvalidRequest` instead of
`PromptTooLarge`. This affects every wire path that classifies by
upstream HTTP status, including Zed cloud's `upstream_http_400` code,
and it silently disables any downstream handling keyed on the
`PromptTooLarge` category. This change sniffs the Anthropic phrasing on
400 responses too, carrying the provider-reported token count.

Closes AI-462

Release Notes:

- Fixed Anthropic "prompt is too long" errors reported with HTTP 400 not
being recognized as context-window overflows.
2026-09-02 14:47:22 +00:00
Sk AkramandMrSubidubi ca3f453f79 Ensure stale git commit template are not persisted (#63604)
## Objective

Fixes #63478

Git commit templates were being persisted as pending commit message
drafts. As a result, if the commit template changed, the previously
applied template could be restored after restarting Zed instead of
loading the updated template.

## Solution

Do not persist the active commit message buffer as a draft when its
contents exactly match the currently applied commit template.

This preserves the existing behavior for genuine user drafts while
allowing the current commit template to be loaded when the panel is
restored.

## Testing

Added tests covering:

* Applying a new commit template after the template changes and the
panel is restored.
* Preserving a user-edited commit message when the commit template
changes.

Validated with:

* `cargo test -p git_ui --
test_commit_template_applied_fresh_after_template_file_change
test_user_draft_preserved_when_template_changes --nocapture`
* `cargo fmt -p git_ui`
* `cargo check -p git_ui`
* `cargo test -p git_ui --lib`
* `cargo clippy -p git_ui --tests -- -D warnings`

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

---

Release Notes:

- Fixed stale git commit templates being restored as pending commit
message drafts.

---------

Co-authored-by: MrSubidubi <finn@zed.dev>
2026-09-02 14:15:00 +00:00
Neel 16a55e429a language_models: Allow cancelling ChatGPT Subscription setup (#63627)
On `main`, the only way to interrupt ChatGPT Subscription setup is to
restart Zed.

---

Release Notes:

- Add a button to cancel ChatGPT Subscription setup
2026-09-02 13:50:06 +00:00
itsfuad 24f9172064 editor: Fix completion menu label overlapping documentation text (#63581)
Closes #63301

The completion label row set `min_w_0()`, which removes a flex item's
automatic minimum size and lets it shrink below its own content width.
The label inside is `flex_none` and never shrinks, so for long
completion labels the text overflowed the row and, with GPUI's default
`Overflow::Visible`, painted directly on top of the right-aligned
documentation text.

Removing `min_w_0()` restores the row's automatic minimum so it no
longer shrinks past the label. The documentation label already has
`flex_shrink(1.0)`, `min_w_0()` and `truncate()`, so it is now the only
element that gives way, shrinking and ellipsizing as intended.

The resulting layout is `[full label] [documentation, ellipsized when it
overflows]`.

### Before

<img width="687" height="426" alt="Screenshot From 2026-09-02 00-48-03"
src="https://github.com/user-attachments/assets/b734b632-fd05-4afc-8b02-b231922646ef"
/>


### After

<img width="853" height="526" alt="Screenshot From 2026-09-02 02-23-41"
src="https://github.com/user-attachments/assets/60281115-5a8d-4f4e-bfe0-c037ff7244e3"
/>


Release Notes:

- Fixed completion menu labels overlapping the documentation text for
long completion items
2026-09-02 13:11:30 +00:00
Matei Oprea d1a6db1bc6 workspace: Fix captured focus when opening modals (#63512)
# Objective

- This PR fixes the captured focus in modals. 
- Fixes #63480 (and actually this was not specific to the task modal. it
was generic and applied to all modals)

## Solution

- Previously when a modal was opened the `previous_focus_handle` was
stealing the focus because it was captured in `show_modal`. The fix was
to capture it before calling `show_modal` or `reveal_stashed_modal` and
pass it to `show_modal`. That fixes the bug :) (yuhuu).

## Testing

- Tested by running the build and trying to reproduce the bug. I
couldn't reproduce it anymore.
- For testing, a reviewer also needs to test the revelal stashed modal
functionality. I did it with the file finder.

## 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 previous window focus handle not being captured correctly when
opening modals
2026-09-02 11:59:16 +00:00
Lena b1c306668b Stop labeling reopened triaged issues as 'needs triage' (#63615)
Release Notes:

- N/A
2026-09-02 11:30:46 +00:00
Anthony Eid 265ea4e838 gpui: Record hang trigger class and set the release frame budget to 24ms (#63586)
Hang incidents come in two classes that consumers could only tell apart
by comparing `stall_ms` against the hang threshold, which is not
recorded in the event: a single event over the threshold, or an interval
whose cumulative foreground spend reached the frame budget. This PR
makes the class explicit and re-tunes the budget.

- `HangIncident` and `SerializedHangIncident` gain `trigger:
HangTrigger` (`threshold` | `budget`).
- The `Hang Incidents` telemetry event reports `threshold_incidents` and
`budget_incidents` alongside the existing `total_incidents` (kept for
existing queries; it is now the sum of the two).
- The release frame budget moves from 8 ms to 24 ms. At 8 ms almost
every busy 60 Hz frame qualified, so the budget class dominated incident
counts without saying much. 24 ms is above every refresh period, so a
budget incident now means the interval dropped at least one frame on any
display. Frame smoothness below that is measured per-frame by `Frame
Duration Report`. `budget_incidents` is the signal for lowering it
further as hangs get fixed. Debug builds already used 100 ms and are
unchanged.

Part of a series on hang-telemetry data quality; #63588 handles
withheld-frame `dirty_at`, and marking OS prompt waits so they stop
registering as task-poll hangs is next.

Release Notes:

- N/A
2026-09-02 05:03:27 +00:00
John Tur 49f5fe7750 Fix misaligned borders around avatars with fractional display scale (#63595)
Before and after:


https://github.com/user-attachments/assets/b165d525-c368-4245-a246-2522e67ff3a0

---

Release Notes:

- N/A
2026-09-02 02:14:38 +00:00
Jakub Konka a13d872bff util: Embed fs_embed assets with debug-embed (#63583)
Zed's `fs_embed!` macro normally reads assets from the checkout in debug
builds. The new `util/debug-embed` feature is intended to compile those
assets into debug binaries, but it previously changed only the
`rust_embed::Filenames` variant while leaving file loading on the
runtime path.

That breaks downstream workspaces such as Delta: the runtime loader
identifies Delta as the repository root, then looks for Zed grammar
assets under Delta's checkout. Tests consequently panic when language
configuration files cannot be found.

This makes `util/debug-embed` select a compile-time `RustEmbed`
expansion in every profile. Builds without the feature retain live
filesystem loading in debug mode. The runtime iterator no longer depends
on a feature-specific `rust_embed::Filenames` variant, so Cargo feature
unification remains safe when another package enables
`rust-embed/debug-embed` directly. The regression fixture uses a
deliberately invalid runtime path when `debug-embed` is enabled, so it
proves that the embedded path is used rather than passing only because
the Zed checkout contains the test assets.

Testing performed:

- `cargo fmt --all -- --check`
- `cargo nextest run -p util --lib`
- `cargo nextest run -p util --lib --features debug-embed`
- `cargo check -p remote_server --features debug-embed`
- `./script/clippy -p util`
- Delta's previously failing
`tools::edit_file::tests::test_edit_file_rejects_scratch_paths_as_read_only`
against this PR's head commit

Release Notes:

- N/A
2026-09-01 21:42:01 +00:00
Mikayla Maki 810f8313f1 Relicense zlog, ztracing, and ztracing_macro under Apache-2.0 (#63573)
Relicenses `zlog`, `ztracing`, and `ztracing_macro` from
GPL-3.0-or-later to Apache-2.0.

GPUI depends on `ztracing`, which depends on `zlog`, so these crates
have to be non-copyleft for GPUI to ship as a permissively licensed
project.

- Switched the `license` field to `Apache-2.0` in all three manifests.
- Added the `LICENSE-APACHE` symlink to `zlog`, and dropped the
`LICENSE-GPL` symlinks from all three. `ztracing` and `ztracing_macro`
already carried both symlinks; now the on-disk license matches the
manifest.
- Declared `license = "Apache-2.0"` for `gpui_util`, which had a
`LICENSE-APACHE` symlink but no `license` field. `script/check-licenses`
doesn't catch that, since it only inspects symlinks.

No source changes; none of these crates carry GPL headers or in-source
license references.

Checked the rest of the subtree while here: the only first-party crates
reachable from `ztracing` via `cargo tree -e normal` are `collections`,
`gpui_util`, `zlog`, and `ztracing_macro`, all Apache-2.0 now.
Third-party deps (`tracing`, `tracing-subscriber`, `chrono`, `log`,
`anyhow`, `tracy-client`) are MIT/Apache.

`script/check-licenses` passes.

Release Notes:

- N/A
2026-09-01 21:39:47 +00:00
Kirill Bulatov 91c7b84774 Download wasi-sdk before cleaning the target directory (#63579)
Fix flacks like
https://github.com/zed-industries/zed/actions/runs/33546906778/job/99987145940?pr=63573

`test_extension_store_with_test_extension` gives the extension builder
`target` as its cache at
`crates/extension_host/src/extension_store_test.rs:801`.
`install_dev_extension` performs a real extension and grammar build at
`crates/extension_host/src/extension_host.rs:1139`.
When `target/wasi-sdk` is absent (e.g. after `target/` cleanup), the
builder downloads and extracts it at
`crates/extension/src/extension_builder.rs:511`.

In the failed run, downloading and extracting the SDK consumed 59
seconds, grammar compilation began at 60 seconds, and the timeout fired
immediately.

Release Notes:

- N/A
2026-09-01 21:20:46 +00:00
Mikayla MakiandConrad Irwin d89930207f util: Make fs_embed! compatible with rust-embed's debug-embed feature (#63577)
Zed's `fs_embed!` macro hand-implements rust-embed's `RustEmbed` trait
in its dev arm so debug builds read assets from the checkout at runtime
(introduced with corgi support in #63396). That trait returns
`rust_embed::Filenames`, an enum with exactly one variant per
compilation context: `Dynamic` when rust-embed's `debug-embed` feature
is off, `Embedded` when it is on. The dev arm constructed
`Filenames::Dynamic` unconditionally.

Cargo unifies features across the entire build graph, so a downstream
workspace that consumes Zed's crates by git dependency and enables
`rust-embed/debug-embed` anywhere (Delta did, for self-contained debug
binaries) changes the enum's shape for `util` itself, and `util` stops
compiling with `E0599: no variant named Dynamic`. Zed's own CI can never
catch this because nothing in Zed's graph enables the feature; it only
surfaces in embedding workspaces, where it blocks any dependency bump
past #63396.

This change makes the combination supported. `util` gains a forwarding
`debug-embed` feature, and `__fs_embed_iter` now has two implementations
under cfgs that mirror rust-embed's variant availability: the existing
boxed-iterator path when the feature is off, and an `Embedded` path when
it is on, which scans the checkout once per embed site and leaks the
cached name list (the `Embedded` variant requires `'static` names; a
per-process list matches the macro's documented contract that dev edits
appear on the next launch, and `get` still reads file contents fresh on
every call). Consumers must enable the feature through
`util/debug-embed` rather than directly on rust-embed — enabling it
behind util's back still breaks, which only rust-embed itself could fix;
the feature's documentation says so.

A new test exercises the dev arm's `iter` and `get` through the macro,
and running util's suite with `--features debug-embed` covers the other
variant; both configurations pass 133 tests, plus clippy and fmt.

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2026-09-01 19:59:31 +00:00
Mikayla Maki cd0241b7e3 anthropic: Handle Claude Fable 5.1 API changes (#63571)
Claude Fable 5.1 introduces two breaking Messages API changes that
produce 400 errors with request shapes Zed currently sends. This change
adapts the shared Anthropic request path so the model works out of the
box, without restructuring how requests are built.

The first change is thinking-block prefix binding. Fable 5.1 binds each
thinking block to the exact conversation prefix that produced it, and
replaying a block after anything earlier changed (the system prompt, the
tools array, or an edited turn) fails the whole request with a 400
reading "The block is bound to a different conversation". Zed routinely
rebuilds the system prompt and tool list between requests (rules file
changes, profile switches, MCP servers coming online), so this would
surface as a hard error mid-thread. Requests to Fable 5.1 now send the
`thinking-binding-controls-2026-08-01` beta header with
`thinking.block_binding.prefix_mismatch_behavior: "drop_block"`, which
makes the API drop invalidated blocks and continue instead of rejecting
the request. Claude Mythos 5.1 doesn't run this check and is excluded.
The cloud and Copilot Chat paths pass `block_binding: None` since their
proxies control the upstream beta headers; opting in there belongs
server-side.

The second change is that forced tool use (`tool_choice: "any"` or
`"tool"`) now returns a 400. Zed sends `"any"` from inline assist's
streaming-tools path, which is on by default. The Anthropic and
Zed-cloud providers now report `tool_choice: any` as unsupported for
Fable/Mythos 5.1, and inline assist already degrades gracefully to
prompt-guided auto tool choice, which is Anthropic's recommended
migration.

Finally, `claude-fable-5-1` and `claude-mythos-5-1` are added to the
compaction model list. This matters more than a routine table update:
with prefix binding, server-side compaction is the sanctioned way to
trim history without invalidating thinking blocks. Everything else
already carries over via the existing `claude-fable-5` id prefix logic
(data-retention consent, Opus 4.8 refusal fallback, which remains a
permitted fallback target for 5.1). Bedrock is intentionally untouched.

Deeper follow-up work is deferred: keeping conversation history
append-only so blocks aren't invalidated in the first place (turn-scoped
system messages, mid-conversation tool changes) and monitoring
`input_transformations` for drop reporting.

Testing:

- New unit tests covering the `block_binding` wire format (sent for
`claude-fable-5-1` only) and beta-header wiring in `Model::from_listed`.
- `cargo nextest run` for `anthropic`, `language_models`,
`language_models_cloud`, and `copilot_chat`; `cargo fmt --check`.

Release Notes:

- Improved support for Claude Fable 5.1
2026-09-01 18:58:47 +00:00
Jakub Konka 966ba1f92a gpui: Add long-press gesture recognition (#63561)
GPUI's touch gesture recognizer handles taps and pans, but its
long-press event was only a placeholder. Applications therefore could
not distinguish a deliberate press-and-hold from a tap or scroll using
the portable touch path.

This adds deadline-driven long-press recognition and dispatches a phased
event stream through GPUI's existing capture and bubble listener path. A
listener claims the gesture by preventing the initial event's default
behavior and capturing it for an entity. Unclaimed gestures remain
eligible for the existing tap and pan behaviors, while claimed gestures
receive movement and termination events without also producing taps or
scrolling.

The timer is cancelled when the pending gesture resolves. `gpui_web` now
translates reusable browser pointer identifiers into touch identifiers
that remain unique for each touch lifetime, preventing an old timer from
acting on a newer touch. Native macOS trackpad scrolling remains on its
existing `ScrollWheelEvent` path and does not enter touch gesture
recognition.

Testing performed:

- `cargo fmt --all -- --check`
- `cargo nextest run -p gpui --lib long_press` (10 passed)
- `RUSTC_BOOTSTRAP=1 cargo check -p gpui_web --target
wasm32-unknown-unknown`

Release Notes:

- N/A
2026-09-01 16:28:50 +00:00
Reinier Millo Sánchez 6c4441c5d9 edit_prediction: Adjust to support Ollama to be used for AI edit prediction (#63519)
# Objective

Fix two related bugs in the Ollama edit-prediction provider config
(`Settings > AI > Edit Prediction > Configure Providers`):

1. The Ollama model dropdown showed only a single model (the
currently-configured one), regardless of what models were actually
available on the configured server.
2. Ollama never appeared as a selectable option in the "Active Provider"
list, even when fully configured.

Both bugs shared the same root cause: several places in the
edit-prediction code path read from the Assistant's separate Ollama
*language model* provider (`language_models.ollama.*`, used by the AI
panel/agent) instead of the edit-prediction-specific
`edit_predictions.ollama.*` settings. These are two independent Ollama
connections that can point at different servers, so the edit-prediction
UI was effectively showing/gating on the wrong provider's state.

This changes fixes #47393 

## Solution

- **Model dropdown**: Added
`edit_prediction::ollama::fetch_models_from_server`, which queries
`/api/tags` directly against the edit-prediction's own configured
`api_url`, independent of the Assistant's Ollama provider. The dropdown
now re-fetches from that URL every time it's opened, so changing the
server URL and reopening the dropdown shows the new server's models.
- **Model filtering**: Fetched models are filtered to those Zed can
infer a completion prompt format for (`infer_prompt_format`), so
chat-only and embedding models (e.g. `nomic-embed-text`, `llama3:70b`)
no longer clutter the list. This function was extracted from
`edit_prediction_registry.rs` (previously private, used only for
prompt-format resolution) into `edit_prediction::fim` so it can be
shared between the dropdown filter and the existing routing logic — same
behavior, no duplication.
- **Provider visibility**: `get_available_providers` now gates Ollama's
visibility on `edit_predictions.ollama.is_some()` (i.e. whether the user
has configured a model), matching the existing pattern already used for
the OpenAI-Compatible provider, instead of checking the unrelated
Assistant provider's authentication state. Removed the now-dead
`ollama::is_available`/`ensure_authenticated` functions and the startup
call that existed solely to make that broken check eventually pass.

## Testing

- Added unit tests for `infer_prompt_format` covering all known model
families
(qwen/codellama/deepseek-coder/starcoder/codestral/glm/zeta/sweep) and
confirming unsupported models (chat/embedding) correctly return `None`.
- Added an async test for `fetch_models_from_server` using a fake HTTP
client, verifying it filters to FIM-capable models and returns them
sorted.
- Added a regression test, `test_ollama_provider_routes_to_fim_model`,
verifying that Ollama + a known model (`qwen2.5-coder:3b`) resolves to
`EditPredictionProviderConfig::Zed(EditPredictionModel::Fim { format:
Qwen })` — this exercises the exact routing path underlying the
provider-visibility fix.
- Manually verified end-to-end against a real local Ollama server:
configured a custom `api_url`, confirmed the model dropdown populated
with the server's actual models, selected one, and confirmed Ollama
appeared in and could be selected from the Active Provider list, with
predictions successfully returned.
- Ran `cargo check` and `./script/clippy` on all touched crates
(`edit_prediction`, `settings_ui`, `edit_prediction_ui`, `zed`); no
warnings.
- Not tested: the `get_available_providers` gating change itself has no
direct test (it's a one-line settings check whose underlying resolution
is covered by the `zed`-crate regression test above); Windows/Linux were
not tested, only macOS.

## Self-Review Checklist:

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

## Showcase


<details>
  <summary>Click to view showcase</summary>
Now when we open the dropdown model selector on Ollama section we will
see the available models in the current server that we are trying to use

<img width="903" height="755" alt="image"
src="https://github.com/user-attachments/assets/873c662b-3624-4530-811c-6f07ab518e35"
/>

Now Ollama will be displayed as provider in the edit prediction
providers dropdown

<img width="903" height="755" alt="image"
src="https://github.com/user-attachments/assets/9dfe737d-6527-4ecd-9803-3d0959075c34"
/>

</details>

---

Release Notes:

- Fixed Ollama edit predictions not appearing as a selectable provider
and the model dropdown showing only a single model instead of the models
available on the configured server
2026-09-01 16:07:40 +00:00
Matei Oprea 04fc4edf86 Improve visibility and wording around close panel on toggle setting (#63548)
# Objective

- Improve documentation for `close_panel_on_toggle` setting. 

## Solution

- Previous docs were a bit ambiguous and since refactoring the setting
name is not possible at the time, I improved the documentation.

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

Release Notes:

- Added the`close_panel_on_toggle` setting to the settings UI and
improved its documentation.
2026-09-01 15:53:33 +00:00
Cole Miller ad0d789038 gpui_linux: Prevent panic while reporting Wayland errors (#63159)
`wayland-backend` falls back to `eprintln!` when its optional `log`
feature is disabled. If a Wayland connection fails while standard error
is unavailable, that fallback panics while trying to report the original
error.

Closes ZED-8BW

Enable the existing `log` feature on `gpui_linux`'s direct
`wayland-backend` dependency. `gpui_linux` already depends on the `log`
facade, so this introduces no new logging system; it routes backend
errors through the configured logger and avoids the secondary
standard-error panic.

Testing performed:

Release Notes:

- Fixed a Linux crash when reporting a Wayland connection error while
standard error is unavailable.
2026-09-01 15:53:08 +00:00
Ben Kunkle aecaacdb44 git: Move diff hunk operations onto buffer diffs (#63556)
# Objective

Keep Git-specific diff-base knowledge in `GitStore`, where Git
operations are defined.

Related to FR-135.

## Solution

Give each `BufferDiff` its supported hunk operations. Keep editor hooks
limited to rendering custom controls.

## 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-01 15:52:33 +00:00
Conrad Irwin 99f85efa71 corgi: Use globs for extra-inputs (#63558)
Corgi 0.1.43 changes how `[extra-inputs]` in `corgi.toml` is read:
entries are glob patterns rather than plain paths, and they select files
rather than directories. Handing corgi a bare directory name used to
mean "everything under here, hashed as a tree"; now it matches nothing
and reports that appending `/**` is the fix. This updates each directory
entry accordingly, and rewords the section comment to describe the new
rules.

The practical gain is that the readable set and the hashed set are now
exactly the same set of files. Each matched file is granted to the
sandbox individually and hashed under its workspace-relative path, so
adding, removing, or renaming a file that a pattern covers changes the
package's source hash even when no file's contents changed. Reading a
file that no pattern matches is denied rather than silently allowed
because it happened to sit inside a granted directory.

Three reads that corgi has been denying all along now have entries.
`eval_cli`'s build script reads `crates/zed/Cargo.toml`, `gpui_wgpu`
includes its WGSL shaders through `include_str!`, and
`zed_extension_api` includes its own `wit` tree through
`wit_bindgen::generate!`. Each of those units fails on `main` today
under `corgi check --workspace`. The last one could not be declared at
all until corgi 0.1.43, because `[extra-inputs]` is keyed by package
name and this workspace resolves three packages named
`zed_extension_api` — the member at 0.8.0 plus published 0.1.0 and 0.7.0
that extensions depend on — so the declaration reached the published
copies and failed the workspace-escape check. Corgi now applies extra
inputs only to local packages, which is safe because a registry package
is hashed as a whole directory and reads its own root freely.

`corgi_version` is pinned to 0.1.43 so everyone picks up the matching
corgi automatically; older corgi releases cannot read these entries.

Testing:

- `corgi check --workspace` passes with no failing units, which it did
not do before this change.
- `corgi build -p zed` links the binary.
- `corgi check --workspace --all-targets` goes from 16 failing units to
13. The remaining 13 are pre-existing undeclared reads in test targets
(font files under `assets/`, `test_data` fixtures and similar) that this
change does not attempt to fix.

Release Notes:

- N/A
2026-09-01 15:40:02 +00:00
Jakub Konka 16da2ea125 gpui: Lock touch scrolling to the dominant axis (#63553)
Touch pans currently preserve small amounts of movement on both axes,
including in the synthetic momentum generated after release. In a nested
scrolling layout, a mostly vertical fling that starts over a
horizontally scrollable child can therefore move the child horizontally
while its ancestor moves vertically.

This locks each touch pan to the dominant axis of its accumulated
movement when it crosses the touch-slop threshold. Initial movement,
predicted updates, release correction, velocity, and momentum are
projected onto that axis, so every scroll listener sees the same
one-dimensional gesture for its full lifetime.

The existing trackpad and wheel behavior remains unchanged; the new rule
is applied by the portable raw-touch recognizer before it emits semantic
scroll events.

Testing:

- `cargo nextest run -p gpui --lib gestures::tests`
- `cargo fmt --all -- --check`
- `./script/clippy -p gpui`
- Built Delta Web for `wasm32-unknown-unknown` with this GPUI worktree
and reached a successful Trunk release build

Release Notes:

- N/A
2026-09-01 14:20:13 +00:00
6d0f8c93d8 git_ui: Add multi-select to git panel for bulk stage, unstage, and discard (#60340)
Closes #26430
Complements: #52935 by Jacob Binnie

Enables multi-select in the Git Panel, following the Project Panel
rules.



https://github.com/user-attachments/assets/2892c1e2-3071-47f9-af1a-48e1c69dbb8a



**Core selection gestures:**

1. Click one file, shift+click a file deeper in the list: all files
between highlight.
2. Click one file, then ctrl/cmd+click another file: it joins the
selection; or removes it when selected.
3. Shift+down extends the selection from the current row; shift+up
shrinks it back and re-extends past the anchor.
4. Escape with a selection clears it and keeps focus; Escape again
toggles focus as before.
5. Plain click collapses selection to file and opens its diff;
double-click triggers the alternate open action.
6. Shift+click on a checkbox still performs the pre-existing range
staging.

**Bulk operation gestures:**

1. Select multiple files, press space: if any member is unstaged, all
become staged; press space again: all unstaged.
2. Right-click a file inside the selection: menu reads
Stage/Discard/Trash N files, depending on context.
3. Select multiple files, press delete: confirmation prompt. Mixed
selections: untracked = trashed, staged = unstaged.

**Folders, in tree view:**

1. Ctrl/cmd+click a folder row behaves like its checkbox does: selects
it as a unit, expands operations to descendants.
2. Folder rows inside a shift range join the selection. A collapsed
folder is selected including its hidden files.
3. The same directory under Tracked and Untracked is two independent
selections (so marks are section-qualified).
5. Plain click on a folder still expands/collapses it and clears the
selection.

**Implementation notes:**

1. Selection is stored as repo paths plus section-qualified tree keys to
survive status refreshes.*
2. Stale entries are pruned on rebuild, selection is cleared on active
repository change.
3. Range selection follows visual order in both flat and tree view.
4. Bulk operations batch into a single git operation.

\* Not sure if this is the best option for storing it.


**Why this is necessary**

- Multi-select has been an ongoing feature wish since 2025 with various
upvotes
- Current state of the art IDEs offer this (VSCode, IntelliJ, VS)
- It greatly increases efficiency using the diff panel


**Why is the PR from #52935 not enough?**

This PR builds on its approach. Thanks to @jacobbinnie. But I noticed a
few things:

- never clears the selection when the active repository changes
- a failed checkout or trash disappears silently
- hardcodes single-click = project diff and double-click = file diff,
ignoring the entry_primary_click_action setting
- its context menu still reads "Stage File" / "Discard Changes"
(singular)
- discard prompt always says "Discard" even for an all-untracked
selection that will actually trash files
- no shift+arrow range extension, no Escape to clear
- it skips directory rows entirely, in tree view you can't act on a
folder's subtree at all
- its range_select only ever accumulates, consecutive shift+clicks grow
the set and nothing shrinks it
- Uses Vec<RepoPath> on marks, linear contains scans -> This PR uses
HashSets, relevant for huge repos.
- doesn't ship any tests -> This PR covers the whole range with tests
too*

\* Tests dominate this PR (~850 lines). The actual feature sits around
400.

Release Notes:

- Added multi-select to the git panel

---------

Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Co-authored-by: Jacob Binnie <jacob.b@linktr.ee>
Co-authored-by: Andrea Leone <andrealeone@hey.com>
2026-09-01 12:59:39 +00:00
Cameron Mcloughlin c940c0c669 gpui_web: Tighten up web keyboard feel (#63533)
Fixes a few edge cases where we weren't correctly tracking whether to
hide the keyboard when touch events happen

Also forces a synchronous render on web after the viewport resizes
(which happens when the keyboard appears/disappears). This prevents a 1
frame delay where the browser would use the old bitmap, stretched to the
new size

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-09-01 12:43:44 +00:00
Aliandzed-zippy[bot] 7378a7f36d util: Prevent panic when parsing a malformed shell variable (#63446)
# Objective

`to_cmd_variable` and `to_powershell_variable` removed the last byte of
a
`${...}` argument assuming it was the closing brace, without checking
one was
there

```rust
// If the input starts with "${", remove the trailing "}"
format!("$env:{}", &var_str[..var_str.len() - 1])
```

# Solution

Use strip_suffix('}') and pass the input through when it isn't a
variable reference

## Testing

added tests to cover this 


To reproduce on Windows, add a context server with a malformed argument
to settings.json:

``` 

"context_servers": {
  "crash-repro": {
    "command": "does-not-matter",
    "args": ["${"]
  }
}
} 
````
Opening the agent panel and zed will crash


Release Notes:

- Fixed a panic when converting a malformed `${` shell variable
reference on Windows

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-31 18:47:00 +00:00
Smit Barmase 7402d91b26 sidebar: Add title renaming for Terminal Threads (#63494)
The Agent Panel already lets users rename Terminal Threads. This adds
the same option to the Threads Sidebar. A rename in either place updates
the other.

<p>
<img width="321" height="89" alt="image"
src="https://github.com/user-attachments/assets/189a8598-f0da-4622-a5b0-b6a18a5750b7"
/>
</p>
<p>
<img width="324" height="77" alt="image"
src="https://github.com/user-attachments/assets/2fc9f7aa-c791-4568-8729-fd3a78322d63"
/>
</p>

Release Notes:

- Added support for renaming Terminal Threads from the Threads Sidebar.
2026-08-31 17:38:52 +00:00
Conrad IrwinandBen Kunkle 72dc742101 Support building with corgi (#63396)
[corgi](https://github.com/ConradIrwin/corgi) is a cargo-compatible
build tool that runs `build.rs` scripts and proc-macros in a sandbox (no
network, no ambient env, reads limited to a package's own `.rs` sources
unless declared). This makes Zed buildable under it. Cargo builds (dev
and release) are unaffected.

### Changes

- **`scratch` patch**: patch `scratch` to a small local copy
(`corgi-patches/scratch`) that reads `OUT_DIR` at runtime instead of
baking it in at compile time. `cxx-build` writes its shared cxxbridge
headers into `scratch::path(...)`; upstream returns a single global dir
(outside any action's `OUT_DIR`) that the sandbox can't grant, while
this patch gives each build script a private, writable dir in its own
entry. webrtc-sys is self-contained, so per-crate scratch dirs are
sufficient. Kept local rather than a cxx git fork because a git checkout
of cxx needs symlink support that Windows cargo CI lacks.
- **Dev asset loading**: add `util::dev_fs_embed!` and switch dev-mode
`rust_embed` asset sources (`assets`, `settings`, `grammars`, `agent`,
`edit_prediction_cli`) to read from the checkout at runtime, locating
the repo root by walking from the executable up to the enclosing `.git`.
This avoids baking `CARGO_MANIFEST_DIR` into the binary (corgi rejects
artifacts that embed the build-time checkout path, and it's wrong in any
other worktree). Release builds still embed via `#[derive(RustEmbed)]`.
- **Stop baking checkout paths into artifacts**: drop
`gpui::GPUI_MANIFEST_DIR`; resolve `../gpui` from `gpui_apple`'s build
script; stage the metal shader into `OUT_DIR` before compiling so the
`.metallib` records the output dir, not the checkout; resolve the repo
root at runtime in `remote` and `inspector_ui` (removing
`inspector_ui`'s `build.rs` / `ZED_REPO_DIR`).
- **corgi.toml**: declare the pinned tools (`cmake`, prebuilt libwebrtc
via `LK_CUSTOM_WEBRTC`), a release-only `ZED_COMMIT_SHA` probe, and the
non-`.rs` / cross-package reads each package performs.

### Validation

- `corgi check` + `corgi build`, dev and release, for `zed` (plus `cli`,
`remote_server`, `ep`) with a warm C++ cache — clean; built binaries
embed no checkout path.
- `corgi fmt --check`, `corgi clippy`, and `corgi test` on the changed
crates (922 tests pass).
- `cargo check -p util` locally; relying on CI for the full cargo
build/test matrix.

### Notes for the reviewer

- Per the repo rule, the first two lines of `README.md` are the
review-confirmation marker; remove them before merging (this is what
Danger is failing on).
- `remote_server` cross-compilation (linux-musl via zigbuild) is not yet
covered by `corgi.toml` — host (macOS arm64) only for now.

### Suggested .rules additions

Only if the team wants corgi guidance in `.rules` (it recurred several
times here): dev builds must not bake the checkout path into artifacts —
no `env!("CARGO_MANIFEST_DIR")` or `file!()`-derived absolute paths in
library/binary output. Resolve the repo root at runtime via
`util::dev_repo_root()` (walks to `.git`), and use `util::dev_fs_embed!`
for dev-mode `rust_embed` sources.

Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2026-08-31 17:37:00 +00:00
Cameron Mcloughlin 87222d1d29 gpui: Platform-specific scroll physics (#63505)
Adds platform-specific scroll behaviour, and also exposes predicted
events for better latency

---

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-08-31 17:08:14 +00:00