Follow-up https://github.com/zed-industries/zed/pull/55153
Fixes
https://github.com/zed-industries/zed/discussions/54553#discussioncomment-17091833
When a repository stores its Git data in `~/work/zed/.bare`, creating a
linked worktree from Zed is broken in two visible ways:
- Zed creates `random-code` at:
```
~/work/worktrees/.bare/random-code/.bare
```
instead of:
```
~/work/worktrees/zed/random-code/zed
```
- Because the checkout ends in `.bare`, Zed displays `.bare` as its
worktree name in the title bar, worktree picker, and agent thread
sidebar. Every worktree Zed creates from that repository gets the same
`.bare` label instead of its generated name.
This problem is specific to the path Zed creates. Worktrees using either
of these layouts are not malformed:
```
~/work/worktrees/zed/random-code/zed
~/work/zed/some-worktree
```
https://github.com/zed-industries/zed/pull/55153 introduced repository
identities for bare repositories. This PR uses that identity in the
remaining worktree naming and creation paths.
There are three repository layouts to account for:
- In a normal repository, the common Git directory is `~/work/zed/.git`,
so Zed derives the main worktree at `~/work/zed`. Existing behavior
remains unchanged.
- With `~/work/zed/.bare`, Git has no main worktree. A checkout named
main is still a linked worktree. Zed now treats `~/work/zed` as the
repository identity, creates new worktrees under `~/work/worktrees/zed`,
and displays their generated names.
- With a bare repository named `~/work/foo.git`, `foo.git` is the
repository identity. Its worktree path remains
`~/work/worktrees/foo.git/random-code/foo.git`. Zed uses foo.git to
derive the worktree name random-code, while displaying the repository
itself as foo.
Existing malformed worktrees such as
`~/work/worktrees/.bare/random-code/.bare` are not moved and may
continue to display `.bare`.
Broken:
<p>
<img width="238" height="58" alt="image"
src="https://github.com/user-attachments/assets/1504e4d0-c34a-471f-8e76-c5ec062b1d77"
/>
</p>
<p>
<img width="274" height="49" alt="image"
src="https://github.com/user-attachments/assets/13266ca9-4e64-426c-b03c-e23c924a3597"
/>
</p>
<p>
<img width="574" height="85" alt="image"
src="https://github.com/user-attachments/assets/0fca58c7-5be7-4d36-9067-066d0b80caf8"
/>
</p>
Release Notes:
- Fixed linked worktree names and creation paths for bare Git
repositories.
# Objective
Follow-up of #61374.
Zed now supports Windows as a remote target, but when connecting from a
Unix platform to Windows, some path handling still uses the native
client's path style (Unix) to construct paths, which causes weird path
displays in different areas.
One of them is the project path stored in the `settings.json` file,
which is related to the open path picker in the codebase:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/open_path_prompt/src/open_path_prompt.rs#L668-L679
For example, if I have a remote project at `D:\code\test_python` and
want to open it in remote development, I usually use path completions,
with `D:\code\` as the parent path and `test_python` as the selected
candidate. Zed directly joins them using `Path::join` on the Unix
platform, which results in `D:\code\/test_python`.
A second thing I found is the displayed name for the git repo. The
related source code is:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/title_bar/src/title_bar.rs#L262-L268
Also taking `D:\code\test_python` as an example: the passed-in
`common_dir_abs_path` is `D:\code\test_python\.git`, and
`repo_identity_path()` directly uses `Path::file_name()` and
`Path::parent()` from the standard library to handle this:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/project/src/git_store.rs#L9956-L9965
Ideally, this function should return `D:\code\test_python`. But due to
the platform mismatch, `D:\code\test_python\.git` is returned; after
further processing in the title bar, we get `D:\code\test_python\` as
the displayed name, while the expected display name is `test_python`.
In the past, only Unix-like systems could serve as remote servers, and
their path separator (`/`) is valid on Windows, so everything looked
fine. But Unix does not support `\` as a valid separator — that's the
root cause. We need to use `PathStyle`, which is designed for processing
paths across platforms, to deal with these cases.
## Solution
- Added new APIs `PathStyle::parent()` and `PathStyle::file_name()`,
which serve as replacements for `Path::parent()` and `Path::file_name()`
to process paths cross-platform.
- Adopted the new APIs in `repo_identity_path()`, and updated the
relevant call sites.
- For the open path picker, use `PathStyle::join_path()` instead of
`Path::join`.
## Testing
The added `PathStyle::parent()` and `PathStyle::file_name()` are covered
by detailed unit tests. These tests verify that the behavior matches the
corresponding methods in `Path`, just independent of the host platform.
For the path display issues, I built and tested manually; a comparison
is attached in the Showcase section.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<details>
<summary>Click to view showcase</summary>
| Content | Before | After |
|:--:|:--:|:--:|
|title bar|<img width="486" height="272" alt="title_bar_before"
src="https://github.com/user-attachments/assets/d14d0e37-a1b8-43ab-b51b-fe9dd1b977eb"
/> | <img width="406" height="274" alt="title_bar_after"
src="https://github.com/user-attachments/assets/fc9193f4-d42c-47a8-a254-4ed08c806a11"
/> |
|path storage| <img width="337" height="264" alt="project_path_before"
src="https://github.com/user-attachments/assets/3352add3-20df-43b9-8a20-10ee7d96e703"
/>| <img width="319" height="262" alt="project_path_after"
src="https://github.com/user-attachments/assets/fa3d7feb-f393-416a-868d-85eb0af5cfb8"
/>|
|open remote| <img width="554" height="135" alt="open_remote_before"
src="https://github.com/user-attachments/assets/62983eca-22ad-472f-8333-8561cfc17357"
/>|<img width="562" height="176" alt="open_remote_after"
src="https://github.com/user-attachments/assets/22528a6b-0e73-4a12-a825-673ba57a63da"
/> |
</details>
## Other things to note
This PR also did a little refactoring: it moved the `PathStyle`-related
tests from the `util` crate to the `path` crate, and updated the
documentation to reflect that Windows can serve as a remote platform.
The recent project picker also suffers from the same cross-platform bug,
but it is not fixed here, because a clean fix requires dealing with
database storage, unlike the direct API changes made here. I will
address it in a follow-up PR.
This PR looks very large, but most of the changes are the test migration
and the new API implementation. I hope the unit tests and comments can
offload some of the burden for reviewers.
---
Release Notes:
- Fixed project paths being built incorrectly when connecting from Unix
machines to Windows remote servers.
Follow-up to #46337, same fix as #48280.
`title_bar` tests enable `remote/test-support`, which adds
`RemoteConnectionOptions::Mock`. But without
`recent_projects/test-support`, the match arms for that variant aren't
compiled, causing a non-exhaustive match error when testing the crate in
isolation:
```
error[E0004]: non-exhaustive patterns: `&RemoteConnectionOptions::Mock(_)` not covered
--> crates/remote_connection/src/remote_connection.rs:233:76
```
CI doesn't catch this because `collab` and `sidebar` enable
`recent_projects/test-support` during workspace-wide tests.
Adding `remote_connection/test-support` instead isn't enough — that just
moves the same error into `recent_projects`.
`recent_projects/test-support` covers both.
Release Notes:
- N/A
Splits the crate graph.
Before, the compilation graph: `editor → picker_preview → search →
project_panel → open_path_prompt → recent_projects → title_bar →
collab_ui → zed`
After, the compilation graph: `editor → picker_preview → search →
agent_ui → sidebar → zed`
With sccache disabled and project fully built, `touch
crates/editor/src/editor.rs` and `cargo build -p zed` took time
Before (0500fd9ee9): 13.19s
After: 11.85s (-10.2% speed up)
Each commit contains a separate compilation instructions, and a test in
the final commit.
The main approach is to split coupled crates and replace them with
`zed_actions` and move some shared functionality into `git_ui_core` new,
shared module.
I've also tried to add a test to prevent common pitfalls, but not sure
I'm happy with the end result — can remove it if it looks too synthetic.
Release Notes:
- N/A
### Summary
This PR fixes three small bugs that could cause a multi-workspace's
reported location to be out of sync with its actual location, which
causes following to break in multiplayer collaboration sessions.
The first bug was that each child workspace's title bar within a
multi-workspace had its own `cx.observe_window_activation` subscription
that would set the associated child workspace's project location. This
caused problems because it ran for all child workspaces instead of just
the active workspace within the multi-workspace. The fix was moving
`cx.observe_window_activation` to the `cx.observe_new` call in the
`call` crate that tracks newly created windows/multi-workspaces.
The second bug was caused by an incorrect `if` statement in a
`MultiWorkspace` subscription that would return early if the window was
active and the event emitted by `MultiWorkspace` wasn't
`ActiveWorkspaceChanged`. This caused issues when the window was
inactive because it would incorrectly set the active call's location to
the wrong project. The fix was making the early return happen if the
window wasn't active.
The third bug was that every child `Workspace` also observed window
activation and called `update_active_view_for_followers`. This allowed
hidden workspaces to report their active view instead of only the active
workspace.
### Testing
I added a property test for bugs one/two and another prop test for bug 3
Release Notes:
- collab: Fix out of sync following bugs
# Objective
Fixes#44529
## Solution
Earlier, the container holding the right side of the title bar applied a
conditional right padding depending on the whether the user was signed
in or not. This PR removes the conditional padding and replaces it with
a constant.
## Testing
The changes where visually verified by replicating the issue and seeing
if the fix works.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
[](https://github.com/user-attachments/assets/017099c3-224e-4e32-9f28-66961e244d1b)
---
## Release Notes:
Fixed drop down arrow shifting upon logging in.
Adds a title_bar.show_worktree_name setting (default: true) that hides
the worktree picker button in the title bar, mirroring how
show_branch_name gates the branch picker. The "/" separator only renders
when both buttons are visible, and the container is omitted entirely
when both are hidden.
The setting is hide-only: it deliberately does not join the
render_project_items gate, so configurations with show_branch_name and
show_project_items both disabled keep hiding the whole group as before.
Requested in discussion
[zed-industries/zed#54902](https://github.com/zed-industries/zed/discussions/54902).
# Objective
The worktree name is always present in the title bar even when unused.
Unlike the branch name it has no dedicated option to disable it.
Requested in discussion
[zed-industries/zed#54902](https://github.com/zed-industries/zed/discussions/54902).
## Solution
Adds a `title_bar.show_worktree_name` setting (default: true) that hides
the worktree picker button in the title bar, mirroring how
show_branch_name gates the branch picker. The "/" separator only renders
when both buttons are visible, and the container is omitted entirely
when both are hidden.
The setting is hide-only: it deliberately does not join the
render_project_items gate, so configurations with show_branch_name and
show_project_items both disabled keep hiding the whole group as before.
## Testing
I tested the setting added by running the application by adding,
removing and toggling the `title_bar.show_worktree_name` setting in the
`settings.json`
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
## Showcase
<img width="1496" height="982" alt="title_bar.show_worktree_name =
false"
src="https://github.com/user-attachments/assets/b2c502de-a8d8-4409-ba04-5ab807c77a8e"
/>
<img width="1496" height="982" alt="title_bar.show_worktree_name = true"
src="https://github.com/user-attachments/assets/6cea7eb5-0e88-454c-9c97-3b4ad62aed51"
/>
---
Release Notes:
- title_bar: Added title_bar.show_worktree_name (default: true) to hide
worktree picker button
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Fixes menu a11y, and adds landmarks with `F6`-navigation.
Also fixes a GPUI bug, and adds debug actions for dumping a11y tree
info.
Since `F6` was already in use by the pause debugger keybind, also
tightens up the debugger keybind context so they require an active
debugger session. When there is one active, `F6` stays as pause
debugger. `ctrl-F6` always works to go to the next landmark.
Also adds an "accessible mode" setting. Currently, this only controls
whether we show all menus all the time, but I suspect it will expand
significantly in the future.
Also adds `.aria_keyshortcuts()` API, but it's not wired up within
accesskit adapters, so is not yet reported to screen readers.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
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
# Objective
On a few occasions I have been wondering if the Zed update download had
stalled, when in fact it's just taking a while. This PR adds a progress
bar to the "Downloading Zed Update..." button to give users feedback
that the download is indeed progressing.
## Solution
Add a custom progress bar inside the button. I tried reusing the
existing ProgressBar component but that has a fixed height of 8px which
caused the button to become taller.
## Testing
- Tested manually using the command palette `collab: simulate update
available` and stepping through the different UI states.
- Added unit 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
## Showcase
<img width="1350" height="748" alt="Image 02-07-2026 at 17 23"
src="https://github.com/user-attachments/assets/ed23c97a-01b8-446b-9693-0c53a69b419d"
/>
Release Notes:
- Added a download progress indicator to the update button.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Adds:
- aria attributes to most UI elements in settings UI
- a new a11y API to GPUI
- a fix for a GPUI keyboard focus bug
## Accesible settings UI
Settings UI should now be fully accessible to users of assistive
technology.
**However**, there are some caveats:
- accessibility features require zed to be launched with the
`ZED_EXPERIMENTAL_A11Y=1` env var to be set
- I have not exhaustively checked every control
- There are some quite surprising keyboard focus behaviours which
predate this code
- The main Zed UI is still largely inaccessible, though a handful of
shared components will now report themselves, but the experience is
suboptimal.
For anyone wishing to try out the settings UI:
- make sure `ZED_EXPERIMENTAL_A11Y=1` is set
- open zed
- press `ctrl-,` (or `cmd+,` on a mac) to open settings UI in a separate
window
## `aria_active_descendant`
This is equivalent to the
[`aria-activedescendant`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-activedescendant)
API on the web.
It allows a container to maintain focus, while indicating that one of
its children should be active. Zed uses this for menus and combo boxes,
for example.
GPUI will report a div with `.aria_active_descendant()` as long as:
- an ancestor is focused
- only one descendant of the focused ancestor has
`.aria_active_descendant()`
Two descendants with this property where the focused node is a common
ancestor is an error.
## GPUI keyboard fix
GPUI will map a space or enter keypress to a div's `on_click` handler,
if it exists. However, the keyboard-driven path was missing some checks
that the mouseclick path has.
With this PR, for an enter/space keypress to be considered a click,
between the "key down" and "key up" events:
- there must be no other key events
- focus must not move to a different node
This fixes an existing bug with combo boxes in zed where:
- enter maps to `menu::Confirm` **on key down*
- the menu item is selected
- focus moves to the combo box
- enter then triggers the combo box's `on_click` **on key up**,
re-opening the menu
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Adds `default_open_behavior` which let's users control which action
should be the default (add to existing window/open a new window)
TODO:
- [x] Use sensible icon (not `IconName::Screen`) when
`default_open_behavior` is set to `new_window`
- [x] Tweak wording for actions in recent projects menu
<img width="420" height="59" alt="image"
src="https://github.com/user-attachments/assets/69ef112e-bf20-4dd1-9994-e4442266ef87"
/>
Release Notes:
- Added `default_open_behavior` which controls which action (add to
sidebar/open in new window) should be the default when selecting a
project from the recent projects menu
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This PR updates the user menu to always show the list of organizations.
We had some logic in here to hide it if the user did not have an
organization selected, which was left over from before organizations
were fully rolled out.
Now that every user should be in at least one organization, we can
remove the old UI states.
Release Notes:
- N/A
For the longest time, we've had a labeled "Share" button on the title
bar whenever you're in a call. However, it was extremely easy to click
that button thinking you'd be sharing _your screen_ instead of your
project. At the end of the day, there wasn't any specific cue that'd
allow you to know what you'd be sharing. This is why people just assumed
you'd share the screen, which is arguably way more common than sharing
the project. We've seen users bump into this confusion countless times,
and this also even happens to us (the whole Zed staff) weekly whenever
we're in meetings.
So, this PR changes that button to be an icon button instead, using a
folder icon to better communicate it means sharing the project. I also
took advantage of the opportunity to change the approach we use for
adding these buttons, using `when` instead of `children.push`; I think
the former is just easier to understand, allowing to more easily picture
the UI in your (my) head. Lastly, also improved what we display in the
tooltip for the project share button, by showing the names of all
projects you'll be sharing, as well as the tooltip that displayed call
diagnostics.
| Before | After |
|--------|--------|
| <img width="778" height="360" alt="Screenshot 2026-06-05 at 3 48
2@2x"
src="https://github.com/user-attachments/assets/363593fb-79f8-42e9-83b9-345bc731846f"
/> | <img width="778" height="360" alt="Screenshot 2026-06-05 at 3 48
3@2x"
src="https://github.com/user-attachments/assets/32afc412-a1fb-45a4-a19e-74e4923c0c8b"
/> |
Release Notes:
- Improved call controls design, making it clearer what button shares
_the project_ vs. _the screen_.
Very often, I'd wake up, to which point there's a new Nightly release
out, and the update button would be stuck in the "Downloading..." step.
It'd only immediately change its state to "Restart" once I quit the app
and re-open it again. Turns out we were just missing a cx.notify in the
callback to trigger a re-render.
Release Notes:
- Fixed a bug where the update version button would be stuck in the
"Downloading..." step.
Closes AI-354
The "Panel Layout" submenu available in the user menu exposed two quick
menu items to switch between the classic and agentic workspace layout.
These will now also be available as actions, reachable through the
command palette.
<img width="600" alt="Screenshot 2026-06-01 at 8 28@2x"
src="https://github.com/user-attachments/assets/c468b958-9588-4646-a689-6e661a8f6e5a"
/>
Release Notes:
- Exposed actions to switch between the classic and agentic workspace
layout in the command palette.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] ~~Unsafe blocks (if any) have justifying comments~~ (N/A)
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Corrects the value used for traffic light clearance/padding when
building with the macOS 26 SDK (or later). This was originally fixed in
#45351 but regressed in #48800 where `TRAFFIC_LIGHT_PADDING` was moved
to `ui/src/utils/constants.rs` but the local `build.rs` in `title_bar`
did not apply to the `ui` crate.
Release Notes:
- N/A
Removes a leftover test label added by #56065
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
GPUI AccessKit integration
This PR is replacing #51097 , and is much more limited in scope. This PR
*ONLY* adds AccessKit support to GPUI, and doesn't touch Zed. Once this
lands, we can start adding aria attributes to Zed's components.
This PR is the first step to addressing #41138 .
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: John Tur <john-tur@outlook.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Agus Zubiaga <agus@zed.dev>
Now that the cloud platform exposes a system-settings endpoint for the
user's selected organization, switch `UserStore` over to it and drop the
local database persistence. The server already returns the current
selected organization for `get_authenticated_user()`.
set_current_organization becomes a optimistic, with the in-memory
selection updated immediately. hen a background task POSTs to the system
settings endpoint.
Stale current_organization_id rows from older installs are left dangling
— harmless and not worth a migration. This is the second step in moving
organization selection to cloud; the first added the
update_system_settings client method.
Part of CLO-716
Release Notes:
- N/A
---------
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Closes AI-244
This PR changes the approach for announcing skills support. It uses the
announcement toast, the same thing used for parallel agents, which
observes a specific version number to be displayed. I ended up
simplifying things a bit by thinking we could rely on documentation for
more detailed information (with more extensive paths and whatnot).
Release Notes:
- N/A
---------
Co-authored-by: Richard Feldman <richard@zed.dev>
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Co-authored-by: Martin Ye <martinye022@gmail.com>
Removes the `skills` feature flag now that Skills are ready to ship to
all users. Cleans up all `cx.has_flag::<SkillsFeatureFlag>()` gates
across the agent, agent_ui, prompt_store, and title_bar crates, drops
the now-unused `feature_flags` dependency from `prompt_store` and
`title_bar`, and removes the dead `update_flags(true, vec!["skills"])`
calls from the agent's skills tests.
Closes AI-269
Release Notes:
- Enabled Skills for all users.
---------
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Co-authored-by: Martin Ye <martinye022@gmail.com>
Closes TRA-150
This PR makes the restricted mode more obvious by:
- Immediately opening the restricted mode modal upon opening an
untrusted project
- Disabling dismissing the modal on escape or click away to force
choosing one of the two options (and avoid accidentally staying in
restricted mode by simply dismissing it)
- Showing the LSP button but with communication about language servers
being disabled for untrusted projects
- Showing a banner in the project settings with the same communication
The motivation for this change was that we tried to be minimal with how
we communicate a project is untrusted, but it was so minimal that people
were confused as to why language servers and other settings weren't
working. It was easy to miss the title bar button, for some reason. The
changes in this PR makes it so acting on this decision (trust or not a
project) is mandatory in order to even start to interact with the
project. I appreciate changes here are more aggressive, but I think it's
better to make you think about this decision vs. letting you be confused
as to why you don't see LS completions or formatting.
Release Notes:
- Made restricted mode more obvious, demanding immediate action when
opening an untrusted project.
Adds a one-time, idempotent startup migration that moves every user Rule
out of the `PromptStore` LMDB database into the new Skills + AGENTS.md
world, in a single pass:
- **Non-Default Rules → global Skills.** Each one becomes
`~/.agents/skills/<slug>/SKILL.md` with `disable-model-invocation:
true`, preserving the original behavior that non-Default Rules were only
ever invoked when the user named them. They're now invokable via
`/skill-name` (and still `@`-mentions).
- **Default Rules → global AGENTS.md.** Each one is appended to
`paths::agents_file()` (e.g. `~/.config/zed/AGENTS.md` on macOS/Linux,
`%APPDATA%\Zed\AGENTS.md` on Windows) under an `## H2` heading
containing the rule's title. Default Rules used to be auto-included in
every conversation; the global AGENTS.md is loaded into the system
prompt of every conversation, so the behavior is preserved.
- **Customized built-in prompts → global AGENTS.md** (currently just the
commit-message prompt). If the user has edited a built-in away from
Zed's shipped `default_content()`, the edited body is appended at the
top of the AGENTS.md block. Uncustomized built-ins (still on the shipped
default) are skipped so we don't pollute AGENTS.md with text the user
never wrote.
The migration is gated on the `skills` feature flag — users without the
flag never have their Rules touched in any way. A single global KVP flag
(`rules_to_skills_migration_done`) short-circuits the migration on
subsequent launches, so it runs at most once per machine even across
release channels. A process-lifetime `AtomicBool` guard additionally
prevents racing duplicate spawns when the underlying `cx.on_flags_ready`
callback fires multiple times at startup.
Migration is intentionally non-destructive: rule rows in the LMDB
database stay in place. Users can still see and edit them through the
existing UI, and a downgrade to a Zed build without skills support won't
lose anything.
Slug generation (`agent_skills::slugify_skill_name`) lowercases ASCII
letters, turns spaces into dashes, and drops every other
non-alphanumeric character entirely — so `foo!bar` becomes `foobar`, not
`foo-bar`. `&` is special-cased to become `and` (so `rock&roll` →
`rock-and-roll`). Slug collisions and pre-existing skill directories are
handled by appending `-2`, `-3`, etc.
A title-bar onboarding banner ("Skills have replaced Rules") surfaces
for every user on the `skills` feature flag. Clicking it opens a small
`AlertModal`-based explainer that summarizes the two destinations and
points users at the new `/skill-name` slash command (and notes that
`@`-mentions still work).
Closes AI-227
Closes AI-232
Release Notes:
- N/A
This PR adds a small refinement to the update button, removing
truncation from the version we display. Instead of just showing the
short version of a SHA, we now display it in full, providing more
detailed information that sometimes was lost. Also am making the button
disabled when it's in the checking, downloading, and installing states,
given clicking on it at these moments doesn't do anything.
Release Notes:
- N/A
This PR renames the `UserId` type in the `client` crate to
`LegacyUserId`.
The `id` field on the `User` has also been renamed to `legacy_id`.
This is strictly a rename, no change in behavior.
Release Notes:
- N/A
Follow up to https://github.com/zed-industries/zed/pull/54406.
Closes https://github.com/zed-industries/zed/issues/54782.
In the PR linked above, we made the label that's displayed in the
project button be always the repository name. However, if you're opening
up a subfolder of that repository as the main-root of a given
project/workspace, we wouldn't display that anymore. This PR fixes that
by _still_ displaying the repo name, but the subfolder, too, in the
titlebar:
<img width="500" alt="Screenshot 2026-04-24 at 4 52@2x"
src="https://github.com/user-attachments/assets/04c2c61d-874d-4694-88c9-06bad9677e49"
/>
Release Notes:
- Fixed a bug where we don't display subfolders of a repository in the
title bar's project button.
Fixes https://github.com/zed-industries/zed/issues/54830
This fixes a bugs where
* when there's no main worktree, we treated the first linked worktree as
main
* the titlebar and sidebar showed two different things when opening a
linked wortree directly
When there's no main worktree, our "project group key" will be the bare
repo path. For displaying this to the user, we try to present something
meaningful:
* If the bare repo is `foo.git`, we'll say "foo"
* If the bare repo is "bar/.bare", we'll "bar"
Release Notes:
- Fixed bugs in Zed's sidebar and titlebar when editing in git worktrees
created from bare repositories.
Closes https://github.com/zed-industries/zed/issues/54545
With the release of the parallel agents feature, we changed the default
panel positions optimizing for an agentic-first layout. Even though we
introduced a settings backfill _and_ the ability to revert after
interacting with the announcement toast, this change seems to be causing
a bit of frustration still. In response, this PR adds a "Panel Layout"
menu in the user menu that allows to quickly toggle between the
"Classic" layout and the "Agentic" layout. If you have a different set
up, you'll see a "custom" item there just confirming that.
| Panel Layout | Custom set up |
|--------|--------|
| <img width="1110" height="866" alt="Screenshot 2026-04-24 at 12
52@2x"
src="https://github.com/user-attachments/assets/197fc4ec-b4b3-4b13-bcb3-9d3495cf0d0a"
/> | <img width="1156" height="866" alt="Screenshot 2026-04-24 at 12
55@2x"
src="https://github.com/user-attachments/assets/ca791b1b-eb6a-47a9-8aa5-c2015f33e5bd"
/> |
Release Notes:
- Added a menu item in the user menu called "Panel Layout" which offers
the ability to quickly swap between the two standard panel layouts:
classic (project panel, git panel, etc., on the left) and agentic (agent
panel on the left, everything else on the right).
No, sadly, the title is not a typo. See
https://www.githubstatus.com/incidents/zsg1lk7w13cf for the context.
I'll read with joy and popcorn through that root cause analysis.
It makes literally zero sense what happened here, but for some completly
bonkers reason GitHub completely messed up the merge queue with
https://github.com/zed-industries/zed/pull/54632.
I have no idea how it happened. It makes literally zero sense. A PR
going into the merge queue should have the same LoC when getting out of
it. GitHub obviously does not check this. GitHub causes extra work with
a feature that is supposed to save time.
Thanks, I guess.
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This PR brings back the button to filter remote branches when accessing
the title bar's branch picker with the mouse. It was unintentionally
removed when we introduced the new worktree picker.
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/54628
Release Notes:
- Fixed a bug where the worktree and branch buttons in the title bar
were still being displayed despite `disable_git` being turned on.
This PR fixes an issue where we'd show incorrect worktree labels when
opening a linked worktree directly. The linked worktree name would be
displayed in the project button but the dedicated worktree button would
be displaying "main", which is incorrect.
Now that we have a dedicated worktree button in the title bar, we can
make the project button always show the root repository name,
effectively matching the threads sidebar.
Release Notes:
- Fixed the title bar worktree button showing "main" when opening a
linked git worktree directly.
This PR makes Zed only have one worktree picker, as opposed to a flavor
of it in the title bar and another in the agent panel. It then moves it
to the title bar, making it always present, so that its trigger is
separate from the branch picker (which now contains only two views:
branches and stashes). For the worktree picker, I'm mostly favoring the
behavior we've introduced in the agent-panel-flavored version.
It also updates the title bar settings migration to use the JSON
`migrate_settings` helper instead of a shallow Tree-sitter rewrite, so
old `show_branch_icon = true` values are promoted to
`show_branch_status_icon = true` across root, platform, release-channel,
and profile settings scopes.
- [x] Move worktree creation logic to the `git_ui` crate to make this
more generic and less agent-specific
- [x] Double-check the remote use case and ensure nothing broke there
- [x] Improve the UX for the detached HEAD state; better invite people
to create a branch
- [x] Migrate `show_branch_icon = true` to `show_branch_status_icon =
true` across nested settings scopes
Suggested .rules additions
When migrating renamed settings keys that can appear in platform
overrides, release-channel overrides, or profiles, prefer the JSON
`migrations::migrate_settings` helper over shallow Tree-sitter key
rewrites unless tests explicitly cover every nested scope that can
contain the key.
Release Notes:
- Improved migration of the title bar branch status icon setting.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This PR makes it so we hide the plan badge next to the username in the
user menu when there are organizations.
We instead show the plans next to each organization:
<img width="257" height="317" alt="Screenshot 2026-04-13 at 1 29 26 PM"
src="https://github.com/user-attachments/assets/0111e7ff-af09-48ba-a043-9e25c2dd24bd"
/>
Closes CLO-649.
Release Notes:
- N/A
> **Foundation PRs:** #53732, #53733, #53734 — These three draft PRs
contain the base refactors (retained workspaces, agent panel overlay
split, ThreadId introduction) that this PR builds on.
## Goal
Remove `DraftId` and merge `draft_threads` + `background_threads` into a
single `retained_threads: HashMap<ThreadId, Entity<ConversationView>>`
in `AgentPanel`. A draft is just a thread that hasn't sent its first
message — no separate identity or storage needed.
## Changes
### agent_panel.rs
- Remove `DraftId` / `DraftIdCounter` / the `Global` impl
- Merge the two maps into `retained_threads`
- Add `thread_id: ThreadId` field to `BaseView::AgentThread`
- Rename methods: `create_draft` → `create_thread`, `activate_draft` →
`activate_retained_thread`, `remove_draft` → `remove_thread`, etc.
- Replace `clear_active_thread` with `show_or_create_empty_draft`
- Update `update_thread_work_dirs` to sync `ThreadMetadataStore` paths
when worktrees change
- Keep `load_agent_thread(...)` cleanup so activating a real thread
removes empty retained drafts
### sidebar.rs
- Remove `active_entry` derivation from `rebuild_contents` (was racing
with deferred effects)
- Add `sync_active_entry_from_panel` called from event handlers instead
- Simplify `ActiveEntry` — remove `ThreadActivation` struct, make
`session_id` optional
- Move `seen_thread_ids` to global scope (was per-group, causing
duplicate thread entries)
- Remove dead code: `clear_draft`, `render_draft_thread`
- Generalize `pending_remote_thread_activation` into
`pending_thread_activation` so all persisted-thread activations suppress
fallback draft reconciliation
- Set the activation guard before local persisted-thread activation
switches workspaces
- Make `reconcile_groups(...)` bail while a persisted-thread activation
is in flight
- On `ActiveViewChanged`, clear empty group drafts as soon as a pending
persisted-thread activation resolves
### thread_metadata_store.rs
- Make `ThreadMetadata.title` an `Option<SharedString>` with
`display_title()` fallback
- Add `update_worktree_paths` for batched path updates when project
worktrees change
### Other crates
- Update all `ThreadMetadata` construction sites and title display sites
across `agent_ui` and `sidebar`
## Fallback draft invariant
This PR now tightens the retained-thread invariant around fallback
drafts vs real thread activation/restoration:
- Fallback drafts are always empty
- User-created drafts worth preserving are non-empty
- While a persisted thread is being activated/restored/loaded, sidebar
reconciliation must not create an empty fallback draft for that target
group/workspace
- Once the real thread becomes active, empty fallback drafts in that
target group are removed
This is enforced by the sidebar-side activation guard plus existing
`AgentPanel` empty-draft cleanup after real-thread load.
## Tests
Added and/or kept focused sidebar regression coverage for:
-
`test_confirm_on_historical_thread_in_new_project_group_opens_real_thread`
-
`test_unarchive_into_inactive_existing_workspace_does_not_leave_active_draft`
-
`test_unarchive_after_removing_parent_project_group_restores_real_thread`
- `test_pending_thread_activation_suppresses_reconcile_draft_creation`
Focused test runs:
- `cargo test -p sidebar activate_archived_thread -- --nocapture`
- `cargo test -p sidebar unarchive -- --nocapture`
- `cargo test -p sidebar archive_last_thread_on_linked_worktree --
--nocapture`
- `cargo test -p sidebar
test_confirm_on_historical_thread_in_new_project_group_opens_real_thread
-- --nocapture`
- `cargo test -p sidebar
test_unarchive_into_inactive_existing_workspace_does_not_leave_active_draft
-- --nocapture`
- `cargo test -p sidebar
test_unarchive_after_removing_parent_project_group_restores_real_thread
-- --nocapture`
- `cargo test -p sidebar
test_pending_thread_activation_suppresses_reconcile_draft_creation --
--nocapture`
## Test fix
Fixed flaky `test_backfill_sets_kvp_flag` — added per-App `AppDatabase`
isolation in `setup_backfill_test` so backfill tests no longer share a
static in-memory DB.
Release Notes:
- N/A
---------
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This changes the behavior of the recent project picker in multi-folder
projects, so that when you select a folder that is a repository, it sets
the active repository in the Git panel as well.
Release Notes:
- N/A
Remove the standalone storybook binary and the story crate, as component
previews are now handled by the component_preview crate.
Also removes the stories features from the ui and title_bar crates.
Release Notes:
- N/A or Added/Fixed/Improved ...