Commit Graph
3163 Commits
Author SHA1 Message Date
Yara 🏳️‍⚧️ 320888142f Rust 1.95 (#55104)
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
2026-04-29 10:27:47 +00:00
dd79ca048e git_graph: Align CommitDataReader with batched commit processing (#54600)
Self-Review Checklist:

- [X] 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
- [X] Performance impact has been considered and is acceptable

Updated `CommitDataReader::read` from single SHA to batched
input/output.
`run_commit_data_reader` is designed to process requests in batches, but
`CommitDataReader::read` previously only sent one SHA per call. So in
practice, commit data was effectively processed one-by-one from the
caller path.


The temporary debug logs show that batching was not performed
previously.

before:
<img width="607" height="154" alt="image"
src="https://github.com/user-attachments/assets/4f9d9041-6209-426f-be44-f28449504c80"
/>

after:
<img width="632" height="121" alt="image"
src="https://github.com/user-attachments/assets/43b349f3-7685-4786-af1e-2a640cdf8ccd"
/>


Release Notes:

- N/A

---------

Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
Co-authored-by: Anthony Eid <anthony@zed.dev>
2026-04-28 08:29:21 +00:00
Tristan Phease eced4eab77 Fix ESLint not starting on Windows (#54945)
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 #54093 (at least the os error 123 in the comments of that
bug)/#54901 (although the diagnosis in that bug is totally wrong)
Used process monitor to work out what that issue was:
<img width="1573" height="94" alt="image"
src="https://github.com/user-attachments/assets/2f82ad1a-8532-465d-9dcd-ba0bd092e9e7"
/>
There's actually a '\n' after node_modules there so it's an invalid
directory. Add trim() to fix.
After adding that change locally, eslint loaded fine

Release Notes:

- Fixed bug where eslint didn't start on Windows
2026-04-27 11:10:58 +00:00
moktamdandmoktamd 5aa7eaa508 dap: Support IPv6 addresses in TCP transport (#52244)
The DAP TCP transport layer was hardcoded to `Ipv4Addr`, so IPv6
addresses like `fd00::a` in a debug config's `connect.host` always
failed with `hostname must be IPv4: invalid IPv4 address syntax`.

Replaced `Ipv4Addr` with `IpAddr` and `SocketAddrV4` with `SocketAddr`
across the `task`, `dap`, `dap_adapters`, and `project` crates. The WASM
extension API still uses `u32` for the host field to avoid a breaking
WIT interface change; IPv4 round-trips through extensions as before.

Fixes #52237

Release Notes:

- Fixed DAP TCP transport rejecting IPv6 addresses when connecting to
remote debug adapters.

---------

Co-authored-by: moktamd <moktamd@users.noreply.github.com>
2026-04-27 08:42:45 +00:00
RainandKirill Bulatov 47fb164f28 project: Use runnable kind to disambiguate between cargo and shell commands (#54011)
Found this bug while investigating why configuring nextest based on the
instructions at
https://github.com/rust-lang/rust-analyzer/issues/21137#issuecomment-4254611341
wasn't working within Zed.

Previously, we'd use `serde(untagged)`, preferring cargo over shell
commands. The problem is that every instance of a shell command is a
valid instance of a cargo command. For example, the shell command:

```json
{
    "label": "test my_test",
    "kind": "shell",
    "args": {
        "environment": {"RUSTC_TOOLCHAIN": "/path/to/toolchain"},
        "cwd": "/project",
        "program": "cargo",
        "args": ["nextest", "run", "--package", "my-crate", "--lib", "--", "my_test", "--exact", "--include-ignored"]
    }
}
```

would end up getting deserialized as a Cargo command, silently dropping
`program` and `args`.

With this fix, we now use the provided `kind` as a tag. We do have to
introduce a `#[serde(flatten)]` unfortunately, which has a few side
effects due to internal buffering, but `#[serde(untagged)]` also does
internal buffering so this doesn't make things worse.

I've manually tested this by configuring:

```json
{
    "lsp": {
        "rust-analyzer": {
            "initialization_options": {
                "runnables": {
                    "test": {
                        "overrideCommand": [
                            "cargo",
                            "nextest",
                            "run",
                            "--package",
                            "${package}",
                            "${target_arg}",
                            "${target}",
                            "--",
                            "${test_name}",
                            "${exact}",
                            "${include_ignored}"
                        ]
                    }
                }
            }
        }
    }
}
```

and ensuring that nextest is correctly invoked.

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 deserialization of rust-analyzer shell runnables.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-04-27 07:36:43 +00:00
1afe44c1b6 git: Improve handling of unsafe repositories (#43693)
These changes update Zed's Git Panel to be able to detect unsafe git
repositories, where the user running Zed doesn't own the `.git`
directory, and show a dedicated empty view in the Git Panel that not
only explains the situation but also allows the user to choose whether
to trust this directory, which will end up running `git config --global
--add safe.directory <path>`.

While testing those changes, it was noted that attempting to add or
reset files after trusting the directory would fail, as expected, but
the UI wouldn't react to the fact that those operations failed. What
this means is, if the user tried to add a file, the UI would show a
checkmark for that file and, after the operation failed, the checkmark
would remain. We now revert that, for both `git add` and `git reset`.

Some more technical notes on this change:

- Introduce `project::git_store::GitAccess` enum to express whether we
actually have access to the repository, exposed via
`git::Repository::access`, which probes the backend with a `git status`
command and classifies the result.
- On unsafe repositories,
`project::git_store::LocalRepositoryState::new` fails to spawn the git
worker, which now cleanly signals `GitAccess::No` rather than leaving
the panel in a broken state.
- Updated `git_ui::git_panel::GitPanel::render_empty_state` with a third
alternative, when `GitAccess::No`, that basically renders a view
explaining why the repository is considered unsafe, together with
buttons for git's documentation on safe directories and a button to add
the repository's folder as a safe directory
- Updated `project::git_store::GitStore` to now watch `~/.gitconfig` and
`$XDG_CONFIG_HOME/git/config`. Watching this files allows the Git Panel
to react when the git configuration is updated, which will be the case
if the user decides to trust the repository. When either changes, a
`GitStoreEvent::GlobalConfigurationUpdated` event is emitted and the
panel refetches repository state.
- Added `project::git_store::Repository::refetch_repo_state` field,
which stores a closure to allow recreating the
`Repository::repository_state` and the job sender after the repository's
directory is trusted, without requiring a project reload.
- Added a `fs::Fs::git_config` trait method, wrapping a real `git
config` invocation. In order to be able to call this, both
`git_store::GitStore::git_config` and `project::Project::git_config`
wrappers have also been introduced. Worth mentioning that this isn't yet
supported for remote projects or collab guests.
- Updated `fs::Fs::git_clone` argument order to match
`fs::Fs::git_config` and `fs::Fs::git_init`.
- Added a new
`project::git_store::pending_op::PendingOps::last_op_errored` method
that allows determining whether the last pending operation failed. This
now allows us to filter out failed operations when determining whether
`git add` or `git reset` failed, so that we can fall through to the real
git status.
- Updated `git_ui::git_panel::GitPanel::change_file_stage` to now call
`update_counts` in its error branch so the cached staged counters stay
consistent with the reverted per-entry state, seeing as we now handle
reverting the UI state if an operation fails.
- Fixed `fs::RealFs::git_init` to fall back to the provided branch name
when `git config --global --get init.defaultBranch` fails, for example,
when the user hsan't configured one.

Co-authored-by: cameron <cameron.studdstreet@gmail.com>

Closes #42286

Release Notes:

- Added a dedicated empty state in the Git Panel for unsafe
repositories, with a "Trust Directory" button that adds the repository
to `safe.directory`
- Fixed stage and unstage checkboxes in the Git Panel not reverting when
a `git add` or `git reset` command failed

---------

Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2026-04-24 17:14:24 +00:00
Oleksiy Syvokon 250e697ff7 project_search: Fix project search status text and refactor search state (#54753)
This change fixes a small bug where we were showing "Loading project..."
even when in fact we had already started the search.

It also refactors three booleans in the `SearchState` enum, so that it's
harder to make similar mistakes in the future.


Release Notes:

- N/A
2026-04-24 10:45:16 +00:00
Lukas Wirth c5a2807492 Remove smol as a dependency from a bunch of crates (#53603)
We aren't making use of it in these crates and it unblocks some
web-related work

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-04-24 10:29:51 +00:00
0194fe0576 git: Replace file history view with git graph (#50288)
## Summary

This PR replaces the git file history view with the git graph view that
doesn't render the graph canvas. This has several advantages

1. Benefits from the graphs performance and lazy loading
2. Gets the graph's search for free
3. Resizable columns
4. The commit information panel
5. Is persistent 
6. Cleans up a lot of code

The one con of this change is the graph doesn't have support
remote/collab support yet, but that is a WIP and should be merged within
a week.

Also, the git graph now propagates errors to the UI, which is the last
thing on the graph's stable launch todo list!

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>
2026-04-24 02:51:19 +00:00
Finn EversandDanilo Leal 9b40411c6a Fix bad GitHub merge queue merge (#54721)
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>
2026-04-23 23:47:30 +00:00
Max Brunsfeld 41cf3a8950 Always preserve worktree order rather than sorting lexicographically (#54716)
Release Notes:

- Zed now keeps project directories in the order they were added, rather
than implicitly sorting them lexicographically.
2026-04-23 22:20:16 +00:00
Danilo Leal 0ab64d6414 branch_picker: Add button to filter remote branches (#54632)
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
2026-04-23 18:26:44 +00:00
Kirill Bulatov 5f68479937 Stop showing backtraces in default logging (#54660)
When using `.log_err()` or `.detach_and_log_err(cx)` or similar.

See also https://github.com/zed-industries/zed/pull/36404,
https://github.com/zed-industries/zed/pull/46383,
https://github.com/zed-industries/zed/pull/44896,
https://github.com/zed-industries/zed/pull/43917 and many more.

Before, a
https://github.com/zed-industries/zed/blob/62bd61a6793c5f983fbc1700825208f19d780d52/crates/languages/src/go.rs#L568
line would show a backtrace even for `.context("no cached binary")?;`
case, same as many other usages around the code:

<img width="2032" height="1162" alt="before"
src="https://github.com/user-attachments/assets/ef2188b3-74c9-4c86-82b8-9fdaed3c26ae"
/>

After:

<img width="1896" height="157" alt="after"
src="https://github.com/user-attachments/assets/a1067d9f-61f4-4833-aeab-9f1042d2514a"
/>



To show a backtrace as before, use `log_err_with_backtrace`.

Release Notes:

- Improved Zed's log output on errors
2026-04-23 14:14:11 +00:00
Oleksiy Syvokon 5294e16547 Wait for worktree scan to complete before starting search (#54534)
When starting a search on a project that is in the middle of a scan, we
used to miss results in files that had not yet been scanned.

This change makes the search wait for the scan to complete.


Closes #9858

Release Notes:

- Fixed incomplete search results when the project scan is incomplete
2026-04-23 13:35:13 +00:00
109c2238aa Fix freeze when binary content written to open empty file (#53074)
Opening an empty file then writing binary content to it on disk causes a
permanent freeze (not a crash — requires force kill).

`reload_impl` loads raw bytes via `load_bytes` and decodes with
`encoding_rs` but never checks if the content is binary. The existing
binary check in `decode_file_text` only runs on fresh opens, not
reloads. So binary content enters the buffer as lossy UTF-8.

Binary data has almost no newlines, producing a single enormous row. The
wrap map's sync fast path in `flush_edits` checks row count (< 100 rows)
but not line length, so it runs `wrap_line` on a multi-MB single line
synchronously on the main thread via `smol::block_on`. Font shaping
millions of non-ASCII replacement characters blocks the UI thread
indefinitely.

Two fixes, both one-condition guards:
- Null-byte check in `reload_impl` before decoding, same heuristic
(first 8000 bytes) used by `decode_file_text` on fresh opens. Binary
content never enters the buffer.
- Column-length guard (`MAX_SYNC_WRAP_COLUMNS = 10_000`) on the wrap map
sync fast path so absurdly long lines fall through to the async
background path. Defense in depth for any single-line content that's too
long to shape synchronously.

## Test plan
- [ ] Open an empty file in Zed, write binary content to it externally
(e.g. `cp /bin/ls /path/to/open-file`) — should show "Binary files are
not supported" instead of freezing
- [ ] Open a compressed file (zip, gz) that starts empty and gets filled
— same behavior
- [ ] Normal text file reload still works (no regression)
- [ ] Very long single-line text files (>10k columns) don't freeze the
editor

---------

Co-authored-by: deadcode-walker <268043493+deadcode-walker@users.noreply.github.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-04-23 12:42:10 +00:00
Kunall Banerjee 96eb05166f lsp: Fix vtsls completeFunctionCalls setting being ignored (#53285)
Some language servers (notably `vtsls` with `completeFunctionCalls`)
update `insertText/textEdit` during `completionItem/resolve` to add
snippet content like function call parentheses. Previously,
`Completion.new_text` was only set from the initial completion response
and never re-derived after resolve, so the snippet text was silently
discarded.

Re-derive `new_text` from the resolved `lsp_completion`. Only the text
content is updated -- replace/insert ranges are left as anchors from the
original response since the LSP ranges in the resolved text_edit are
stale when completions are cached across keystrokes (re: #34094).

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

Closes #53275.

Release Notes:

- Fixed the `vtsls` `completeFunctionCalls` setting being ignored
2026-04-23 12:02:11 +00:00
Cole Miller 582f6a8fd3 Remove a debug_panic from the LSP store (#54549)
This is reachable when you pass a path to the Zed binary that doesn't
exist, so it feels a bit too aggressive.

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 ...
2026-04-23 07:25:55 +00:00
Korbin de ManandChris Biscardi e4e656fb42 Add "Add to .gitignore" action in project_panel (#47377)
This PR adds a "Add to .gitignore" action to the project panel's
right-click context menu. Similar to the "Restore File" action that I
previously added, I frequently find myself wanting this in the project
panel.

<img width="380" height="391" alt="image"
src="https://github.com/user-attachments/assets/e4438fbe-b070-40c8-9e57-84b003fa5c15"
/>

With the restore file option:
<img width="382" height="408" alt="image"
src="https://github.com/user-attachments/assets/84425de8-04e5-4969-8991-edc46e6420dc"
/>

Notes:
- **Implementation**: The `add_to_gitignore` function is essentially
copy-pasted from `git_panel.rs`.

- **Error handling**: Added toast notification on error, which is
consistent with `restore_file` in project_panel and `perform_checkout`
in git_panel.
Note that `add_to_gitignore` in git_panel does NOT show a toast (just
uses `detach_and_log_err`). I don't know if this is on purpose.
To follow up, I can either: match the project_panel implementation to
the git_panel one (no toast), or update the git_panel implementation to
also show a toast on error.

- **Menu grouping**: Previously "Restore File" and "View File History"
were in separate sections, but both relate to git. With this third git
action, I grouped all three together under a single separator (see
screenshot).
We could also keep "View File History" separate and only group "Restore
File" + "Add to .gitignore" together (both modify the working tree state
in some way), if we don't want to alter the existing UI too much.

Release Notes:

- Added "Add to .gitignore" option to the project panel context menu for
files in git repositories.

---------

Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
2026-04-23 05:46:58 +00:00
Anthony Eid 58c4dda8b9 git: Fix remote branch picker not showing branches (#54575)
This sends `branch_list` in live `UpdateRepository` messages so
downstream repository snapshots stay in sync and the remote branch
picker can populate correctly. Collab DB replay for join/reconnect will
follow in a separate change.

This fixes a bug where the branch picker wouldn't show any branches in
remote environments

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 #54530

Release Notes:

- git: Fix remote branch picker not showing any branches
2026-04-22 20:26:43 -04:00
Anthony EidandRemco Smits 72d004c8e8 git_graph: Add remote support for commit data handler (#54468)
### Motivation

To support remote Git graph usage, we need remote support for the Git
APIs that the graph depends on. This PR adds remote support for
`CommitDataHandler` (the `git cat-file --batch` process manager),
allowing remote Git graph consumers to fetch visible commit data without
polling.

#### Summary

The Git graph separates the UI and data layers so the UI can continue
rendering while commit data is fetched in the background. This change
extends that model to remote repositories by allowing
`GitStore::fetch_commit_data(sha: Oid, await_result: bool, cx: &mut
Context) -> &CommitDataState` to await remote commit loading.

For simplicity, the `Starting` variant was removed from
`CommitDataState`. `CommitDataState::Loading(Option<...>)` now stores
`Some(...)` when `await_result == true` is passed to
`fetch_commit_data`. This allows the data layer to await commit loading
without polling, and only when explicitly requested.

I also removed the `Graph` prefix from `CommitData`-related types
because this API is general-purpose and not limited to the graph. Longer
term, I hope to replace `Repository::show` with the commit data
functionality, since it already provides built-in caching.

#### Bug Fixes

- Fix stale `Loading(...)` entries that survive enqueue failure or
handler shutdown.
- Fix commit data handler bookkeeping so `pending_requests`,
`completion_senders`, and `CommitDataState` remain consistent.
- Fix remote commit-data loading so the data layer can await results
instead of polling.

#### Testing

- Add property tests for commit data fetching.
- Add a collab integration test that verifies batched remote commit-data
fetching.

#### Follow Up

In a follow-up, I want to replace the `Repository::show` backend with
the commit data handler and remove `CommitDetails` from the codebase as
a cleanup and maintenance pass. The commit data handler already provides
caching and is a better long-term path for commit metadata access.

I may also want to allow the `CommitData` type to propagate errors to
callers.

For the Git graph, the remaining work is remote search and initial data
fetching.

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: Remco Smits <djsmits12@gmail.com>
2026-04-22 16:11:51 -04:00
Kirill Bulatov 76883bb983 Support code lens in the editor (#54100) 2026-04-22 20:02:45 +03:00
meloceneandSmit Barmase 2a6ee04013 Add line_ending setting to control line-ending normalization (#54356)
Closes #49581

Adds a `line_ending` language setting that controls how line endings are
handled for new files and during format/save:

- `detect` (default) — detects existing line endings; new files use the
platform default
- `prefer_lf` / `prefer_crlf` — sets LF or CRLF for new files and files
with no existing convention, while preserving existing files
- `enforce_lf` / `enforce_crlf` — normalizes all line endings to LF or
CRLF on every format/save

The setting can be configured globally, per-language, or via
`.editorconfig`'s `end_of_line` property (which maps to `enforce_lf` /
`enforce_crlf`).

Release Notes:

- Added `line_ending` setting to control how line endings are handled
for new files and normalized on save.
- Added support for `.editorconfig` `end_of_line` property to enforce
line endings.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-04-22 22:21:26 +05:30
Conrad Irwin c97442029a Fix hang in replace all when the query contains non-ASCII text and regex-special characters (#54422)
Closes #54331
Updates #50848

Release Notes:

- Fixed hang in replace all when the query contained non-ASCII text and
regex-special characters
2026-04-22 10:47:52 -06:00
Hitesh RohiraandJohn Tur f8295ffaca Fix blank git diff view on Windows when working in a subfolder (#52234)
## Context

Fixes a Windows path handling bug in `crates/util/src/paths.rs` when
computing a relative path via `strip_prefix`. (Closes #51758 )

Previously, Windows prefix matching only handled drive-letter
case-insensitivity. It could still fail when the parent and child paths
referred to the same location but used different separator styles (`\`
vs `/`) or different casing in later path segments. That caused valid
Windows paths to return `None` instead of a relative path, which caused
the diff to break.

This change normalizes Windows paths for prefix comparison by
lowercasing any ASCII characters and converting backslashes to forward
slashes before checking the prefix.

Tests were added for mixed-case and mixed-separator Windows paths to
cover the bug and prevent further regressions.

## How to Review

1. Check the `strip_prefix` Windows branch to confirm the new
normalization logic only affects prefix comparison and still rejects
partial-segment matches.
2. Check the added tests for mixed separator and mixed casing cases on
Windows paths.

## 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:

- Fix blank git diff view on Windows when working in a subfolder

---------

Co-authored-by: John Tur <john-tur@outlook.com>
2026-04-21 18:24:49 -04:00
Oliver Azevedo Barnes 7db7ea9277 terminal: Use system shell for non-terminal uses (like spinning up external agents) (#51741)
Closes #46551

Zed was using the `terminal.shell` setting for some actions unrelated to
the terminal GUI, like environment capture, ACP agent startup, context
server startup, and vim `:!`, and so if a user set it to `tmux` or
`nushell`, those paths would fail.

This PR ensures paths unrelated to Zed's terminal use the system path
instead.

Manual testing:

Set `terminal.shell` to `tmux` or any another non-bash executable.

Starting an external agent thread shouldn't break.

Release Notes:

- Fixed ACP agent and other breakage when `terminal.shell` was set to a
non-shell program like `tmux`
2026-04-21 08:06:40 +00:00
Vinícius Dutra 4d78f26c27 Add support for Netpbm image previews (#54256)
This PR adds support for rendering **Netpbm** image formats (`.pbm`,
`.ppm`, `.pgm`) within Zed's built-in image viewer.

These formats are particularly useful for projects that want minimal
external dependencies, a common scenario in academic environments and
low-level graphics programming.

Since the underlying `image` crate and `GPUI` already provide support
for these codecs, this change explicitly exposes the `Pnm` variant
within `gpui::ImageFormat` by mapping it to `image::ImageFormat::Pnm`.

## Screenshots/Examples

Below is an example of `.pbm`, `.ppm`, and `.pgm` files being rendered
correctly in the image preview (images taken from
https://filesamples.com):
<img width="1917" height="1012" alt="pnm_example"
src="https://github.com/user-attachments/assets/0056133f-908c-4c91-ba9d-53aef0657b05"
/>



Release Notes:
  - Added support for PNM image previews (`.pbm`, `.ppm`, `.pgm`).
2026-04-20 16:51:13 +03:00
Arthur Fournier 03414d8058 languages: Fix Python LSP workspace folder detection in uv workspaces (#53781)
Closes #47926

  ## Summary

When using a uv (or Poetry/PDM) workspace with multiple subprojects,
Python LSP servers (Pyright, Ruff, ty, etc.) are initialized with the
subproject directory as their workspace folder instead of the workspace
root. This happens because `PyprojectTomlManifestProvider::search()`
returns the first (innermost)
  `pyproject.toml` found walking up the directory tree.

  For example, in a uv workspace like:

  main-project/
  ├── pyproject.toml       # workspace root with [tool.uv.workspace]
  ├── uv.lock
  ├── packages/
  │   └── project-api/
  │       └── pyproject.toml   # subpackage
  └── projects/
      └── project-a/
          └── pyproject.toml   # subpackage

Opening a file in `packages/project-api/` would register
`packages/project-api/` as the LSP workspace folder instead of
`main-project/`.

  ## Approach

The fix uses lockfile existence as a heuristic to detect workspace
roots. The updated `search()` method walks all ancestors (similar to
`CargoManifestProvider`) and:

  - Tracks the **innermost** `pyproject.toml` as a fallback
- Tracks the **outermost** `pyproject.toml` that has a sibling lockfile
(`uv.lock`, `poetry.lock`, `pdm.lock`, or `Pipfile.lock`)
- Returns the outermost workspace root if found, otherwise falls back to
the innermost

This works within the existing `ManifestDelegate` interface (existence
checks only, no file content reading).

  | Scenario | Result |
  |---|---|
| uv workspace (root `pyproject.toml` + `uv.lock`) | Returns workspace
root |
| Poetry workspace (root `pyproject.toml` + `poetry.lock`) | Returns
workspace root |
| Simple project (single `pyproject.toml`, no lockfile) | Returns
project dir (unchanged) |
| Independent subprojects (no lockfile at any level) | Returns each
project's own dir (unchanged) |

Since the manifest provider is set at the Python **language** level,
this fix applies to all Python LSP servers (Pyright, Ruff, ty, etc.).

  ## Test plan

- [x] Added unit tests for `PyprojectTomlManifestProvider` covering all
scenarios above
- [x] Existing integration test
`test_running_multiple_instances_of_a_single_server_in_one_worktree`
passes (independent subprojects without lockfiles)
  - [x] `cargo check -p languages` compiles cleanly
- [x] Manual testing with a real uv workspace (Pyright and Ruff both
receive correct workspace root)

Release Notes:

- Fixed Python LSP servers (Pyright, Ruff, etc.) using the wrong
workspace folder in uv/Poetry/PDM workspaces with multiple subprojects.
2026-04-20 10:10:03 +02:00
Max Brunsfeld 8c5dfe5691 Fix remote projects not appearing in the sidebar after adding them to the window (#54198)
Release Notes:

- N/A
2026-04-18 00:25:15 +00:00
Max Brunsfeld 7b0f59bd04 Clean up empty zed-created ancestor dirs of deleted worktrees (#54202)
Release Notes:

- N/A
2026-04-17 12:57:50 -07:00
Finn Eitreim 722f3089ed fuzzy_nucleo: Optimize path matching with CharBag prefilter and add benchmarks (#54112)
This PR was originally a part of
https://github.com/zed-industries/zed/pull/53551 so theres more info
about its motivation there.

- Add a CharBag prefilter on path candidates to skip irrelevant entries
before invoking nucleo's matcher.
- Use binary_search on sorted matched char indices when reconstructing
byte positions (perf improvement).
- Add a criterion benchmark comparing `fuzzy_nucleo` path matching
against the existing fuzzy crate.

Performance Chart:

| Benchmark | Size | Nucleo (before) | Nucleo (after) | Fuzzy |
Before/Fuzzy | After/Fuzzy |

|-----------|-----:|----------------:|---------------:|------:|-------------:|------------:|
  | 1-word | 100 | 14.14 µs | 9.12 µs | 9.06 µs | 1.56x | 1.01x |
  | 1-word | 1,000 | 164.37 µs | 114.11 µs | 110.43 µs | 1.49x | 1.03x |
  | 1-word | 10,000 | 1.83 ms | 1.39 ms | 1.41 ms | 1.30x | 0.99x |
  | 2-word | 100 | 12.83 µs | 3.51 µs | 979 ns | 13.10x | 3.59x |
  | 2-word | 1,000 | 131.65 µs | 33.46 µs | 6.37 µs | 20.67x | 5.25x |
  | 2-word | 10,000 | 1.24 ms | 338.84 µs | 52.46 µs | 23.64x | 6.46x |o

Exact Current State:
| query | size | nucleo | fuzzy | nucleo/fuzzy |
  |---|---:|---:|---:|---:|
  | 1-word | 100 | 8.62 µs | 9.22 µs | 0.93× |
  | 1-word | 1000 | 102 µs | 111 µs | 0.92× |
  | 1-word | 10000 | 1.13 ms | 1.28 ms | 0.88× |
  | 2-word | 100 | 3.48 µs | 0.98 µs | 3.55× |
  | 2-word | 1000 | 29.9 µs | 6.39 µs | 4.68× |
  | 2-word | 10000 | 271 µs | 53.4 µs | 5.08× |
  | 4-word | 100 | 0.85 µs | 0.53 µs | 1.60× |
  | 4-word | 1000 | 2.99 µs | 1.66 µs | 1.80× |
  | 4-word | 10000 | 20.1 µs | 9.14 µs | 2.20× |

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:

- fuzzy_nucleo: improved the performance of path matching
2026-04-17 16:20:45 +02:00
Yara 🏳️‍⚧️andAustin Cummings 73126dcb81 editor: Introduce Bookmarks (#54174)
Adds basic bookmark functionality to the editor, allowing users to mark
lines and later navigate between them. This is an MVP and will later be
expanded with a picker, vim marks integration and syntax tree based
bookmark positions. In this MVP bookmarks shift under external edits.

# UI
## Adding/Removing bookmarks
To add a bookmark:
- run the toggle bookmark action 
- hold secondary and click in the gutter
- open the context menu by right clicking in the gutter and select add
bookmark To remove a bookmark:
- run the toggle bookmark action 
- click on the bookmarks icon in the gutter
- open the context menu by right clicking in the gutter and select
remove bookmark

remove all bookmarks with `workspace: clear bookmarks`


# Implementation
This mirrors the implementation of breakpoints. The rendering of the
gutter was refactored to make place for bookmark icons and buttons:
- Code was extracted to a `Gutter` struct
- Runnables, breakpoints and bookmarks are now collected ahead of
layouting. Just before layouting we remove the items that collide and do
not have priority.
- The `phantom_breakpoint` is replaced by a `gutter_hover_button`

## In depth phantom breakpoint discussion:
This was phantom_breakpoint. It worked as follows:
 - A fake breakpoint was added to the list of breakpoints.
- While rendering the breakpoints it a breakpoint turned out to be fake
it would get a different description and look.
- The breakpoint list was edited run_indicators ("play buttons")
rendering to removes the fake breakpoint if it collided.

This would not scale to more functionality. Now we only render
breakpoints, bookmarks and run indicators. Then we render a button if
there is not breakpoint, bookmark or run indicator already present. We
can do so since the rendering of such "gutter indicators" has been
refactored into two phases:
 - collect the items.
 - render them if no higher priority item collides.

This is far easier and more readable which enabled me to easily take the
phantom_breakpoint system and use it for placing bookmarks as well :)

Note: this was previously merged but it needed a better squashed commit
message. For the actual PR see: 51404. This reverts commit
7e523a2d2b.

Release Notes:

- Added Bookmarks

Co-authored-by: Austin Cummings <me@austincummings.com>
2026-04-17 13:54:43 +02:00
Yara 🏳️‍⚧️ 7e523a2d2b Revert "editor: Bookmarks MVP" to update its description (#54163)
Reverts zed-industries/zed#51404 because I forgot to updated the
squashed commits description ....
2026-04-17 10:55:05 +00:00
Austin CummingsandYara 79473da756 editor: Bookmarks MVP (#51404)
Closes #4526

Adds basic bookmark functionality to the editor, allowing users to mark
lines and later navigate between them.

### What's new

**Toggling bookmarks**
Users can toggle a bookmark on the current line(s) via the `editor:
toggle bookmark` action. A bookmark icon appears in the gutter for each
bookmarked line.

**Navigation**
Two new actions, `editor: go to next bookmark` and `editor: go to
previous bookmark`, navigate between bookmarks in the current buffer,
wrapping around at the ends of the buffer.

**Viewing all bookmarks**
`editor: view bookmarks` opens all bookmarks across the project in a
multibuffer, similar to how references and diagnostics are surfaced.

**Clearing bookmarks**
`workspace: clear bookmarks` removes all bookmarks in the current
project.

**Persistence**
Bookmarks are persisted to the workspace database and restored when the
workspace is reopened. They are stored as `(path, row)` pairs and
resolved back to text anchors. Out of range or unresolvable bookmarks
are skipped with a logged warning.

**Gutter rendering**
Bookmark icons are rendered in the gutter using the existing gutter
button layout system, consistent with breakpoints. They are suppressed
on lines that already show a breakpoint or phantom breakpoint indicator.
A new `gutter.bookmarks` setting (defaulting to `true`) controls their
visibility.

### What's left

- [x] Lazily load buffers that have bookmarks
- [x] Clean up test boilerplate
- [ ] Assign default keybindings
- [ ] Compare line of saved bookmarks with current buffer (gray out the
"stale" bookmarks)

### What's next (and nice to haves)
- [ ] Resilience against external edits
- [ ] Save column position with the bookmark
- [ ] Bookmarks attached to syntactic structures?
- [ ] Labeled bookmarks?

---

Release Notes:

- Added bookmarks: toggle bookmarks on lines with `editor: toggle
bookmark`, navigate with `editor: go to next bookmark` / `editor: go to
previous bookmark`, view all bookmarks with `editor: view bookmarks`,
and clear with `workspace: clear bookmarks`. Bookmarks are shown in the
gutter and persisted across sessions.

---------

Co-authored-by: Yara <git@yara.blue>
2026-04-17 12:39:07 +02:00
Anthony EidandSmit Barmase 302e591e3d agent: Fix find_or_create repository to support remote (#54074)
### Summary

Follow up to: https://github.com/zed-industries/zed/pull/54001

This PR makes
`agent_ui::thread_worktree_archive::find_or_create_repository` whether
or not the repository it's searching for is on a remote machine. In the
case where it's on a remote machine that has an active connection in
Zed's connection pool, we return the repository; otherwise, we error
out.

I implemented it this way so archiving a thread on a remote machine that
isn't connected deletes the metadata without showing a remote connection
modal to a user. In the future, we can work around this by having better
git worktree garbage collection, where remote machines remove git
worktree's that were created by Zed and have no thread metadata on
connection too.

Finally, this PR gets archive threads working on remotes!


#### Follow Ups 

1. Replace instances of `std::fs` with Zed's Fs trait in the archive
thread codepaths
2. Make archive thread work properly for workspace's that are not open
(local and remote)

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: Smit Barmase <heysmitbarmase@gmail.com>
2026-04-16 16:36:09 -07:00
Bennet Bo Fenner dbb057b192 agent_ui: Do not save thread metadata for collab projects (#54094)
Make sure that we never write thread metadata to the DB for a thread
running on a collab project.

When joining a collab project and starting a native thread we would set
all your threads that had no paths associated with to the path of the
collab project (in `move_thread_paths`).

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
2026-04-16 20:05:57 +00:00
8fefbb1339 git_panel: Load template commit message (#42827)
Closes #41371

Release Notes:

- Adds loading commit message from template file set in `git config
commit.template`

---------

Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2026-04-16 10:14:52 -07:00
João Soares 11cfb9e330 Ensure language servers from extension properly start on workspace restoration (#51308)
Closes #49877

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Fixed extension language servers not starting when Zed launches with
files already open from a restored session.
2026-04-16 18:26:37 +02:00
Pratik KarkiandKirill Bulatov b6b2b63370 Gate Format Selections on whether the active formatter can actually format ranges (#53178)
## What Changed

- compute range-format support from formatter configuration and
language-server capabilities
- show `Format Selections` only when at least one selected buffer has a
range-capable formatter
- keep Prettier-supported range formatting available without depending
on LSP support
- hide the action for formatter modes that cannot honor selections, such
as external-command and code-action formatters
- keep the action handler safe by rechecking support and returning early
when range formatting is unavailable
- restrict capability checks to the servers actually registered for the
current buffer
- add regression coverage for supported, unsupported, and mixed-server
cases
- document when `Format Selections` is available in both action docs and
user docs


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 #25796

Release Notes:
- Improved `Format Selections` so it is only shown when the active
formatter supports range formatting.

Testing I did:

Here are the formatters I used:
<img width="829" height="434" alt="Screenshot_20260405_102047"
src="https://github.com/user-attachments/assets/cae4a238-277e-4188-873f-189e9f098699"
/>

Note: I've chosen three formatters:
1. Prettier, which supports range formatting
2. clangd (LSP) which also supports range formatting
3. gopls which do not support range formatting


[Screencast_20260405_102431.webm](https://github.com/user-attachments/assets/69ce3f95-0b73-46a0-853d-3b5be6329dde)

---------

Signed-off-by: Pratik Karki <pratik@prertik.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-04-16 09:11:22 +03:00
Anthony Eid d60b55675b agent: Support remote archive thread git operations (#54001)
### Summary

This PR implements remote support for git store operations that the
sidebar's archive thread checkpoint/restore featured relied on. This was
the second to last blocker for remote usage of this feature.

I also made a shared backend between `update_ref` and `delete_ref`
called `edit_ref` because they run the same git command and this allowed
for some code unification.

#### Remote Git Operations 
- `Repository::update_ref`
- `Repository::delete_ref`
- `Repository::repair_worktrees`
- `Repository::create_archive_checkpoint`
- `Repository::restore_archive_checkpoint`


#### Follow up

`agent_ui::thread_worktree_archive::find_or_create_repository` needs to
be made aware of the remote machine that the repository it's searching
for is on. Once that is completed, we can get the correct repo when
archiving a remote thread and the flow should work without any problems.

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
2026-04-15 19:55:37 +00:00
Danilo LealandNathan Sobo 6beecae6df agent_ui: Improve the new thread worktree UX (#53941)
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>
2026-04-15 03:47:19 +00:00
Cole Miller 652f1fa3b0 git: Fix a race that caused incorrect hunk staging information (#53929)
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.
2026-04-14 17:08:16 -04:00
Ben Brandt 07e9a2d25a acp: Use npm --prefix for registry npx agents (#53560)
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.
2026-04-14 11:10:31 +00:00
saberoueslati 5688167d22 recent_projects: Fix worktree path resolving to bare repo in recent projects modal (#52996)
## 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
2026-04-14 12:27:37 +03:00
Richard FeldmanandEric Holk 66ac781e65 Start new git worktrees in detached HEAD state (#53840)
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>
2026-04-14 00:35:28 +00:00
Cole Miller 9264f7f883 git: Add missing language_changed notification for branch diffs (#53757)
We need to reparse the base text using the same language as the main
buffer, whenever the main buffer's language changed. We already do this
for the uncommitted diff, but it was missing for the branch (OID-based)
diffs. (We don't need it for the unstaged diff because we don't
currently show you that base text anywhere in the UI, so its language is
immaterial.)

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
2026-04-13 13:09:56 -04:00
55e47138e9 agent_ui: Unify draft and background threads into retained threads (#53737)
> **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>
2026-04-13 09:07:09 +00:00
Max Brunsfeld b15969086e Set active repository when picking a root folder in recent project menu (#53645)
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
2026-04-10 12:12:42 -07:00
Richard Feldman 5d32b56e07 Disambiguate project names (#52848)
Disambiguate project names in the sidebar (and project picker) so that
we don't show e.g. `zed, zed` but rather `foo/zed, bar/zed` if the last
path component is the same but they are different absolute paths.

Release Notes:

- N/A
2026-04-09 14:11:55 -04:00
e25885bbe6 project_panel: Add redo and restore support (#53311)
- Introduce `project_panel::Redo` action
- Update all platform keymaps in order to map
`redo`/`ctrl-shift-z`/`cmd-shift-z` to the `project_panel::Redo` action

### Restore Entry Support

- Update both `Project::delete_entry` and `Worktree::delete_entry` to
return the resulting `fs::TrashedEntry`
- Introduce both `Project::restore_entry` and `Worktree::restore_entry`
to allow restoring an entry in a worktree, given the `fs::TrashedEntry`
- Worth pointing out that support for restoring is not yet implemented
for remote worktrees, as that will be dealt with in a separate pull
request
  
### Undo Manager

- Split `ProjectPanelOperation` into two different enums, `Change` and
`Operation`
- While thinking through this, we noticed that simply recording the
operation that user was performing was not enough, specifically in the
case where undoing would restore the file, as in that specific case, we
needed the `trash::TrashedEntry` in order to be able to restore, so we
actually needed the result of executing the operation.
- Having that in mind, we decided to separate the operation (intent)
from the change (result), and record the change instead. With the change
being recorded, we can easily building the operation that needs to be
executed in order to invert that change.
- For example, if an user creates a new file, we record the
`ProjectPath` where the file was created, so that undoing can be a
matter of trashing that file. When undoing, we keep track of the
`trash::TrashedEntry` resulting from trashing the originally created
file, such that, redoing is a matter of restoring the
`trash::TrashedEntry`.
- Refer to the documentation in the `project_panel::undo` module for a
better breakdown on how this is implemented/handled.

- Introduce a task queue for dealing with recording changes, as well as
undo and redo requests in a sequential manner
- This meant moving some of the details in `UndoManager` to a
`project_panel::undo::Inner` implementation, and `UndoManager` now
serves as a simple wrapper/client around the inner implementation,
simply communicating with it to record changes and handle undo/redo
requests
- Callers that depend on the `UndoManager` now simply record which
changes they wish to track, which are then sent to the undo manager's
inner implementation
- Same for the undo and redo requests, those are simply sent to the undo
manager's inner implementation, which then deals with picking the
correct change from the history and executing its inverse operation
- Introduce support for tracking restore changes and operations
- `project_panel::undo::Change::Restored` – Keeps track that the
file/directory associated with the `ProjectPath` was a result of
restoring a trashed entry, for which we now that reverting is simply a
matter of trashing the path again
- `project_panel::undo::Operation::Restore` – Keeps track of both the
worktree id and the `TrashedEntry`, from which we can build the original
`ProjectPath` where the trashed entry needs to be restored
- Move project panel's undo tests to a separate module
`project_panel::tests::undo` to avoid growing the
`project::project_panel_tests` module into a monolithic test module
- Some of the functions in `project::project_panel_tests` were made
`pub(crate)` in order for us to be able to call those from
`project_panel::tests::undo`
  
### FS Changes

- Refactored the `Fs::trash_file` and `Fs::trash_dir` methods into a
single `Fs::trash` method
- This can now be done because `RealFs::trash_dir` and
`RealFs::trash_file` were simply calling `trash::delete_with_info`, so
we can simplify the trait
- Tests have also been simplified to reflect this new change, so we no
longer need a separate test for trashing a file and trashing a directory
- Update `Fs::trash` and `Fs::restore` to be async
- On the `RealFs` implementation we're now spawning a thread to perform
the trash/restore operation

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

Relates to #5039

Release Notes:

- N/A

---------

Co-authored-by: Yara <git@yara.blue>
Co-authored-by: Miguel Raz Guzmán Macedo <miguel@zed.dev>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2026-04-09 18:49:16 +01:00
d812adc833 sidebar: Better handling for threads in remote workspaces (#53451)
This PR greatly improves our handling of remote threads in the sidebar.

One primary issue was that many parts of the sidebar were only looking
at a thread's path list and not its remote connection information. The
fix here is to use `ProjectGroupKey` more consistently throughout the
sidebar which also includes remote connection information.

The second major change is to extend the MultiWorkspace with the ability
to initiate the creation of remote workspaces when needed. This involved
refactoring a lot of our remote workspace creation paths to share a
single code path for better consistency.

Release Notes:

- (Preview only) Fixed remote project threads appearing as a separate
local project in the sidebar

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2026-04-09 06:56:28 +00:00