While at it, annotate more functions that are potentially related to
language parsing in buffers.
Also, on macOS, in order to actually have callstack frames properly
recorded by Tracy, you need to manually run `dsymutil` on the binary.
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/34402
Release Notes:
- MCP servers can now be run on the remote server when using remote
development. This can be enabled by setting the `"remote": true`
property in the settings entry for the MCP server.
---------
Co-authored-by: localcc <kate@zed.dev>
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
## Motivation
This PR unifies the async execution infrastructure between GPUI and
other components that depend on the `scheduler` crate (such as our cloud
codebase). By having a scheduler that lives independently of GPUI, we
can enable deterministic testing across the entire stack - testing GPUI
applications alongside cloud services with a single, unified scheduler.
## Summary
This PR completes the integration of the `scheduler` crate into GPUI,
unifying async execution and enabling deterministic testing of GPUI
combined with other components that depend on the scheduler crate.
## Key Changes
### Scheduler Integration (Phases 1-5, previously completed)
- `TestDispatcher` now delegates to `TestScheduler` for timing, clock,
RNG, and task scheduling
- `PlatformScheduler` implements the `Scheduler` trait for production
use
- GPUI executors wrap scheduler executors, selecting `TestScheduler` or
`PlatformScheduler` based on environment
- Unified blocking logic via `Scheduler::block()`
### Dead Code Cleanup
- Deleted orphaned `crates/gpui/src/platform/platform_scheduler.rs`
(older incompatible version)
## Intentional Removals
### `spawn_labeled` and `deprioritize` removed
The `TaskLabel` system (`spawn_labeled`, `deprioritize`) was removed
during this integration. It was only used in a few places for test
ordering control.
cc @maxbrunsfeld @as-cii - The new priority-weighted scheduling in
`TestScheduler` provides similar functionality through
`Priority::High/Medium/Low`. If `deprioritize` is important for specific
test scenarios, we could add it back to the scheduler crate. Let me know
if this is blocking anything.
### `start_waiting` / `finish_waiting` debug methods removed
Replaced by `TracingWaker` in `TestScheduler` - run tests with
`PENDING_TRACES=1` to see backtraces of pending futures when parking is
forbidden.
### Realtime Priority removed
The realtime priority feature was unused in the codebase. I'd prefer to
reintroduce it when we have an actual use case, as the implementation
(bounded channel with capacity 1) could potentially block the main
thread. Having a real use case will help us validate the design.
## Testing
- All GPUI tests pass
- All scheduler tests pass
- Clippy clean
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ GPUI │
│ ┌──────────────────────┐ ┌────────────────────────────┐ │
│ │ gpui::Background- │ │ gpui::ForegroundExecutor │ │
│ │ Executor │ │ - wraps scheduler:: │ │
│ │ - scheduler: Arc< │ │ ForegroundExecutor │ │
│ │ dyn Scheduler> │ └────────────┬───────────────┘ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ └──────────┬──────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Arc<dyn Scheduler> │ │
│ └───────────┬───────────┘ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌────────────────────┐ │
│ │ PlatformScheduler│ │ TestScheduler │ │
│ │ (production) │ │ (deterministic) │ │
│ └──────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Yara <git@yara.blue>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Missing required extension files or directories currently result in
opaque "Directory not found" errors being logged during the update index
phase. This can be frustrating to those developing extensions. Add some
context so folks know where to start looking.
Release Notes:
- N/A
---------
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
While profiling Zed, I noticed around 12 `tokio-runtime-worker` threads.
Since `gpui_tokio` runs a Tokio runtime with only two worker threads,
this meant something else was spinning up a default Tokio runtime (My
machine has 10 cores).
After digging into it a bit, it looks like `wasmtime-wasi` needs a Tokio
runtime for some of its calls. That’s also why we run extension tasks on
`gpui-tokio` in the first place.
Reproduction case:
1. Run a clean Zed build.
2. Sample the process → only 2–3 Tokio threads.
3. Install a WASM extension (for example
https://github.com/zed-extensions/nix), which shouldn’t pull in anything
that creates its own runtime.
4. Sample the process again → 10+ Tokio worker threads show up.
```
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
744 Thread_3086626 DispatchQueue_1: com.apple.main-thread (serial)
744 Thread_3086629: RayonWorker0
....
744 Thread_3086651: MacWatcher
744 Thread_3086653: MacWatcher
744 Thread_3086661: com.apple.NSEventThread
744 Thread_3086680: tokio-runtime-worker
744 Thread_3086681: tokio-runtime-worker
...
744 Thread_3087087: tokio-runtime-worker
744 Thread_3087089: tokio-runtime-worker
744 Thread_3087090: tokio-runtime-worker
744 Thread_3087091: tokio-runtime-worker
744 Thread_3087092: tokio-runtime-worker
744 Thread_3087093: tokio-runtime-worker
744 Thread_3087094: tokio-runtime-worker
744 Thread_3087095: tokio-runtime-worker
744 Thread_3087096: tokio-runtime-worker
744 Thread_3087097: tokio-runtime-worker
...
```
Release Notes:
- Reduced number of threads when using extensions
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Closes #ISSUE
This PR is rather a nice to have change than anything critical, so
review priority should remain low.
Switch to using `semver::Version` for representing node binary and npm
package versions. This is in an effort to root out implicit behavior and
improve type safety when interacting with the `node_runtime` crate by
catching invalid versions where they appear. Currently Zed may
implicitly assume the current version is correct, or always install the
newest version when a invalid version is passed. `semver::Version` also
doesn't require the heap, which is probably more of a fun fact than
anything useful.
`npm_install_packages` still takes versions as a `&str`, because
`latest` can be used to fetch the latest version on npm. This could
likely be made into an enum as well, but would make the PR even larger.
I tested changes with some node based language servers and external
agents, which all worked fine. It would be nice to have some e2e tests
for node. To be safe I'd put it on nightly after a Wednesday release.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
This fixes an issue where the snippet file location would not be the
proper one for compiled extensions because it would be populated with an
absolute path instead of a relative one in relation to the extension
output directory. This caused the copy operation downstream to not do
anything, because it copied the file to the location it already was
(which was not the output directory for that extension).
Also adds some tests and pulls in the `Fs` so we do not have such issues
with snippets a third time hopefully.
Release Notes:
- N/A
Implements a specialized constructor `LanguageName::new_static` for
`&'static str` which reduces allocations.
`LanguageName::new` always backs the underlying `SharedString` with an
owned `Arc<str>` even when a `&'static str` is passed. This makes us
allocate each time we create a new `LanguageName` no matter what.
Creating a specialized constructor for `&'static str` allows us to
essentially construct them for free.
Additional change:
Encourages using explicit constructors to avoid needless allocations.
Currently there were no instances of this trait being called where the
lifetime was not `'static` saving another 48 locations of allocation.
```rust
impl<'a> From<&'a str> for LanguageName {
fn from(str: &'a str) -> Self {
Self(SharedString::new(str))
}
}
// to
impl From<&'static str> for LanguageName {
fn from(str: &'static str) -> Self {
Self(SharedString::new_static(str))
}
}
```
Release Notes:
- N/A
To do
* [x] Default to no context retrieval. Allow opting in to LSP-based
retrieval via a setting (for users in `zeta2` feature flag)
* [x] Feed this context to models when enabled
* [x] Make the zeta2 context view work well with LSP retrieval
* [x] Add a UI for the setting (for feature-flagged users)
* [x] Ensure Zeta CLI `context` command is usable
---
* [ ] Filter out LSP definitions that are too large / entire files (e.g.
modules)
* [ ] Introduce timeouts
* [ ] Test with other LSPs
* [ ] Figure out hangs
Release Notes:
- N/A
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Agus Zubiaga <agus@zed.dev>
This PR forks a new version of the `zed_extension_api` in preparation
for new changes.
We're jumping from v0.6.0 to v0.8.0 for the WIT because we released
v0.7.0 of the `zed_extension_api` without any WIT changes (it probably
should have been v0.6.1, instead).
Release Notes:
- N/A
Follow up to #39021.
<img width="576" height="141" alt="image"
src="https://github.com/user-attachments/assets/c89885a4-e664-4614-9bb0-86442dff34ee"
/>
- Add migration to remove `source` tag because `ContextServerSettings`
is now untagged
- Fix typos in context server modal
- PR seems to have removed the `test_action_namespaces` test, which I
brought back in this PR
Release Notes:
- Fixed an issue where the `source` property of MCP settings would show
up as unrecognised
https://github.com/zed-industries/zed/pull/40883 implemented this
incorrectly. It was marking a random background thread as a wasm thread
(whatever thread picked up the wasm epoch timer background task),
instead of marking the threads that actually run the wasm extension.
This has two implications:
1. it didn't prevent extension panics from tearing down as planned
2. Worse, it actually made us hide legit panics in sentry for one of our
background workers.
Now 2 still technically applies for all tokio threads after this, but we
basically only use these for wasm extensions in the main zed binary.
Release Notes:
- Fixed extension panics crashing Zed on Linux
### What this solves
This PR adds support for HTTP and SSE (Server-Sent Events) transports to
Zed's context server implementation, enabling communication with remote
MCP servers. Currently, Zed only supports local MCP servers via stdio
transport. This limitation prevents users from:
- Connecting to cloud-hosted MCP servers
- Using MCP servers running in containers or on remote machines
- Leveraging MCP servers that are designed to work over HTTP/SSE
### Why it's important
The MCP (Model Context Protocol) specification includes HTTP/SSE as
standard transport options, and many MCP server implementations are
being built with these transports in mind. Without this support, Zed
users are limited to a subset of the MCP ecosystem. This is particularly
important for:
- Enterprise users who need to connect to centralized MCP services
- Developers working with MCP servers that require network isolation
- Users wanting to leverage cloud-based context providers (e.g.,
knowledge bases, API integrations)
### Implementation approach
The implementation follows Zed's existing architectural patterns:
- **Transports**: Added `HttpTransport` and `SseTransport` to the
`context_server` crate, built on top of the existing `http_client` crate
- **Async handling**: Uses `gpui::spawn` for network operations instead
of introducing a new Tokio runtime
- **Settings**: Extended `ContextServerSettings` enum with a `Remote`
variant to support URL-based configuration
- **UI**: Updated the agent configuration UI with an "Add Remote Server"
option and dedicated modal for remote server management
### Changes included
- [x] HTTP transport implementation with request/response handling
- [x] SSE transport for server-sent events streaming
- [x] `build_transport` function to construct appropriate transport
based on URL scheme
- [x] Settings system updates to support remote server configuration
- [x] UI updates for adding/editing remote servers
- [x] Unit tests using `FakeHttpClient` for both transports
- [x] Integration tests (WIP)
- [x] Documentation updates (WIP)
### Testing
- Unit tests for both `HttpTransport` and `SseTransport` using mocked
HTTP client
- Manual testing with example MCP servers over HTTP/SSE
- Settings validation and UI interaction testing
### Screenshots/Recordings
[TODO: Add screenshots of the new "Add Remote Server" UI and
configuration modal]
### Example configuration
Users can now configure remote MCP servers in their `settings.json`:
```json
{
"context_servers": {
"my-remote-server": {
"enabled": true,
"url": "http://localhost:3000/mcp"
}
}
}
```
### AI assistance disclosure
I used AI to help with:
- Understanding the MCP protocol specification and how HTTP/SSE
transports should work
- Reviewing Zed's existing patterns for async operations and suggesting
consistent approaches
- Generating boilerplate for test cases
- Debugging SSE streaming issues
All code has been manually reviewed, tested, and adapted to fit Zed's
architecture. The core logic, architectural decisions, and integration
with Zed's systems were done with human understanding of the codebase.
AI was primarily used as a reference tool and for getting unstuck on
specific technical issues.
Release notes:
* You can now configure MCP Servers that connect over HTTP in your
settings file. These are not yet available in the extensions API.
```
{
"context_servers": {
"my-remote-server": {
"enabled": true,
"url": "http://localhost:3000/mcp"
}
}
}
```
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Closes#40906Closes#39729
SFTP uploads weren't quoting the install directory which was causing
extension syncing to fail. We were also only running `install_extension`
once per remote-connection instead of once per project (thx @feeiyu for
pointing this out) so extension weren't being loaded in subsequently
opened remote projects.
Release Notes:
- N/A
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This fixes various issues where rustfmt failed to format code due to too
long strings, most of which I stumbled across over the last week and
some additonal ones I searched for whilst fixing the others.
Release Notes:
- N/A
This hopefully resolves the lingering test failures on linux,
but also adds some logging just in case this isn't the problem...
Release Notes:
- N/A
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
When trying to split and clone a non clone-able workspace item we now
attempt split and move instead of doing nothing. Additionally we disable
the split menu buttons if we can't split the active item at all.
Release Notes:
- Improved handling of unsplittable panes
Set a TLS bit to skip invoking the crash handler when a detached thread
panics.
cc @P1n3appl3 - is this at odds with what we need the crash handler to
do?
May close#39289, cannot repro without a nightly build
Release Notes:
- Fixed extension panics crashing Zed on Linux
Co-authored-by: dino <dinojoaocosta@gmail.com>
Fixes ZED-12D
`wasmtime_wasi` might call into tokio futures (to sleep for example)
which requires access to the tokio runtime. So we are required to run
these extensions in the tokio thread pool
Release Notes:
- Fixed extensions causing zed to occasionally panic
We've been considering removing workspace-hack for a couple reasons:
- Lukas ran into a situation where its build script seemed to be causing
spurious rebuilds. This seems more likely to be a cargo bug than an
issue with workspace-hack itself (given that it has an empty build
script), but we don't necessarily want to take the time to hunt that
down right now.
- Marshall mentioned hakari interacts poorly with automated crate
updates (in our case provided by rennovate) because you'd need to have
`cargo hakari generate && cargo hakari manage-deps` after their changes
and we prefer to not have actions that make commits.
Currently removing workspace-hack causes our workspace to grow from
~1700 to ~2000 crates being built (depending on platform), which is
mainly a problem when you're building the whole workspace or running
tests across the the normal and remote binaries (which is where
feature-unification nets us the most sharing). It doesn't impact
incremental times noticeably when you're just iterating on `-p zed`, and
we'll hopefully get these savings back in the future when
rust-lang/cargo#14774 (which re-implements the functionality of hakari)
is finished.
Release Notes:
- N/A
Before this change the active theme and icon theme were retrofitted onto
the ThemeSettings.
Now they're in their own new global (GlobalTheme::theme(cx) and
GlobalTheme::icon_theme(cx))
This lets us remove cx from the settings traits, and tidy up a few other
things along the way.
Release Notes:
- N/A
This PR fixes the JSON schema for the `ExtensionCapabilityContent`.
Having the nested structs in the variants caused the `kind` property to
not be generated properly. Inlining the fields into the variants fixes
this.
Release Notes:
- N/A
This PR adds the ability to control the capabilities granted to
extensions by the extension host via the new
`granted_extension_capabilities` setting.
This setting is a list of the capabilities granted to any extension
running in Zed.
The currently available capabilities are:
- `process:exec` - Grants extensions the ability to invoke commands
using
[`zed_extension_api::process::Command`](https://docs.rs/zed_extension_api/latest/zed_extension_api/process/struct.Command.html)
- `download_file` - Grants extensions the ability to download files
using
[`zed_extension_api::download_file`](https://docs.rs/zed_extension_api/latest/zed_extension_api/fn.download_file.html)
- `npm:install` - Grants extensions the ability to install npm packages
using
[`zed_extension_api::npm_install_package`](https://docs.rs/zed_extension_api/latest/zed_extension_api/fn.npm_install_package.html)
Each of these capabilities has parameters that can be used to customize
the permissions.
For instance, to only allow downloads from GitHub, the `download_file`
capability can specify an allowed `host`:
```json
[
{ "kind": "download_file", "host": "github.com", "path": ["**"] }
]
```
The same capability can also be granted multiple times with different
parameters to build up an allowlist:
```json
[
{ "kind": "download_file", "host": "github.com", "path": ["**"] },
{ "kind": "download_file", "host": "gitlab.com", "path": ["**"] }
]
```
When an extension is not granted a capability, the associated extension
APIs protected by that capability will fail.
For instance, trying to use `zed_extension_api::download_file` when the
`download_file` capability is not granted will result in an error that
will be surfaced by the extension:
```
Language server phpactor:
from extension "PHP" version 0.4.3: failed to download file: capability for download_file https://github.com/phpactor/phpactor/releases/download/2025.07.25.0/phpactor.phar is not granted by the extension host
```
Release Notes:
- Added a `granted_extension_capabilities` setting to control the
capabilities granted to extensions.
Closes https://github.com/zed-industries/zed/issues/38690Closes#37353
### Background
On Windows, paths are normally separated by `\`, unlike mac and linux
where they are separated by `/`. When editing code in a project that
uses a different path style than your local system (e.g. remoting from
Windows to Linux, using WSL, and collaboration between windows and unix
users), the correct separator for a path may differ from the "native"
separator.
Previously, to work around this, Zed converted paths' separators in
numerous places. This was applied to both absolute and relative paths,
leading to incorrect conversions in some cases.
### Solution
Many code paths in Zed use paths that are *relative* to either a
worktree root or a git repository. This PR introduces a dedicated type
for these paths called `RelPath`, which stores the path in the same way
regardless of host platform, and offers `Path`-like manipulation APIs.
RelPath supports *displaying* the path using either separator, so that
we can display paths in a style that is determined at runtime based on
the current project.
The representation of absolute paths is left untouched, for now.
Absolute paths are different from relative paths because (except in
contexts where we know that the path refers to the local filesystem)
they should generally be treated as opaque strings. Currently we use a
mix of types for these paths (std::path::Path, String, SanitizedPath).
Release Notes:
- N/A
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Peter Tripp <petertripp@gmail.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>