This PR adds a button in the Git Panel to open the `git: branch diff`
view. The button only shows if the staging area is clean/no changes and
if the branch is not main/master. I've been using this action so much
these days and we should expose it on the UI so it's more discoverable.
<img width="500" height="1736" alt="Screenshot 2026-02-16 at 6 30@2x"
src="https://github.com/user-attachments/assets/0b037811-2167-419f-b63f-9bdb12e4352e"
/>
Release Notes:
- N/A
This change improves performance of project diff in that:
* scrolling in split view for very large diffs (think chromium repo with
`git reset HEAD~1000`) is now very smooth on macOS and fairly smooth on
Linux
* switching from split to unified is very smooth on macOS, and fairly
smooth on Linux
There still remains the case of (severe) hangs when switching from
unified to split however, but it will be addressed in a follow-up PR.
Anyhow, here's the screenshot of the Instruments.app capture of opening
chromium repo in Zed in split view, scrolling a little, moving to
unified, scrolling some more, and moving back to split. Prior to this
change, split -> unified would cause a severe hang, whereas now it's a
hang and thus feels much smoother already (without Instruments profiling
is barely visible). Unified -> split severe hangs are still there but
don't last as long.
<img width="2301" height="374" alt="Screenshot 2026-02-16 at 5 46 23 PM"
src="https://github.com/user-attachments/assets/f687f8d4-cffd-47f1-ada1-f6c4d3ac3cd4"
/>
Release Notes:
- Improved project diff performance when opening very large
diffs/repositories.
Release Notes:
- Added agent panel restoration. Now restarting your editor won't cause
your thread to be forgotten.
---------
Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
Co-authored-by: Eric Holk <eric@zed.dev>
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Cameron Mcloughlin <cameron.studdstreet@gmail.com>
- Fix panics caused by reusing cached matches for the wrong side
- Highlight matches on the side that was searched only
- Clear matches in non-searched editor when initiating a new search
Release Notes:
- N/A
---------
Co-authored-by: Eric <eric@zed.dev>
Co-authored-by: Jakub <jakub@zed.dev>
Ensure that `git_ui::stash_picker::StashList.handle_show_toast` emits a
`DismissEvent` so that, when the user confirms they wish to view a stash
entry, the modal is actually dismissed and does not block the user's
view.
Release Notes:
- Fixed issue where viewing a stash entry would not dismiss the modal
It's happeningggggg
Release Notes:
- Changed the Agent Panel so that the Active Thread is restored on
restart.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Co-authored-by: Richard Feldman <richard@zed.dev>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Searching (and related vim stuff like `*`/`n`/`N`) now work in the LHS
of a
split diff.
Also fixes the bug with indent guides being visible through the spacer
checkerboard pattern.
Release Notes:
- N/A
Currently we always compute breadcrumbs and sticky headers on every
editor paint which is not cheap to do especially in bigger files, moving
this off to be computed on event handling where they change and then
caching them can save serveral milliseconds per render in bigger files.
This also puts matching brackets refreshing and document highlights on a
background task, as this tends to block the main task for prolonged time
as well.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Closes#48195
Filter out `remote_info` when viewing stashes by adding `.filter(|_|
self.stash.is_none())`.
Release Notes:
- Fixed "View on GitHub" button incorrectly appearing when viewing
stashes
The indent guide computation was using visible list indices directly to
access entries, instead of mapping through `logical_indices` first. This
caused incorrect depths to be read from hidden entries when a folder was
collapsed, resulting in stray vertical lines extending to unrelated folders.
Closes#48189
Release Notes:
- Fixed a visual bug in the Git Panel where collapsing a folder in tree
view would cause indent guide lines to incorrectly extend to unrelated
folders below it.
GitHub's commit API endpoint is rate limited to 60 requests/hour for
unauthenticated users. This causes avatar loading to fail after toggling
blame a few times.
This PR uses GitHub's CDN avatar endpoint
`https://avatars.githubusercontent.com/u/e?email={email}&s=128` instead,
which doesn't count against API rate limits. The author email is already
available from local git data (blame output), so
no API calls are needed.
- When author email is available, constructs the CDN URL directly (zero
API calls)
- Falls back to existing API-based behavior when email is unavailable
- Adds unit tests for URL construction
Closes#47590
## Test plan
- [x] `./script/clippy` passes
- [x] `cargo test -p git_hosting_providers` passes (89 tests including 3
new ones i added)
- [ ] Manual test: Open a file, toggle git blame, verify avatars load
without hitting rate limits
Release Notes:
- Fixed GitHub avatar rate limiting in git blame by using CDN endpoint
instead of API calls (#47590)
This branch:
1. teaches `--diff `command line option to to recurse into folders if
provided.
2. Adds a `MultiDiffView` that shows _all_ changed files in a single,
scrollable view.
This is necessary to provide a smooth user experience for `jj` and Zed
users who wish to use Zed as their jj difftool.
I'm not fully sure how this change interacts with
https://github.com/zed-industries/zed/pull/44936, or what plans y'all
have in mind.
Here's a screenshot of the resulting behavior:
<img width="1090" height="950" alt="Screenshot 2025-12-17 at 9 10 52 AM"
src="https://github.com/user-attachments/assets/8efd09b4-974f-4059-9f94-539c484c6d4a"
/>
I setup zed to handle jj diffs by adding the following to my jj config:
```toml
[aliases]
zdiff = ["diff", "--tool", "zed"]
[merge-tools.zed]
program = "/Users/dbarsky/Developer/zed/target/debug/cli"
# omit diff-invocation-mode to keep the default (JJ passes two dirs)
diff-args = [
"--zed", "/Users/dbarsky/Developer/zed/target/debug/zed",
"--wait",
"--new",
"--diff",
"$left",
"$right",
]
```
Release Notes:
- `--diff`, if provided with folders instead of files, will recurse into
those directories.
- Added a `MultiDiffView`, which will show all changed files within a
single, scrollable view.
**AI Disclosure**: Pretty much all of this code was written using Codex
with GPT-5.1-Codex. I edited by hand and tested this.
---------
Co-authored-by: Lukas Wirth <lukas@zed.dev>
We were using primary/secondary in some places which is just
unnecessarily confusing.
Release Notes:
- N/A
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Basically just replaced `SharedString::new("` with
`SharedShring::new_static("` which removes the allocation to `Arc<str>`.
Unfortunately this can't be enforced at compile time without trait
specialization which is only available on nightly. You could assert that
`TypeId`'s differ, but `TypeId` only exists at runtime.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
When working in a workspace with multiple repositories, the git panel
provides a repository picker to switch between them. However, there was
no visual indication of which repositories have uncommitted changes:
users had to either select each repository individually or check the
project panel where modified directories are highlighted.
This change adds git status icons to the repository picker, allowing
users to see at a glance which repositories contain changes (modified,
added, deleted, or conflicted files). The icons use the same visual
language already established for file status throughout the git panel.
Additionally, the repository picker now matches the branch picker's
styling for visual consistency:
- Added "Repositories" header
- Aligned popover width and positioning
- Added scrollbar
- Added check icon next to currently selected repo
- Added selected branch under repo list item
- Sort by display name is now case insensitive
Before:
<img width="1200" height="815" alt="Screenshot 2026-01-27 at 11 43 55"
src="https://github.com/user-attachments/assets/12c1008b-4724-44bf-80c9-e9ad97755090"
/>
After:
<img width="1761" height="1196" alt="Screenshot 2026-01-27 at 14 07 52"
src="https://github.com/user-attachments/assets/cd778f42-ade0-4da0-9732-2d8631c04124"
/>
Branch picker for style reference:
<img width="1200" height="815" alt="Screenshot 2026-01-27 at 11 44 03"
src="https://github.com/user-attachments/assets/369b0d29-8fed-4293-98c2-52c2d780fe9a"
/>
Release Notes:
- Git: Improved the project picker in the panel by also displaying the
GIt status icon on them, to clearly indicate which repos have changes.
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
- **title_bar: Extract platform_title_bar from title_bar**
- **file_finder no longer depends on search and agent_servers no longer
depend on language_models**
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
The rate limiter's semaphore guard was being held for the entire
duration of a turn, including during tool execution. This caused
deadlocks when subagents tried to acquire permits while parent requests
were waiting for them to complete.
## The Problem
In `run_turn_internal`, the stream (which contains the `RateLimitGuard`
holding the semaphore permit) was kept alive throughout the entire loop
iteration - including during **tool execution**:
1. Parent request acquires permit
2. Parent starts streaming, consumes response
3. Parent starts executing tools (subagents)
4. **Stream/guard still held** while tools execute
5. Subagents try to acquire permits → blocked because parent still holds
permit
6. Deadlock if all permits are held by parents waiting for subagent
children
## The Fix
Two changes were made:
1. **Drop the stream early**: Added an explicit `drop(events)` after the
stream is fully consumed but before tool execution begins. This releases
the rate limit permit so subagents can acquire it.
2. **Removed the `bypass_rate_limit` workaround**: Since the root cause
is now fixed, the bypass mechanism is no longer needed.
Note: no release notes because subagents are still feature-flagged, and
this rate limiting change isn't actually observable without them.
Release Notes:
- N/A
This PR implements a UI for the side-by-side diff, using blocks to align
the two sides and adding a coherent `SplitEditorElement`.
Release Notes:
- N/A
---------
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR improves the performance of the `CopyButton` component by
tracking the copied state locally through a `CopyButtonState` struct
instead of making an OS call every time the component re-renders. Also
pushing a slight improvement here by resetting the state after two
seconds so as to make the check mark go away after you clicked to copy.
Release Notes:
- N/A
## Problem
When subagents use the `edit_file` tool, it creates an `EditAgent` that
makes its own model request to get the edit instructions. These "nested"
requests compete with the parent subagent conversation requests for rate
limiter permits.
The rate limiter uses a semaphore with a limit of 4 concurrent requests
per model instance. When multiple subagents run in parallel:
1. 3 subagents each hold 1 permit for their ongoing conversation streams
(3 permits used)
2. When all 3 try to use `edit_file` simultaneously, their edit agents
need permits too
3. Only 1 edit agent can get the 4th permit; the other 2 block waiting
4. The blocked edit agents can't complete, so their parent subagent
conversations can't complete
5. The parent conversations hold their permits, so the blocked edit
agents stay blocked
6. **Deadlock**
## Solution
Added a `bypass_rate_limit` field to `LanguageModelRequest`. When set to
`true`, the request skips the rate limiter semaphore entirely. The
`EditAgent` sets this flag because its requests are already "part of" a
rate-limited parent request.
(No release notes because subagents are still feature-flagged.)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
The recently-introduced unified Git picker was previously only available
if you reached for the branch, worktree or stash pickers through the
keybinding. Now, if you click on the title bar's branch button, you'll
also be able to quickly view the worktree and stash pickers.
Release Notes:
- N/A
While at it, annotate more functions that are potentially related to
language parsing in buffers.
Also, on macOS, in order to actually have callstack frames properly
recorded by Tracy, you need to manually run `dsymutil` on the binary.
Release Notes:
- N/A
<img width="611" height="102" alt="Screenshot 2026-01-15 at 4 18 30 PM"
src="https://github.com/user-attachments/assets/ba422cbb-4607-47c7-94c7-77752d7b4479"
/>
When viewing a branch diff (e.g., 'Changes since origin/main'), the
toolbar was hidden because `ProjectDiffToolbar` filters for
`DiffBase::Head` only. This meant users couldn't send review comments to
the Agent panel from the branch diff view.
Now there's a new `BranchDiffToolbar` which:
- Only activates for branch diff views (`DiffBase::Merge`)
- Shows only the 'Send Review to Agent' button (not stage/unstage
controls)
- Only appears when there are review comments (same behavior as the
existing toolbar)
(No release notes because this is still feature-flagged.)
Release Notes:
- N/A
This PR removes the code for the legacy plans.
No more users will be on this plan as of January 17th, so it's fine to
land these changes now (as they won't be released until the 21st).
Closes CLO-76.
Release Notes:
- N/A
Happy New Years! This PR is a second take at
https://github.com/zed-industries/zed/pull/38127 (cc @ConradIrwin)
This PR is significantly less complicated than the last attempt: while
we still keep our data on the `NavigationHistory` object, we no longer
tightly integrate it with the existing back/forward "browser history."
Instead, we keep our own stack of `(origin, target)` pairs (in a struct
to make it easy to extend with e.g., tag names in the future).
The PR is split into two separable commits. Most of the implementation
is in the second commit, which:
- Defines the stack data structure
- Implements `pane::GoToOlderTag` and `pane::GoToNewerTag` in terms of
the stack
- Hooks into `navigate_to_hover_links` to push tag stack entries
This last bit is the most fiddly. The core challenge is that we need to
keep track of the `origin` location and calculate the `target` location
across three codepaths that might involve creating a new editor and/or
splitting the pane. One thing in particular I found difficult was that
an editor's `nav_history` (an `ItemNavHistory`) seems to be populated
asynchronously. Instead of relying on it, I decided in this code to make
my own `ItemNavHistory`. I briefly tried to refactor the code in
question, but it seemed like it would significantly increase the scope
of the change.
I prefer this all-in-one tracking centered around
`navigate_to_hover_links ` to the `start/finish` approach taken in
b69a2ea200
because I find it easier to convince myself that the right data is being
populated at the right times. Of course, let me know if you think
there's a better solution.
Closes#14206
Release Notes:
- ??? I don't know what to write here! Suggestions welcome
Closes#46142
Release Notes:
- Fixed AI commit message button in Git panel being hidden instead of
disabled when no AI provider is configured. The button now remains
visible with a tooltip explaining how to enable the feature.
Screenshot:
<img width="90%" alt="Screenshot 2026-01-10 at 18 16 12"
src="https://github.com/user-attachments/assets/6af9c845-7857-40e1-bfb5-3118f1af8360"
/>
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Doesn't support editing or deleting comments yet, but inputs work:
<img width="797" height="881" alt="Screenshot 2026-01-14 at 11 51 36 AM"
src="https://github.com/user-attachments/assets/746e085b-a919-475a-b804-ee0377e40a0b"
/>
<img width="698" height="178" alt="Screenshot 2026-01-14 at 11 47 51 AM"
src="https://github.com/user-attachments/assets/3edac0e8-62e5-4af5-a324-df2bd293f3ca"
/>
<img width="695" height="695" alt="Screenshot 2026-01-14 at 11 47 58 AM"
src="https://github.com/user-attachments/assets/64795ffd-62b4-48ea-a46c-7724221095d7"
/>
### Features implemented:
- **Local comment storage**: Comments are stored per-hunk in the Editor,
with chronological ordering
- **Expandable comments section**: Shows "N Comments" header that can
expand/collapse
- **Inline editing**: Click edit to transform a comment row into an
editable text field with confirm/cancel buttons
- **Delete functionality**: Remove individual comments
- **Send Review to Agent**: Toolbar button with badge showing comment
count, batch-submits all comments across all files/hunks to the Agent
panel
- **User avatars**: Shows the current user's avatar (from their Zed
account) next to comments, falls back to Person icon when not logged in
- **Visual tests**: Added tests for one comment, multiple comments
expanded, and comments collapsed
Note that this is behind a feature flag, so no release notes yet.
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: David Baldwin <baldwindavid@gmail.com>
This PR introduces a project dropdown when working with multiple
folders/projects in one workspace. Here are some interaction details
that I hope improves the UX of working on this scenario significantly:
- The dropdown shows the currently "active" project, which is determined
by:
- Either the file you're currently editing
- Or the file you have just recently switched to
- Some example cases:
- If you are focused on file from project A but switch to project B in
the titlebar, nothing happens. However, as soon as you type on the file
from project A, the title bar will update and your active project will
return to being project A.
- If you're focused on file from project A and change tabs to a file
from project B, the title bar will update, showing project B as the
active one.
- The content you'll see in the branch picker will correspond to the
currently active project
- It's still possible to reach the "Recent Projects" picker through the
project dropdown
- It's possible to do all interactions (trigger dropdown, select active
project, and remove project from workspace) with the keyboard
https://github.com/user-attachments/assets/e2346757-74df-47c5-bf4d-6354623b6f47
Note that this entire UX is valid only for a multiple folder workspace
scenario; nothing changes for the single project case.
Release Notes:
- Workspace: Improved the UX of working with multiple projects in the
same workspace through introducing a project dropdown that more clearly
shows the currently active project as well as allowing you to change it.
Adds a very simple diff review button behind a feature flag, which
appears in the gutter of people who have the flag (currently just me;
it's not even enabled for staff, since it doesn't do anything yet).
Mostly this PR just adds the feature flag, the button, and tests.
Release Notes:
- N/A