a30bc61
Delete worktree directory before git metadata cleanup during archive (#53959)
Click to expand commit body
When archiving a thread's linked worktree, `git worktree remove` can
fail to delete the working directory while still removing the admin
metadata in `.git/worktrees/<name>`. This leaves an orphaned folder on
disk that no longer appears in `git worktree list`.
## Fix
Delete the directory ourselves first with `std::fs::remove_dir_all`,
then call `git worktree remove --force` to clean up only the admin
entry. Git already handles the case where the working tree is already
gone (since
[git/git@ee6763a](https://github.com/git/git/commit/ee6763af0a3b97225803c6c908a29de40336cf38)).
Also fixes `FakeGitRepository::remove_worktree` to handle a missing
working tree directory (matching real git behavior) by scanning
`.git/worktrees/` entries when the `.git` pointer file can't be read.
Release Notes:
- Fixed archiving an agent thread sometimes leaving the worktree folder
on disk even though the git worktree was removed.
Richard Feldman
created
848c3da
docs: Fix stale MCP extension links (#53946)
Click to expand commit body
This fixes #53740.
A few MCP docs links were still pointing at old extension slugs, so they
led to dead pages. This updates those links to the current canonical
slugs.
Release Notes:
- N/A
Hamza Paracha
created
ad5d015
cli: Fix -n behavior and refactor open options (#53939)
Click to expand commit body
This fixes a regression where `zed -n .` in a subdirectory of an
already-open
project would redirect to the parent window instead of creating a new
one.
The root cause was that commit 66d2cb20c9 ("Adjust `zed -n` behavior")
made
`-n` run the worktree matching loop with subdirectory matching enabled,
when
previously `-n` skipped matching entirely.
## Changes
### Bug fix
- **Restore `-n` to always create a new window.** No worktree matching,
no
exceptions. This matches the behavior from when `-n` was first
introduced.
### New `--classic` flag
- Adds a hidden `--classic` CLI flag that explicitly selects the
pre-sidebar
default behavior: new window for directories, reuse existing window for
files already in an open worktree.
- The `cli_default_open_behavior` setting now toggles between `-e` (add
to
sidebar) and `--classic` behavior. When set to `new_window`, the classic
logic is used instead of unconditionally opening a new window.
### Refactor CLI open options
Replaces the old grab-bag of `open_new_workspace: Option<bool>`,
`force_existing_window: bool`, `classic: bool`, and `reuse: bool` with:
- **`cli::CliOpenBehavior` enum** β a single enum on the IPC boundary
with
variants `Default`, `AlwaysNew`, `Add`, `ExistingWindow`, `Classic`, and
`Reuse`.
- **`workspace::WorkspaceMatching` enum** β describes how to match paths
against existing worktrees (`None`, `MatchExact`, `MatchSubdirectory`).
- **`workspace::OpenOptions`** β uses `WorkspaceMatching` plus a simple
`add_dirs_to_sidebar: bool` instead of overlapping boolean flags.
The translation from CLI enum to workspace options happens in
`open_listener.rs`, keeping both layers clean and independent.
Release Notes:
- N/A
Eric Holk
created
dc5e2f1
sidebar: Show branch name after worktree name (#53900)
Click to expand commit body
<img width="297" height="505" alt="Screenshot 2026-04-14 at 3 20 23β―PM"
src="https://github.com/user-attachments/assets/90366ccd-86db-497e-9c81-af94b4144ebe"
/>
Display the git branch name alongside the worktree name in the sidebar's
thread list (or without the worktree name, if it's a main worktree).
Release Notes:
- Added branch name display next to worktree names in the agent sidebar
thread list.
Richard Feldman
created
6beecae
agent_ui: Improve the new thread worktree UX (#53941)
Click to expand commit body
Closes https://github.com/zed-industries/zed/issues/53262
- Remove the ability to pick a branch from the agent panel; delegate
this to the title bar picker
- Make the worktree creation earger, just as you selected whether you
want to create it from main or current branch
- Remove flicker when creating a new worktree and switching to a
previously existing one
- Improve some UI stuff: how we display that a worktree is
creating/loading, the branch and worktree icons, etc.
- Fixed a bug where worktrees in a detached HEAD state wouldn't show up
in the worktree pickers
A big part of the diff of this PR is the removal of everything involved
with the `StartThreadIn` enum/the set up involved in only creating the
worktree by the time of the first prompt send.
Release Notes:
- Agent: Improved and simplified the UX of creating threads in Git
worktrees.
- Git: Fixed a bug where worktrees in a detached HEAD state wouldn't
show up in the worktree picker.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Danilo Leal
and
Nathan Sobo
created
6467d4f
Improve error handling in worktree restore and archive paths (#53927)
Click to expand commit body
Improves the worktree restore and archive code paths:
- In `restore_worktree_via_git`, the old code blindly attempted
`change_branch` and fell back to `create_branch` on failure, which could
clobber a branch that had moved to a different SHA during archival. Now
resolves the branch ref first and only checks out the branch if it still
points at the original commit; if the branch has moved, the worktree
stays in detached HEAD. If the branch doesn't exist, tries to recreate
it.
- In `change_worktree_paths` and `change_worktree_paths_by_main`,
archived threads are now excluded from path mutations so their folder
paths are preserved for restore.
- In the sidebar, `ProjectGroupKey` construction for archived thread
activation now uses `from_worktree_paths` (which resolves to main
worktree paths) instead of `new` with the linked worktree's folder
paths. This ensures that restoring a linked worktree thread matches the
main repo workspace rather than creating a spurious new one.
- Added `Repository::resolve_ref` for resolving a git ref to its SHA.
- Added tests for `resolve_ref`, branch-moved/not-moved/deleted restore
scenarios, and workspace-matching on restore.
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
---------
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
Conrad Irwin
and
Kunall Banerjee
created
f49d932
sidebar: Simplify project group menu (#53933)
Click to expand commit body
Remove the ability to add and remove individual folders from project
groups in the sidebar.
## Changes
**Sidebar project group menu:**
- When there are 2+ local project groups, the ellipsis menu shows "Open
Project in New Window" and "Remove Project" (no separators, no folder
listing)
- When there's only one group or it's remote, the ellipsis menu is
replaced with a close X button that removes the project directly
**Project picker labels:**
- "Open Local Project" β "Open Local Folders"
- "Open Remote Project" β "Open Remote Folder"
- "Add Local Project" β "Add Local Folders"
- "Add Remote Project" β "Add Remote Folder"
**Dead code removal:**
- `MultiWorkspace::remove_folder_from_project_group`
- `MultiWorkspace::prompt_to_add_folders_to_project_group`
- `MultiWorkspace::add_folders_to_project_group`
- `MultiWorkspace::update_project_group_key`
- `MultiWorkspaceEvent::ProjectGroupKeyUpdated`
- `Sidebar::move_threads_for_key_change`
- `ThreadMetadataStore::change_worktree_paths_by_main`
- Associated tests for removed functionality
Per-workspace thread regrouping (when a workspace's worktree paths
change) continues to work via the existing `WorktreePathsChanged` β
`move_thread_paths` flow. The existing
`test_worktree_add_only_regroups_threads_for_changed_workspace` test
(renamed and strengthened) verifies that only the changed workspace's
threads are regrouped, while sibling worktree threads remain in their
original group.
Release Notes:
- Improved sidebar project group menu to show a simple close button for
single-project windows and a streamlined two-item menu for multi-project
windows.
Nathan Sobo
created
5611cc2
compliance: Fix casing of GitHub in structs and traits (#53935)
Click to expand commit body
Release Notes:
- N/A
Finn Evers
created
a750316
acp: Initial support for ACP usage (#53894)
Click to expand commit body
Adds initial beta test of ACP usage stats. Behind a flag for now while
we work on standardizing the usage values.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Ben Brandt
created
d367d3f
compliance: Make trait more flexible (#53914)
Click to expand commit body
This will make this easier to use with the GitHub worker.
Release Notes:
- N/A
Finn Evers
created
652f1fa
git: Fix a race that caused incorrect hunk staging information (#53929)
Click to expand commit body
In `GitStore::open_diff_internal`, when opening a `DiffKind::Unstaged`
diff, we previously always overwrote the `unstaged_diff` field of
`BufferGitState`. This causes a bug in the following situation:
- We call `open_unstaged_diff`, and it hits an await point where it is
loading the index text
- While that task is suspended, we call `open_uncommitted_diff`. It
reaches `open_diff_internal` and sets
`buffer_git_state.uncommitted_diff` and
`buffer_git_state.unstaged_diff`. It also sets the secondary diff for
the uncommitted diff to be the unstaged diff that it just opened.
- The `open_unstaged_diff` task wakes up and enters
`open_diff_internal`. It creates a new entity for the unstaged diff and
overwrites `buffer_git_state.unstaged_diff` with it, but it doesn't
update the secondary diff of the uncommitted diff, which still has the
entity that was produced in the previous step.
- Now the uncommitted diff's secondary diff will never receive updates
from the `GitStore`, causing staging information to be incorrect.
The fix is for `open_diff_internal` to not overwrite an existing
unstaged diff.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed a bug that could cause diff hunks to have an incorrect staged
status.
Cole Miller
created
5d15e01
Route open_thread through load_agent_thread to prevent duplicate sessions (#53859)
Click to expand commit body
`AgentPanel::open_thread` (called when clicking `@thread` mention links,
pasting thread links, or opening threads via the CLI) was calling
`external_thread` directly, bypassing the de-duplication guards in
`load_agent_thread`. This meant clicking a thread link to the
currently-active thread would create a redundant `ConversationView`
sharing the same `NativeAgent` session. When the old CV was later
evicted from `background_threads`, its `on_release` called
`close_all_sessions`, removing the session and breaking the surviving CV
with "Session not found".
Fix this by routing `open_thread` through `load_agent_thread`, which
checks the active view, retained threads, and background threads before
creating a new `ConversationView`. This prevents the duplicate from
being created in the first place.
Release Notes:
- Fixed a "Session not found" error that could occur after clicking a
thread mention link.
Richard Feldman
created
bf0fcfb
Preserve archived thread project paths after worktree removal (#53893)
Click to expand commit body
When a thread created in a git worktree is archived, the archive flow
removes the linked worktree from the project. If a subsequent thread
event fires after this (e.g. an async title-generation task completing),
`handle_thread_event` recalculates `worktree_paths` from the project's
current state β which no longer includes the removed worktree β and
overwrites the archived thread's stored paths with empty ones.
This causes restoring the thread to prompt the user to re-associate a
project, instead of restoring it directly.
**Fix:** return early from `handle_thread_event` when the thread is
already archived, so the stored paths are never overwritten.
Release Notes:
- Fixed archived threads in git worktrees losing their project
association.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Mikayla Maki
created
0bbe9bf
sidebar: Filter thread groups by remote host identity (#53918)
Click to expand commit body
### Summary
Follow up on: https://github.com/zed-industries/zed/pull/53550
Threads in the sidebar are now filtered by remote connection in addition
to path list. Previously, two different machines with the same absolute
project paths (e.g. both at `/home/user/project`) would have their
threads merged into a single sidebar group. Now each remote host gets
its own group.
To support this, this PR introduces `RemoteConnectionIdentity`, a
normalized subset of `RemoteConnectionOptions` that includes only the
fields relevant for identity matching (e.g. SSH host + username + port,
but not nickname or connection timeout). All remote host comparisons in
the sidebar, thread metadata store, and workspace persistence now go
through `same_remote_connection_identity()` instead of raw `==` on
`RemoteConnectionOptions`.
#### Follow Up on remoting for sidebar
1. Make the neighbor in archive thread fallback to the main git worktree
instead of the next thread
2. Start implementing remote git operations that archive feature depends
on
3. Make remote connection pool equality use `RemoteConnectionIdentity`
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Anthony Eid
,
Max Brunsfeld
, and
Richard Feldman
created
bb59cac
cli: Hide -r/--reuse from --help in favor of -e/--existing (#53924)
Click to expand commit body
Soft-deprecates the `-r`/`--reuse` CLI flag by hiding it from `--help`
output. The flag remains fully functional for backward compatibility,
but new users will discover `-e`/`--existing` instead.
The change is a single `hide = true` addition to the clap arg attribute.
Release Notes:
- N/A
Eric Holk
created
edac6a7
Move edit prediction metrics into shared crate (#53912)
Click to expand commit body
Release Notes:
- N/A
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Oleksiy Syvokon
and
Ben Kunkle
created
a33a1eb
agent_ui: Reuse visible sessions when reopening threads (#53905)
Click to expand commit body
When reopening a thread that is already visible in the agent panel,
`open_thread` could recreate the session instead of reusing the existing
visible thread. That left the UI holding a thread whose backend session
could be closed out from under it.
This change routes `AgentPanel::open_thread` through
`load_agent_thread`, which already handles the right behavior for
existing sessions:
- reuse the active thread when it already matches
- promote a retained thread when it matches
- only load when the session is not already present
The regression coverage is now a focused behavioral test at the
`AgentPanel::open_thread` boundary that verifies reopening an
already-visible session keeps the thread usable.
cc @bennetbo
Release Notes:
- Fixed reopening an already-visible agent thread so it reuses the
existing session instead of creating a broken duplicate.
Nathan Sobo
created
1bc0e23
sidebar: Add adjustments to project header (#53891)
Click to expand commit body
- Change design a bit so that the separation between projects is clearer
- Add ability to cmd-click to focus most recent workspace
- Make hover and collapse/expand interactions unconditional, enabled by
adding a "No threads yet" empty state
- Improved keyboard nav by making cmd-n create a new thread in the
currently focused group
https://github.com/user-attachments/assets/e9cde153-d3f1-4945-9e45-db1597637a44
Release Notes:
- Agent: Improved the threads sidebar header by making the separation
between projects more distinct.
Danilo Leal
created
11edacf
cli: Defer app activation until after open-behavior prompt (#53915)
Click to expand commit body
On macOS, the CLI uses `LSOpenFromURLSpec` to deliver the `zed-cli://`
URL to the running Zed app. With `kLSLaunchDefaults`, Launch Services
activates (brings to foreground) the Zed app as a side effect of URL
delivery. This happens before the IPC handshake completes and before the
user can answer the terminal prompt asking whether to open in a new
window or existing workspace, forcing them to manually switch back to
the terminal.
## Fix
**CLI side** (`crates/cli/src/main.rs`): Add `kLSLaunchDontSwitch` to
the launch flags so macOS delivers the URL without activating the app.
**App side** (`crates/zed/src/zed/open_listener.rs`): Add
`cx.activate(true)` in `handle_cli_connection` after the prompt resolves
(or immediately for the URL-only path), so the app comes to the
foreground at the right time.
Linux and Windows are unaffected β they use Unix sockets and named pipes
respectively, which don't have activation side effects.
Release Notes:
- Fixed the Zed CLI activating the app window before the user answers
the open-behavior prompt in the terminal.
Eric Holk
created
c8b3da6
recent_projects: Fix clipping branch and project name (#53906)
Click to expand commit body
Just fixing an issue where the project and branch labels weren't
truncating in the project popover.
<img width="600" height="1054" alt="Screenshot 2026-04-14 at 11β― 49@2x"
src="https://github.com/user-attachments/assets/eefa5027-34cd-41da-9590-cb12a89cdb51"
/>
Release Notes:
- N/A
Danilo Leal
created
eed33ab
sidebar: Fallback to main git worktree path when opening thread in deleted git worktree (#53899)
Click to expand commit body
### Summary
This PR is the first step in improving Zed's error handling when a user
opens an old thread that's associated with a deleted git worktree.
Before, the thread would open in an empty project with a broken state.
This PR instead opens the thread in the workspace associated with the
threadβs main git worktree when available.
### Follow ups
1. Implement remote support for this fallback
2. Update `ThreadMetadataStore` database to set paths from deleted
worktree to the main worktree
3. If the main git worktree is deleted as well, fallback to the
currently active workspace
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 #ISSUE
Release Notes:
- N/A
Anthony Eid
created
101083e
gpui_tokio: Use shutdown_background to avoid WASI panic on exit (#53904)
Click to expand commit body
When the Tokio runtime is dropped during Zed shutdown, it drives all
spawned tasks to cancellation by polling them one last time. The
`wasmtime-wasi` crate wraps child task `JoinHandle`s in an
`AbortOnDropJoinHandle` whose `Future::poll` calls `.expect("child task
panicked")` on the join result β but Tokio can also return
`JoinError::Cancelled` (not just panics), causing the expect to panic
with:
```
child task panicked: JoinError::Cancelled(Id(45))
```
This showed up as Sentry issue ZED-69A (106 events, 85 users, 100%
Windows, stable channel).
The fix is to explicitly call `shutdown_background()` on the owned Tokio
runtime during `GlobalTokio::drop`, which immediately drops all spawned
tasks without polling them again, avoiding the wasmtime-wasi panic path
entirely.
Release Notes:
- Fixed a crash on exit caused by the Tokio runtime shutdown triggering
a panic in extension WASI tasks (Windows).
Richard Feldman
created
da6ac6c
workspace: Add separate "format and save" action (#53710)
Click to expand commit body
Release Notes:
- Added `workspace: format and save` action which always formats,
regardless of settings
Cameron Mcloughlin
created
01fb476
client: Don't override organization plans with personal plan (#53842)
Click to expand commit body
This PR makes it so we don't override organization plans with the user's
personal plan.
If an organization is selected and does not have a plan, we want to
return `None` for the plan.
Closes CLO-655.
Release Notes:
- N/A
Closes #30644
Many X11 environments expect a window icon to be supplied [as pixel data
on a window property
`_NET_WM_ICON`](https://specifications.freedesktop.org/wm-spec/1.4/ar01s05.html#id-1.6.13).
I confirmed this change fixes the icon in xfce4 for me, I think its
likely it also fixes https://github.com/zed-industries/zed/issues/37961
but I haven't tested it.
## Questions
* [`image::RgbaImage` is exposed to the public API of
gpui](https://github.com/zed-industries/zed/pull/40096/files#diff-318f166d72ad9476bd0a116446f5db3897fc1a4eb1d49aaf8105608bcf49ea53R1136).
I would guess this is undesirable, but I wasn't sure of the best way to
use gpui's native `Image` type..
* Currently [the icon is embedded into the
binary](https://github.com/zed-industries/zed/pull/40096/files#diff-89af0b4072205c53b518aa977d6be48997e1a51fa4dbf06c7ddd1fec99fc510eR101).
If this is undesirable, zed could alternatively implement [icon
lookup](https://specifications.freedesktop.org/icon-theme-spec/latest/#icon_lookup)
and try and find its icon from the system at runtime.
## Future work
* It might be nice to expose a `set_window_icon` method also (it could
be used for example to show dirty state in the icon somehow), but I'm
unfamiliar with what other platforms support and if this could be beyond
X11 (there is a [wayland
protocol](https://wayland.app/protocols/xdg-toplevel-icon-v1) though!).
Release Notes:
- Fixed missing window icon on X11
---------
Co-authored-by: Yara <git@yara.blue>
kitt
and
Yara
created
5c7325a
title_bar: Don't show a badge for organizations without a plan (#53841)
Click to expand commit body
This PR makes it so we don't show a plan badge for organizations that
don't have a plan.
Closes CLO-654.
Release Notes:
- N/A
Marshall Bowers
created
a49739e
sidebar: Consistent thread display time (#53887)
c49973d
sidebar: Always focus agent when selecting thread (#53892)
Cameron Mcloughlin
created
07e9a2d
acp: Use npm --prefix for registry npx agents (#53560)
Click to expand commit body
Because we weren't going through the normal npm subcommand route, we
weren't getting a prefix flag applied. Which meant some users were
seeing errors of incorrect package managers when used with a JS project.
We still want the agent to run in the project dir if we can, we just
don't want it resolving packages from that project. (This actually means
I can run it in our claude-agent-acp repo again :D )
I refactored the node_runtime functions a bit to make these subcommand
functions a bit more inline wiht each other and actually fixed an issue
where --prefix might have been added after `--` previously which
wouldn't be correct anyway.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- acp: Fix npm-based agents resolving based on current project.
Ben Brandt
created
0a0da3f
agent_ui: Only allow editing when agent supports truncation (#53886)
Click to expand commit body
Follow up to #53850. #53850 fixed the panic, but had the side effect
that we would allow editing messages in the UI, even if the agent did
not support it.
Related #53735
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Bennet Bo Fenner
created
7240593
agent_ui: Do not show notifications when sidebar is open (#53883)
Click to expand commit body
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Co-authored-by: Gaauwe Rombouts <mail@grombouts.nl>
Bennet Bo Fenner
and
Gaauwe Rombouts
created
5688167
recent_projects: Fix worktree path resolving to bare repo in recent projects modal (#52996)
Click to expand commit body
## Context
When using a bare-repo-based git worktree layout (e.g. `foo/.bare` as
the bare repository and `foo/my-feature` as a linked worktree), the
"recent projects" modal was showing `foo/.bare` instead of
`foo/my-feature`.
The root cause was in `original_repo_path_from_common_dir` β when
resolving a linked worktree back to its "main" repo, the function reads
the `commondir` file which, for bare repos, points to the bare directory
itself (e.g. `foo/.bare`). Since that path doesn't end in `.git`, the
old code fell back to returning it as-is. This bare repo path was then
substituted into the workspace's stored paths, causing the modal to show
the bare directory instead of the actual worktree the user had opened.
The fix makes `original_repo_path_from_common_dir` return
`Option<PathBuf>`, returning `None` when `common_dir` doesn't end with
`.git`. `resolve_git_worktree_to_main_repo` propagates this `None`,
meaning the original worktree path is preserved in recent projects
rather than being replaced with the bare repo path.
Closes #52931
Video of the manual test after the fix is below :
[Screencast from 2026-04-02
16-05-48.webm](https://github.com/user-attachments/assets/9659c7a7-c095-4c23-af59-17715f84ce3e)
## How to Review
- **`crates/git/src/repository.rs`** :
`original_repo_path_from_common_dir` changed to return
`Option<PathBuf>`. Returns `None` for bare repos (no `.git` suffix). The
existing `original_repo_path` call site falls back to `work_directory`
when `None` is returned, preserving its prior behaviour. Unit test
expectations updated accordingly, with the bare-repo case now asserting
`None`.
- **`crates/project/src/git_store.rs`** :
`resolve_git_worktree_to_main_repo` now simply forwards the
`Option<PathBuf>` returned by `original_repo_path_from_common_dir`
directly, propagating `None` for bare repos so the caller keeps the
original worktree path.
- **`crates/workspace/src/persistence.rs`** : New test
`test_resolve_worktree_workspaces_bare_repo` exercises the exact
scenario from the issue: a workspace entry pointing to a linked worktree
whose `commondir` resolves to a bare repo. Asserts the path is left
unchanged.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed recent projects modal showing `.bare` folder instead of the
worktree directory for bare-repo-based git worktree setups
saberoueslati
created
8420716
anthropic: Preserve custom model thinking mode after thinking-toggle refactor (#52975)
Click to expand commit body
PR #51946 broke `Model::Custom` thinking behavior: `mode()`,
`supports_thinking()`, and `supports_adaptive_thinking()` all inferred
capabilities from hardcoded built-in model lists, so any `Custom`
variant always fell back to `Default` regardless of its configured
`mode` field.
### Fixes
- **`Model::mode()`** β `Custom` now short-circuits to `mode.clone()`
before the built-in inference logic
- **`Model::supports_thinking()`** β `Custom` returns `true` when `mode`
is `Thinking { .. }` or `AdaptiveThinking`
- **`Model::supports_adaptive_thinking()`** β `Custom` returns `true`
when `mode` is `AdaptiveThinking`
Built-in model behavior is unchanged.
### Tests
Three regression tests added covering the three `Custom` mode cases:
explicit `Thinking`, `AdaptiveThinking`, and `Default` (which must
disable both flags).
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed custom Anthropic models losing their configured
thinking/adaptive-thinking mode after the thinking-toggle refactor
(#51946)
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Context
When using regex buffer search (e.g. `^something`), Zed correctly
navigates only to actual matches. However, navigating to a match selects
the matched text, which triggers the **selection occurrence highlight**
feature. That feature performs a *plain literal* search for the selected
word and highlights all occurrences, including ones that don't satisfy
the regex. The user would see a 4th mid-line occurrence highlighted,
even though `^something` never matched it, this behavior is quite
confusing.
The fix tracks whether the current selection was set by search
navigation via a new `from_search: bool` on `SelectionEffects`. When
`last_selection_from_search` is set and `BufferSearchHighlights` are
active, selection occurrence highlights are suppressed. Making a manual
text selection during an active search clears the flag, restoring normal
occurrence-highlight behavior.
The behavior now matches how VSCode handles this case.
The video below demonstrates the behavior after the fix and shows that
it matches the VSCode behavior now
[Screencast from 2026-03-28
01-33-46.webm](https://github.com/user-attachments/assets/07a005b8-53b1-4abf-93d2-96406f0b6a11)
Closes #52589
## How to Review
Three files changed β read in this order:
1. **`crates/editor/src/editor.rs`** Adds `from_search: bool` to
`SelectionEffects` (with a builder method) and
`last_selection_from_search: bool` to `Editor`.
`selections_did_change()` records the flag from effects.
`prepare_highlight_query_from_selection()` returns `None` early when
both `last_selection_from_search` and active `BufferSearchHighlights`
are set.
2. **`crates/editor/src/items.rs`** `activate_match()` now calls
`.from_search(true)` on its `SelectionEffects` so search-driven
selections are marked at the source.
3. **`crates/search/src/buffer_search.rs`** Regression test
`test_regex_search_does_not_highlight_non_matching_occurrences`:
verifies that after search navigation, `SelectedTextHighlight` is
suppressed and exactly 3 `BufferSearchHighlights` exist; and that after
a manual selection, `SelectedTextHighlight` is restored.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed regex buffer search highlighting non-matching word occurrences
via the selection occurrence highlight feature
saberoueslati
created
bf185f7
Update Rust crate rand to v0.9.3 [SECURITY] (#53855)
Click to expand commit body
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [rand](https://rust-random.github.io/book)
([source](https://redirect.github.com/rust-random/rand)) |
workspace.dependencies | patch | `0.9.2` β `0.9.3` |
---
> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/15138) for more information.
### GitHub Vulnerability Alerts
####
[GHSA-cq8v-f236-94qc](https://redirect.github.com/rust-random/rand/pull/1763)
It has been reported (by @​lopopolo) that the `rand` library is
[unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library)
(i.e. that safe code using the public API can cause Undefined Behaviour)
when all the following conditions are met:
- The `log` and `thread_rng` features are enabled
- A [custom
logger](https://docs.rs/log/latest/log/#implementing-a-logger) is
defined
- The custom logger accesses `rand::rng()` (previously
`rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`)
methods on `ThreadRng`
- The `ThreadRng` (attempts to) reseed while called from the custom
logger (this happens every 64 kB of generated data)
- Trace-level logging is enabled or warn-level logging is enabled and
the random source (the `getrandom` crate) is unable to provide a new
seed
`TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe`
code to cast `*mut BlockRng<ReseedingCore>` to `&mut
BlockRng<ReseedingCore>`. When all the above conditions are met this
results in an aliased mutable reference, violating the Stacked Borrows
rules. Miri is able to detect this violation in sample code. Since
construction of [aliased mutable references is Undefined
Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html),
the behaviour of optimized builds is hard to predict.
Affected versions of `rand` are `>= 0.7, < 0.9.3` and `0.10.0`.
---
### Release Notes
<details>
<summary>rust-random/rand (rand)</summary>
###
[`v0.9.3`](https://redirect.github.com/rust-random/rand/compare/0.9.2...0.9.3)
[Compare
Source](https://redirect.github.com/rust-random/rand/compare/0.9.2...0.9.3)
</details>
---
### Configuration
π **Schedule**: (in timezone America/New_York)
- Branch creation
- ""
- Automerge
- At any time (no schedule defined)
π¦ **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
β» **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
π **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
Release Notes:
- N/A
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjExMC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This was leftover from trying to hold the invariant of one empty draft,
which was dropped in #53852.
Removes all automatic draft deletion:
- `retain_running_thread` discarded empty drafts when navigating away
- `remove_empty_draft` cleaned up all retained drafts when loading from
history
- `open_external_thread_with_server` removed empty drafts when opening
external threads
Release Notes:
- Fixed agent drafts being silently discarded when navigating between
threads
Nathan Sobo
created
fb9415e
sidebar: Click project header row to toggle fold instead of switching worktrees (#53861)
Click to expand commit body
Previously, clicking a project header in the agent sidebar would
activate/switch to that worktree's workspace, resuming whatever thread
was most recently active. This felt jarring β activating a random thread
based on recency isn't that useful when the user can just click the
specific thread they want. There's also no clear semantic for clicking
the overall group header since each thread maps to a specific workspace
and there's no single workspace to activate for the group.
This changes the click target for folding from just the chevron to the
entire header row. The worktree-switching behavior is removed β clicking
anywhere on the row now toggles the fold, which is a more predictable
and useful interaction.
The hover-only buttons on the right side (ellipsis menu, collapse
threads, new thread) continue to work as before, with their own click
handlers that stop propagation.
Release Notes:
- Improved sidebar project headers to toggle fold on click instead of
switching worktrees.
Nathan Sobo
created
acf5da9
Guard CLI first-run prompt with agents-v2 flag (#53839)
Click to expand commit body
Gates the CLI first-run prompt (from #53663) on the `agent-v2` feature
flag, giving us an escape hatch if something goes wrong.
## What this does
**Commit 1: Gate on agent-v2 flag**
- Adds an `AgentV2FeatureFlag` check at the top of the open behavior
resolution. When the flag is off, the prompt is skipped.
- Refactors `maybe_prompt_open_behavior` β `resolve_open_behavior`:
moves the explicit-flags guard (`-n`, `-e`, `--reuse`) to the caller and
drops three parameters from the function signature, since the function
was only inspecting those values to decide whether to bail early.
**Commit 2: Default to new-window when flag is disabled**
- When the flag is off, falls back to the pre-#53254 behavior of opening
projects in a new window, rather than silently adding to the sidebar.
Release Notes:
- N/A
Eric Holk
created
b310904
Allow empty project groups in sidebar (#53852)
Click to expand commit body
Previously, the sidebar would automatically create an empty draft thread
for any project group that had no threads (via `reconcile_groups`). This
added complexity and felt janky β the user would see a phantom "Draft"
entry appear for every workspace they opened, even before they intended
to start a conversation.
Now, project groups can simply be empty. When a group has no threads:
- The fold indicator renders as closed and grayed out (disabled β no
click handler or tooltip)
- The plus button is always visible on the right side of the header (not
hidden behind hover)
- Keyboard fold toggling is disabled for the group
- Clicking the plus button creates the first thread and expands the
group
Draft threads are no longer auto-created anywhere:
- `AgentPanel::load` no longer creates a draft when there is no
previously active conversation
- Archiving the last thread in a group clears the panel instead of
creating a replacement draft
- `show_or_create_empty_draft` and `clear_active_thread` are removed
This removes a significant amount of supporting infrastructure that only
existed to maintain the "no group may be empty" invariant:
- `WorkspaceSidebarDelegate` trait and `AgentPanelSidebarDelegate`
struct
- `reconcile_groups` method and its 12 call sites
- `clear_empty_group_drafts` method and its 3 call sites
- `show_or_create_empty_draft` and `clear_active_thread` methods
- `reconciling` field on `Sidebar`
- `sidebar_delegate` field, setter, and getter on `Workspace`
Release Notes:
- Improved the sidebar to show empty project groups with a visible plus
button instead of auto-creating placeholder draft threads.
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Nathan Sobo
,
Zed Zippy
, and
Max Brunsfeld
created
66ac781
Start new git worktrees in detached HEAD state (#53840)
Click to expand commit body
Create worktrees in detached HEAD state, then attempt to check out the
requested branch. If the checkout fails (e.g. the branch is already in
use by another worktree), log a warning and stay in detached HEAD state
instead of showing an error to the user.
This simplifies the worktree creation flow by:
- Removing the occupied-branch fallback logic that would generate random
branch names
- Always using `CreateWorktreeTarget::Detached` for worktree creation
- Attempting branch checkout as a best-effort post-creation step
- Updating the branch picker UI to reflect the new behavior
Release Notes:
- Threads now start git worktrees in detached HEAD state if branch is in
use or unspecified, instead of generating a random branch name.
---------
Co-authored-by: Eric Holk <eric@zed.dev>
Richard Feldman
and
Eric Holk
created
549db9f
acp_thread: Make UserMessageId required in AgentConnection::prompt (#53850)
Click to expand commit body
The `user_message_id` parameter on `AgentConnection::prompt` was
`Option<UserMessageId>`, but `NativeAgentConnection::prompt` immediately
called `.expect()` on it, crashing when the value was `None`.
Because the `expect` message said `UserMessageId` was required, this PR
makes the parameter not optional which makes the panic impossible.
This means we also need to unconditionally generate an ID in `send`,
where before we gated this on whether `truncate` returned `Some`.
Generating IDs unconditionally should be find, especially because the
prompt requires them.
Release Notes:
- N/A
Based on a partial revert of: 7bcdb12b4c5e9de0e4632c770336799e7c8d13d6
The main difference is instead of a feature flag we now check
`ReleaseChannel::Stable` != current_release_channel when the UI checks
if agent v2 (sidebar) features should be enabled.
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 ...
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Anthony Eid
and
Max Brunsfeld
created
092fedc
Fix the opening of the agent panel when clicking Try Now in new onboarding notification (#53845)
Click to expand commit body
This fixes an issue reported by @Veykril where the "Try Now" button
would open a different panel than the agent panel. The bug was caused by
us attempting to focus the agent panel before layout settings updates
had been applied.
This should also make all programmatic settings updates more responsive,
because they won't have to wait for FS watchers to take effect.
Release Notes:
- N/A
---------
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Max Brunsfeld
and
Anthony Eid
created
909dfd0
compliance: Expose some more methods (#53831)
Click to expand commit body
They will again come in handy for the GitHub worker.
Release Notes:
- N/A
Finn Evers
created
15dce9d
Always remove linked worktree workspaces before archive cleanup (#53672)
Click to expand commit body
When archiving a thread's last reference to a linked worktree, the
worktree workspace must be removed from the MultiWorkspace before the
background cleanup task runs `git worktree remove`. Previously, only the
workspace found via exact PathList match on the thread's `folder_paths`
was removed. This missed cases where the workspace's root paths diverged
from the thread's `folder_paths` (e.g. after folders were added/removed
from the workspace).
Now we also scan `roots_to_archive` for any linked worktree workspaces
that contain the worktree being archived and include them in the removal
set. This ensures all editors are dropped, releasing their
`Entity<Worktree>` references (held through `File` structs in buffers),
so `wait_for_worktree_release` completes and `git worktree remove` can
proceed.
Release Notes:
- Fixed some linked worktree directories not always being cleaned up
from disk when archiving a thread.
Richard Feldman
created
25e02cb
project_panel: Always open panel on pane's reveal in project panel (#53539)
Click to expand commit body
Update the way `pane::RevealInProjectPanel` is handled to ensure that,
regardless of whether the file belongs to any open project, the project
panel is always activated and focused.
This refactor is a result of some internal feedback after changing its
handling so as to show a notification stating that the item that the
user was trying to reveal didn't belong to an open project
βΒ https://github.com/zed-industries/zed/pull/51246 .
We feel users are probably already used to relying on `cmd-shift-e` (on
macOS), in pretty much every context, in order to open the project
panel, and so having situations where it doesn't actually happen seems
like a bad user experience.
Relates to #23967
Release Notes:
- Improved `pane: reveal in project panel` to open the project panel,
even if working with an unsaved buffer.
Dino
created
5f2373b
Skip git worktree removal when archiving threads on main worktrees (#53629)
Click to expand commit body
When archiving a thread that lives on a main worktree (not a linked
worktree), `build_root_plan` was still returning a `RootPlan`, which
caused the archive flow to call `git worktree remove` on the main
working tree. Git rightfully refuses this with:
```
fatal: '/Users/rtfeldman/code/zed' is a main working tree
```
This fix makes `build_root_plan` return `None` for non-linked worktrees,
so the archive-to-disk machinery is simply skipped. The thread is marked
archived in the metadata store and can be unarchived later β no git
operations needed.
Since `build_root_plan` now guarantees a linked worktree when it returns
`Some`, `RootPlan::worktree_repo` is tightened from
`Option<Entity<Repository>>` to `Entity<Repository>`, removing the
fallback codepath and the `is_some()` guard in `archive_worktree_roots`.
Release Notes:
- Fixed a crash when archiving an agent thread that was opened on the
main project (not a linked git worktree).