# Objective
Wayland windows have no way to restrict which parts of the surface
accept pointer and touch input. This adds support for setting an input
region, so events outside it pass through to whatever is below the
window. This is useful for shaped or partially click-through windows.
Clicks in green area can pass through the window, clicks in red area do
not:
<img width="1057" height="395" alt="image"
src="https://github.com/user-attachments/assets/2039af62-e43b-4834-b877-edad2a8f5ccf"
/>
## Solution
Add `Window::set_input_region`, which takes `Option<&[Bounds<Pixels>]>`:
- `Some(rects)` restricts pointer and touch input to the union of the
rectangles, in window coordinates.
- `Some(&[])` is an empty region, so the window receives no input at all
and is fully click-through.
- `None` resets the region to the default, so the whole window receives
input again.
On Wayland this maps to `wl_surface.set_input_region`, building a
`wl_region` from the rectangles or clearing it for `None`, and commits
so the change applies immediately rather than waiting for the next
frame. The method is a no-op on other platforms.
## Testing
Tested on Linux with Wayland.
- Tested in my own GPUI application, which uses a fullscreen layer for
overlays while allowing clicks outside of the rendered elements to be
passed through to the underlying windows.
- No automated test was added, since this calls through to the
compositor and is checked by observing input routing.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- N/A
Closes#60162.
MCP servers whose tool `inputSchema` uses `$ref`/`$defs` (e.g., Notion
MCP v2.x, and any server using Zod/Pydantic-generated schemas) are
silently rejected with:
```
ERROR Schema cannot be made compatible because it contains "$ref"
```
The affected tools are dropped from the agent panel — the user never
sees them and there is no user-visible error.
## Root cause
`adapt_to_json_schema_subset` rejects any schema containing `$ref` via
`UNSUPPORTED_KEYS`:
```rust
const UNSUPPORTED_KEYS: [&str; 4] = ["if", "then", "else", "$ref"];
```
This is hit by every provider that uses `JsonSchemaSubset` format
(Google Gemini, xAI Grok, OpenAI-compatible proxies, Vercel AI Gateway,
Copilot Chat for Google/xAI vendors, OpenRouter for gemini/grok models).
Providers using `JsonSchema` (Anthropic direct, OpenAI direct) don't hit
this check — `$ref` is passed through to the API, which may or may not
handle it correctly.
This is not an edge case. Every modern MCP server using Zod
(TypeScript), Pydantic (Python), or JSON Schema with shared definitions
generates `$ref`/`$defs` in tool schemas.
## Fix
Add a `resolve_refs` step in `adapt_schema_to_format` that dereferences
all `$ref` pointers using the document's own `$defs` (or legacy
`definitions`) map, making the schema self-contained before
format-specific processing. Applied at the entry point so both
`JsonSchema` and `JsonSchemaSubset` formats benefit.
**Scope note:** previously `JsonSchema` providers (Anthropic direct,
OpenAI direct) received the raw `$ref`/`$defs` and were expected to
handle it themselves — which most do not. After this change, both paths
receive a self-contained schema with refs inlined. This is intentional:
it fixes the same root cause for both paths and avoids provider-specific
behavior divergence.
Supported `$ref` forms:
- `#/$defs/<name>` (JSON Schema draft 2019-09+)
- `#/definitions/<name>` (draft 4-7 legacy)
Edge cases:
- **Nested `$ref`** (definition references another definition): resolved
recursively.
- **Sibling properties alongside `$ref`** (e.g. `{ "$ref": "...",
"description": "..." }`, legal under draft 2019-09+): merged onto the
resolved definition, with siblings overriding the definition's keys.
- **Cyclic references** (A → B → A, or self-referential schemas like a
Tree node): replaced with an empty schema `{}` ("any JSON value"). The
tool still works, just without type info for that recursive field.
- **Unsupported `$ref` forms** (e.g., external URLs): returns an error
with a clear message.
- **Missing definition target**: returns an error naming the missing
ref.
## Testing
Added 10 unit tests in `crates/language_model_core/src/tool_schema.rs`
that cover the patterns produced by Zod/Pydantic-generated MCP schemas:
- `test_refs_are_resolved_via_adapt_schema_to_format` — basic `$ref` →
`$defs` resolution
- `test_refs_in_defs_are_resolved` — nested `$ref` (definition
references another definition)
- `test_refs_in_array_items_are_resolved` — `$ref` inside `array.items`
- `test_legacy_definitions_prefix_is_supported` — old
`#/definitions/<name>` prefix
- `test_schema_without_defs_is_unchanged` — schemas with no `$defs` are
unaffected
- `test_refs_fail_for_unsupported_prefix` — external URL refs error
clearly
- `test_refs_fail_for_missing_definition` — missing target errors
clearly
- `test_cyclic_refs_are_replaced_with_empty_schema` — A → B → A cycle
replaced with `{}`
- `test_self_referential_ref_is_replaced_with_empty_schema` — Tree-like
self-ref replaced with `{}`
- `test_ref_sibling_properties_are_preserved` — sibling properties
alongside `$ref` are merged onto the resolved definition
Existing tests (which call `adapt_to_json_schema_subset` and
`preprocess_json_schema` directly) are unaffected — the fix is additive
at the `adapt_schema_to_format` level.
## Disclosure
I used an LLM to help draft the implementation and tests. I reviewed and
understand the change — it adds one new function (`resolve_refs`) with
two helpers (`parse_ref`, `resolve_refs_recursive`), plus unit tests.
Release Notes:
- Fixed MCP tools with `$ref`/`$defs` in their `inputSchema` being
silently rejected by providers using the JSON Schema Subset format
(Google Gemini, xAI Grok, OpenAI-compatible proxies, etc.). Tools from
servers like Notion MCP v2.x, and any server using Zod or
Pydantic-generated schemas, now work correctly.
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
Closes#56973, Follow-up for
https://github.com/zed-industries/zed/pull/56976
When a completion's `additionalTextEdits` contained a zero-width
insertion touching the edge of the primary edit, the overlap check
treated it as overlapping and silently skipped it. This broke
rust-analyzer's ref-match completions (`&foo`), which deliver the `&` as
a zero-width additional edit at the primary edit's start (#56973). The
same root cause previously broke auto-imports at the very start of a
file (#26136), which was worked around in #37746 with a special case for
edits at position (0, 0).
This PR replaces that special case with a general rule: a zero-width
additional edit only overlaps the primary edit when it falls strictly
inside it. i.e. touching the boundary is fine.
This one check handles both the file-start auto-import case and the `&`
ref-match case, so the (0, 0) workaround from #37746 is removed.
Non-insertion edits still go through the original overlap check from
#1871.
Added three regression tests:
- the file-start auto-import (#26136)
- the `&` insertion at the primary edit's start (#56973)
- overlapping edits being skipped while non-overlapping ones apply
(general skip case)
Release Notes:
- Fixed rust-analyzer completions like `&some_var` inserting only the
variable name and dropping the leading `&` when accepted.
# Objective
Fixes#59979
With hard tabs on, expanding a multi-line snippet only re-indents the
lines that already start with a tab. Anything with no leading whitespace
(closing brackets, mostly) stays at column 0.
## Solution
Block autoindent shifts each line by the first line's delta, but only
when the line's indent kind matches the target kind. A line with no
indentation defaults to `IndentKind::Space`, so under hard tabs it never
matches and gets skipped. An empty indent doesn't really have a kind, so
I let it adopt the target kind before the check. Lines that actually
have space indentation in a tab buffer are still left alone. Normalizing
those felt like a bigger question than this bug, happy to look at it
separately if wanted.
## Testing
New `test_autoindent_block_mode_with_hard_tabs`, same shape as the
snippet in the issue. Fails on main (closing brace stays at column 0),
passes with the fix. `cargo test -p language` and `-p editor` are green,
clippy and fmt too.
## 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 multi-line snippets leaving unindented lines at column 0 when
`hard_tabs` is enabled.
Zed bundles the markdown grammar's block scanner natively, and its
`serialize()` `memcpy`s the open-block stack into tree-sitter's fixed
1024-byte serialization buffer with no bounds check. Markdown with
roughly 255+ nested blocks overflows that buffer, and because it sits at
the front of `struct TSParser`, the overflow clobbers the adjacent
parse-stack pointer and heap. Debug builds of the tree-sitter runtime
catch this with an assertion, but release builds like Zed's have no
check and silently corrupt parser memory — which is why this surfaced as
wild crashes deep in tree-sitter's parse stack rather than clean
failures. Still open upstream as
tree-sitter-grammars/tree-sitter-markdown#243.
This PR points `tree-sitter-md` at a `zed-industries` fork whose
`serialize()` refuses to write state that doesn't fit (bounded by the
same running counter the header writes advance, so the check can't
drift). The scanner then deserializes to a fresh state, and the
pathologically nested region surfaces as ordinary tree-sitter `ERROR`
nodes — visible, safe degradation for an adversarial input class,
deliberately chosen over the two alternatives: truncating the block
stack would deserialize into a plausible-but-wrong state and produce
silently incorrect trees, and the scanner ABI offers no error channel at
all (`serialize()` returns a length into a fixed buffer; there is no way
to fail a parse). A nesting-depth cap at block-open time would give
fully deterministic semantics, but that's a behavior change across 13
scanner call sites that belongs upstream, not in a hotfix fork.
The pinned branch is upstream's `9a23c1a9` (the revision Zed already
pinned) plus exactly two commits, for easy review: the guard
(zed-industries/tree-sitter-markdown@179422edf8)
and regression tests
(zed-industries/tree-sitter-markdown@b596e73728).
The deep-nesting test aborts on the unguarded scanner and passes with
the guard; a moderate-nesting test pins that inputs fitting the buffer
still parse cleanly. The same change is also up as
zed-industries/tree-sitter-markdown#1 into the fork's default branch
(`split_parser`), so future pin bumps don't lose it; if upstream fixes
#243, we can drop the fork entirely on the next bump.
Closes FR-115
Release Notes:
- Fixed a potential crash when editing Markdown with deeply nested
blocks
This PR explores the addition of a new feature and UI to improve
visibility into partially staged commits.
Currently, the Git panel shows tracked and untracked changes, but it
does not clearly distinguish between staged and unstaged changes.
As a result, it’s difficult to quickly see which changes are not staged
in the current UI. Both staged and unstaged changes are combined into
the `Uncommitted Changes` multibuffer. This developer experience differs
from other editors, most notably VS Code; which presents separate Staged
Changes and Changes lists.
### Staged and unstaged diffs in multibuffers
This PR introduces an alternative UI for unstaged changes that aligns
with the overall Zed experience. Instead of showing changes on a
per-file basis, staged and unstaged diffs are each displayed in their
own multibuffers, similar to how `Uncommitted Changes` currently works.
For example the following screenshot shows the current `Uncommitted
Changes` on the left, the `Staged Changes` in the middle and the
`Unstaged Changes` buffer on the right for comparison
<img width="1408" height="859"
src="https://github.com/user-attachments/assets/aa709f7a-041d-4cb1-95d6-84c0f5fff688"
/>
### Indicators/interactions
The new multibuffers can be opened in two ways:
1. Via a new `U` chip, which appears when a file has unstaged changes
2. Via new menu options
(See screenshots below for both interaction paths.)
<table>
<tr>
<td style="text-align: center; vertical-align: top;">
<p>via the chip</p>
<img
height="400"
src="https://github.com/user-attachments/assets/3ef69f02-b787-499c-959a-25f50b3728e8"
alt="Via the chip"
/>
</td>
<td style="text-align: center; vertical-align: top;">
<p>via the menu</p>
<img
height="400"
src="https://github.com/user-attachments/assets/f5be8b6d-ccdc-4420-bd29-75570b558016"
alt="Via the menu"
/>
</td>
</tr>
</table>
### Design goals
- minimally intrusive UI changes (small new badge and menu items)
- adhere by Zed'ism (use multibuffer where possible)
- avoid disabling any current interactions (Uncommitted Changes ui is
unchanged)
- avoid introducing an app level view mode (no new settings needed)
### Experience goals
- make it easy to see what changes are not staged
- make it easy to see that a file has unstaged changes (avoid developers
accidently leaving out changes in a commit; a personal issue that I have
when using Zed)
- elegantly handle large file's unstaged changes (follows the same
collapse and expanding seen in `Uncommitted Changes`)
### How to try
- Clone the repo and run `cargo run`
- Make a change to a file and stage it
- Make another change to the file (the `U` indicator will appear)
- Click the `U` to see the unstaged view
### Open questions/rough edges
- [ ] determine if this user experience is useful for others
- [ ] ensure all interactions work as expected (response to all update
cases)
In general I'm really interested in hearing the community's feedback
about this interface, more than happy to make any changes or explore a
different solution!
### Related issue:
- https://github.com/zed-industries/zed/pull/36646
- https://github.com/zed-industries/zed/issues/26560
Release Notes:
- Support partially staged commit multibuffers via a staged and unstaged
changes view.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Stacked on #60502 and targets it — #60502 must land first (its
orchestrator fix is what lets this `tooling/lints/`-touching PR go green
rather than tripping the `rdeps(lints)` nextest filter). Re-creates the
symlinks from #60504, which was accidentally merged into #60502's branch
and reverted.
Follow-up to #60468, which added a `LICENSE-APACHE` symlink to the
`tooling/lints` crate but not to the `test_fixture` sub-crates. Those
five sub-crates each carry a `Cargo.toml`, so `script/check-licenses`
requires a `LICENSE-GPL`/`LICENSE-APACHE` symlink in each, and
`check_licenses` fails on any PR that changes `Cargo.lock`. This adds
`LICENSE-APACHE` symlinks to the five fixture crates, matching #60468;
`script/check-licenses` passes locally afterward.
Release Notes:
- N/A
The `orchestrate` job maps changed directories to root-workspace package
names, and when no mapping was found it fell back to using the raw
directory name as a package. Because `tooling/lints` is a separate
workspace (not a root-workspace member), a change under
`tooling/lints/**` produced the filter `rdeps(lints)`, which `cargo
nextest run --workspace` rejects with "operator didn't match any
packages" — failing `run_tests` for any such PR. This drops that
fallback so an unmapped directory falls through to the existing "no
package changes → run all tests" path instead.
Release Notes:
- N/A
This PR adds the new `id_v2` and `legacy_user_id` fields to the
`AuthenticatedUser` type and starts using them in place of the `id`
field.
Release Notes:
- N/A
PR https://github.com/zed-industries/zed/pull/45892 changed the logic
for rendering completion labels and divided rendering up into the "main"
part (consisting of the completion's `filter_range`) and "details" part
(everything after `filter_range`), but no longer renders text that comes
before the `filter_range`. This text is probably not relevant in too
many cases but makes some Rust completions unclear and ambiguous, as can
be seen in this example:
Without this change:
<img width="1262" height="313" alt="Image"
src="https://github.com/user-attachments/assets/dcdd9da4-c449-445d-b379-771b368c3778"
/>
With this change:
<img width="1328" height="376" alt="grafik"
src="https://github.com/user-attachments/assets/05fdaf95-7a18-4d50-8e3b-35be10d9a1ef"
/>
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#56973
Release Notes:
- Fix completion labels not being rendered completely
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Seeing `script/check-license` fail because we forgot to add a license in
#58496
> Error: tooling/lints does not contain a LICENSE-GPL or LICENSE-APACHE
symlink
Release Notes:
- N/A
This PR adds a bunch of design improvements to the toolbar of (tab)
views that display diffs: the uncommitted changes, branch diff, and
agent diff tabs. This involves adjusting spacing, sizing, and other
small tweaks across all of these views, including touching up the
divider component API a little bit, adjusting Git icons design, adding
diff stat numbers to the uncommitted changes tab so its consistent with
the others, and more (e.g., moving the split buttons into its own
component to ensure they look the same across all uses). Ended up also
going on a slight de-tour to make all uses of the split button in the
Git panel consistent design-wise.
All in all, this is just tidying up the design of all of these surfaces
that are all relatively similar.
| Branch Diff | Uncommitted Diff | Single-file Diff | Git Panel |
|--------|--------|--------|--------|
| <img width="800" alt="Screenshot 2026-07-06 at 11 25@2x"
src="https://github.com/user-attachments/assets/4ebf87e7-c52d-41d9-9de3-7944125114a1"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11 25 2@2x"
src="https://github.com/user-attachments/assets/51ccd2eb-904b-455a-a708-b4cb50b3a7cb"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11 26@2x"
src="https://github.com/user-attachments/assets/6ae7df68-d1bd-4d36-a250-ba16e43c4e8e"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11 26 2@2x"
src="https://github.com/user-attachments/assets/e032bc60-4551-41f0-b578-90ed305167c2"
/> |
Release Notes:
- Added diff stat numbers to the uncommitted changes view.
- Fixes#60238.
- The text finder could spike memory into the tens of gigabytes and
crash the app. The finder was copying the full matched line into every
match it kept, so memory grew with the number of matches times the size
of each line. Enough matches carrying enough text and the process runs
out of memory.
## Solution
- Stop storing line text on matches. Each match now keeps only its
position and column, and the text shown in a row is built lazily for the
visible rows, using a bounded slice around the match rather than the
whole line. Line boundaries come from the buffer's line index instead of
re-scanning the content per match.
- Cap the number of matches the finder builds while streaming results,
using the same ceiling project search already applies. This keeps the
finder from ever assembling an unbounded match list on the UI thread.
- Behavior is unchanged: every occurrence is still its own row, jumping
to a match lands on the exact line and column, and the rendered text and
highlighting look the same. The finder just no longer holds text
proportional to the match count.
## Testing
- Added tests covering the new behavior: the match count is capped while
streaming, every occurrence below the ceiling still becomes its own
match at the correct line and column, and the rendered slice around a
match stays bounded on a huge line while still covering a whole short
line.
- Verified by hand with the reproduction from the issue. The screenshot
below shows the memory usage and the matching against the issue data:
<img width="1277" height="1053" alt="Screenshot 2026-07-03 at 17 43 11"
src="https://github.com/user-attachments/assets/71c0aa3b-2423-427d-91ba-792951d9ba31"
/>
## 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 crash and high memory usage in the text finder.
## Objective
- Provide initial preview layout information for the picker delegate.
This ensures that when match items with different styles need to be
displayed under horizontal or vertical layouts, they render correctly on
the first display.
## Solution
- Pass the initial layout information to the delegate in the picker
constructor
## 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
# Objective
Fixes#60436
Pressing Escape (or triggering any workspace-level action that closes
modals, such as `pane::DeploySearch` / `search::NewSearch`) while the
Text Finder was open crashes the app with:
```
cannot read workspace::Workspace while it is already being updated
crates/gpui/src/app/entity_map.rs:164
```
`TextFinder::on_before_dismiss` read the `Workspace` entity
(`workspace.read(cx).database_id()`) to persist the last search query.
Dismissal can be initiated from inside a `workspace.register_action`
handler — e.g. `buffer_search`'s `SearchActionsRegistrar` calls
`workspace.hide_modal(...)` while the `Workspace` entity is leased — so
the modal layer invokes `on_before_dismiss` synchronously under that
lease, and the read trips GPUI's re-entrancy guard. Since the finder
seeds the last query on open, the query is non-empty immediately, making
the crash reproducible on the very first Escape.
Dump file analysis confirms the diagnosis.
## Solution
Stop reading the `Workspace` entity in the dismiss path. Both places
that create the modal (`TextFinder::open` and
`TextFinder::open_from_project_search`) already run inside
`workspace.update_in`, where `workspace.database_id()` is a plain field
access on `&mut Workspace`. Capture the `Option<WorkspaceId>` there,
store it on `TextFinder`, and have `on_before_dismiss` use the stored
id. The dismiss path now touches no entity that can be mid-update, so it
is safe regardless of which code path initiates `hide_modal`. The
remaining reads in `on_before_dismiss` (`picker` and its query editor)
are never leased in any dismissal chain.
The `id` is captured once at creation; a workspace that gains a database
id during the modal's lifetime would persist under `None` (i.e. skip
persistence), which matches the previous behavior for unpersisted
workspaces.
## Testing
- Verified the fix by code review and re-tested in a rebuilt bundle
(local build).
- To reproduce/verify: open the Text Finder (`text_finder::Toggle`),
type a query (or rely on a seeded one), then press Escape with a binding
that resolves to `editor::Cancel`, or press `cmd-shift-f`
(`DeploySearch`) while the finder is open. Before this change the app
crashes. After it, the modal dismisses and the query is persisted.
- Tested on macOS 26.5.1 (arm64); the affected code is
platform-independent.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks — no unsafe blocks
- [x] The content adheres to Zed's UI standards — no UI changes
- [x] Tests cover the new/changed behavior — added
- [x] Performance impact has been considered and is acceptable — one
`Option<WorkspaceId>` copy at modal creation
---
Release Notes:
- Fixed a crash when closing the Text Finder while a workspace action
(e.g. Escape via `editor::Cancel`, or deploying search) triggered the
dismissal
Document how to configure the Tailwind CSS language server for Go
(Templ).
Ref #43969.
Release Notes:
- N/A
---------
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
This PR makes it so that when you install an agent from the registry we
set it as the default agent. We apply the same behaviour when installing
an ACP agent from the onboarding page, which should make it less
confusing for new users (they won't see the Zed agent when they see a
new thread, but instead see the agent they installed)
https://github.com/user-attachments/assets/81f4711f-4c9a-4606-882a-9f944c90dfa3
Release Notes:
- agent: Improved onboarding experience when installing ACP agents
Documents how to configure the Tailwind CSS language server for Gleam,
and updates the link on the Tailwind landing page to anchor at the new
section so it matches the pattern used for Astro, ERB, HEEx, HTML,
TypeScript, JavaScript, PHP, Svelte, and Vue.
The config follows what was documented in #43968 when Gleam was added to
`tailwind.rs`.
Refs: #43969
Release Notes:
- N/A
---------
Co-authored-by: Kaedin Hano-Hollis <180361443+kaedinhanohano@users.noreply.github.com>
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
Removing the feature flag now that the API is stable.
Release Notes:
- acp: Support boolean toggles for ACP session configuration in agents
that use them.
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
● Closes#50285
## Summary
When `inline_blame` is disabled in settings and `editor::BlameHover` is
triggered,
the blame popover fails to appear on the first invocation because
`start_git_blame`
kicks off an async task to fetch blame data, but `blame_hover`
immediately tries to
read that data synchronously before it's available.
This fix registers a one-shot observation on the blame entity when it's
freshly
created, so the popover is shown once blame data has finished
generating.
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [ ] ~Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)~
(No UI changes)
## Videos:
### Before:
https://github.com/user-attachments/assets/d2ca4f8e-8186-49af-9908-5a82bfca0de2
Ps: pressed the keybind two times
### After:
https://github.com/user-attachments/assets/08575cd9-2bbc-462d-92fa-f0e7ef23d8d6
## Release Notes:
- Fixed blame hover popover not appearing on first trigger when inline
blame is disabled (#50285)
---------
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
This PR improves the onboarding experience when using the agent panel.
Previously we would pick a fallback model in case the provider failed to
authenticate/was slow to resolve models. However, this code had a race
condition (for providers that resolve models dynamically like
Anthropic/GitHub Copilot), since we pick a fallback immediately after
all providers have been authenticated. However, at that point the
configured provider might not have resolved its models, so we would fall
back to a different provider. At some point we added a workaround for
the zed.dev provider.
We landed on a much simpler approach that eliminates the race condition:
We only pick a fallback model in case the user actually has no model
configured in his settings. In case the user has a model configured, we
won't fallback and show an actionable error message:
1. Model is not set and no fallback available
<img width="862" height="78" alt="image"
src="https://github.com/user-attachments/assets/e8e7472a-1c05-4cd2-8efc-49e6d921b0a4"
/>
2. Model is set, but provider is not authenticated
<img width="865" height="65" alt="image"
src="https://github.com/user-attachments/assets/3c8cbf1d-7dd5-4b2e-809a-61e6662721a3"
/>
3. Model is set, provider is authenticated, but model is not in model
list
<img width="863" height="63" alt="image"
src="https://github.com/user-attachments/assets/b97defa2-3fb4-4ec0-b3c6-26878d1c815c"
/>
4. Model is set, but provider is not recognised
<img width="865" height="67" alt="image"
src="https://github.com/user-attachments/assets/ecff1e3f-4f6b-47eb-a25d-125a104baafc"
/>
This plays well with the reason why we have the fallback model in the
first place: We only want to pick a fallback for users that open Zed for
a first time and e.g. have an Anthropic API key present in their
environment. As soon as the user manually changes his provider/model we
won't apply the fallback anymore.
Release Notes:
- agent: Improved error messaging when provider is not configured
- agent: Improve fallback model selection
---------
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
## Summary
- The default settings in `assets/settings/default.json` disable
`kotlin-language-server` (prefixed with `!`) and enable `kotlin-lsp` as
the primary LSP, but the Kotlin documentation listed them the other way
around. This swaps the order so the docs match reality.
## Test plan
- [x] Verified `assets/settings/default.json` has
`["!kotlin-language-server", "kotlin-lsp", "..."]` for Kotlin
- [x] Confirmed the documentation now lists `kotlin-lsp` as the primary
Language Server and `kotlin-language-server` as the alternate
Release Notes:
- N/A
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
Prevent collapsing a folder in one Git panel section from also
collapsing the same folder path in other sections.
## Solution
Key directory expansion state by `TreeKey`, which includes both the
section and repository path, instead of by `RepoPath` alone. This also
keeps persisted tree state, stale-state cleanup, and selected-file
reveal behavior section-aware.
## Testing
- Added `test_tree_view_directory_expansion_is_scoped_to_section` to
cover the same folder path under Tracked and Untracked independently.
- `cargo fmt -p git_ui -- --check`
- `git diff --check`
- Attempted `cargo test -p git_ui
test_tree_view_directory_expansion_is_scoped_to_section --lib`, but
dependency compilation could not complete because the local disk ran out
of space. Reviewers can run that command to execute the focused
regression 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
## Suggested .rules additions
- In the Git panel tree view, key per-row UI state by `TreeKey` rather
than `RepoPath`, because the same directory can appear in multiple
sections.
---
Release Notes:
- Fixed collapsing a folder in one Git panel section also collapsing it
in other sections.
When `disable_ai` is set, bindings to AI-namespaced actions (assistant,
agent, inline_assistant, acp, edit_prediction, zeta) are now dropped at
keymap load time. Previously the bindings stayed active and their
handlers silently no-op'd, which shadowed lower-precedence editor
defaults — pressing ctrl-enter in an editor was captured by
`assistant::InlineAssist` and did nothing instead of falling through to
`editor::NewlineBelow`.
The filter applies to both default and user bindings, and a settings
observer reloads the keymap when `disable_ai` toggles at runtime.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#56692
Release Notes:
- Fixed AI keybindings remaining active and shadowing editor defaults
when AI features are disabled
---------
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
# Objective
Zed ignores files marked by Git as type-changed (T), causing commits
containing only these changes to show 0 Changed Files.
For example, commit 86590085000dca2e9dfe967470fa42423ef7ceac changes
crates/eval_utils/LICENSE-GPL from a regular file to a symlink, but Zed
displays no changes.
## Solution
Handle TypeChanged files like modified files by loading both their old
and new contents.
## Testing
- Added parser coverage for the T status.
- Added a repository test for a regular-file-to-symlink change.
- Ran cargo test -p git.
- Ran ./script/clippy -p git.
- Manually verified the example commit on macOS.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and [icon](https://github.com/zed-
industries/zed/blob/main/crates/icons/README.md) guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
Before:
<img width="200" alt="image"
src="https://github.com/user-attachments/assets/277c5938-5c2c-47b7-902d-9061a14c062a"
/>
After:
<img width="200" alt="image"
src="https://github.com/user-attachments/assets/f99d0005-0712-4843-814e-d73b11f64782"
/>
———
Release Notes:
- Fixed type-changed files not appearing in Git Graph and commit views.
# Objective
Before this change, we watched the themes directory itself. During
rescans, this could generate events for the directory, causing Zed to
attempt to load `event.path` as a file via
`fs.load_bytes(&event.path).await.log_err()`. This happened because
`fs.metadata(&event.path).await.ok().flatten().is_some()` also returns
true for directories.
Since load_bytes will always fail for a directory, we can avoid the
unnecessary call by skipping it whenever `event.path` refers to a
directory.
The rescan happens when Zed lost sync with the filesystem. That will
produce the following logs:
```
2026-07-01T16:03:35+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more
2026-07-01T16:03:35+02:00 ERROR [crates/zed/src/main.rs:1891] Is a directory (os error 21)
```
## Solution
The solution is that we just can check if the `event.path` is a
directory if so we can skip the
`fs.load_bytes(&event.path).await.log_err()` part described aboth.
## Testing
All tests should still pass and there should be no impact since this
only happens on rescans when the system is under pressure with alot of
fs events.
**Note**: No regression test was added since there's nothing to test
here.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- N/A
# Objective
Fixes#57766
Allow users to select and copy the text of commit messages from the git
graph details panel.
## Solution
Implements selectable commit message in the detail panel using
`MarkdownElement`s a la `commit_view`.
### Affordances considered and abandoned:
- "copy message" and/or "copy subject" buttons, but the UI here is
already pretty tight and I don't feel confident enough in my design
chops or familiarity with Zed to propose bigger UI changes here.
- Default-collapsed message with expand button, a la `commit_view`. The
use-case of this panel is to get the gist of a commit while moving
somewhat quickly through the graph. One might argue that the subject
line alone is enough for that, but often it isn't and the thought of
having to constantly expand commit messages rather than making the
message immediately visible with scroll felt like it would produce a
repetitious experience.
## Testing
- Adds two unit tests to verify that selection works and is idempotent
## 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
Video demonstrating the functionality:
https://github.com/user-attachments/assets/b910aaa3-2db2-4da8-904b-21b270677ca9
---
Release Notes:
- Show full commit message as markdown in details panel of the git graph
## Summary
Fix agent message hyperlinks that point to Windows file paths but are
not parsed as openable project paths.
This covers links like:
```md
[Cargo.toml](</C:/Projects/Example Workspace/Cargo.toml:2>)
[filename.ext](C:\Projects\Example%20Workspace\path\to\filename.ext:42)
[AGENTS.md](</c/Projects/Example Workspace/AGENTS.md>)
```
## Problem
Agent responses can emit Markdown hyperlinks whose targets are Windows
paths rather than `file://` URLs. Some of those targets include a
leading slash before the drive (`/C:/...`), Git Bash/MSYS-style drive
prefixes (`/c/...`), percent-escaped spaces, or line suffixes. These
were not normalized before mention parsing, so clicking the hyperlink
could do nothing instead of opening the file.
## Solution
- Normalize hyperlink path targets before parsing them as `MentionUri`
paths.
- Decode percent escapes in bare path targets so `%20` becomes a literal
space before path/line parsing.
- Convert Windows-compatible hyperlink paths such as `/C:/...` and
`/c/...` into native Windows paths.
- Generate file resource links from `find_path_tool` through
`MentionUri::to_uri()` instead of hand-building `file://` strings.
## Result
Before: clicking agent path hyperlinks did not open the referenced file.
After:
https://github.com/user-attachments/assets/6c7fad77-4a1e-4497-a4f9-4a4fdf86d527
## Validation
- `cargo test -p acp_thread test_parse_windows --features test-support`
- `cargo fmt --check`
## Follow-up changes
Additions on top of the original work above:
- Moved the hyperlink heuristics into a dedicated
`MentionUri::parse_hyperlink` entry point. `MentionUri::parse` stays
strict, so canonical mention URIs round-trip verbatim and other callers
(message editor, thread deserialization, resource links) are unaffected.
- Percent escapes that decode to path separators (`%2F`, `%5C`) are left
encoded, so decoding can never change which directories a path
traverses.
- Bare paths with escapes are ambiguous (a file may literally be named
`a%20b.rs`): `open_link` prefers the decoded interpretation and falls
back to `MentionUri::parse_hyperlink_literal` when the decoded path
doesn't resolve in the project but the literal one does.
- Links to files outside the project's worktrees now open, gated by an
async existence check through the project `Fs` (correct for remote
projects; broken links no longer create empty buffers or add worktrees).
`open_link` and the mention-crease open path are unified into one
`open_abs_path_at_point`, which now also places the cursor for
out-of-project selection/symbol links.
- `grep_tool` resource links also go through `MentionUri::to_uri()` now,
fixing malformed `file://C:\...` URIs and unencoded spaces.
- Added tests: percent-escape disambiguation, out-of-project link
opening, drive-letter normalization, UNC paths, and literal-path parsing
(`cargo test -p acp_thread mention`, `cargo test -p agent_ui open_link`,
`cargo test -p agent grep_tool`); manually verified the link spellings
above on Windows.
Release Notes:
- Fixed agent path hyperlinks on Windows when paths contain spaces or
shell-style drive prefixes.
---------
Co-authored-by: Martin Ye <martin@zed.dev>
Follow-up to #60360 and #59016 (cc @NeelChotai @bennetbo).
Claude Sonnet 5 and Claude Fable 5 cannot be invoked with on-demand
throughput — AWS requires an inference profile, and only `us.*` and
`global.*` profiles exist for these models ([Sonnet 5 model
card](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-anthropic-claude-sonnet-5.html),
[Fable 5 model
card](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-anthropic-claude-fable-5.html)).
For users in EU/APAC regions without `allow_global` enabled, Zed
generated profile IDs like `eu.anthropic.claude-sonnet-5`, which fail
with:
```
ResourceNotFoundException: Model not found.
```
And falling back to the bare model ID isn't an option either, since
direct invocation fails with:
```
Invocation of model ID anthropic.claude-fable-5 with on-demand throughput isn't supported.
Retry your request with the ID or ARN of an inference profile that contains this model.
```
Confirmed against the live AWS API — only `us.*` and `global.*` profiles
exist:
```
❯ aws bedrock list-inference-profiles --region eu-west-1 \
--query "inferenceProfileSummaries[?contains(inferenceProfileId, 'sonnet-5') || contains(inferenceProfileId, 'fable')].[inferenceProfileId,status]" \
--output table
------------------------------------------------
| ListInferenceProfiles |
+------------------------------------+---------+
| global.anthropic.claude-sonnet-5 | ACTIVE |
| global.anthropic.claude-fable-5 | ACTIVE |
+------------------------------------+---------+
```
This change removes both models from the EU match arm and routes them
through the global inference profile when no regional profile is
available. US regions continue to use the `us.*` profile. Verified
working from `eu-west-1`.
Note: this means requests from non-US regions route through the global
profile, which may dispatch inference to any supported AWS region.
That's inherent to how AWS exposes these models — there is no
EU-resident option today.
Release Notes:
- Fixed Claude Sonnet 5 and Claude Fable 5 failing on Amazon Bedrock in
non-US regions.
---------
Co-authored-by: Neel <neel@zed.dev>
If one gets a Nightly update but does not restart and rather dismisses
the notification, the next update check will do the update again.
This is caused by the fact that the version check is done based on
semver, but Nightly has the very same version that differs by the SHA
only.
Adjust the Nightly update check to skip re-downloads if SHA parts of the
version match also.
https://github.com/zed-industries/zed/pull/59852 does more changes, this
PR extracts the part I am sure about.
Release Notes:
- N/A
Adds a dylint library under tooling/lints that flags Zed-specific
anti-patterns:
* shared_string_from_str_literal,
* async_block_without_await,
* entity_update_in_render,
* notify_in_render,
* owned_string_into_shared,
* len_in_loop_condition, and
* blocking_io_on_foreground.
Includes UI tests, a single-lint helper, and workspace.metadata.dylint
registration so cargo dylint --all discovers it. The library pins its
own nightly toolchain (kept out of the main workspace) and tracks dylint
6.
Release Notes:
- N/A
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A or Added/Fixed/Improved ...
# Objective
As mentioned in #59514, the git panel currently runs a full `git status`
for checking whether `git` has access to the repository. This was
introduced in #43693 and currently runs on every file save which is
problematic for large repos where `git status` runs a lot of
computation.
## Solution
This PR caches the `git_access` on the git panel such that we don't need
re-check for git access on every file save.
## Testing
I manually verified that the git panel doesn't trigger anymore
unnecessary git status commands.
**main:**
```
2026-06-18T00:04:24+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967643
2026-06-18T00:04:24+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967643
2026-06-18T00:04:24+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967643
2026-06-18T00:04:24+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967643
2026-06-18T00:04:24+01:00 DEBUG [project.format.local] formatting buffer '"/Users/lgeiger/code/zed/CONTRIBUTING.md"'
2026-06-18T00:04:24+01:00 DEBUG [project.format.local] no changes made while formatting
2026-06-18T00:04:24+01:00 DEBUG [git::repository] Checking for git status in ["CONTRIBUTING.md"]
2026-06-18T00:04:25+01:00 DEBUG [git::repository] Checking for git status in []
```
```
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z -- CONTRIBUTING.md
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager diff --numstat --no-renames HEAD -- CONTRIBUTING.md
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager config --get commit.template
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z --
```
**This PR:**
```
2026-06-18T02:47:54+01:00 DEBUG [project::git_store] start recalculating diffs for buffer 4294967656
2026-06-18T02:47:54+01:00 DEBUG [project::git_store] finished recalculating diffs for buffer 4294967656
2026-06-18T02:47:55+01:00 DEBUG [project.format.local] formatting buffer '"/Users/lgeiger/code/zed/CONTRIBUTING.md"'
2026-06-18T02:47:55+01:00 DEBUG [project.format.local] no changes made while formatting
2026-06-18T02:47:55+01:00 DEBUG [git::repository] Checking for git status in ["CONTRIBUTING.md"]
```
```
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager diff --numstat --no-renames HEAD -- CONTRIBUTING.md
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager status --porcelain=v1 --untracked-files=all --no-renames -z -- CONTRIBUTING.md
/opt/homebrew/bin/git -c core.fsmonitor=false -c log.showSignature=false --no-optional-locks --no-pager config --get commit.template
```
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
/cc @dinocosta
---
Release Notes:
- Improved Git Panel performance by no longer re-checking repository
access on every file change
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
# Objective
Fix IME candidate window not following cursor position in the integrated
terminal when running fullscreen TUI applications like opencode.
When using IME (Input Method Editor) in Zed's terminal with fullscreen
TUI applications (e.g., opencode), the candidate window does not follow
the cursor position. This issue does not occur in normal terminal usage
(e.g., bash shell).
# Solution
The root cause was three-layer blocking preventing IME position updates
in ALT_SCREEN mode:
1. **ALT_SCREEN blocking**: `selected_text_range()` returned `None` in
ALT_SCREEN mode, causing `selected_bounds()` to return `None`
2. **Missing trigger**: `Event::Wakeup` did not call
`invalidate_character_coordinates()`, so cursor movement did not trigger
IME position updates
3. **Composition blocking**: `update_ime_position()` skipped updates
when `state.composing` was true
Fixes:
- Remove ALT_SCREEN check in `selected_text_range()` so IME position
updates work in fullscreen TUI apps
- Add `window.invalidate_character_coordinates()` in `Event::Wakeup` to
trigger IME position updates when terminal cursor moves
- Remove `state.composing` check in `update_ime_position()` to allow IME
position updates during text-input-v3 composition
- Remove unused `terminal` field from `TerminalInputHandler` struct
# Testing
**Did you test these changes? If so, how?**
- Yes, tested on Linux GNOME Wayland with iBus input method
- Verified IME candidate window correctly follows cursor in opencode
- Verified normal terminal usage with IME still works correctly
**Are there any parts that need more testing?**
- Other IMEs (fcitx, etc.) may need testing
**How can other people (reviewers) test your changes?**
1. Open Zed's integrated terminal
2. Run a fullscreen TUI application like `opencode`
3. Activate IME (e.g., iBus with Chinese input)
4. Type text and observe the IME candidate window follows the cursor
**What platforms did you test these changes on?**
- Linux (GNOME Wayland) - tested
- macOS - not tested (may have different IME behavior)
- Windows - not tested (different code path)
# Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards (UX/UI and icon
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
# Showcase
<details>
<summary>Before</summary>
<video
src="https://github.com/user-attachments/assets/ee2fac4e-801b-49af-a57e-32ce25e01db5"
width="320" height="180" />
</details>
<details>
<summary>After</summary>
<video
src="https://github.com/user-attachments/assets/c669ea99-2ffc-4179-b587-a47873e33e70"
width="320" height="180" />
</details>
---
Release Notes:
- Fixed IME candidate window not following cursor in terminal TUI apps
I encountered an issue where I couldn't sign in to ChatGPT Subscription
on Windows:
```
ChatGPT subscription sign-in failed to persist credentials:
Failed to write credentials to Windows Credential Manager:
占位程序接收到错误数据。 (0x800706F7)
```
Interestingly, only one of my three ChatGPT accounts had this problem —
the other two signed in successfully.
## What I Found
After investigating, I noticed that the OAuth scope in
`openai_subscribed.rs` requests 6 permissions:
```
openid profile email offline_access api.connectors.read api.connectors.invoke
```
I wrote a test script to measure token sizes and found that:
- With 6 scopes: my problematic account's token was **2578 bytes**
- With 4 scopes (removing `api.connectors.read` and
`api.connectors.invoke`): the same token was **2516 bytes**
Since Windows Credential Manager has a 2560-byte limit
(`CRED_MAX_CREDENTIAL_BLOB_SIZE`), this could explain why some accounts
fail while others succeed — it depends on the base token size.
## My Hypothesis
The issue seems to be that:
- Error code `0x800706F7` = `RPC_X_BAD_STUB_DATA` (size limit, not
format)
- Accounts with larger base tokens exceed the limit when the extra 48
chars are added
- Accounts with smaller base tokens still fit, which is why this isn't
universally reproducible
I'm not 100% certain this is the root cause, but the evidence seems to
point in this direction.
## Proposed Fix
I removed `api.connectors.read` and `api.connectors.invoke` from the
OAuth scope, since:
- These scopes don't appear to be used by Zed's current ChatGPT
integration
- OpenCode (another tool using the same OAuth provider) successfully
uses only 4 scopes
- This fix allowed my problematic account to sign in
However, I'd like to ask the maintainers:
- Are there plans to use OpenAI Connectors API in the future?
- Are there security or compliance reasons for requesting these extra
scopes?
If the answer is yes to either, we'd need a different approach (e.g.,
splitting credentials, using encrypted file storage, or checking token
size before storage).
## Testing
- [x] Verified my problematic account now signs in successfully
- [x] Verified my other accounts still work
- [x] Ran `cargo check -p language_models` (compilation successful)
- [ ] Would appreciate help testing on macOS/Linux
## Questions
1. Does this analysis make sense?
2. Are there any other considerations I'm missing?
3. Would it be helpful to add a size check with a clearer error message
for future cases?
I'm happy to adjust this approach based on your feedback.
Release Notes:
- Fixed ChatGPT Subscription sign-in failing on Windows for some
accounts by removing unused OAuth scopes (`api.connectors.read`,
`api.connectors.invoke`) that pushed JWT tokens over Windows Credential
Manager's limit.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
the jetbrains overlay binds `ctrl-alt-l` (linux) / `cmd-alt-l` (macos)
to `editor::Format` (jetbrains "reformat code"), which collides with the
default `agent::OpenRulesLibrary` binding. the agent panel shows the
conflicting key as the rules tooltip but pressing it formats the buffer
instead of opening rules. mirrors the windows keymap by switching the
linux/macos overlays to `shift-alt-l` in the AgentPanel context (with
the colliding key explicitly null-ed), so the hint and the action stay
in sync.
closes#49764.
Release Notes:
- Fixed the JetBrains keymap so the agent panel "Rules" entry uses
`shift-alt-l` and no longer flickers a non-functional `ctrl-alt-l` /
`cmd-alt-l` shortcut.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#56189
Release Notes:
- Fixed bug to handle dev container Dockerfiles with chained aliases
---------
Co-authored-by: Martin Ye <martin@zed.dev>
MCP servers may accept `initialize` unauthenticated but return `401`
with a `WWW-Authenticate` challenge only on a later request such as
`tools/list` or `tools/call`. Previously Zed only started the Auth flow
when `initialize` itself was challenged, so these servers failed
opaquely and stayed stuck in `Running` with a dead client.
`ContextServerStore` now handles `TransportError::AuthRequired` returned
from any request, not just startup: it runs Auth discovery and
transitions the server into `AuthRequired` so the UI offers to
authenticate. The discovery logic is shared with the startup path, and
the tool/prompt request sites route their errors through it.
Release Notes:
- Fixed MCP servers that require auth only on tool calls (not on
`initialize`) failing to prompt for authentication.
---------
Co-authored-by: Tom Houlé <tom@tomhoule.com>
Renders the per-file added/removed line counts (already tracked per
buffer by the multibuffer) in each diff multibuffer header, matching the
overall stat shown in the branch diff toolbar.
### Before
<img width="1624" height="1061" alt="Screenshot 2026-07-02 at 11 50 42
AM"
src="https://github.com/user-attachments/assets/3e46a90c-a4e1-4b72-8ec9-80931a7e4a9a"
/>
### After
<img width="1624" height="1061" alt="Screenshot 2026-07-02 at 12 03 58
PM"
src="https://github.com/user-attachments/assets/25900790-82f5-44e9-9a3b-731a3090f23e"
/>
Release Notes:
- Improved diff multibuffer headers to show per-file added/removed line
counts
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
When prompt caching is enabled, `into_bedrock` pushes a `CachePoint`
block
onto a message's content whenever `message.cache && supports_caching` is
true.
This push happens before the `if bedrock_message_content.is_empty() {
continue; }`
guard. As a result, a message whose content filters down to empty (for
example,
a message that contained only content stripped during conversion) still
gets
appended to the request carrying nothing but a `cachePoint`. Bedrock
rejects such
a message with a `ValidationException`, breaking the whole request.
The Anthropic path is already internally consistent here: in
`crates/language_models/src/provider/anthropic.rs` (around the message
assembly
in `completion.rs`) the empty-content check runs first, so an empty
message is
dropped before any cache marker is attached. The Bedrock path should
behave the
same way.
This change gates the `CachePoint` push on non-empty content
(`&& !bedrock_message_content.is_empty()`), so an empty message is left
empty and
then skipped by the existing `continue`, exactly mirroring the Anthropic
ordering.
The fix is minimal and touches only the cache-point condition.
Release Notes:
- Fixed Bedrock requests failing with ValidationException when the last
message filtered to empty content while prompt caching was enabled.
---------
Signed-off-by: Yi LIU <yi@quantstamp.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Also orders the Claude models from most to least capable.
Release Notes:
- Added Sonnet 5 to Bedrock provider
Co-authored-by: David Irvine <aviddiviner@gmail.com>