# Objective
`test_rename_that_also_renames_file` (added in #59104) is
order-dependent: it passes at seed 0, which CI runs, but fails on many
others (e.g. 11, 15, 17). Any unrelated change that schedules one extra
task shifts the deterministic test scheduler enough to flip it at seed 0
too — which is how it surfaced, while working on #61009. The bug it
exposes is real and pre-existing:
#59104 stopped the content swap, but the open buffer still relied on the
filesystem watcher to follow the file to its new path. Depending on the
order the watcher reports the old path's deletion and the new path's
creation, the entry id isn't carried over, and the buffer is stranded at
the now-deleted old path (shown as saved) and never re-associates.
## Solution
Move the worktree entry explicitly after the rename, preserving its id,
the same way `rename_entry` (project panel renames) already does.
## Testing
- `test_rename_that_also_renames_file` now runs 30 seeds to cover both
orderings.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed a symbol rename that also renames the file leaving the open
buffer on the old path
Closes#39860
This PR resolves relative image paths from the Markdown source file's
project path and load images through the project image store. SVG images
over remote connections remain unsupported and are left for a follow-up.
Release Notes:
- Fixed images not rendering in Markdown Preview over remote.
This PR bumps the version of the Proto extension to v0.3.3.
Release Notes:
- N/A
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
PR #62502 changed the ChatGPT subscription models to report the
corresponding public API context windows. That was based on a mistaken
assumption: subscription requests go through the separate Codex backend,
which still rejects requests around the previous context limit.
Because the advertised context window also determines when Zed compacts
a conversation, reporting 1.05M tokens delays compaction until after the
Codex backend rejects the request. This reverts #62502 and restores the
previous conservative limits. Longer term, we should load the
account-specific model metadata from the Codex `/models` endpoint rather
than maintaining this list by hand.
Release Notes:
- Fixed automatic context compaction for GPT models accessed through a
ChatGPT subscription.
ChatGPT subscription models currently report the short-context billing
thresholds (272k or 372k tokens) as their maximum context windows. Those
thresholds matter when Zed is paying metered API costs, but subscription
requests are billed directly by OpenAI.
This updates the subscribed models to report the full context windows
supported by the corresponding public API models: 1.05M tokens for
GPT-5.4, GPT-5.5, and GPT-5.6, and 400k tokens for GPT-5.4 Mini. It also
reports the 128k output limit so context accounting reserves capacity
for the response. Request serialization is unchanged; the unsupported
`max_output_tokens` parameter is still omitted from requests to the
Codex backend.
Release Notes:
- Improved context window usage for GPT models accessed through a
ChatGPT subscription.
# Objective
- Fixes#62238
- Properly escapes paths in the sftp PUT line
## Solution
- 10-line wrapper function that escapes paths as sftp expects. Namely:
paths in quotes with `\\` and `"` escaped.
## Testing
- Did you test these changes? If so, how? `cargo check`
- Are there any parts that need more testing? Up to you, this is a
simple change and I dont think sftp with default install paths ever
worked on MacOS
- How can other people (reviewers) test your changes? Is there anything
specific they need to know? Just connect to a remote on OSX and see if
the logs had an sftp upload failure in there
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fix remote uploads over sftp where the paths contain spaces
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
## What
`docs/.conventions/brand-voice/SKILL.md` declares:
```yaml
name: brand-writer
```
while sitting in a directory called `brand-voice`.
The Agent Skills specification requires the two to be identical:
> The required `name` field: … **Must match the parent directory name**
> — <https://agentskills.io/specification#name-field>
So this skill fails `skills-ref validate` today.
## Which side is wrong
The directory — and this repository settles it three separate ways, with
no outside context needed.
**1. The sibling copy already uses the matching name.**
`.factory/skills/brand-writer/` holds the same four files (`SKILL.md`,
`rubric.md`, `taboo-phrases.md`, `voice-examples.md`) under
`brand-writer`.
**2. `crates/agent_skills/README.md` documents the skill system using
this exact skill, and the name it documents is `brand-writer`:**
```
line 107: <name>brand-writer</name>
line 149: the model … calls `skill { name: "brand-writer" }`
line 151: when the user types `/brand-writer`
line 158: <skill_content name="brand-writer">
```
That name is load-bearing — it is what the skill tool invokes and what
the slash command types. The directory name is referenced twice, both
inside `docs/.conventions/CONVENTIONS.md`.
**3. Six of the repository's seven skills already match their
directory:**
| skill | matches? |
| --- | --- |
| `.agents/skills/gpui-test` | ✅ |
| `.agents/skills/lint-creator` | ✅ |
| `.agents/skills/zed-cherry-pick` | ✅ |
| `.factory/skills/brand-writer` | ✅ |
| `.factory/skills/humanizer` | ✅ |
| `crates/agent_skills/builtin/create-skill` | ✅ |
| **`docs/.conventions/brand-voice`** | ❌ the only one |
## The change
The frontmatter is untouched. Only the directory moves, plus the two
references to it:
- `docs/.conventions/brand-voice/` → `docs/.conventions/brand-writer/`
(4 files, pure rename)
- `CONVENTIONS.md:5` — `[brand-voice/](./brand-voice/)` →
`[brand-writer/](./brand-writer/)`
- `CONVENTIONS.md:368` — `` `brand-voice/rubric.md` `` → ``
`brand-writer/rubric.md` ``
`git grep brand-voice` returns nothing afterwards.
If you would rather keep the directory name and rename the field to
`brand-voice`, that is a one-line change instead and I am happy to
switch it — but it would give the two copies of one skill two different
names, and it would diverge from the name
`crates/agent_skills/README.md` documents.
## One thing I noticed but did not touch
The two copies have drifted. `.factory/skills/brand-writer/SKILL.md` is
279 lines and includes a *"Phase 4: Humanizer Pass"* section;
`docs/.conventions/`'s copy is 265 lines, lacks that section, and
renumbers Validation from Phase 5 to Phase 4. That is a separate
question about which copy is canonical, so it is left alone here.
---
Found with [AgentCompass](https://github.com/YoavLax/agent-compass), an
offline static analyzer for AI-agent repo readiness. Verified by hand
against the spec before opening.
Release Notes:
- N/A
Since #60772, a worktree's ignore rules are also applied to the
directories above its root. Because of this, an `info/exclude` pattern
naming one of those parent directories marks it as ignored, and with it
the whole worktree below.
Stop the walk at the repository containing the worktree root.
Also skip exclude rules for paths outside the work directory they are
anchored at, as `.gitignore` and global gitignore rules already do.
Release Notes:
- Fixed a worktree being reported as entirely ignored when its
repository's `info/exclude` named one of the worktree's parent
directories
# Objective
- Stop language-server update checks from waiting forever.
**Note:** I tried to find any existing issue but no luck.
## Solution
- Set one time limit for the full response body. If the GitHub, for
example, release request stops responding, return an error. Do not let
it block language-server update checks without limit.
## Testing
- Did you test these changes? If so, how?
1. This is a flaky issue, reproducing it is not that trivial.
2. The easiest way I found is just restarting Zed until you get the
notification in the status bar `Checking for updates
<language_server_naem>`
- Are there any parts that need more testing?
No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
See above.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- macOS
- Linux
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<img width="2624" height="2260" alt="CleanShot 2026-08-03 at 20 29
11@2x"
src="https://github.com/user-attachments/assets/83e2781c-15bc-4924-be33-88c26f20387d"
/>
---
Release Notes:
- Fixed language servers update checks
Spotted
```
The package `block v0.1.6` currently triggers the following future incompatibility lints:
> warning: static of uninhabited type
> --> .../block-0.1.6/src/lib.rs:64:5
> |
> 64 | static _NSConcreteStackBlock: Class;
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> |
> = note: uninhabited statics cannot be initialized, and any access would be an immediate error
> = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
> = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
The package `proc-macro-error2 v2.0.1` currently triggers the following future incompatibility lints:
> warning[E0365]: extern crate `proc_macro` is private and cannot be re-exported
> --> .../proc-macro-error2-2.0.1/src/lib.rs:494:13
> |
> 494 | pub use proc_macro;
> | ^^^^^^^^^^
> |
> = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
> = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
> help: consider making the `extern crate` item publicly accessible
> |
> 277 | pub extern crate proc_macro;
> | +++
```
warnings recently.
The former is impossible to fix quickly as needs a migration to `objc2`,
but the latter is easily fixed by a version bump, ergo this PR.
Release Notes:
- N/A
# Objective
I noticed that in workspace symbol search, the function's symbol kind
has become `Trait`.
## Solution
Add `to_proto` and a macro to define the mapping instead of `as i32`.
## Testing
Updated the test.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed `SymbolKind` mapping to LSP protocol values
OpenAI reasoning summaries are streamed as multiple indexed parts, and
each new reasoning output item starts its indexes at zero. The Responses
event mapper previously treated those indexes as global, so adjacent
reasoning items could be concatenated without whitespace, producing text
such as `**First item****Second item**`.
Track the current summary part by both its item ID and summary index,
and emit a separator whenever that pair changes. Text delta events now
retain their summary index as a fallback when a separate part-added
event is absent, while sharing the same boundary handling to avoid
duplicate separators.
Testing performed:
- `cargo check -p open_ai`
- `cargo nextest run -p open_ai`
- `cargo fmt -p open_ai -- --check`
- `./script/clippy -p open_ai`
Release Notes:
- Fixed missing separators between OpenAI reasoning summaries.
# Objective
Helix uses tab/shift-tab to navigate code action menus. Currently, this
will indent the code instead of navigating within the menu.
## Solution
Add keymaps.
## Testing
I tested it manually.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Added support for using `tab` and `shift-tab` to navigate the code
actions menu in Helix mode
Show a modal when invoking the stash action to allow users to provide an
optional custom message for the stash entry.
Closes#62430
# Image
<img width="1622" height="1106" alt="Screenshot 2026-08-10 at 9 14
00 PM"
src="https://github.com/user-attachments/assets/0d26dac2-919d-4bb1-b6a7-433ceff18955"
/>
<img width="1622" height="1106" alt="Screenshot 2026-08-10 at 9 14
11 PM"
src="https://github.com/user-attachments/assets/896b68ff-999f-4ec9-a6a4-e0e7a6867286"
/>
# Objective
Zed's stash action runs `git stash push --quiet --include-untracked --`
with no `-m`, so every stash is labelled with git's auto-generated `WIP
on <branch>: <sha> <subject>`. That text describes the commit you were
sitting on, not what you stashed — so two stashes taken from the same
commit are indistinguishable.
This undercuts the stash picker (`git::ViewStash`), which lists entries
as `#<index>: <message>` and fuzzy-searches over exactly that string.
The search box already exists; there is just nothing meaningful to
search, because every candidate is a variation of the same
auto-generated line.
## Solution
`git::StashAll` now opens a single-line modal ("Optionally provide a
stash message") before stashing.
- Confirming with text passes `--message <text>` to `git stash push`.
- Confirming with the field empty omits the flag entirely, keeping git's
default description — so the prompt is a one-keystroke pass-through and
existing muscle memory still works.
- Cancelling aborts the stash, so the prompt doubles as a confirmation
step.
Implementation:
- `StashMessageModal` (`Editor::single_line`) in `git_panel.rs`, toggled
from `GitPanel::stash_all`. `menu::Confirm` trims the input and maps
empty to `None`.
- `message: Option<String>` threaded through `Repository::stash_all` →
`stash_entries` → `GitRepository::stash_paths`. The flag is appended
before the `--` separator so a message is never parsed as a pathspec.
- New `message` field on the `Stash` proto message, so remote and collab
projects behave identically.
One non-obvious detail: the modal is opened via `cx.defer_in` rather
than inline. `git::StashAll` is registered on the workspace
(`git_ui.rs`) as well as on the panel element, and
`Workspace::register_action` dispatches while `Workspace` is leased — so
opening the modal inline re-enters that update and hits GPUI's
`double_lease_panic`. This only reproduces when focus is *outside* the
Git Panel, which makes it easy to miss.
`Option<String>` rather than `String` is deliberate: `--message ""`
produces a blank stash description, which is strictly worse than git's
default.
## Testing
Manually verified the modal in a local build on macOS: the prompt
appears on `git::StashAll`, accepts a message, and the named entry shows
up in the stash picker.
Also verified at the git level by replaying the exact argument vector
`stash_paths` builds against a scratch repo with mixed staged / unstaged
/ untracked changes:
| Case | Result |
|---|---|
| `stash push --quiet --include-untracked --message "my named stash" --
<paths>` | `stash@{0}: my named stash`; worktree clean, untracked file
included |
| same, without `--message` | `stash@{0}: <sha> <subject>` — git's
default text |
| `--message "x" --` with no paths (clean repo) | exit 0, no stash
created — the empty pathspec does **not** stash everything |
`cargo fmt --check` clean, `./script/clippy -p git -p fs -p project -p
git_ui` passes with `--deny warnings`, and the existing suites pass
(`cargo test -p project -p git_ui`, 436 tests).
Worth a reviewer's attention: trigger `git::StashAll` with focus in the
**editor** rather than the Git Panel. That routes through the workspace
action registration and is the case the `cx.defer_in` deferral exists to
keep from panicking.
No new automated tests — the behavior is testable with the existing
`git_panel.rs` harness (`init_test`, `GitPanel::new`) if reviewers would
prefer coverage over a manual check.
## 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
added
- [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 — no new tests; see Testing
- [x] Performance impact has been considered and is acceptable — one
extra process argument; no new work on any hot path
---
Release Notes:
- Added an optional stash message prompt when stashing changes
`
---------
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
# Objective
- Make Git Panel grouping sections collapsible so users can hide
sections they are not currently interested in.
- Support collapsible sections when grouping changes by tracking and by
staging.
- Provide a clear visual indicator showing whether each section is
expanded or collapsed.
## Solution
- Added per-section collapsed state to the Git Panel.
- Made grouping headers clickable to toggle their section between
expanded and collapsed.
- Added chevron indicators that point down when expanded and right when
collapsed.
- Applied the behavior to both flat and tree views.
- Kept the stage/unstage checkbox independent from the header collapse
interaction.
- Ensured a previously collapsed Tracked section does not hide files
after switching to Group by None.
## Testing
- Ran `rustfmt --edition 2024 crates/git_ui/src/git_panel.rs --check`.
- Ran `cargo check -p git_ui`.
- Ran `cargo test -p git_ui`:
- 129 tests passed
- 0 tests failed
- Ran `git diff --check`.
- Attempted `./script/clippy -p git_ui` twice. It produced no lint
diagnostics but did not finish compiling the release, all-targets,
all-features dependency graph within the available timeout.
- Manually verify by selecting both grouping modes in the Git Panel and
clicking each section header in flat and tree views. Confirm that:
- The section contents are hidden and restored.
- The chevron updates to reflect the current state.
- Clicking the stage/unstage checkbox does not collapse the section.
- Switching to Group by None does not leave tracked files hidden.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
https://github.com/user-attachments/assets/77ec4c88-4a6d-4e49-ac9f-ddbf80e724ca
---
Release Notes:
- Improved Git Panel organization by allowing grouped change sections to
be collapsed
# Objective
When developing remotely, when I close the uncommitted changes tab, I
need some time to load before I can copy the path. Or have to switch to
the project panel to find the specific file. All of this is annoying, so
I added a copy path action to the git panel's context menu and key
bindings consistent with the project panel.
## Solution
Already described in the Objective section.
## Testing
I wrote a unit test and tested it manually.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<img width="411" height="535" alt="showcase"
src="https://github.com/user-attachments/assets/a17e7633-eb92-4737-aa30-958fe58bb99f"
/>
<img width="717" height="427" alt="showcase"
src="https://github.com/user-attachments/assets/d067e892-17de-4527-ac20-16cad6f38015"
/>
---
Release Notes:
- Added "Copy Path" and "Copy Relative Path" actions to the Git Panel's
context menu
The hosted-model reference now includes Claude Opus 5. This closes the
gap between the public documentation and the models that `cloud`
currently offers to Zed Pro and Zed Business customers.
The pricing table lists the provider price and Zed price for input,
output, cache-write, and cache-read tokens. The context-window table
lists the current 1M-token hosted limit. This change does not alter
model access or billing behavior.
Testing performed:
- `cd docs && npx prettier --check src/account/zed-hosted-models.md`
- `cd docs && mdbook build`
Release Notes:
- N/A
GPUI's input-latency histograms only sample frames that were preceded by
input, so a window that janks while animating or while streaming content
(agent panel output, terminal scrollback) never shows up in the fleet's
latency reports. Hang detection catches outright stalls, but frames that
are merely late — stutters in the 30–100ms range during animation —
currently aren't visible anywhere.
This adds a `frame-duration-histogram` feature to GPUI with a per-window
tracker recording two histograms: the duration of every `Window::draw`,
and the interval between consecutively presented frames while the window
is animating (a next-frame callback was already scheduled at the
previous present, so frames are being produced back-to-back and a
stretched interval means frames were missed). Intervals are only
recorded for active windows, since inactive windows are deliberately
throttled to a lower frame rate, and re-presents of unchanged frames
(e.g. sustaining the display's refresh rate during high-rate input) are
excluded. Zed enables the feature and reports both histograms every five
minutes as a "Frame Duration Report" telemetry event alongside the
existing "Latency Report", bucketed at roughly the 120Hz/60Hz/30Hz frame
budgets so dropped-frame rates can be aggregated across the fleet.
Release Notes:
- Added frame rendering performance to the diagnostics Zed collects when
telemetry is enabled, to help find and fix stutters and dropped frames.
> “Smart quotes” are the ideal form of quotation marks and apostrophes,
and are commonly curly or sloped. "Dumb quotes," or straight quotes, are
a vestigial constraint from typewriters when using one key for two
different marks helped save space on a keyboard.
Also helps us be consistent. I’m going to make a PR to our marketing
site to fix these issues as well, to bring further consistency to our
copy (docs / marketing / otherwise). Starting with v0.5.0 and up,
[`smart-punctuation`](6bf7fadc29/CHANGELOG.md (config-changes))
is enabled by default, so we just need this temporarily.
Good read: https://smartquotesforsmartpeople.com/
---
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/61208
Before, Zed showed no toasts on startup when tasks.json contained
malformed entries, also if there were two top-level arrays, the last one
was silently discarded without any toasts too.
The PR fixes both.
Release Notes:
- Fixed error toast not showing for malformed tasks.json
# Objective
Zed's Markdown parser accepts tilde-fenced code blocks, but Mermaid
extraction only strips backtick fences. As a result, a block like this
is parsed as Mermaid while the fence itself is still passed to the
renderer:
```markdown
~~~mermaid
graph TD;
~~~
```
## Solution
Teach the Markdown code-block helpers to recognize triple-tilde fences
alongside triple-backtick fences.
The change stays in the existing parsing path, so Mermaid rendering does
not need a separate special case. A regression test covers extraction
from a tilde-fenced Mermaid block.
## Testing
- `cargo fmt --all -- --check`
- `cargo test -p markdown` (138 tests)
- `./script/clippy -p markdown`
- `cargo build -p zed`
- Opened a `~~~mermaid` block in the built Zed Dev app on macOS and
verified that Markdown Preview renders the diagram
## 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 Mermaid diagrams in Markdown previews when they use triple-tilde
fences.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
Ensure that, when users undo project panel operations, we don't trash
files with unsaved edits as that could lead to data loss, as outlined
[here](https://github.com/zed-industries/zed/issues/62243#issuecomment-5203625087).
Closes#62243
## Solution
Update `UndoManager::trash` to require confirmation before moving files
to the trash. For files with unsaved edits, users can save, discard, or
cancel the operation while clean files receive a standard trash
confirmation, same as shown when trashing a file through the Project
Panel.
This helps avoid the issue where, if an user undoes a file creation for
a file that has unsaved edits and then quits Zed, the edits that were
saved in memory, as well as the Project Panel history, will now be gone
and there's no way to recover the data.
Batch operations have also been updated to now show a single
confirmation before making filesystem changes, preventing partial
execution when cancelled and warning about unsaved edits.
Lastly, the trash/delete prompt building has been refactored in order
for the Project Panel and Undo Manager to share the same wording,
file-list truncation, and unsaved-change warnings.
## Testing
Tested both manually as well as added the following tests:
* `project_panel::tests::undo::undo_create_cancel_trash`
* `project_panel::tests::undo::undo_create_dirty_file`
* `project_panel::tests::undo::cancel_partial_trash_batch`
* `project_panel::tests::undo::batch_trash_warns_about_unsaved_changes`
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
The screen recording below shows the trash confirmation dialog on both a
clean and dirty files, on both undo and redo flows.
https://github.com/user-attachments/assets/0f9b96f5-0357-4e3f-8ec2-141486942c89
---
Release Notes:
- Fixed issue with undoing or redoing project panel operations that
could lead to a file with unsaved edits being trashed without
confirmation.
Now, this is one of these beautiful cases where GitHubs API ist just so
pleasant to work with: Because PRs are treated as issues, assigning an
assignee to a PR suddenly requires issue write permissions, despite the
issue in question being a PR. Not having that permission resulted in
some missing assignees on zed zippy bumps and failures of the workflows
as seen in
https://github.com/zed-industries/zed/actions/runs/31339736929/job/93311493258.
In comparison, labelling PRs requires PR write permissions as seen in
https://github.com/zed-industries/zed/pull/61525🤡
Beautiful API and a pleasure to work with, 10/10 would recommend.
Release Notes:
- N/A
Recommends GPT-5.6 Sol for both OpenAI BYOK and OpenAI subscription.
Also unifies the naming so that we use the same OpenAI model names for
the Zed/OpenAI BYOK and OpenAI subscription providers.
Release Notes:
- N/A
This reverts commit 6297c88f42.
---
fixes#62286fixes#62095https://github.com/zed-industries/zed/pull/61467 fixed its intended bug,
but at the same time introduced an issue where running tasks that would
cause new tasks to be terminated immediately.
https://github.com/zed-industries/zed/pull/62322 tried to fix that
forward, but was unsuccessful. In the mean-time I am going to revert the
original PR.
We can try to re-land the original bugfix in a future PR.
Release Notes:
- N/A
Follow-up to #59838, implementing what was discussed at the end of
#59829: cmd-click navigation now respects `lsp_results_location` when
go-to-definition falls back to find-all-references (invited in
https://github.com/zed-industries/zed/issues/59829#issuecomment-4989966493:
"It would! Feel free to hook that up if you'd like to!").
## Problem
Cmd-clicking a symbol's definition falls back to find-all-references,
but the results always open in a multibuffer even with
`"lsp_results_location": "picker"`. The hover-link click path calls the
editor navigation methods directly, so the action handlers registered by
`lsp_locations` never get a chance to intercept.
## Solution
- `handle_click_hovered_link`'s fallback now dispatches the
`FindAllReferences` action (with `open_results_in: None`, deferring to
the global setting) instead of calling the method, so the
`lsp_locations` handler can intercept it, or propagate to the editor's
built-in handler when the setting is `multi_buffer`, preserving today's
behavior exactly.
- The plain cmd-click arm of `cmd_click_reveal_task` now runs the
definition query via `go_to_definition_of_kind` (no internal references
fallback) instead of `go_to_definition`, so the click path has a single
fallback decision point: the dispatching one. Without this, the method's
baked-in fallback opened a multibuffer before the dispatch could run.
- `go_to_definition_of_kind` visibility widened to `pub(crate)` for the
call from `hover_links.rs`.
Shift/alt click variants (type definition, splits) are untouched.
Keyboard invocations were already intercepted and are unchanged.
## Testing
- New test `test_cmd_click_fallback_honors_lsp_results_location` in
`lsp_locations`, following the module's existing test patterns: fake LSP
returning no definition and two references, `lsp_results_location:
picker`, simulated cmd-click at the cursor's pixel position, asserts the
picker opens. The test fails without this change.
- `cargo nextest run -p lsp_locations`: 6/6.
- `cargo nextest run -p editor -E 'test(hover) or test(fallback) or
test(go_to_definition) or test(references)'`: 54/54.
- `cargo fmt` and `./script/clippy` clean.
- Verified manually in a release build: with the setting on,
cmd-clicking a definition opens the picker; with it off, behavior is
unchanged.
Per the contributing guidelines' note on AI assistance: this change was
developed with heavy AI assistance (Claude Code). I have reviewed and
understand the full diff and the reasoning behind each hunk, and I'm the
one answering review feedback.
Release Notes:
- Fixed cmd-click go-to-definition falling back to a references
multibuffer even when `lsp_results_location` is set to `picker`.
# Objective
The `gpui::img` element always overrides the `aspect_ratio` field, so if
you have an image element that applies its own `.aspect_ratio()` it just
gets wiped out.
## Solution
Only apply the aspect ratio default if one is not already set.
## Testing
It's a very minor change but I did add a small test to ensure it
actually gets overridden.
## 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
This came from an issue where vertical images inside an element (square
in this case, as you'd see in an image gallery) do not behave correctly
with `object_fit` values of `ObjectFit::Contain` or
`ObjectFit::ScaleDown`.
This was simply because despite the image element having a fixed square
size (`img().size(px(200.))`), the aspect ratio would be forced to the
ratio of the image itself, so vertical images weren't being properly
fitted into their containers.
Minimal repro for that issue:
https://github.com/zaknesler/gpui-object-fit
So with this change, you can set `.aspect_square()` and the object fit
will behave as you'd expect:
<img width="1237" height="986" alt="image"
src="https://github.com/user-attachments/assets/5b1045a8-bd71-4b77-8bbd-c3b12112bcb0"
/>
---
Release Notes:
- gpui: Fix image element's aspect ratio overriding existing value
## Summary
- Add `terminal.starts_open` setting so the terminal panel can open
automatically in new workspaces, like project and git panels already can
- Expose the setting through terminal settings docs, default settings,
Settings Editor metadata, and the terminal panel implementation
- I also added a matching settings page item for the existing
`git_panel.start_open` setting
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)
- [ ] Tests cover the new/changed behaviour
- I decided not to add tests as the behaviour seems covered by the
existing settings tests, and similar areas don't seem to have their own
explicit tests.
- [x] Performance impact has been considered and is acceptable
Related to #51542 (issue mentions possibly adding for all panels, closed
with implementation for `git_panel`)
Release Notes:
- Added `terminal.starts_open` to control whether the terminal panel
opens automatically in new workspaces
# Objective
Follow-up to zed-industries/extensions#7062.
## Solution
Add `("windows-batch", &["bat", "cmd"])` to
`SUGGESTIONS_BY_EXTENSION_ID`
## 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:
- Added a suggestion to install the `windows-batch` extension when
opening `.bat` and `.cmd` files.
## Context
This is a rebase of #52302, which was approved by @Veykril in May but
still needed a rebase before it could be merged — it seems the original
author @MostlyKIGuess forgot about it. I rely on this fix daily for REPL
over SSH on an unstable connection and need it rather urgently, so I
cherry-picked the original commit (with authorship preserved) and
resubmitted it as a new PR.
Closes#51834
Supersedes #52302
## How to Review
The code itself was already reviewed and approved in #52302. This PR
only rebases it onto latest `main`, with one simple conflict resolution
against #53014: when all retries are exhausted, the error now uses the
improved message from that PR (suggesting `pip install ipykernel` on the
remote host) instead of the plain one. Comparing this diff against the
original PR's diff should make the review straightforward.
## 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:
- repl: Fixed iopub connection failures over SSH on slow or unstable
connections by retrying with exponential backoff.
Co-authored-by: mostlykiguess <bruvistrue93@gmail.com>
the buffer search and project search bars both already load the `regex`
language and put it on their query buffer when the regex filter is on.
the text finder never got that, so a regex you type in there is just
plain text.
did the same thing here. the only slightly annoying part was that the
picker's head editor is `pub(crate)`, so text_finder couldn't get at it.
added a small `query_editor()` accessor to `Picker` for that.
`adjust_query_regex_language` mirrors the two existing ones.
test asserts the query buffer's language is regex with the filter on,
and gone once it's off.
Closes#59945.
Release Notes:
- Improved the text finder by highlighting the query as a regex when the
regex filter is on
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
# Objective
- Zed can hang (and eventually get force-killed) when opening certain
binary files, because `analyze_byte_content`'s UTF-16 heuristic
misclassifies them as UTF-16LE/BE text.
- Reproduced with a real-world case: a ~92 MB OTBM game map file (the
binary map format used by OpenTibia/Tibia servers), which interleaves
short ASCII strings with small u16 length/type fields. Its byte pattern
(mostly-zero high bytes, very few control characters) passed the
existing check, so Zed read the entire file, decoded it as UTF-16, and
opened it as an editable buffer with tens of millions of characters and
effectively no line breaks — a pathological case for the text
layout/renderer that hangs or crashes the app (most noticeably on
Windows).
## Solution
`is_plausible_utf16_text` in `crates/language/src/file_content.rs`
previously only rejected the UTF-16 hypothesis when too many code units
were control characters (> 2%). That's not sufficient on its own: binary
formats that interleave short ASCII fragments with small numeric fields
can have a very low control-character ratio while still not being real
text — most of their "characters" land on stray symbol/high-byte values
rather than letters, digits, or spaces.
This PR adds a second, independent requirement: at least 30% of the
analyzed code units must be letters, digits, or spaces (the bulk of any
real UTF-16 text sample). Both conditions now have to hold for a byte
sequence to be classified as UTF-16 text — otherwise it falls through to
`ByteContent::Binary`, and file loading is rejected early, as intended
for binary files, instead of decoding the whole file as garbled text.
## Testing
- Added `test_length_prefixed_binary_not_misdetected_as_utf16le` in
`crates/worktree/src/worktree.rs`, using a synthetic byte pattern that
reproduces the same statistical shape as the real file (null high bytes,
low control-character ratio, no word-like low bytes) — asserts it is now
classified `Binary`.
- Verified against the real 92 MB `.otbm` file that triggered the bug
(not committed, since it's user data): before the fix it was classified
`Utf16Le`, after the fix it's classified `Binary`.
- Ran the full existing `analyze_byte_content` /
`is_plausible_utf16_text` test suite (`cargo test -p worktree --lib
tests::`) — all 7 tests pass, including the pre-existing positive
UTF-16LE/UTF-16BE detection tests, so legitimate UTF-16 files are
unaffected.
- Built a full `--release` binary on Windows and confirmed opening the
real file now shows "Binary files are not supported" immediately instead
of hanging.
## 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
code
- [x] The content adheres to Zed's UI standards — N/A, no UI change
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable — only
affects classification of the first 1 KB of a file, negligible cost
---
Release Notes:
- Fixed: Zed no longer hangs when opening certain binary files (e.g.
game asset/map formats) that were previously misdetected as UTF-16 text.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
RPC log grouping only tracked whether consecutive messages had the same
transport direction. This made an untimed request appear beneath the
duration header of an unrelated response when both were sent in the same
direction.
Before:
// Send (took 53.0ms):
{"jsonrpc":"2.0","id":"##CodeLensRefreshRequest#1226","result":null}
{"jsonrpc":"2.0","id":53,"method":"textDocument/diagnostic"}
After:
// Send (took 53.0ms):
{"jsonrpc":"2.0","id":"##CodeLensRefreshRequest#1226","result":null}
// Send:
{"jsonrpc":"2.0","id":53,"method":"textDocument/diagnostic"}
Apply the same boundary handling to received messages while continuing
to group consecutive untimed messages.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
Closes#62007
Adds Gemini 3.6 Flash to the Google AI provider so it can be selected in
the agent, alongside the existing Gemini 3.5 Flash.
Google released Gemini 3.6 Flash on July 21, 2026. It keeps the 1
million token context window, has a 64k output limit, and supports
thinking. The model is added with the same capabilities and thinking
levels as 3.5 Flash (Minimal, Low, Medium, High, defaulting to Medium).
The provider builds its model list from `google_ai::Model::iter()`, so
adding the enum variant is enough for it to show up in the model
dropdown. The thinking behavior in `completion.rs` keys off the
`gemini-3` id prefix, so it already applies to this model.
Release Notes:
- Added Gemini 3.6 Flash to the Google AI models
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GPUI's declarative hover styles are recomputed from the current frame's
hit test, but `on_hover` listeners previously updated only in response
to mouse movement or the pointer leaving the window. When layout moved a
different element beneath a stationary pointer, the new element looked
hovered without receiving its hover-start callback.
This change reconciles each hover listener against the current hit test
during painting and defers transitions until after the paint cycle, when
application callbacks can safely update state. Reconciliation pauses
while a mouse press is pending so hover-only controls remain mounted
between mouse-down and mouse-up.
The regression coverage moves an element beneath and away from a
stationary pointer and verifies both transitions. It also verifies that
repainting during a stationary mouse press does not generate a spurious
hover exit.
Testing:
- `cargo test -p gpui --lib`
- `cargo fmt --check -p gpui`
- `cargo check -p delta --bin delta` with Delta temporarily patched to
the local GPUI checkout
Release Notes:
- Fixed hover interactions not updating when interface elements move
beneath a stationary pointer.
Spinners rendered near each other (like a sidebar full of running
threads) each start rotating from the moment their element first
renders, so they spin out of phase and the group looks jittery.
This adds `Animation::repeat_synced()`, which derives the phase from a
clock shared by the whole app instead of the element's mount time, and
switches `with_rotate_animation` over to it, so every spinner with the
same period now renders the same frame at the same time. The epoch is
read off the scheduler clock at app creation, so the phase stays
deterministic under the test scheduler.
Release Notes:
- Improved loading spinners to rotate in phase with one another
Currently, GPUI on web calls `requestAnimationFrame` every frame, which
causes it to do meaningful GPU work every frame, even if it was
identical.
This PR makes GPUI only call `requestAnimationFrame` when it has new
content to display.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
The markdown preview used `vertical_scrollbar_for()` which always sets
the scrollbar to auto-hide mode, ignoring the user's `scrollbar.show`
setting.
This fix uses
`Scrollbars::for_settings::<EditorSettingsScrollbarProxy>()` so the
markdown preview respects the same editor scrollbar visibility setting
as regular editor panes (always, auto, system, never).
Changes:
- Replaced `vertical_scrollbar_for()` with `custom_scrollbars()` +
`Scrollbars::for_settings::<EditorSettingsScrollbarProxy>()` in the
markdown preview render method
Fixes#60380
Release Notes:
- Fixed `scrollbar.show` setting not being respected in Markdown
previews
---------
Co-authored-by: Akshit Jain <akshitj11@users.noreply.github.com>
Co-authored-by: MrSubidubi <finn@zed.dev>
# Objective
- Fixes#61925.
- GPUI already carries AccessKit author IDs through its platform
adapters, but applications cannot set one on an ordinary element.
## Solution
- Add `accessibility_id(...)` beside the other semantic builders.
- Store the value separately from GPUI's element ID and write it to
`Node::set_author_id`.
- Document that applications should keep the value stable and unique
within the accessibility tree.
- Document the platform mapping accurately: UIA `AutomationId` on
Windows, `AXIdentifier` on macOS, and AT-SPI `AccessibleId` on Linux
stacks whose deployed adapter exposes it.
## Testing
Exact candidate `d099c529`:
- `cargo fmt --all -- --check`
- `git diff --check`
- `cargo test -p gpui test_accessibility_id_builder_writes_author_id
--offline`: 1 passed, 218 filtered out
The test exercises the public builder and verifies that the author ID
reaches the AccessKit node. Validation is unit-level; this branch has
not run live platform UIA, AX, or AT-SPI end-to-end tests.
## Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments ; no unsafe block
added
- [x] The content adheres to Zed's UI standards ; no visual change
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
---------
Co-authored-by: Friday <260232009+buildfriday@users.noreply.github.com>
Label | Description
-- | --
area:integrations/git/panel | Feedback for the Git panel UI and
behavior.
area:gpui/graphics/wgpu | Feedback for GPUI's WGPU graphics backend,
including initialization and rendering.
area:breadcrumbs | Feedback for editor path and symbol breadcrumbs.
area:title bar | Issues suitable for title bar.
area:ai/agent thread/checkpoints | Feedback for Agent checkpoint
creation, comparison, restoration, and related Git behavior.
area:ai/agent thread/tools | Feedback for built-in Agent tools,
including execution, permissions, inputs, and outputs.
Release Notes:
- N/A
While building Zed with nightly rustc I've noticed it doesn't compile
because of good old pathfinder_simd. It also emits a bunch of warnings
about use of f64 literals where f32 is expected, so I've fixed them - it
should make future upgrades more straightforward.
# Objective
Prevent the thread from automatically scrolling to the end when
expanding a "Context Compacted" message at the end of the thread, as we
suspect the user would likely be trying to read it from top to bottom.
## Solution
Update how the `ThreadView` behaves when expanding a "Context Compacted"
message, namely by updating `ThreadView::toggle_compaction_expansion` in
order to anchor the scroll position, which disables the tail following
behavior, ensuring that the scroll offset is kept.
In order to better support this, a new method is introduced to
`gpui::elements::list::ListState`, `anchor_scroll_position`, which takes
the current scroll offset and scrolls to it which, in turns, disables
the following behavior.
Another option would be to simply introduce
`gpui::elements::list::ListState::stop_following` but I'm not sure
whether we'd want to expose that implementation detail, even though we
already have `gpui::elements::list::ListState::is_following_tail` .
## Testing
Tested both manually as well as introduced a new test for
`ListState::anchor_scroll_position`.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<details>
<summary>Before</summary>
https://github.com/user-attachments/assets/cf8ee10f-9c74-429d-afed-7a39ccd71c67
</details>
<details>
<summary>After</summary>
https://github.com/user-attachments/assets/78edfca9-099a-4fdb-9c4e-75f790096957
</details>
---
Release Notes:
- Improved expanding "Context Compacted" messages in the Agent Panel to
ensure that the scroll position is preserved, instead of automatically
scrolling to the end of the thread.
---------
Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>