Makes it so that "Restore checkpoint" shows up as soon as the model
performs an edit, instead of waiting until the turn ends
Release Notes:
- Fixed the agent panel to show "Restore checkpoint" as soon as the
agent starts editing instead of waiting until the turn ends
Closes:
- https://github.com/zed-industries/zed/discussions/56359
Self-Review Checklist:
- [ YES ] I've reviewed my own diff for quality, security, and
reliability
- [ N/A ] Unsafe blocks (if any) have justifying comments
- [ N/A ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ YES ] Tests cover the new/changed behavior
- [ YES ] Performance impact has been considered and is acceptable
Open to feedback or alternate approaches.
Could do `--ssh user@host:~code/proj` if preferred.
Or really cowboy it: regex replace `s|:~|/~|` and `s|:/|/|`; re-attempt
`Url::parse`
CC: @ConradIrwin
Release Notes:
- Add support for SCP style SSH urls: `zed ssh://user@host:~/code/proj`
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
------
This PR adds a settings panel above the CSV table with dropdown menus to
control rendering behavior, and a performance metrics overlay for
debugging.
Currently it's mostly used for me during dev phase, but before release
of CSV preview feature all dev-only options will be cleaned up, and
future features like "copy selected" will have their settings in this
bar
<img width="2260" height="1674" alt="image_2026-04-09_11-52-24"
src="https://github.com/user-attachments/assets/9039fd59-5c46-4be4-9f33-b9825a3cdce3"
/>
**What changed:**
- Adds `render_settings_panel()` method with dropdown menus for:
- **Rendering Mode**: Variable Height (multiline support) vs Uniform
Height (better performance)
- **Text Alignment**: Top vs Center vertical alignment within cells
- **Font Type**: UI Font vs Monospace for better readability (will be
exposed to user settings)
- **Experimental**: Popover menu with toggles for debug features
- Adds `render_performance_metrics_overlay()` method showing:
- CSV parsing duration
- Rendered row count and indices
- Positioned in bottom-right corner with semi-transparent styling
Context:
Will iterate on it with @Anthony-Eid
Release Notes:
- N/A
---------
Co-authored-by: Anthony Eid <anthony@zed.dev>
Treat `.agents/skills/` (project-local) and `~/.agents/skills/` (global)
as **sensitive paths**, on par with `.zed/` and the global config
directory. The agent's built-in editing tools (`edit_file`,
`write_file`, `create_directory`, `delete_path`, `move_path`,
`copy_path`) now require explicit user authorization before modifying
anything inside those paths, because the contents of skill files control
agent behavior.
This protection is worth landing on its own, ahead of Zed adding its own
skills support: other agents (e.g. Claude Code) already write skill
files into these locations, so a Zed installation may already have
skills on disk that should not be silently editable by the agent.
Also tightens the **pre-existing `.zed/` check** to compare path
components case-insensitively. macOS and Windows use case-insensitive
filesystems by default, so without this fix a malicious settings author
could bypass the local-settings classifier with `.ZED/settings.json`
(the canonicalized inode would match, but the path-component comparison
would miss it). The new `.agents/skills/` check has the same hazard and
now shares a single `component_matches_ignore_ascii_case` helper with
the `.zed/` check.
Introduces the `agent_skills` crate, scoped for now to just the path
constants and helpers (`global_skills_dir`,
`project_skills_relative_path`, `SKILL_FILE_NAME`) so the
tool-permission machinery can recognize the agent skills tree without
depending on a skill discovery / parsing / loading layer. Those will
land in follow-up PRs.
Closes AI-217
Release Notes:
- Agent: Require user confirmation before letting tools modify files
inside `.agents/skills/` (per-project) or `~/.agents/skills/` (global),
so skills installed by any agent are protected from unsolicited edits
---------
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Co-authored-by: Martin Ye <martinye022@gmail.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
The Bedrock Converse API supports placing `CachePoint` blocks inside the
`system` field, but we were sending the system prompt as a single
`SystemContentBlock::Text`, which leaves the system tokens dependent on
whatever message-level breakpoint happens to fall within the 20-block
lookback window.
This widens `bedrock::Request.system` from `Option<String>` to
`Vec<BedrockSystemContentBlock>` and has `into_bedrock` emit
`[Text(system), CachePoint(Default)]` whenever the model supports prompt
caching. The system prompt now anchors its own cache prefix, on top of
the existing tool-list anchor and per-message breakpoint, so a stable
system prompt keeps producing cache hits even when earlier conversation
turns change.
Bedrock does not support automatic caching or the 1-hour TTL, so the
default 5-minute ephemeral cache is the only option for this provider.
Release Notes:
- Improved Bedrock prompt cache utilization by anchoring the system
prompt as its own cache prefix
Closes#55481
Adds Vim-mode access to the existing Helix jump-to-word overlay via `g
z`. We use `g z` because it is currently unassigned in Vim mode, while
`g w` is already used for rewrap.
Most of the implementation lives in `helix.rs` because the existing jump
overlay, label generation, and Helix/Vim modal behavior are currently
intertwined there. This keeps the change small and reuses the existing
navigation overlay logic instead of doing a broader refactor.
In Vim normal mode, jump labels behave like a cursor motion: selecting a
label moves the cursor to the start of the target word without selecting
it. In Vim visual mode, jump labels extend the selection like a Vim
word-start motion, preserving Vim’s inclusive visual-selection behavior.
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:
- Added Vim-mode jump-to-word navigation on `g z`.
## Context
The process_tool_use closure used a single chars_read_so_far counter
shared across all REWRITE_SECTION_TOOL_NAME tool use events. When the
LLM produced multiple separate rewrite tool uses (different IDs), the
counter from the first tool use carried over into the second. If the
second tool use had a shorter replacement_text, the slice indexing
panicked with index out of bounds.
(This caused my first ever Zed panic today.)
Fix by tracking bytes-read per tool use ID using a HashMap keyed on
LanguageModelToolUseId. Also replace the direct slice index with .get()
so any remaining out-of-bounds case is handled gracefully instead of
panicking.
Looks like it hasn't been reported yet. At least I couldn't find any
related issues.
## How to Review
I hope the fix is pretty self-explanatory. We keep track of multiple
rewrite tools, which explains the extra ceremony around getting the
right character count, but apart from that it's pretty straightforward.
The performance impact should be neglible because:
1. Once the completion stream ends (or the task is dropped/cancelled),
the entire Arc<Mutex<HashMap>> is freed.
2. The number of entries is tiny. In a single completion request the LLM
will produce at most a handful of
REWRITE_SECTION_TOOL_NAME tool uses. Each entry is just an Arc<str> key
+ usize value.
So the HashMap grows for the duration of one handle_completion call and
is then dropped wholesale.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [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 an out-of-bounds panic when the AI produced multiple inline
rewrites in a single completion.
Switches the Anthropic provider from hand-stamping `cache_control` onto
the last message content block over to Anthropic's top-level automatic
prompt caching, paired with explicit long-TTL (1h) anchors on the last
tool definition and on the system prompt.
The prefix order `tools` → `system` → `messages` satisfies Anthropic's
requirement that longer TTLs appear earlier in the prefix, so the static
prefix is cached for 1h (surviving idle gaps longer than the 5-minute
default) while the rapidly-changing conversation tail uses the
free-to-refresh 5-minute TTL via the top-level automatic breakpoint.
Three of the four available cache breakpoints are used (last tool,
system, automatic conversation), leaving one in reserve.
As a side benefit, this fixes a latent issue where the previous stamping
loop could place `cache_control` on a `Thinking` content block, which
the Anthropic API does not allow. Automatic caching is documented to
walk past ineligible blocks (including thinking) when selecting its
breakpoint, so we now delegate that responsibility to the server.
The new shape we send (when caching is enabled):
```json
{
"tools": [{ "...": "...", "cache_control": {"type": "ephemeral", "ttl": "1h"} }],
"system": [
{"type": "text", "text": "...", "cache_control": {"type": "ephemeral", "ttl": "1h"}}
],
"messages": [ /* no per-block cache_control */ ],
"cache_control": {"type": "ephemeral"}
}
```
Release Notes:
- Improved Anthropic prompt cache utilization, reducing latency and cost
for ongoing conversations
---------
Co-authored-by: Martin Ye <martinye022@gmail.com>
Resolves https://github.com/zed-industries/zed/issues/56518
This diff fixes code lens decorations continuing to paint into the
gutter when the editor is horizontally
scrolled. Code lens entries were rendered as flex editor blocks with
explicit gutter padding, which allowed
them to bypass the text viewport clipping used by content-only blocks.
With this change, code lens entries render as spacer-style custom blocks
instead. Spacer blocks already
scroll with buffer content and paint through the text-side mask, so the
code lens padding can be relative to
the editor text area and decorations clip at the left edge of the
viewport.
| Before | After |
| --- | --- |
| <video
src="https://github.com/user-attachments/assets/dc567ce5-ad04-4ba2-9156-ec4ec087bd41"
controls width="320"></video> | <video
src="https://github.com/user-attachments/assets/abb5ba2c-981f-4399-903b-0f8fa9a560e4"
controls width="320"></video> |
Release Notes:
- Fixed code lens decorations painting outside the editor viewport when
horizontally scrolling.
Code had been assuming (erroneously, but understandably) that
LlmApiToken::acquire would give them a valid token.
This is not true, as those tokens expire and you must call refresh
explicitly.
Add some helpers to do the retry for you, and rename acquire to cached
to be
clearer about the intent.
Closes #ISSUE
Release Notes:
- Fixed some rare cases where API requests would fail with Unauthorized
Follows similar approach as
https://github.com/zed-industries/zed/pull/55927
Adds a force-delete path to the worktree picker. Normal delete now
prompts when Git reports modified or untracked files, and
Alt/Option-delete can force delete directly.
Release Notes:
- Added support for force deleting worktrees that contain modified or
untracked files.
## Summary
Fixes scroll position inversion when content height changes during a
scrollbar drag (e.g. in the agent panel while streaming responses).
### Root cause
`set_offset_from_scrollbar` used the **live** `items.summary().height`
for `content_height` and computed a `drag_offset` correction (`live −
frozen`). However, `max_offset_for_scrollbar()` → `max_scroll_offset()`
already uses the **frozen** `scrollbar_drag_start_height` during drag.
This mismatch means:
1. The scrollbar computes thumb position using the frozen height range
2. `set_offset_from_scrollbar` converts that position using the live
height range
3. As content grows during drag, `drag_offset` increases
4. `(point.y - drag_offset).abs()` produces an incorrectly large value,
overshooting `scroll_max`
The `.abs()` call also masked the sign convention:
`compute_click_offset` (in `scrollbar.rs`) returns `-max_offset *
percentage` — a negative value — but `.abs()` converted it regardless of
sign, hiding the mismatch.
### Fix
- Use `scrollbar_drag_start_height` (frozen during drag) for
`content_height` in `set_offset_from_scrollbar`, matching
`max_scroll_offset()`. Both sides of the scrollbar mapping now use the
same height reference.
- Replace `(point.y - drag_offset).abs()` with `(-point.y)` to correctly
convert the negative scroll offset.
- Remove the symmetric `drag_offset` from
`scroll_px_offset_for_scrollbar`, which reported position back to the
scrollbar and suffered from the same inconsistency.
- Update existing tests to use negative offsets, matching the actual
values produced by the scrollbar component.
- Add a regression test that freezes height, grows content, drags the
scrollbar, and asserts the position is correct.
## Test plan
- [x] Existing tests updated to use correct sign convention (negative
offsets)
- [x] New regression test `test_scrollbar_drag_with_growing_content`:
verifies scroll position remains correct when content grows during a
scrollbar drag
- [ ] Manual: open agent panel, start a long generation, drag scrollbar
while content is streaming — position should track the thumb correctly
Release Notes:
- Fixed scrollbar position jumping or inverting when content height
changes during a scrollbar drag (e.g. in the agent panel while
streaming).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Adds streaming RPC forwarding to collab so guests can call
`GetInitialGraphData` and `SearchCommits` against a remote host project.
Previously these requests had no forwarder registered on the server and
would fail when invoked by a guest.
This mirrors the existing single-response forwarding pattern with new
analogues:
- `StreamResponse<R>` + `MessageContext::forward_request_stream`
- `Server::add_request_stream_handler`
- `forward_read_only_project_stream_request`, registered for both
messages
Also hardens both the unary and stream handlers to send
`respond_with_error` when a handler returns `Ok` without sending/ending
a response, so the client doesn't hang waiting for a reply that will
never arrive.
I added git graph collab integration tests for this as well.
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#55954
Release Notes:
- N/A
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:
- Fixed an issue where re-running the `git: branch diff` after changing
the active project would not refresh the branch diff to show the branch
diff of the active project
This PR adds support to create custom git task that are triggered from
the git graph context menu. Both Sublime Merge and Fork have custom
command support, and I use custom commands I've built out frequently to
speed up some of my tasks at Zed. Thus, I'd like to have support in
Zed's git graph so I can use Zed even more!
It offers initial support for the following env variables:
- `ZED_GIT_SHA`
- `ZED_GIT_SHA_SHORT`
- `ZED_GIT_REPOSITORY_NAME`
- `ZED_GIT_REPOSITORY_PATH`
These are only populated in the git graph context.
This PR also introduces a the `git-command` tag, which is needed so the
git graph can filter down to these custom git commands, and so other
tasks aren't polluting the context menu.
An example would be (in the global `tasks.json`):
```json
{
"label": "Branches containing commit: $ZED_GIT_SHA_SHORT",
"command": "git",
"args": ["branch", "-a", "--contains", "$ZED_GIT_SHA"],
"tags": ["git-command"],
},
```
And then in the context menu:
<img width="646" height="296" alt="SCR-20260511-mnfa"
src="https://github.com/user-attachments/assets/0e7b811b-f47d-4a2f-9270-99e392c38663"
/>
And the output in the terminal:
<img width="585" height="184" alt="SCR-20260511-mnks"
src="https://github.com/user-attachments/assets/54d7d205-6212-4eff-8dbb-c8e908996747"
/>
The awesome thing about using tasks is we get all the task
infrastructure for free, such as history!
<img width="591" height="292" alt="SCR-20260511-mnud"
src="https://github.com/user-attachments/assets/6315be8f-dd33-470f-bfcd-aa56d7fbfdce"
/>
<img width="602" height="173" alt="SCR-20260511-moch"
src="https://github.com/user-attachments/assets/b528422c-efcc-4a7d-9783-73d945e9665b"
/>
And we have all the task configuration options too out of the box.
---
Right now, this only works with global tasks. It isn't clear how to shoe
in support for worktree-specific tasks (`.zed/tasks.json`) in a clear
way, as not all invocations of the git graph are in an area that has a
clear worktree id, and so we sort of have to guess or fallback to
something else. That can be a followup once it's more clear how we
should cover that. Or maybe someone else has a better solution.
I chose to only ship with these 4 git-specific variables for now. The
git graph also currently ONLY resolve those variables. We can adjust /
add in more in follow up PRs.
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:
- Added support for running global custom Git command tasks from the Git
Graph commit context menu.
This PR adds a history view to the git panel. It draws from similar
implementations of commit listing in other places like the file history
view and the git graph.
| Changes View | History View |
|--------|--------|
| <img width="2600" height="2026" alt="Screenshot 2026-05-12 at 3
38@2x"
src="https://github.com/user-attachments/assets/00d7d21b-8516-481a-a34e-86589b8ced52"
/> | <img width="2688" height="2114" alt="Screenshot 2026-05-12 at 3
39@2x"
src="https://github.com/user-attachments/assets/4a87c04a-011b-40fc-a04c-b791720d9abc"
/> |
Release Notes:
- Git: Added a history view to the Git panel that allows to quickly see
in a list all the commits for a given branch.
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
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
This PR replaces the `TransitionalUserService` with the
`CloudUserService`, as all of the calls are now all going through Cloud.
This allows us to delete the `TransitionalUserService`, the
`DatabaseUserService`, as well as the backing database queries that are
no longer used.
Closes CLO-758.
Release Notes:
- N/A
This PR makes it so we route the `UserService::search_channel_members`
call through Cloud instead of hitting the database.
This is the last of the calls to be routed through Cloud. We'll clean up
the old database-backed implementations in a follow-up PR.
Closes CLO-746.
Release Notes:
- N/A
Here are the overall changes I'm adding in this PR:
- Don't create a new thread when switching to a new external agent while
in parked draft state
- Include parked draft threads in the thread switcher
- Add the draft thread item in the sidebar when navigating away from a
draft, as opposed to only on cmd-n/new thread
- Upon deleting content from a parked draft, remove its entry from the
sidebar. From this point on, we convert that draft back into the
ephemeral state so it behaves the same way as a fresh new draft would.
Release Notes:
- N/A
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 or Added/Fixed/Improved ...
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 (none)
Release Notes:
- Google: Added Gemini 3.1 Flash Lite
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Helps #51567
Refs #54531
Summary:
- Add total timeouts for ACP Registry JSON fetches and icon fetches,
including response body reads.
- Download registry icons concurrently and keep icon failures non-fatal,
so a blocked icon CDN does not delay registry availability by one
timeout per agent.
- Surface the stored registry fetch error in the ACP Registry empty
state and add a retry action.
This addresses cases where the registry request, or one of the icon
requests, never finishes. It does not make blocked networks succeed, but
it prevents the UI from sitting on `Loading registry...` indefinitely
and gives the user something actionable instead.
Test plan:
- `git diff --check HEAD~1..HEAD`
- `cargo fmt --check --package project --package agent_ui`
- `cargo check -p project`
- `cargo check -p agent_ui`
- `cargo test -p project --features test-support registry_refresh_`
Release Notes:
- Fixed the ACP Registry getting stuck on loading when registry or icon
requests hang.
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
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#56314
When running `cargo run -p gpui --example hello_world` on a wayland
linux machine, the code panics and give the following output:
```
thread 'main' (15645) panicked at crates/gpui_linux/src/linux.rs:55:14:
internal error: entered unreachable code
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
and the related code is:
c8f09caee4/crates/gpui_linux/src/linux.rs (L29-L57)
`gpui::guess_compositor()` correctly returns `"Wayland"`, but the
corresponding match arm is gated behind `#[cfg(feature = "wayland")]` in
`gpui_linux`, and that feature is never enabled. During the extract
gpui_platform refactor (#49277), the `wayland` and `x11` features were
added to the `zed` binary's dependency on `gpui_platform`, but were
missed in the `[dev-dependencies]` of `gpui/Cargo.toml`, which is what
the examples use.
This PR adds the missing features to the dev-dependency so that
`gpui_platform` propagates them to `gpui_linux` when building examples.
Release Notes:
- N/A or Added/Fixed/Improved ...
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
## Summary
Expose whether the scrollbar is currently being dragged via a new
`is_scrollbar_dragging()` method on `ListState`.
This returns `true` between `scrollbar_drag_started()` and
`scrollbar_drag_ended()` calls. It lets consumers distinguish scrollbar
drags from wheel/trackpad scrolls, which is useful for suppressing
auto-scroll or follow-tail behavior during manual scrollbar positioning.
## Test plan
- [x] Code review — one-liner accessor, delegates to existing
`scrollbar_drag_start_height` field
- [ ] Verify compilation with `cargo check -p gpui`
Release Notes:
- N/A
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This PR makes the empty states of the Git panel a little bit more
polished by making font sizes and button placement more consistent. Also
ended up cleaning up the `panel_button` abstraction as that felt a bit
unnecessary. We're just using the buttons directly like we do in other
places in the codebase.
Release Notes:
- N/A
## Summary
- Adds a new concept page (`docs/src/windows-and-projects.md`)
explaining how Zed handles multiple projects in windows
- Fixes the VS Code migration guide which incorrectly stated "Zed does
not support multi-root workspaces"
- Adds cross-links from Getting Started, CLI Reference, and Parallel
Agents docs
## Context
With multi-workspace now universally enabled, the default behavior is:
- **File > Open** opens projects in the current window's sidebar (not a
new window)
- **Cmd+Enter** in Open Recent opens in a new window
- **CLI `-n` flag** forces a new window
The VS Code migration guide was telling users the opposite of reality.
This PR fixes that and provides a central concept page that other docs
can link to.
## Changes
| File | Change |
|------|--------|
| `windows-and-projects.md` | New concept page |
| `SUMMARY.md` | Add to Working with Code section |
| `getting-started.md` | Note about sidebar default + link |
| `migrate/vs-code.md` | Fix "no multi-root" claim → explain sidebar
model |
| `reference/cli.md` | Link to concept page from flags section |
| `ai/parallel-agents.md` | Cross-reference in Multiple Projects section
|
## Test plan
- [ ] Verify page renders correctly on docs site
- [ ] Check all internal links resolve
- [ ] Confirm `{#kb projects::OpenRecent}` renders the correct
keybinding
Release Notes:
- N/A
Follow-up to #54791 with some fixes to the activity indicator which
resulted in
- the button no longer being clickable when it should
- the indicator showing a spinner instead of the proper symbol when
downloading or when it should show a warning symbol
Release Notes:
- Fixed some issues where the activity indicator would show the wrong
icon and not be clickable on errors present.
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#54689
Release Notes:
- Support editing the thread title for external agent threads
This fixes extension installation when Zed's cache directory and data
directory are on different filesystems or mount points. On my Linux
system, `~/.cache` is a separate btrfs subvolume so it can be excluded
from system snapshots, while `~/.local/share` is on the main home
subvolume. Installing extensions failed because extension archives were
unpacked under `paths::temp_dir()` and then renamed into the installed
extensions directory.
The error showed up as:
```text
2026-05-11T17:08:57+02:00 INFO [extension_host] installing extension dockerfile latest version
2026-05-11T17:08:58+02:00 ERROR [crates/extension_host/src/extension_host.rs:842] Invalid cross-device link (os error 18)
```
Linux rename(2) returns EXDEV (os error 18) across filesystem
boundaries. This is the same class of issue addressed for settings
writes in #8437 and later generalized in
2b3e453d2f. The regression was introduced
by #54355, which made extension updates safer by unpacking into a
temporary directory before renaming into place.
This change creates the temporary unpack directory inside the installed
extensions directory instead. That keeps the final rename on the same
filesystem as the destination while preserving the existing
direct-unpack fallback if creating the temporary directory fails. A
possible alternative would be to create a dedicated temporary install
directory under `extensions/`, alongside `extensions/installed/`. I
chose, however, to keep the temporary directory directly beside the
final destination because that matches the destination-local temp-file
approach used in the earlier fixes referenced above.
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
No separate issue. The change is small and includes the reproduction
context here. I did not add a regression test because the failure
depends on cache and data directories being on different
filesystems/subvolumes; this was verified manually by reproducing EXDEV
when installing extensions with `~/.cache` on a separate btrfs
subvolume, then confirming the patch fixes extension installation.
Release Notes:
- Fixed installing extensions when Zed's cache and data directories are
on different filesystems.
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 ...
## Background: Amazon Bedrock Guardrails
AWS Bedrock Guardrails enables configurable safety and compliance
controls for generative AI applications:
- Evaluates both user inputs and model responses against policies.
:contentReference[oaicite:8]{index=8}
- Can block or filter content based on harmful categories, denied
topics, PII, or hallucination criteria.
:contentReference[oaicite:9]{index=9}
- Guardrails are applied during inference API calls by specifying
`guardrailIdentifier` and `guardrailVersion` in the request.
:contentReference[oaicite:10]{index=10}
Relevant AWS documentation:
- User Guide:
https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html
- How Guardrails Works:
https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-how.html
- API Reference (GuardrailConfiguration):
https://docs.aws.amazon.com/bedrock/latest/APIReference/API_GuardrailConfiguration.html
Some AWS environments enforce IAM policies that require a guardrail to
be specified on every Bedrock API call (via a `StringEquals` condition
on `bedrock:GuardrailIdentifier`). Without this, Zed returns
`AccessDenied` and Bedrock models are completely unusable in those
environments.
This adds two optional settings, `guardrail_identifier` and
`guardrail_version`, to the Bedrock provider config. When set, a
`GuardrailStreamConfiguration` is attached to every `converse_stream`
request. When unset, behaviour is identical to before.
```json
{
"language_models": {
"bedrock": {
"guardrail_identifier": "arn:aws:bedrock:us-east-1:123456789012:guardrail/abc123",
"guardrail_version": "DRAFT"
}
}
}
```
`guardrail_version` defaults to `"DRAFT"` if omitted.
Release Notes:
- agent: Added `guardrail_identifier` and `guardrail_version` settings
for AWS Bedrock, enabling use in environments where IAM policies require
a guardrail on all model requests
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This PR makes it so we route the `UserService::fuzzy_search_users` call
through Cloud instead of hitting the database.
Closes CLO-745.
Release Notes:
- N/A
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A or Added/Fixed/Improved ...
Self-Review Checklist:
- [ ] 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
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Closes https://github.com/zed-industries/zed/issues/56219
Contains 3 commist:
*
https://github.com/zed-industries/zed/pull/56380/changes/a8d55273d6cddb39868a1fd669c5069a1133a373
shows better errors when CLI or main binary fail early: no backtraces,
better error context, diff file paths shown
*
https://github.com/zed-industries/zed/pull/56380/changes/d389f7ee239dcf9bfa2bfe91729d96d2c1931663
stops opening Zed if cli `--diff` path argument(s) does not exist, also
switches over async fs API on the Zed side.
This is a behavior change, as before Zed tried to open or connect to an
instance — can be reverted if needed.
With `Path::exists` check CLI will do now:
<img width="669" height="55" alt="now"
src="https://github.com/user-attachments/assets/bdfbef2f-1b28-443d-8a01-0ff73ec0bba1"
/>
If I remove that bit, Zed will now open in the same cwd where the CLI is
invoked in:
<img width="1724" height="639" alt="reverted"
src="https://github.com/user-attachments/assets/69cd171b-aca3-445b-8647-5786f3360ce4"
/>
*
https://github.com/zed-industries/zed/pull/56380/changes/49787b7366336711b5bfc11ba3661f3ba70ce8ca
fixes an underlying bug leading to memory leak.
If on current `main`, I apply
```diff
diff --git a/crates/zed/src/zed/open_listener.rs b/crates/zed/src/zed/open_listener.rs
index 18ea7c0869..5db22521f2 100644
--- a/crates/zed/src/zed/open_listener.rs
+++ b/crates/zed/src/zed/open_listener.rs
@@ -791,6 +791,7 @@ async fn open_local_workspace(
// working directory so the workspace opens with the right context.
if !user_provided_paths && !diff_paths.is_empty() {
if let Ok(cwd) = std::env::current_dir() {
+ log::error!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {cwd:?}");
workspace_paths.push(cwd.to_string_lossy().into_owned());
}
}
```
I see the following logs:
```
2026-05-11T09:52:35+03:00 INFO [zed] ========== starting zed version 1.3.0+dev.7bdcb6172263dc05c0b59be76e09f3e89e23e4f1, sha 7bdcb61 ==========
2026-05-11T09:52:36+03:00 INFO [zed] Using git binary path: "/Applications/Zed Dev.app/Contents/MacOS/git"
2026-05-11T09:52:36+03:00 INFO [util] set environment variables from shell:/bin/zsh, path:/opt/homebrew/opt/llvm/bin:/Applications/Postgres.app/Contents/Versions/16/bin/:/Users/someonetoignore/Developer/PlaydateSDK/bin/:/Users/someonetoignore/.docker/bin/:/opt/homebrew/opt/armv7-unknown-linux-gnueabihf/bin/:/opt/homebrew/opt/rustup/bin/:/opt/homebrew/opt/go@1.19/bin/:/usr/local/opt/llvm/bin/:/Users/someonetoignore/.jetbrains/bin/:/Users/someonetoignore/.cargo/bin/:/usr/local/git/bin/:/opt/homebrew/Cellar/openjdk@21/21.0.6//bin/:/Users/someonetoignore/.local/state/fnm_multishells/75815_1778482356501/bin:/opt/homebrew/opt/ruby/bin:/opt/homebrew/lib/ruby/gems/4.0.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pkg/env/active/bin:/opt/pmk/env/global/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Applications/Wireshark.app/Contents/MacOS:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Users/someonetoignore/Library/pnpm:/opt/homebrew/opt/llvm/bin:/Applications/Postgres.app/Contents/Versions/16/bin/:/Users/someonetoignore/Developer/PlaydateSDK/bin/:/Users/someonetoignore/.docker/bin/:/opt/homebrew/opt/armv7-unknown-linux-gnueabihf/bin/:/opt/homebrew/opt/rustup/bin/:/opt/homebrew/opt/go@1.19/bin/:/usr/local/opt/llvm/bin/:/Users/someonetoignore/.jetbrains/bin/:/Users/someonetoignore/.cargo/bin/:/usr/local/git/bin/:/opt/homebrew/Cellar/openjdk@21/21.0.6//bin/:/Users/someonetoignore/.local/state/fnm_multishells/23413_1778480085615/bin:/opt/homebrew/opt/ruby/bin:/opt/homebrew/lib/ruby/gems/4.0.0/bin:/Users/someonetoignore/.cargo/bin:/Applications/iTerm.app/Contents/Resources/utilities:/Users/someonetoignore/.orbstack/bin:/Users/someonetoignore/.orbstack/bin
2026-05-11T09:52:36+03:00 INFO [zed::reliability] Debug assertions enabled, skipping hang monitoring
2026-05-11T09:52:36+03:00 WARN [zed::reliability] Minidump endpoint not set
2026-05-11T09:52:36+03:00 INFO [extension_host] extensions updated. loading 21, reloading 0, unloading 0
2026-05-11T09:52:37+03:00 ERROR [crates/zed/src/main.rs:1936] canonicalizing "crates/grammars/src": No such file or directory (os error 2)
2026-05-11T09:52:37+03:00 INFO [client] set status on client 0: Authenticating
2026-05-11T09:52:37+03:00 ERROR [zed::zed::open_listener] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ "/"
2026-05-11T09:52:37+03:00 INFO [project::trusted_worktrees] Worktree "/" is not trusted
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/.VolumeIcon.icns": canonicalizing "/.VolumeIcon.icns": No such file or directory (os error 2)
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/Users/someonetoignore/.gitconfig.zed": canonicalizing "/Users/someonetoignore/.gitconfig.zed": No such file or directory (os error 2)
2026-05-11T09:52:37+03:00 INFO [workspace] Rendered first frame
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/usr/lib/libnetwork.dylib": canonicalizing "/usr/lib/libnetwork.dylib": No such file or directory (os error 2)
2026-05-11T09:52:37+03:00 WARN [fs] Failed to read symlink target metadata for path "/usr/sbin/weakpass_edit": Permission denied (os error 13)
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/usr/sbin/weakpass_edit": canonicalizing "/usr/sbin/weakpass_edit": Permission denied (os error 13)
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/usr/lib/libz.1.2.12.dylib": canonicalizing "/usr/lib/libz.1.2.12.dylib": No such file or directory (os error 2)
2026-05-11T09:52:37+03:00 ERROR [worktree] error reading target of symlink "/usr/lib/libpcre2-8.dylib": canonicalizing "/usr/lib/libpcre2-8.dylib": No such file or directory (os error 2)
2026-05-11T09:52:38+03:00 ERROR [worktree] error reading target of symlink "/var/run/docker.sock": canonicalizing "/var/run/docker.sock": No such file or directory (os error 2)
2026-05-11T09:52:38+03:00 ERROR [worktree] error processing "/var/db/DifferentialPrivacy": Operation not permitted (os error 1)
2026-05-11T09:52:38+03:00 ERROR [worktree] error reading target of symlink "/usr/lib/libipconfig.dylib": canonicalizing "/usr/lib/libipconfig.dylib": No such file or directory (os error 2)
2026-05-11T09:52:38+03:00 ERROR [worktree] error reading target of symlink "/private/var/run/docker.sock": canonicalizing "/private/var/run/docker.sock": No such file or directory (os error 2)
2026-05-11T09:52:38+03:00 ERROR [worktree] error processing "/private/var/db/DifferentialPrivacy": Operation not permitted (os error 1)
2026-05-11T09:52:38+03:00 ERROR [worktree] error processing "/Library/Caches/com.apple.amsengagementd.classicdatavault": Operation not permitted (os error 1)
2026-05-11T09:52:38+03:00 ERROR [worktree] error reading target of symlink "/usr/lib/libpcre2-posix.dylib": canonicalizing "/usr/lib/libpcre2-posix.dylib": No such file or directory (os error 2)
2026-05-11T09:52:38+03:00 ERROR [worktree] error processing "/Library/Caches/com.apple.aneuserd": Operation not permitted (os error 1)
2026-05-11T09:52:38+03:00 ERROR [worktree] error processing "/Library/Caches/com.apple.aned": Operation not permitted (os error 1)
```
According to
https://apple.stackexchange.com/questions/284754/what-is-the-default-working-directory-of-a-script-run-via-launchd
, the current directory of a running macOS app could be `/` if started
the way similar to how we do it via the CLI:
7bdcb61722/crates/cli/src/main.rs (L1306-L1329)
This means that every `std::env::current_dir()` is potentially dangerous
currently, as e.g. diff code tries to open this `/` as a worktree and
index it fully.
It seems that we're "ok" for now: the dangerous code is mostly in
extensions (there we set the cwd) and cli tools, and 2 places in
"development" Zed's code are left after this one is fixed.
There's one in `fs.rs` but that one is cfg-gated to Windows only hence
should not be an issue, at least the related one.
I'm not sure if this is the best way to fix the issue: setting `/` as an
app's current directory seems also wrong and maybe that invocation CLI
code could be altered somehow?
Maybe, `open_local_workspace` could be reworked somehow?
Seems that now we need a "shared directory" for both files we diff which
seems inevitable though, hence I've went on with passing the CLI's
current dir when opening items and that fixes the `/` issue along with
the OOM for now.
Release Notes:
- Fixed a memory leak with diffing non-existing files with Zed cli