# Objective
Let git indicators — the editor gutter, file colors, and `git::Diff` —
show all changes on the current branch relative to its merge base with
the default branch, instead of only uncommitted changes.
Supersedes #60398; thanks to @samuelcolvin for the original
implementation and motivation.
Closes FR-135
## Solution
- New `git.diff_base` setting (`"head"` | `"default_branch"`), applied
live and toggleable per session from the editor controls menu ("Diff
Against Default Branch").
- Statuses come from a real merge-base-to-worktree tree diff (`git diff
--merge-base`), so local edits that revert branch changes correctly show
as unchanged.
- `GitStore` shares one `DiffBufferList` per repository with the Branch
Diff view; `repo_snapshots` and `project_path_git_status` keep returning
index/worktree truth, while display surfaces use separate `display_*`
APIs.
- `BufferDiff` now records what its base is (`DiffBaseKind`); hunks
whose base isn't HEAD are read-only in the gutter — stage/restore
buttons and keybindings are inert, so committed work can't be silently
rewritten.
- `git::Diff` follows the setting; new `git::DiffHead` always opens the
HEAD diff; `git::BranchDiff` is renamed `git::DiffBranch` (deprecated
alias kept).
Tradeoffs / known limitations:
- Hunk-level staging is unavailable while in `default_branch` mode
(whole-file staging via the git panel still works). Staging just the
uncommitted sub-ranges of a branch hunk is a follow-up.
- Remote hosts running an older server ignore the new
`GetTreeDiff.includes_worktree` proto field and degrade to
committed-changes-only branch diffs.
- Repositories with no resolvable default branch fall back to
HEAD-relative behavior; a failed first resolution retries on the next
branch-list change.
## Testing
- Real-git-repo tests for the merge-base-to-worktree diff's edge cases:
files recreated after index deletion, committed deletions recreated on
disk, and symlinks.
- GPUI tests for status semantics (a branch change reverted on disk
shows clean), `git::Diff` routing, live setting changes, and read-only
hunk enforcement (restore/stage leave buffer and index untouched).
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Git: Added a `git.diff_base` setting (`"head"` or `"default_branch"`)
that makes the editor gutter, file colors, and diff view show all
changes on the current branch since its merge base with the default
branch, instead of only uncommitted changes.
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Applies the same fix as #43277 to Zed's native agent, which indeed fixes
this issue for me locally (which I could only reproduce when
specifically telling the agent to not use `--no-pager`, FWIW).
Closes#42943
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed hang when the Zed Agent runs a `git` command with a pager
configured.
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Fixes the bug that made us remove the sandbox.
The bug in question was very dumb:
- there is sophisticated machinery for detecting whether a user-granted
writable path is swapped out for a symlink in the timing gap between
approval and sandbox creation
- there was no equivalent machinery to do the same for the (much larger)
gap between a user *persisting an approval* (either for the current
thread or permanently via settings)
- The fix is essentially to store canonical (i.e. absolute and
symlink-free at all depths) paths as the source of truth, but retain the
raw path for display purposes
- On WSL, there is extra care needed becasue of the bidirectional
mounting (i.e. `/mnt/c/...` and `\\wsl.localhost\Ubuntu\...`). In
particular, `/mnt/c/...` paths, since their inodes do not necessarily
pin NTFS file references, weaken the sandbox guarantees, and so we need
some extra UI to call this out and docs etc...
This also does not remove the feature flag, but just toggles it to
"enabled_for_all"
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
# Objective
- Treat a follow-up sent during pending tool approval as a denial the
agent can understand.
## Solution
- Preserve the follow-up interruption through permission handling and
return a specific denial result to the model.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Agent: Fixed agents not recognizing follow-up messages as denial of
pending tool calls.
## Summary
- Open relative file links with GitHub-style line fragments at the
referenced line
- Support line navigation from agent responses and Markdown previews
- Preserve decoded-first path resolution with literal percent-escape
fallback
## Testing
- cargo test -q -p util test_source_line_from_fragment -- --nocapture
- cargo test -q -p acp_thread test_hyperlink_percent_escapes_are_decoded
-- --nocapture
- cargo test -q -p agent_ui test_open_link -- --nocapture
- cargo test -q -p markdown_preview -- --nocapture
- cargo fmt --all -- --check
Release Notes:
- Improved relative file links with line numbers to open at the
referenced line.
This is necessary to remove some `util` dependencies from crates, as
well as better sharing for our projects. This also includes the WIP
AbsPath abstraction as well as some bug fixes from internal tooling.
Release Notes:
- N/A or Added/Fixed/Improved ...
Closes security loopholes and updates docs:
- installs seccomp filter for blocking naughty syscalls
- tightens macos seatbelt profile
- fetch tool responses that redirect are now constrained by allowed
domains list
Also adds a few "Learn More" buttons that link to the new docs.
Also fixes a bug where the agent would try to create a
`~/.config/zed/AGENTS.md` directory
Also adds unicode confusable detection to URL/path privilege escalation
prompts.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Removes the feature flag. The RFD is in Preview and I am confident it
will be stable without major changes by the time this hits Zed Stable.
Release Notes:
- acp: Allow ACP agents to use Elicitation capturing structure user
input.
`update_last_checkpoint` swallows `compare_checkpoints` errors with
`.unwrap_or(true)`. The "Restore checkpoint" button silently disappears
and nothing gets logged, which is what made the linked issue painful to
track down in the first place.
The sibling `update_last_checkpoint_if_changed` a few lines up already
handles the same call with `.context(...).log_err()` and an early
return, so I did the same here. On error the checkpoint's visibility is
left alone instead of being forced to hidden. I didn't propagate the
error because the task result gets `?`'d in `run_turn`'s cleanup, and
failing there would leave the panel stuck in its generating state.
Added a regression test that breaks the comparison mid-turn (recreating
`.git` makes the fake repo forget its checkpoints) and asserts an
already-visible checkpoint stays visible. It fails on main and passes
with this change. The new log line shows up when it runs: `failed to
compare checkpoints: invalid left checkpoint: ...`
Closes#59100
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 checkpoint comparison errors silently hiding the "Restore
Checkpoint" button in the agent panel.
Co-authored-by: pstemporowski <110726755+pstemporowski@users.noreply.github.com>
Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
Fixes#53527.
## Summary
- Suggest `untitled.<extension>` when saving an untitled editor buffer
with a selected non-Plain Text language.
- Preserve the existing title-based suggestion for existing files, Plain
Text buffers, and buffers without a language extension.
- Add a regression test for an untitled Rust buffer suggesting
`untitled.rs`.
## Testing
- `mise exec rust@1.95.0 -- cargo fmt --check -p editor`
- `mise exec rust@1.95.0 -- cargo test -p editor
test_suggested_filename_uses_language_extension_for_untitled_buffer
--lib`
## Suggested .rules additions
None.
Release Notes:
- Fixed Save As suggestions for untitled buffers with a selected
language.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
## Summary
Fix agent message hyperlinks that point to Windows file paths but are
not parsed as openable project paths.
This covers links like:
```md
[Cargo.toml](</C:/Projects/Example Workspace/Cargo.toml:2>)
[filename.ext](C:\Projects\Example%20Workspace\path\to\filename.ext:42)
[AGENTS.md](</c/Projects/Example Workspace/AGENTS.md>)
```
## Problem
Agent responses can emit Markdown hyperlinks whose targets are Windows
paths rather than `file://` URLs. Some of those targets include a
leading slash before the drive (`/C:/...`), Git Bash/MSYS-style drive
prefixes (`/c/...`), percent-escaped spaces, or line suffixes. These
were not normalized before mention parsing, so clicking the hyperlink
could do nothing instead of opening the file.
## Solution
- Normalize hyperlink path targets before parsing them as `MentionUri`
paths.
- Decode percent escapes in bare path targets so `%20` becomes a literal
space before path/line parsing.
- Convert Windows-compatible hyperlink paths such as `/C:/...` and
`/c/...` into native Windows paths.
- Generate file resource links from `find_path_tool` through
`MentionUri::to_uri()` instead of hand-building `file://` strings.
## Result
Before: clicking agent path hyperlinks did not open the referenced file.
After:
https://github.com/user-attachments/assets/6c7fad77-4a1e-4497-a4f9-4a4fdf86d527
## Validation
- `cargo test -p acp_thread test_parse_windows --features test-support`
- `cargo fmt --check`
## Follow-up changes
Additions on top of the original work above:
- Moved the hyperlink heuristics into a dedicated
`MentionUri::parse_hyperlink` entry point. `MentionUri::parse` stays
strict, so canonical mention URIs round-trip verbatim and other callers
(message editor, thread deserialization, resource links) are unaffected.
- Percent escapes that decode to path separators (`%2F`, `%5C`) are left
encoded, so decoding can never change which directories a path
traverses.
- Bare paths with escapes are ambiguous (a file may literally be named
`a%20b.rs`): `open_link` prefers the decoded interpretation and falls
back to `MentionUri::parse_hyperlink_literal` when the decoded path
doesn't resolve in the project but the literal one does.
- Links to files outside the project's worktrees now open, gated by an
async existence check through the project `Fs` (correct for remote
projects; broken links no longer create empty buffers or add worktrees).
`open_link` and the mention-crease open path are unified into one
`open_abs_path_at_point`, which now also places the cursor for
out-of-project selection/symbol links.
- `grep_tool` resource links also go through `MentionUri::to_uri()` now,
fixing malformed `file://C:\...` URIs and unencoded spaces.
- Added tests: percent-escape disambiguation, out-of-project link
opening, drive-letter normalization, UNC paths, and literal-path parsing
(`cargo test -p acp_thread mention`, `cargo test -p agent_ui open_link`,
`cargo test -p agent grep_tool`); manually verified the link spellings
above on Windows.
Release Notes:
- Fixed agent path hyperlinks on Windows when paths contain spaces or
shell-style drive prefixes.
---------
Co-authored-by: Martin Ye <martin@zed.dev>
# Objective
ACP agents (Cursor, Claude Code, Codex, etc.) start a display-only
`terminal::Terminal` for each bash tool call. After the call exits, the
terminal stays alive so that its output stays visible. But the
`alacritty` `Grid` keeps a `Storage` cache that's never reclaimed.
Across a long session this memory adds up.
Partially fixes#57099
## Solution
Added `Terminal::shrink_to_used`, called from the `Exit` branch of
`on_terminal_provider_event`. This calls `Grid::truncate()` on the
alacritty grid, shrinking the `Storage` cache portion while leaving
user-visible scrollback.
## Testing
- `cargo nextest run -p terminal
shrink_to_used_preserves_user_visible_scrollback` passes — exercises the
path with >10K rows of scrollback.
- `./script/clippy` clean.
- Manually verified: ran a noisy bash tool call via an ACP agent,
observed exit, then scrolled back through the output, no regression.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Improved memory usage of ACP terminals after the tool call exits
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This PR removes/simplifies some APIs that were leftover after moving the
agent settings from the agent panel into the agent settings UI.
Behavior/UI should be identical.
- Removed `ConfigurationViewTargetAgent` since only a single variant was
used
- Removed `configuration_view` and `configuration_view_v2` and replaced
it with `settings_view`
- Removed all the custom configuration views that were replaced by the
API key view abstraction
- Removed `intitial_title` and `initial_description` and moved it to
`ProviderSettingsView`
Release Notes:
- N/A
Removes git sandbox feature
The reason is essentially:
- write access to a `.git` dir can be trivially escalated to unsandboxed
access
- therefore, it is misleading to offer git access separate from
unsandboxed access
- instead, we encourage the model to use `--no-optional-locks` to avoid
needing write access to `git status`, etc.
Adds sandboxing to fetch tool
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Behind a feature flag as we iterate on the RFD
Release Notes:
- N/A
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Large change to sandboxing:
- fixes a nasty TOCTOU relating to a symlink swap attack, documented in
the `sandboxing/README.md`
- Adds UI and restrictions when in an untrusted workspace
- Adds tests for (soon to be removed) git support
---
Release Notes:
- N/A or Added/Fixed/Improved ...
# Objective
Fix the agent `terminal` tool in headless eval environments. In the eval
sandbox, terminal commands failed before the shell ran with `IOError:
Not a tty (os error 25)` because PTY setup attempted to acquire a
controlling terminal.
## Solution
- Add a `terminal::HeadlessTerminal` global that is set by `eval_cli`
only.
- When headless mode is enabled, run terminal task commands as plain
subprocesses with piped stdout/stderr instead of opening a PTY.
- Pump subprocess output through the existing terminal emulator/event
channel so output capture, completion, and task killing keep working.
- Build ACP terminal commands non-interactively in headless mode.
- Keep the normal editor terminal path unchanged when the global is
unset.
- Handle non-PTY output edge cases by preserving split CRLF sequences
and avoiding an indefinite wait if subprocess exit-status polling
errors.
## Testing
- `cargo fmt --all`
- `cargo test -p util non_interactive_omits_interactive_flag`
- `cargo test -p terminal test_no_pty_task_terminal_captures_output`
- `cargo test -p terminal test_convert_lf_to_crlf_preserves_split_crlf`
- `cargo test -p terminal test_write_output`
- `cargo check -p eval_cli`
- `git --no-pager diff --check`
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed the agent terminal tool failing with "Not a tty" in
headless/eval environments
# Objective
Fix unreliable working/status indicators for ACP agent threads.
ACP threads update their internal running state when a turn starts,
completes, or is canceled, but those status-only changes were not being
emitted as thread events. The agent UI could miss transitions unless
another entry-related event happened nearby, making it particularly hard
to monitor the status of multiple agent threads running at once.
Hope this helps, and thanks for making Zed.
## Solution
- Add an `AcpThreadEvent::StatusChanged` event.
- Emit it when `running_turn` is set, cleared, or canceled.
- Have `ConversationView` handle the event by syncing the active thread
view's generating indicator.
- Treat status changes as UI state only, not root thread metadata
changes.
## Testing
- `cargo check -p sidebar -p project -p git_ui -p workspace`
- Manually verified in a local dev build on macOS that ACP agent
status/working indicators update reliably.
No automated test was added; this changes UI synchronization for ACP
thread status events.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed unreliable working indicators for ACP agent threads.
This separates the two user-message identities we currently need in
agent threads:
- `protocol_id`: the ACP `messageId` used to group or split streamed
message chunks from ACP agents.
- `client_id`: the Zed-generated user message ID used by the native
agent for truncate, rewind, edit/regenerate, checkpoints, token usage,
and persistence.
The main behavior change is that ACP protocol message IDs now affect
message merging/rendering without leaking Zed-native client IDs into ACP
agents by default. Agents that can accept Zed-generated user message IDs
opt into that path through `AgentSessionClientUserMessageIds`, which
owns both ID generation and prompt submission. The native Zed agent
implements that capability; normal ACP agents continue through the
protocol-only `prompt` path.
In ACP v2 we'll have a mechanism for getting user message replays that
will allow the agent to adequately generate it's own opaque id that we
can then use for these other capabilities. But for now, this split at
least makes sure we keep the two concepts distinct.
Release Notes:
- N/A
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
We weren't handling these really before, just rendering the URI. This
should provide best-effort support for what we can render.
<img width="800" height="359" alt="image"
src="https://github.com/user-attachments/assets/51f101c7-c3be-4801-9000-62000a71faa6"
/>
(I will remove the extra labels that was just for testing)
Release Notes:
- acp: Support embedded resources in tool calls.
Agent terminal sandboxing now protects `.git` metadata by default and
exposes an explicit `allow_git_access` approval. Without it, file
contents of the `.git` directories for opened worktrees and discovered
repositories (including a linked worktree's common `.git`) cannot be
read or written, though their metadata stays visible; when approved,
those Git directories become writable so commands like fetch/commit
work. SSH commit signing keeps working because the inherited
`SSH_AUTH_SOCK` is allowed as local Unix-socket IPC, which does not let
sandboxed commands send network packets to other machines. The Seatbelt
profile also allows PTY terminal-control ioctls so signing/passphrase
prompts can manage terminal state.
This intentionally restricts only `.git` itself (whose location we know
exactly, including the worktree case) rather than
`.gitignore`/`.gitattributes`/`.gitmodules`, since those can be nested
arbitrarily and the goal is to keep the policy expressible as a plain
deny-by-default allowlist that will port to Linux and Windows sandboxes
later.
Closes AI-334
Release Notes:
- Improved agent terminal sandboxing for Git metadata, Git worktrees,
and SSH commit signing.
## Summary
Fixes#37815.
`State::fetch_models()` calls `/api/tags` to list models, then calls
`/api/show` for **every** model in that list to get its capabilities,
collecting the results with `collect::<Result<Vec<_>>>()?`. If
`/api/show` errors for even one model, the whole batch fails and
`fetched_models` is never populated. Since `is_authenticated()` is
defined as `!self.fetched_models.is_empty()`, this means a single bad
model permanently breaks both authentication state and the model picker
for the entire Ollama provider - with no error surfaced anywhere (not
the UI, not the logs), which matches the reports in #37815 of "Connect
does nothing" / "no logs, no nothing".
I hit this myself: I had a stale local reference to an Ollama Cloud
model that had been retired server-side. `/api/show` for that one model
returned `410 Gone`, which silently broke Connect and the model picker
for every other model too. Removing the retired model with `ollama rm`
fixed it immediately, which confirmed the root cause.
## Fix
Instead of aborting the whole fetch on the first error, skip individual
models that fail `/api/show` and log a warning, keeping the rest.
Extracted this into a small `skip_failed_models` helper so it's
unit-testable without mocking HTTP.
## Disclosure
I used Claude (Anthropic's Claude Code) to help track down this root
cause (tracing through `fetch_models`/`is_authenticated` in this file)
and draft the fix + tests below. I reviewed and understand the change -
it's a small, targeted fix to a single function plus two unit tests for
the new helper.
## Test plan
- [x] `cargo check -p language_models` passes
- [x] `cargo test -p language_models --lib ollama::` - all 3 tests pass
(the 2 new ones plus the existing
`test_merge_settings_preserves_display_names_for_similar_models`,
unaffected by this change)
- [x] `cargo fmt -p language_models -- --check` - no diff
## Release Notes
Release Notes:
- Fixed Ollama models silently failing to show up in the model picker
(and "Connect" appearing to do nothing) when a single model's details
couldn't be fetched, e.g. a retired Ollama Cloud model
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Follow-ups to the recently-landed agent terminal sandboxing work.
- Make the persistent "Allow Unsandboxed Terminal Commands" setting
(`allow_unsandboxed`) the single off-switch for the agent terminal
sandbox: when enabled, the sandboxed terminal tool isn't exposed and the
system prompt omits the sandbox section, so the model uses the plain
`terminal` tool (and on Windows, WSL sandbox setup is skipped). This
removes the dead, unwired `disabled` setting that was meant to do the
same thing but had no UI, writer, or docs. Per-command and per-thread
`unsandboxed: true` grants are unchanged.
- Expand the blocklist of Windows-specific environment variables that
aren't forwarded into the WSL sandbox (system locations, `HOME`/profile
paths, host/session identity, CPU descriptors, etc.) so they can't
shadow or break Linux commands. It stays a blocklist, so portable
variables like `LANG` still reach the command.
Release Notes:
- N/A
We finally have a cancellation mechanism to use! Made the non
side-effectful handlers stop their work if we get a cancel request
notification.
Release Notes:
- N/A
Summary
- Adds Windows agent terminal sandboxing by routing commands through WSL
and Bubblewrap.
- Supports native Windows and WSL project paths, including elevated
write grants for WSL paths.
- Shows a confirmation prompt to turn off sandboxing when WSL sandbox
setup is unavailable.
This builds on the work in the sandbox-linux branch.
Closes AI-376
Release Notes:
- Added Windows terminal sandboxing for agent commands when sandboxing
is enabled.
---------
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Adds UI for the various scenarios where sandboxing can fail on linux:
- no `bwrap` on the path
- `bwrap` is setuid
- `bwrap` exists but cannot create unprivileged userns
---
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: Martin Ye <martin@zed.dev>
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Co-authored-by: Martin Ye <martin@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
This makes unrestricted sandbox network access an explicit sandbox mode
instead of a fallback when the enforcing proxy is unavailable.
Host-specific network access still uses the proxy, while approved
arbitrary network access skips proxy setup and maps directly to
unrestricted egress.
Release Notes:
- Improved agent terminal sandbox network permission handling.
---------
Co-authored-by: Martin Ye <martin@zed.dev>
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Final PR of a four-PR stack adding hostname-allowlisted network access
to agent terminal sandboxing. Stacked on #59219 — review/merge #59217,
#59218, and #59219 first.
Spawns the `http_proxy` allowlisting proxy for sandboxed terminal
commands that request network, and pins the Seatbelt policy to its
loopback port (`NetworkAccess::LocalhostPort`) so all egress is forced
through it. The child's proxy environment variables are pointed at the
proxy and any inherited `NO_PROXY` is blanked so nothing connects
direct; a real upstream proxy from the environment is chained through
when present. The proxy and its Seatbelt config file share one RAII
handle so both live exactly as long as the command, and per-connection
events are drained to the log.
The proxy binds loopback, so it only applies to local projects on macOS;
elsewhere the wrap falls back to unrestricted egress as before (the
agent layer widens such requests accordingly).
Release Notes:
- Added the ability to grant agent terminal commands network access to
specific hosts (rather than all-or-nothing), enforced by an allowlisting
proxy.
---------
Co-authored-by: Martin Ye <martin@zed.dev>
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Third of a four-PR stack adding hostname-allowlisted network access to
agent terminal sandboxing. Stacked on #59218 — review/merge #59217 and
#59218 first.
Replaces the boolean `allow_network` terminal-sandbox escalation with a
hostname allowlist. The `terminal` tool now takes `allow_hosts` (exact
hostnames or leading-`*.` subdomain wildcards, validated up front) and
`allow_all_hosts` as a broad escape hatch. Approval prompts name the
requested hosts, thread grants and persistent "allow always" settings
cover requests via host-pattern subsumption the same way write paths use
subtree containment, and the authorization card in the agent panel lists
the requested hosts.
Host allowlists aren't enforced yet in this PR: `SandboxWrap` carries
the allowlist, but any network request still maps to unrestricted egress
at the Seatbelt layer, matching previous behavior. Enforcement via the
in-process proxy lands in the final PR of the stack. All of this is
behind the existing sandboxing feature flag. For non-local projects
(where the loopback proxy won't apply), host requests are widened to
"arbitrary network access" before prompting so approvals match
enforcement. Old persisted `network: bool` authorization details still
deserialize via a serde alias.
Release Notes:
- N/A
---------
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Co-authored-by: Martin Ye <martin@zed.dev>
Fourth PR of the stack adding hostname-allowlisted network access to
agent terminal sandboxing. Stacked on the `http_proxy` crate PRs
(#59217, #59222, #59223) — review/merge those first; this PR's diff is
only the sandbox change.
Replaces the `allow_network: bool` field on the macOS Seatbelt
`SandboxPermissions` with a `NetworkAccess` enum: `None` (block all
egress), `All` (the previous `allow_network: true` behavior), and
`LocalhostPort(u16)`, which confines a sandboxed command to a single
loopback port. The new variant emits a Seatbelt rule permitting outbound
TCP only to `localhost:<port>` and isn't constructed yet; it exists to
pin sandboxed commands to the in-process network proxy in a later PR.
The sole consumer maps its existing boolean to `All`/`None`, so behavior
is unchanged.
Release Notes:
- N/A
Summary:
- Include terminal command text in sandbox authorization metadata.
- Render the command in sandbox permission prompts, including prompts to
run outside the sandbox.
- Keep write-path details visible alongside the command when both are
present.
Tests:
- cargo test -p agent sandbox
- cargo check -p agent_ui
Release Notes:
- Improved agent sandbox permission prompts to show the command being
requested.
Closes AI-393
When the user proactively cancels a turn, we mark all pending entries as
cancelled. But if something else stops/halts a turn, we weren't doing
that in the case of compaction, which means we would be stuck in a
loading state forever.
Release Notes:
- N/A _(feature hasn't been publicly released yet so no notes)_
Allows contents to update without dropping the permission (caused by
claude subagents)
Closes
https://github.com/agentclientprotocol/claude-agent-acp/issues/708
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 failed permissions requests for external agents
Running `/compact` rendered a `/compact` user-message bubble during the
live session, but that text is never sent to the model as an ordinary
user turn — it triggers a built-in compaction that produces its own
"Context compacted" entry. Showing the bubble was misleading (it implied
the model received `/compact`), and it was also inconsistent: after a
reload the bubble vanished, since the persisted thread only carries an
empty marker. This changes the direction so native slash commands are
never echoed as user messages at all, live or after reload.
`AcpThread` gains a `send_command` path that runs the turn (so the agent
still receives and handles `/compact`) without pushing a user-message
entry or capturing a git checkpoint. In the UI, `leading_native_command`
now matches a native command whether or not it has trailing text, so
both `/compact` and `/compact do X` route through the command path; the
queued-message path detects native commands too, so a `/compact` typed
while a turn is generating behaves the same. MCP/ACP commands are
unaffected and still render as normal user messages, since their text is
a real argument the agent consumes.
Release Notes:
- N/A
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Fixes an issue where compaction would get marked as cancelled if the
previous turn took a while to cancel. E.g. you could reproduce this when
sending a normal message, and then interrupting generation by sending
`/compact`. If the task for the prior turn took a while to complete, it
would mark the compaction triggered by `/compact` as cancelled, even
though it was not.
Release Notes:
- N/A
This PR changes how base texts are managed by the `buffer_diff` crate,
to enable keeping two diff entities alive that share the same base text
buffer entity. Previously, each diff owned its own base text buffer and
edited it when calling `BufferDiff::set_snapshot`, so the only way to
reuse the same base text between two diffs was to have two independent
buffers for it, which is pretty inefficient.
After this PR, each diff still has a base text buffer, but
`set_snapshot` doesn't edit it. Instead, that responsibility moves into
the caller. For updating the base text buffer, this PR also introduces a
new pair of APIs, `Buffer::snapshot_with_edits` and
`Buffer::fast_forward`, which allow us to move the parsing of the new
base text into the background and then install the new syntax tree
synchronously on the foreground.
The git store uses the low-level APIs `set_snapshot` and `fast_forward`
directly, and manages the head text and index text buffers itself
(garbage-collecting them when they're no longer needed); this enables
adding an `open_staged_diff` API which returns a diff between the
managed index buffer and the managed head buffer (the latter is also
used for the uncommitted diff's base text). Other downstreams don't need
to reuse a base text buffer, and those have been migrated to use the
high-level `set_base_text` API, which now calls `set_snapshot` and
`fast_forward` internally, with a guard to prevent concurrent updates.
Another change worthy of note is that we now always diff the old base
text with the new base text to create `snapshot_with_edits`.
There are also some incidental bug fixes:
- Fixed an issue where a dangling weak unstaged diff could stick around
in the git store forever
- Restored the `IndexMatchesHead` optimization that had become
inoperative in the remote case
- Fixed a crash in the multibuffer due to the handling of
`BufferDiffEvent::LanguageChanged`, which could cause the multibuffer to
have transforms that were inconsistent with the diff base text.
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 ZED-81P
Release Notes:
- Fixed a rare crash that could occur while using the uncommitted diff.
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
<img width="325" height="201" alt="Screenshot 2026-06-09 at 1 38 32 PM"
src="https://github.com/user-attachments/assets/a6518073-1e17-41ff-a8fc-cb279fcd4436"
/>
Adds support for Anthropic's Claude Fable 5 model when using your own
Anthropic API key. Because Fable 5 cannot be offered under Zero Data
Retention (Anthropic retains inference logs for 30 days), this gates the
model behind an explicit data-retention consent: a new
telemetry.anthropic_retention setting (default off, surfaced in the
Privacy section of the settings UI), and a hard, non-retryable check in
the cloud completion path that raises a typed error when consent is
missing.
When Fable 5 declines a request, it transparently falls back to Claude
Opus 4.8 (matching Anthropic's server-side behavior), and the agent
panel shows a callout for the consent error with "Switch to Opus 4.8" /
"Accept" actions that resume the failed turn so the user's message
continues without retyping.
Closes AI-382
Release Notes:
- Add Claude Fable 5 to Anthropic BYOK
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
We can't compute the actual token usage until we send a new request, so
we hide the token count until you send another message. Matching the
behaviour that we have for new threads
Release Notes:
- N/A
Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Here are the things I tried to tackle on this PR:
- Make the compaction call stand out a bit more from other regular tool
calls
- Make text size of the compaction's markdown output be consistent with
the thread body text
- Don't show regular thread loading spinner while compaction is in
progress, given that has its own spinner
- Add a different icon than scissors for compaction and add it to the
autocomplete menu so its consistent w/ skills items
<img width="600" alt="Screenshot 2026-06-09 at 10 57@2x"
src="https://github.com/user-attachments/assets/5c3d25af-aa49-42e1-b6b6-c3f95c664456"
/>
Release Notes:
- N/A
Makes it so that we show "Compaction cancelled" when the user interrupts
generation.
Also fixes another small issue where the chevron of the expanded state
would not reflect if it is expanded/collapsed while there is no summary
yet.
Release Notes:
- N/A
<img width="851" height="315" alt="Screenshot 2026-06-09 at 2 15 51 AM"
src="https://github.com/user-attachments/assets/958f2d2f-db7d-4afb-b4b3-ed11f36b00e7"
/>
<img width="644" height="260" alt="Screenshot 2026-06-09 at 2 16 04 AM"
src="https://github.com/user-attachments/assets/e6a74c6b-aba5-4fbb-991c-25842ced5832"
/>
<img width="619" height="128" alt="Screenshot 2026-06-09 at 2 18 08 AM"
src="https://github.com/user-attachments/assets/ba7fa303-852b-4a17-b8df-ea5bd4df7c11"
/>
Adds an always-available `/compact` slash command to Zed's native agent
that forces a summary-based context compaction of the current
conversation, regardless of token usage. This reuses the agent's
existing compaction logic (always the summary strategy, never
provider-native), bypassing the automatic-compaction token threshold and
minimum-context-window guard since the user explicitly asked to compact.
The command lives entirely in `NativeAgent`/`NativeAgentConnection`, so
external (ACP) agents are untouched and keep their own `/compact`
implementations.
The command is gated behind the `handoff` feature flag, matching the
gate on automatic compaction, so it's only advertised and dispatched
when that flag is enabled. When the flag is off, typing `/compact` is
treated as an ordinary prompt.
Because the agent panel always renders the typed `/compact` as a user
message, the manual compaction records a matching zero-content user
message in the model thread (skipped when building model requests) so
that rewinding/truncating that message works instead of erroring, while
keeping the command itself out of the model's context.
The slash-command popup now groups commands into separate sections by
source — "Commands" (built-in, e.g. `/compact`), "MCP Server Commands",
and "ACP Agent Commands" — so same-named commands from different sources
show up as distinguishable duplicates. The source category travels on
each command's ACP `_meta`.
Release Notes:
- N/A
---------
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Stabilizes context windows + persistent session/delete for acp agents
that support them
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: Show context window usage and cost metrics for external agents
that support it.
- acp: Persist session deletion from history for external agents that
support it.
Removing the `Rule` variant from `MentionUri` in #58080 broke
deserialization of any thread saved before the rules-to-skills
migration. Loading one failed with `unknown variant `Rule``, making
those threads inaccessible.
This restores access without bringing back the rules feature:
- Reintroduce a backward-compatible `Rule` mention variant so legacy
threads deserialize again.
- Preserve the original rule `id` through save/load so a thread re-saved
by a newer build still loads on older Zed versions (and synthesize a
valid placeholder when the id is missing).
- Clicking a legacy rule mention now opens the skill the rule was
migrated into, and shows a notification linking the Skills docs. On
remote/collab projects the migrated file lives on the local machine, so
it opens as a read-only buffer. If no matching skill exists, it does
nothing.
Closes https://github.com/zed-industries/zed/issues/58498
Closes AI-371
Release Notes:
- Fixed old threads that mention Rules being inaccessible after Rules
were migrated to Skills
Summary:
- Allow agent tool-call locations outside visible worktrees to resolve
as local buffers.
- Fall back to opening absolute paths from the tool-call click handler.
Tests:
- cargo test -p acp_thread
test_tool_call_location_resolves_external_file
- cargo check -p agent_ui
Closes AI-362
Release Notes:
- Fixed opening agent-created files outside the current project, such as
global skill files.