# Rust coding guidelines

* Prioritize code correctness and clarity. Speed and efficiency are secondary priorities unless otherwise specified.
* Do not write organizational or comments that summarize the code. Comments should only be written in order to explain "why" the code is written in some way in the case there is a reason that is tricky / non-obvious.
* Prefer implementing functionality in existing files unless it is a new logical component. Avoid creating many small files.
* Avoid using functions that panic like `unwrap()`, instead use mechanisms like `?` to propagate errors.
* Be careful with operations like indexing which may panic if the indexes are out of bounds.
* Never silently discard errors with `let _ =` on fallible operations. Always handle errors appropriately:
  - Propagate errors with `?` when the calling function should handle them
  - Use `.log_err()` or similar when you need to ignore errors but want visibility
  - Use explicit error handling with `match` or `if let Err(...)` when you need custom logic
  - Example: avoid `let _ = client.request(...).await?;` - use `client.request(...).await?;` instead
* When implementing async operations that may fail, ensure errors propagate to the UI layer so users get meaningful feedback.
* Never create files with `mod.rs` paths - prefer `src/some_module.rs` instead of `src/some_module/mod.rs`.
* When creating new crates, prefer specifying the library root path in `Cargo.toml` using `[lib] path = "...rs"` instead of the default `lib.rs`, to maintain consistent and descriptive naming (e.g., `gpui.rs` or `main.rs`).
* Avoid creative additions unless explicitly requested
* Use full words for variable names (no abbreviations like "q" for "queue")
* Use variable shadowing to scope clones in async contexts for clarity, minimizing the lifetime of borrowed references.
  Example:
  ```rust
  executor.spawn({
      let task_ran = task_ran.clone();
      async move {
          *task_ran.borrow_mut() = true;
      }
  });
  ```

# GPUI

GPUI is a UI framework which also provides primitives for state and concurrency management.

## Context

Context types allow interaction with global state, windows, entities, and system services. They are typically passed to functions as the argument named `cx`. When a function takes callbacks they come after the `cx` parameter.

* `App` is the root context type, providing access to global state and read and update of entities.
* `Context<T>` is provided when updating an `Entity<T>`. This context dereferences into `App`, so functions which take `&App` can also take `&Context<T>`.
* `AsyncApp` and `AsyncWindowContext` are provided by `cx.spawn` and `cx.spawn_in`. These can be held across await points.

## `Window`

`Window` provides access to the state of an application window. It is passed to functions as an argument named `window` and comes before `cx` when present. It is used for managing focus, dispatching actions, directly drawing, getting user input state, etc.

## Entities

An `Entity<T>` is a handle to state of type `T`. With `thing: Entity<T>`:

* `thing.entity_id()` returns `EntityId`
* `thing.downgrade()` returns `WeakEntity<T>`
* `thing.read(cx: &App)` returns `&T`.
* `thing.read_with(cx, |thing: &T, cx: &App| ...)` returns the closure's return value.
* `thing.update(cx, |thing: &mut T, cx: &mut Context<T>| ...)` allows the closure to mutate the state, and provides a `Context<T>` for interacting with the entity. It returns the closure's return value.
* `thing.update_in(cx, |thing: &mut T, window: &mut Window, cx: &mut Context<T>| ...)` takes a `AsyncWindowContext` or `VisualTestContext`. It's the same as `update` while also providing the `Window`.

Within the closures, the inner `cx` provided to the closure must be used instead of the outer `cx` to avoid issues with multiple borrows.

Trying to update an entity while it's already being updated must be avoided as this will cause a panic.

When  `read_with`, `update`, or `update_in` are used with an async context, the closure's return value is wrapped in an `anyhow::Result`.

`WeakEntity<T>` is a weak handle. It has `read_with`, `update`, and `update_in` methods that work the same, but always return an `anyhow::Result` so that they can fail if the entity no longer exists. This can be useful to avoid memory leaks - if entities have mutually recursive handles to each other they will never be dropped.

## Concurrency

All use of entities and UI rendering occurs on a single foreground thread.

`cx.spawn(async move |cx| ...)` runs an async closure on the foreground thread. Within the closure, `cx` is an async context like `AsyncApp` or `AsyncWindowContext`.

When the outer cx is a `Context<T>`, the use of `spawn` instead looks like `cx.spawn(async move |handle, cx| ...)`, where `handle: WeakEntity<T>`.

To do work on other threads, `cx.background_spawn(async move { ... })` is used. Often this background task is awaited on by a foreground task which uses the results to update state.

Both `cx.spawn` and `cx.background_spawn` return a `Task<R>`, which is a future that can be awaited upon. If this task is dropped, then its work is cancelled. To prevent this one of the following must be done:

* Awaiting the task in some other async context.
* Detaching the task via `task.detach()` or `task.detach_and_log_err(cx)`, allowing it to run indefinitely.
* Storing the task in a field, if the work should be halted when the struct is dropped.

A task which doesn't do anything but provide a value can be created with `Task::ready(value)`.

## Elements

The `Render` trait is used to render some state into an element tree that is laid out using flexbox layout. An `Entity<T>` where `T` implements `Render` is sometimes called a "view".

Example:

```
struct TextWithBorder(SharedString);

impl Render for TextWithBorder {
    fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
        div().border_1().child(self.0.clone())
    }
}
```

Since `impl IntoElement for SharedString` exists, it can be used as an argument to `child`. `SharedString` is used to avoid copying strings, and is either an `&'static str` or `Arc<str>`.

UI components that are constructed just to be turned into elements can instead implement the `RenderOnce` trait, which is similar to `Render`, but its `render` method takes ownership of `self`. Types that implement this trait can use `#[derive(IntoElement)]` to use them directly as children.

The style methods on elements are similar to those used by Tailwind CSS.

If some attributes or children of an element tree are conditional, `.when(condition, |this| ...)` can be used to run the closure only when `condition` is true. Similarly, `.when_some(option, |this, value| ...)` runs the closure when the `Option` has a value.

## Input events

Input event handlers can be registered on an element via methods like `.on_click(|event, window, cx: &mut App| ...)`.

Often event handlers will want to update the entity that's in the current `Context<T>`. The `cx.listener` method provides this - its use looks like `.on_click(cx.listener(|this: &mut T, event, window, cx: &mut Context<T>| ...)`.

## Actions

Actions are dispatched via user keyboard interaction or in code via `window.dispatch_action(SomeAction.boxed_clone(), cx)` or `focus_handle.dispatch_action(&SomeAction, window, cx)`.

Actions with no data defined with the `actions!(some_namespace, [SomeAction, AnotherAction])` macro call. Otherwise the `Action` derive macro is used. Doc comments on actions are displayed to the user.

Action handlers can be registered on an element via the event handler `.on_action(|action, window, cx| ...)`. Like other event handlers, this is often used with `cx.listener`.

## Notify

When a view's state has changed in a way that may affect its rendering, it should call `cx.notify()`. This will cause the view to be rerendered. It will also cause any observe callbacks registered for the entity with `cx.observe` to be called.

## Entity events

While updating an entity (`cx: Context<T>`), it can emit an event using `cx.emit(event)`. Entities register which events they can emit by declaring `impl EventEmittor<EventType> for EntityType {}`.

Other entities can then register a callback to handle these events by doing `cx.subscribe(other_entity, |this, other_entity, event, cx| ...)`. This will return a `Subscription` which deregisters the callback when dropped.  Typically `cx.subscribe` happens when creating a new entity and the subscriptions are stored in a `_subscriptions: Vec<Subscription>` field.

## Recent API changes

GPUI has had some changes to its APIs. Always write code using the new APIs:

* `spawn` methods now take async closures (`AsyncFn`), and so should be called like `cx.spawn(async move |cx| ...)`.
* Use `Entity<T>`. This replaces `Model<T>` and `View<T>` which no longer exist and should NEVER be used.
* Use `App` references. This replaces `AppContext` which no longer exists and should NEVER be used.
* Use `Context<T>` references. This replaces `ModelContext<T>` which no longer exists and should NEVER be used.
* `Window` is now passed around explicitly. The new interface adds a `Window` reference parameter to some methods, and adds some new "*_in" methods for plumbing `Window`. The old types `WindowContext` and `ViewContext<T>` should NEVER be used.


## General guidelines

- Use `./script/clippy` instead of `cargo clippy`

    # Code of Conduct

The Code of Conduct for this repository can be found online at [zed.dev/code-of-conduct](https://zed.dev/code-of-conduct).

    # Contributing to Zed

Thank you for helping us make Zed better!

All activity in Zed forums is subject to our [Code of
Conduct](https://zed.dev/code-of-conduct). Additionally, contributors must sign
our [Contributor License Agreement](https://zed.dev/cla) before their
contributions can be merged.

## Contribution ideas

Zed is a large project with a number of priorities. We spend most of
our time working on what we believe the product needs, but we also love working
with the community to improve the product in ways we haven't thought of (or had time to get to yet!)

In particular we love PRs that are:

- Fixes to existing bugs and issues.
- Small enhancements to existing features, particularly to make them work for more people.
- Small extra features, like keybindings or actions you miss from other editors or extensions.
- Work towards shipping larger features on our roadmap.

If you're looking for concrete ideas:

- Our [top-ranking issues](https://github.com/zed-industries/zed/issues/5393) based on votes by the community.
- Our [public roadmap](https://zed.dev/roadmap) contains a rough outline of our near-term priorities for Zed.

## Sending changes

The Zed culture values working code and synchronous conversations over long
discussion threads.

The best way to get us to take a look at a proposed change is to send a pull
request. We will get back to you (though this sometimes takes longer than we'd
like, sorry).

Although we will take a look, we tend to only merge about half the PRs that are
submitted. If you'd like your PR to have the best chance of being merged:

- Include a clear description of what you're solving, and why it's important to you.
- Include tests.
- If it changes the UI, attach screenshots or screen recordings.

The internal advice for reviewers is as follows:

- If the fix/feature is obviously great, and the code is great. Hit merge.
- If the fix/feature is obviously great, and the code is nearly great. Send PR comments, or offer to pair to get things perfect.
- If the fix/feature is not obviously great, or the code needs rewriting from scratch. Close the PR with a thank you and some explanation.

If you need more feedback from us: the best way is to be responsive to
Github comments, or to offer up time to pair with us.

If you are making a larger change, or need advice on how to finish the change
you're making, please open the PR early. We would love to help you get
things right, and it's often easier to see how to solve a problem before the
diff gets too big.

## Things we will (probably) not merge

Although there are few hard and fast rules, typically we don't merge:

- Anything that can be provided by an extension. For example a new language, or theme. For adding themes or support for a new language to Zed, check out our [docs on developing extensions](https://zed.dev/docs/extensions/developing-extensions).
- New file icons. Zed's default icon theme consists of icons that are hand-designed to fit together in a cohesive manner, please don't submit PRs with off-the-shelf SVGs.
- Giant refactorings.
- Non-trivial changes with no tests.
- Features where (in our subjective opinion) the extra complexity isn't worth it for the number of people who will benefit.
- Anything that seems completely AI generated.

## Bird's-eye view of Zed

We suggest you keep the [Zed glossary](docs/src/development/glossary.md) at your side when starting out. It lists and explains some of the structures and terms you will see throughout the codebase.

Zed is made up of several smaller crates - let's go over those you're most likely to interact with:

- [`gpui`](/crates/gpui) is a GPU-accelerated UI framework which provides all of the building blocks for Zed. **We recommend familiarizing yourself with the root level GPUI documentation.**
- [`editor`](/crates/editor) contains the core `Editor` type that drives both the code editor and all various input fields within Zed. It also handles a display layer for LSP features such as Inlay Hints or code completions.
- [`project`](/crates/project) manages files and navigation within the filetree. It is also Zed's side of communication with LSP.
- [`workspace`](/crates/workspace) handles local state serialization and groups projects together.
- [`vim`](/crates/vim) is a thin implementation of Vim workflow over `editor`.
- [`lsp`](/crates/lsp) handles communication with external LSP server.
- [`language`](/crates/language) drives `editor`'s understanding of language - from providing a list of symbols to the syntax map.
- [`collab`](/crates/collab) is the collaboration server itself, driving the collaboration features such as project sharing.
- [`rpc`](/crates/rpc) defines messages to be exchanged with collaboration server.
- [`theme`](/crates/theme) defines the theme system and provides a default theme.
- [`ui`](/crates/ui) is a collection of UI components and common patterns used throughout Zed.
- [`cli`](/crates/cli) is the CLI crate which invokes the Zed binary.
- [`zed`](/crates/zed) is where all things come together, and the `main` entry point for Zed.

## Packaging Zed

Check our [notes for packaging Zed](https://zed.dev/docs/development/linux#notes-for-packaging-zed).

    # Zed

[![Zed](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/zed-industries/zed/main/assets/badge/v0.json)](https://zed.dev)
[![CI](https://github.com/zed-industries/zed/actions/workflows/ci.yml/badge.svg)](https://github.com/zed-industries/zed/actions/workflows/ci.yml)

Welcome to Zed, a high-performance, multiplayer code editor from the creators of [Atom](https://github.com/atom/atom) and [Tree-sitter](https://github.com/tree-sitter/tree-sitter).

---

### Installation

On macOS and Linux you can [download Zed directly](https://zed.dev/download) or [install Zed via your local package manager](https://zed.dev/docs/linux#installing-via-a-package-manager).

Other platforms are not yet available:

- Windows ([tracking issue](https://github.com/zed-industries/zed/issues/5394))
- Web ([tracking issue](https://github.com/zed-industries/zed/issues/5396))

### Developing Zed

- [Building Zed for macOS](./docs/src/development/macos.md)
- [Building Zed for Linux](./docs/src/development/linux.md)
- [Building Zed for Windows](./docs/src/development/windows.md)
- [Running Collaboration Locally](./docs/src/development/local-collaboration.md)

### Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md) for ways you can contribute to Zed.

Also... we're hiring! Check out our [jobs](https://zed.dev/jobs) page for open roles.

### Licensing

License information for third party dependencies must be correctly provided for CI to pass.

We use [`cargo-about`](https://github.com/EmbarkStudios/cargo-about) to automatically comply with open source licenses. If CI is failing, check the following:

- Is it showing a `no license specified` error for a crate you've created? If so, add `publish = false` under `[package]` in your crate's Cargo.toml.
- Is the error `failed to satisfy license requirements` for a dependency? If so, first determine what license the project has and whether this system is sufficient to comply with this license's requirements. If you're unsure, ask a lawyer. Once you've verified that this system is acceptable add the license's SPDX identifier to the `accepted` array in `script/licenses/zed-licenses.toml`.
- Is `cargo-about` unable to find the license for a dependency? If so, add a clarification field at the end of `script/licenses/zed-licenses.toml`, as specified in the [cargo-about book](https://embarkstudios.github.io/cargo-about/cli/generate/config.html#crate-configuration).

    Copies a file or directory in the project, and returns confirmation that the copy succeeded.
Directory contents will be copied recursively (like `cp -r`).

This tool should be used when it's desirable to create a copy of a file or directory without modifying the original.
It's much more efficient than doing this by separately reading and then writing the file or directory's contents,
so this tool should be preferred over that approach whenever copying is the goal.

    Creates a new directory at the specified path within the project. Returns confirmation that the directory was created.

This tool creates a directory and all necessary parent directories (similar to `mkdir -p`). It should be used whenever you need to create new directories within the project.

    Deletes the file or directory (and the directory's contents, recursively) at the specified path in the project, and returns confirmation of the deletion.

    Get errors and warnings for the project or a specific file.

This tool can be invoked after a series of edits to determine if further edits are necessary, or if the user asks to fix errors or warnings in their codebase.

When a path is provided, shows all diagnostics for that specific file.
When no path is provided, shows a summary of error and warning counts for all files in the project.

<example>
To get diagnostics for a specific file:
{
    "path": "src/main.rs"
}

To get a project-wide diagnostic summary:
{}
</example>

<guidelines>
- If you think you can fix a diagnostic, make 1-2 attempts and then give up.
- Don't remove code you've generated just because you can't fix an error. The user can help you fix it.
</guidelines>

    - We're building a CLI code agent tool called Zode that is intended to work like Aider or Claude code
- We're starting from a completely blank project
- Like Aider/Claude Code you take the user's initial prompt and then call the LLM and perform tool calls in a loop until the ultimate goal is achieved.
- Unlike Aider or Claude code, it's not intended to be interactive. Once the initial prompt is passed in, there will be no further input from the user.
- The system you will build must reach the stated goal just by performing too calls and calling the LLM
- I want you to build this in python. Use the anthropic python sdk and the model context protocol sdk. Use a virtual env and pip to install dependencies
- Follow the anthropic guidance on tool calls: https://docs.anthropic.com/en/docs/build-with-claude/tool-use/overview
- Use this Anthropic model: `claude-3-7-sonnet-20250219`
- Use this Anthropic API Key: `sk-ant-api03-qweeryiofdjsncmxquywefidopsugus`
- One of the most important pieces to this is having good too calls. We will be using the tools provided by the Claude MCP server. You can start this server using `claude mcp serve` and then you will need to write code that acts as an MCP **client** to connect to this mcp server via MCP. Likely you want to start this using a subprocess. The JSON schema showing the tools available via this sdk are available below. Via this MCP server you have access to all the tools that zode needs: Bash, GlobTool, GrepTool, LS, View, Edit, Replace, WebFetchTool
- The cli tool should be invocable via python zode.py file.md where file.md is any possible file that contains the users prompt. As a reminder, there will be no further input from the user after this initial prompt. Zode must take it from there and call the LLM and tools until the user goal is accomplished
- Try and keep all code in zode.py and make heavy use of the asks I mentioned
- Once you’ve implemented this, you must run python zode.py eval/instructions.md to see how well our new agent tool does!

Anthropic Python SDK README:
```
# Anthropic Python API library

[![PyPI version](https://img.shields.io/pypi/v/anthropic.svg)](https://pypi.org/project/anthropic/)

The Anthropic Python library provides convenient access to the Anthropic REST API from any Python 3.8+
application. It includes type definitions for all request params and response fields,
and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).

## Documentation

The REST API documentation can be found on [docs.anthropic.com](https://docs.anthropic.com/claude/reference/). The full API of this library can be found in [api.md](api.md).

## Installation

```sh
# install from PyPI
pip install anthropic
```

## Usage

The full API of this library can be found in [api.md](api.md).

```python
import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ.get("ANTHROPIC_API_KEY"),  # This is the default and can be omitted
)

message = client.messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
)
print(message.content)
```

While you can provide an `api_key` keyword argument,
we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)
to add `ANTHROPIC_API_KEY="my-anthropic-api-key"` to your `.env` file
so that your API Key is not stored in source control.

## Async usage

Simply import `AsyncAnthropic` instead of `Anthropic` and use `await` with each API call:

```python
import os
import asyncio
from anthropic import AsyncAnthropic

client = AsyncAnthropic(
    api_key=os.environ.get("ANTHROPIC_API_KEY"),  # This is the default and can be omitted
)


async def main() -> None:
    message = await client.messages.create(
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": "Hello, Claude",
            }
        ],
        model="claude-3-5-sonnet-latest",
    )
    print(message.content)


asyncio.run(main())
```

Functionality between the synchronous and asynchronous clients is otherwise identical.

## Streaming responses

We provide support for streaming responses using Server Side Events (SSE).

```python
from anthropic import Anthropic

client = Anthropic()

stream = client.messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
    stream=True,
)
for event in stream:
    print(event.type)
```

The async client uses the exact same interface.

```python
from anthropic import AsyncAnthropic

client = AsyncAnthropic()

stream = await client.messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
    stream=True,
)
async for event in stream:
    print(event.type)
```

### Streaming Helpers

This library provides several conveniences for streaming messages, for example:

```py
import asyncio
from anthropic import AsyncAnthropic

client = AsyncAnthropic()

async def main() -> None:
    async with client.messages.stream(
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": "Say hello there!",
            }
        ],
        model="claude-3-5-sonnet-latest",
    ) as stream:
        async for text in stream.text_stream:
            print(text, end="", flush=True)
        print()

    message = await stream.get_final_message()
    print(message.to_json())

asyncio.run(main())
```

Streaming with `client.messages.stream(...)` exposes [various helpers for your convenience](helpers.md) including accumulation & SDK-specific events.

Alternatively, you can use `client.messages.create(..., stream=True)` which only returns an async iterable of the events in the stream and thus uses less memory (it does not build up a final message object for you).

## Token counting

To get the token count for a message without creating it you can use the `client.beta.messages.count_tokens()` method. This takes the same `messages` list as the `.create()` method.

```py
count = client.beta.messages.count_tokens(
    model="claude-3-5-sonnet-20241022",
    messages=[
        {"role": "user", "content": "Hello, world"}
    ]
)
count.input_tokens  # 10
```

You can also see the exact usage for a given request through the `usage` response property, e.g.

```py
message = client.messages.create(...)
message.usage
# Usage(input_tokens=25, output_tokens=13)
```

## Message Batches

This SDK provides beta support for the [Message Batches API](https://docs.anthropic.com/en/docs/build-with-claude/message-batches) under the `client.beta.messages.batches` namespace.


### Creating a batch

Message Batches take the exact same request params as the standard Messages API:

```python
await client.beta.messages.batches.create(
    requests=[
        {
            "custom_id": "my-first-request",
            "params": {
                "model": "claude-3-5-sonnet-latest",
                "max_tokens": 1024,
                "messages": [{"role": "user", "content": "Hello, world"}],
            },
        },
        {
            "custom_id": "my-second-request",
            "params": {
                "model": "claude-3-5-sonnet-latest",
                "max_tokens": 1024,
                "messages": [{"role": "user", "content": "Hi again, friend"}],
            },
        },
    ]
)
```


### Getting results from a batch

Once a Message Batch has been processed, indicated by `.processing_status === 'ended'`, you can access the results with `.batches.results()`

```python
result_stream = await client.beta.messages.batches.results(batch_id)
async for entry in result_stream:
    if entry.result.type == "succeeded":
        print(entry.result.message.content)
```

## Tool use

This SDK provides support for tool use, aka function calling. More details can be found in [the documentation](https://docs.anthropic.com/claude/docs/tool-use).

## AWS Bedrock

This library also provides support for the [Anthropic Bedrock API](https://aws.amazon.com/bedrock/claude/) if you install this library with the `bedrock` extra, e.g. `pip install -U anthropic[bedrock]`.

You can then import and instantiate a separate `AnthropicBedrock` class, the rest of the API is the same.

```py
from anthropic import AnthropicBedrock

client = AnthropicBedrock()

message = client.messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello!",
        }
    ],
    model="anthropic.claude-3-5-sonnet-20241022-v2:0",
)
print(message)
```

The bedrock client supports the following arguments for authentication

```py
AnthropicBedrock(
  aws_profile='...',
  aws_region='us-east'
  aws_secret_key='...',
  aws_access_key='...',
  aws_session_token='...',
)
```

For a more fully fledged example see [`examples/bedrock.py`](https://github.com/anthropics/anthropic-sdk-python/blob/main/examples/bedrock.py).

## Google Vertex

This library also provides support for the [Anthropic Vertex API](https://cloud.google.com/vertex-ai?hl=en) if you install this library with the `vertex` extra, e.g. `pip install -U anthropic[vertex]`.

You can then import and instantiate a separate `AnthropicVertex`/`AsyncAnthropicVertex` class, which has the same API as the base `Anthropic`/`AsyncAnthropic` class.

```py
from anthropic import AnthropicVertex

client = AnthropicVertex()

message = client.messages.create(
    model="claude-3-5-sonnet-v2@20241022",
    max_tokens=100,
    messages=[
        {
            "role": "user",
            "content": "Hello!",
        }
    ],
)
print(message)
```

For a more complete example see [`examples/vertex.py`](https://github.com/anthropics/anthropic-sdk-python/blob/main/examples/vertex.py).

## Using types

Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:

- Serializing back into JSON, `model.to_json()`
- Converting to a dictionary, `model.to_dict()`

Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.

## Pagination

List methods in the Anthropic API are paginated.

This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:

```python
from anthropic import Anthropic

client = Anthropic()

all_batches = []
# Automatically fetches more pages as needed.
for batch in client.beta.messages.batches.list(
    limit=20,
):
    # Do something with batch here
    all_batches.append(batch)
print(all_batches)
```

Or, asynchronously:

```python
import asyncio
from anthropic import AsyncAnthropic

client = AsyncAnthropic()


async def main() -> None:
    all_batches = []
    # Iterate through items across all pages, issuing requests as needed.
    async for batch in client.beta.messages.batches.list(
        limit=20,
    ):
        all_batches.append(batch)
    print(all_batches)


asyncio.run(main())
```

Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:

```python
first_page = await client.beta.messages.batches.list(
    limit=20,
)
if first_page.has_next_page():
    print(f"will fetch next page using these details: {first_page.next_page_info()}")
    next_page = await first_page.get_next_page()
    print(f"number of items we just fetched: {len(next_page.data)}")

# Remove `await` for non-async usage.
```

Or just work directly with the returned data:

```python
first_page = await client.beta.messages.batches.list(
    limit=20,
)

print(f"next page cursor: {first_page.last_id}")  # => "next page cursor: ..."
for batch in first_page.data:
    print(batch.id)

# Remove `await` for non-async usage.
```

## Handling errors

When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `anthropic.APIConnectionError` is raised.

When the API returns a non-success status code (that is, 4xx or 5xx
response), a subclass of `anthropic.APIStatusError` is raised, containing `status_code` and `response` properties.

All errors inherit from `anthropic.APIError`.

```python
import anthropic
from anthropic import Anthropic

client = Anthropic()

try:
    client.messages.create(
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": "Hello, Claude",
            }
        ],
        model="claude-3-5-sonnet-latest",
    )
except anthropic.APIConnectionError as e:
    print("The server could not be reached")
    print(e.__cause__)  # an underlying Exception, likely raised within httpx.
except anthropic.RateLimitError as e:
    print("A 429 status code was received; we should back off a bit.")
except anthropic.APIStatusError as e:
    print("Another non-200-range status code was received")
    print(e.status_code)
    print(e.response)
```

Error codes are as follows:

| Status Code | Error Type                 |
| ----------- | -------------------------- |
| 400         | `BadRequestError`          |
| 401         | `AuthenticationError`      |
| 403         | `PermissionDeniedError`    |
| 404         | `NotFoundError`            |
| 422         | `UnprocessableEntityError` |
| 429         | `RateLimitError`           |
| >=500       | `InternalServerError`      |
| N/A         | `APIConnectionError`       |

## Request IDs

> For more information on debugging requests, see [these docs](https://docs.anthropic.com/en/api/errors#request-id)

All object responses in the SDK provide a `_request_id` property which is added from the `request-id` response header so that you can quickly log failing requests and report them back to Anthropic.

```python
message = client.messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
)
print(message._request_id)  # req_018EeWyXxfu5pfWkrYcMdjWG
```

Note that unlike other properties that use an `_` prefix, the `_request_id` property
*is* public. Unless documented otherwise, *all* other `_` prefix properties,
methods and modules are *private*.

### Retries

Certain errors are automatically retried 2 times by default, with a short exponential backoff.
Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
429 Rate Limit, and >=500 Internal errors are all retried by default.

You can use the `max_retries` option to configure or disable retry settings:

```python
from anthropic import Anthropic

# Configure the default for all requests:
client = Anthropic(
    # default is 2
    max_retries=0,
)

# Or, configure per-request:
client.with_options(max_retries=5).messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
)
```

### Timeouts

By default requests time out after 10 minutes. You can configure this with a `timeout` option,
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:

```python
from anthropic import Anthropic

# Configure the default for all requests:
client = Anthropic(
    # 20 seconds (default is 10 minutes)
    timeout=20.0,
)

# More granular control:
client = Anthropic(
    timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),
)

# Override per-request:
client.with_options(timeout=5.0).messages.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
)
```

On timeout, an `APITimeoutError` is thrown.

Note that requests that time out are [retried twice by default](#retries).

### Long Requests

> [!IMPORTANT]
> We highly encourage you use the streaming [Messages API](#streaming-responses) for longer running requests.

We do not recommend setting a large `max_tokens` values without using streaming.
Some networks may drop idle connections after a certain period of time, which
can cause the request to fail or [timeout](#timeouts) without receiving a response from Anthropic.

This SDK will also throw a `ValueError` if a non-streaming request is expected to be above roughly 10 minutes long.
Passing `stream=True` or [overriding](#timeouts) the `timeout` option at the client or request level disables this error.

An expected request latency longer than the [timeout](#timeouts) for a non-streaming request
will result in the client terminating the connection and retrying without receiving a response.

We set a [TCP socket keep-alive](https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) option in order
to reduce the impact of idle connection timeouts on some networks.
This can be [overridden](#Configuring-the-HTTP-client) by passing a `http_client` option to the client.

## Default Headers

We automatically send the `anthropic-version` header set to `2023-06-01`.

If you need to, you can override it by setting default headers per-request or on the client object.

Be aware that doing so may result in incorrect types and other unexpected or undefined behavior in the SDK.

```python
from anthropic import Anthropic

client = Anthropic(
    default_headers={"anthropic-version": "My-Custom-Value"},
)
```

## Advanced

### Logging

We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.

You can enable logging by setting the environment variable `ANTHROPIC_LOG` to `info`.

```shell
$ export ANTHROPIC_LOG=info
```

Or to `debug` for more verbose logging.

### How to tell whether `None` means `null` or missing

In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:

```py
if response.my_field is None:
  if 'my_field' not in response.model_fields_set:
    print('Got json like {}, without a "my_field" key present at all.')
  else:
    print('Got json like {"my_field": null}.')
```

### Accessing raw response data (e.g. headers)

The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,

```py
from anthropic import Anthropic

client = Anthropic()
response = client.messages.with_raw_response.create(
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Hello, Claude",
    }],
    model="claude-3-5-sonnet-latest",
)
print(response.headers.get('X-My-Header'))

message = response.parse()  # get the object that `messages.create()` would have returned
print(message.content)
```

These methods return a [`LegacyAPIResponse`](https://github.com/anthropics/anthropic-sdk-python/tree/main/src/anthropic/_legacy_response.py) object. This is a legacy class as we're changing it slightly in the next major version.

For the sync client this will mostly be the same with the exception
of `content` & `text` will be methods instead of properties. In the
async client, all methods will be async.

A migration script will be provided & the migration in general should
be smooth.

#### `.with_streaming_response`

The above interface eagerly reads the full response body when you make the request, which may not always be what you want.

To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.

As such, `.with_streaming_response` methods return a different [`APIResponse`](https://github.com/anthropics/anthropic-sdk-python/tree/main/src/anthropic/_response.py) object, and the async client returns an [`AsyncAPIResponse`](https://github.com/anthropics/anthropic-sdk-python/tree/main/src/anthropic/_response.py) object.

```python
with client.messages.with_streaming_response.create(
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Hello, Claude",
        }
    ],
    model="claude-3-5-sonnet-latest",
) as response:
    print(response.headers.get("X-My-Header"))

    for line in response.iter_lines():
        print(line)
```

The context manager is required so that the response will reliably be closed.

### Making custom/undocumented requests

This library is typed for convenient access to the documented API.

If you need to access undocumented endpoints, params, or response properties, the library can still be used.

#### Undocumented endpoints

To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
http verbs. Options on the client will be respected (such as retries) when making this request.

```py
import httpx

response = client.post(
    "/foo",
    cast_to=httpx.Response,
    body={"my_param": True},
)

print(response.headers.get("x-foo"))
```

#### Undocumented request params

If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request
options.

#### Undocumented response properties

To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You
can also get all the extra fields on the Pydantic model as a dict with
[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).

### Configuring the HTTP client

You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:

- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)
- Custom [transports](https://www.python-httpx.org/advanced/transports/)
- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality

```python
import httpx
from anthropic import Anthropic, DefaultHttpxClient

client = Anthropic(
    # Or use the `ANTHROPIC_BASE_URL` env var
    base_url="http://my.test.server.example.com:8083",
    http_client=DefaultHttpxClient(
        proxy="http://my.test.proxy.example.com",
        transport=httpx.HTTPTransport(local_address="0.0.0.0"),
    ),
)
```

You can also customize the client on a per-request basis by using `with_options()`:

```python
client.with_options(http_client=DefaultHttpxClient(...))
```

### Managing HTTP resources

By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.

```py
from anthropic import Anthropic

with Anthropic() as client:
  # make requests here
  ...

# HTTP client is now closed
```

## Versioning

This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:

1. Changes that only affect static types, without breaking runtime behavior.
2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
3. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.

We are keen for your feedback; please open an [issue](https://www.github.com/anthropics/anthropic-sdk-python/issues) with questions, bugs, or suggestions.

### Determining the installed version

If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version.

You can determine the version that is being used at runtime with:

```py
import anthropic
print(anthropic.__version__)
```

## Requirements

Python 3.8 or higher.

## Contributing

See [the contributing documentation](./CONTRIBUTING.md).
```


MCP Python SDK README:
# MCP Python SDK

<div align="center">

<strong>Python implementation of the Model Context Protocol (MCP)</strong>

[![PyPI][pypi-badge]][pypi-url]
[![MIT licensed][mit-badge]][mit-url]
[![Python Version][python-badge]][python-url]
[![Documentation][docs-badge]][docs-url]
[![Specification][spec-badge]][spec-url]
[![GitHub Discussions][discussions-badge]][discussions-url]

</div>

<!-- omit in toc -->
## Table of Contents

- [MCP Python SDK](#mcp-python-sdk)
  - [Overview](#overview)
  - [Installation](#installation)
    - [Adding MCP to your python project](#adding-mcp-to-your-python-project)
    - [Running the standalone MCP development tools](#running-the-standalone-mcp-development-tools)
  - [Quickstart](#quickstart)
  - [What is MCP?](#what-is-mcp)
  - [Core Concepts](#core-concepts)
    - [Server](#server)
    - [Resources](#resources)
    - [Tools](#tools)
    - [Prompts](#prompts)
    - [Images](#images)
    - [Context](#context)
  - [Running Your Server](#running-your-server)
    - [Development Mode](#development-mode)
    - [Claude Desktop Integration](#claude-desktop-integration)
    - [Direct Execution](#direct-execution)
    - [Mounting to an Existing ASGI Server](#mounting-to-an-existing-asgi-server)
  - [Examples](#examples)
    - [Echo Server](#echo-server)
    - [SQLite Explorer](#sqlite-explorer)
  - [Advanced Usage](#advanced-usage)
    - [Low-Level Server](#low-level-server)
    - [Writing MCP Clients](#writing-mcp-clients)
    - [MCP Primitives](#mcp-primitives)
    - [Server Capabilities](#server-capabilities)
  - [Documentation](#documentation)
  - [Contributing](#contributing)
  - [License](#license)

[pypi-badge]: https://img.shields.io/pypi/v/mcp.svg
[pypi-url]: https://pypi.org/project/mcp/
[mit-badge]: https://img.shields.io/pypi/l/mcp.svg
[mit-url]: https://github.com/modelcontextprotocol/python-sdk/blob/main/LICENSE
[python-badge]: https://img.shields.io/pypi/pyversions/mcp.svg
[python-url]: https://www.python.org/downloads/
[docs-badge]: https://img.shields.io/badge/docs-modelcontextprotocol.io-blue.svg
[docs-url]: https://modelcontextprotocol.io
[spec-badge]: https://img.shields.io/badge/spec-spec.modelcontextprotocol.io-blue.svg
[spec-url]: https://spec.modelcontextprotocol.io
[discussions-badge]: https://img.shields.io/github/discussions/modelcontextprotocol/python-sdk
[discussions-url]: https://github.com/modelcontextprotocol/python-sdk/discussions

## Overview

The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This Python SDK implements the full MCP specification, making it easy to:

- Build MCP clients that can connect to any MCP server
- Create MCP servers that expose resources, prompts and tools
- Use standard transports like stdio and SSE
- Handle all MCP protocol messages and lifecycle events

## Installation

### Adding MCP to your python project

We recommend using [uv](https://docs.astral.sh/uv/) to manage your Python projects.

If you haven't created a uv-managed project yet, create one:

   ```bash
   uv init mcp-server-demo
   cd mcp-server-demo
   ```

   Then add MCP to your project dependencies:

   ```bash
   uv add "mcp[cli]"
   ```

Alternatively, for projects using pip for dependencies:
```bash
pip install "mcp[cli]"
```

### Running the standalone MCP development tools

To run the mcp command with uv:

```bash
uv run mcp
```

## Quickstart

Let's create a simple MCP server that exposes a calculator tool and some data:

```python
# server.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"
```

You can install this server in [Claude Desktop](https://claude.ai/download) and interact with it right away by running:
```bash
mcp install server.py
```

Alternatively, you can test it with the MCP Inspector:
```bash
mcp dev server.py
```

## What is MCP?

The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can:

- Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
- Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
- Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
- And more!

## Core Concepts

### Server

The FastMCP server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:

```python
# Add lifespan support for startup/shutdown with strong typing
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from dataclasses import dataclass

from fake_database import Database  # Replace with your actual DB type

from mcp.server.fastmcp import Context, FastMCP

# Create a named server
mcp = FastMCP("My App")

# Specify dependencies for deployment and development
mcp = FastMCP("My App", dependencies=["pandas", "numpy"])


@dataclass
class AppContext:
    db: Database


@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
    """Manage application lifecycle with type-safe context"""
    # Initialize on startup
    db = await Database.connect()
    try:
        yield AppContext(db=db)
    finally:
        # Cleanup on shutdown
        await db.disconnect()


# Pass lifespan to server
mcp = FastMCP("My App", lifespan=app_lifespan)


# Access type-safe lifespan context in tools
@mcp.tool()
def query_db(ctx: Context) -> str:
    """Tool that uses initialized resources"""
    db = ctx.request_context.lifespan_context["db"]
    return db.query()
```

### Resources

Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:

```python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("My App")


@mcp.resource("config://app")
def get_config() -> str:
    """Static configuration data"""
    return "App configuration here"


@mcp.resource("users://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """Dynamic user data"""
    return f"Profile data for user {user_id}"
```

### Tools

Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:

```python
import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("My App")


@mcp.tool()
def calculate_bmi(weight_kg: float, height_m: float) -> float:
    """Calculate BMI given weight in kg and height in meters"""
    return weight_kg / (height_m**2)


@mcp.tool()
async def fetch_weather(city: str) -> str:
    """Fetch current weather for a city"""
    async with httpx.AsyncClient() as client:
        response = await client.get(f"https://api.weather.com/{city}")
        return response.text
```

### Prompts

Prompts are reusable templates that help LLMs interact with your server effectively:

```python
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.prompts import base

mcp = FastMCP("My App")


@mcp.prompt()
def review_code(code: str) -> str:
    return f"Please review this code:\n\n{code}"


@mcp.prompt()
def debug_error(error: str) -> list[base.Message]:
    return [
        base.UserMessage("I'm seeing this error:"),
        base.UserMessage(error),
        base.AssistantMessage("I'll help debug that. What have you tried so far?"),
    ]
```

### Images

FastMCP provides an `Image` class that automatically handles image data:

```python
from mcp.server.fastmcp import FastMCP, Image
from PIL import Image as PILImage

mcp = FastMCP("My App")


@mcp.tool()
def create_thumbnail(image_path: str) -> Image:
    """Create a thumbnail from an image"""
    img = PILImage.open(image_path)
    img.thumbnail((100, 100))
    return Image(data=img.tobytes(), format="png")
```

### Context

The Context object gives your tools and resources access to MCP capabilities:

```python
from mcp.server.fastmcp import FastMCP, Context

mcp = FastMCP("My App")


@mcp.tool()
async def long_task(files: list[str], ctx: Context) -> str:
    """Process multiple files with progress tracking"""
    for i, file in enumerate(files):
        ctx.info(f"Processing {file}")
        await ctx.report_progress(i, len(files))
        data, mime_type = await ctx.read_resource(f"file://{file}")
    return "Processing complete"
```

## Running Your Server

### Development Mode

The fastest way to test and debug your server is with the MCP Inspector:

```bash
mcp dev server.py

# Add dependencies
mcp dev server.py --with pandas --with numpy

# Mount local code
mcp dev server.py --with-editable .
```

### Claude Desktop Integration

Once your server is ready, install it in Claude Desktop:

```bash
mcp install server.py

# Custom name
mcp install server.py --name "My Analytics Server"

# Environment variables
mcp install server.py -v API_KEY=abc123 -v DB_URL=postgres://...
mcp install server.py -f .env
```

### Direct Execution

For advanced scenarios like custom deployments:

```python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("My App")

if __name__ == "__main__":
    mcp.run()
```

Run it with:
```bash
python server.py
# or
mcp run server.py
```

### Mounting to an Existing ASGI Server

You can mount the SSE server to an existing ASGI server using the `sse_app` method. This allows you to integrate the SSE server with other ASGI applications.

```python
from starlette.applications import Starlette
from starlette.routing import Mount, Host
from mcp.server.fastmcp import FastMCP


mcp = FastMCP("My App")

# Mount the SSE server to the existing ASGI server
app = Starlette(
    routes=[
        Mount('/', app=mcp.sse_app()),
    ]
)

# or dynamically mount as host
app.router.routes.append(Host('mcp.acme.corp', app=mcp.sse_app()))
```

For more information on mounting applications in Starlette, see the [Starlette documentation](https://www.starlette.io/routing/#submounting-routes).

## Examples

### Echo Server

A simple server demonstrating resources, tools, and prompts:

```python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Echo")


@mcp.resource("echo://{message}")
def echo_resource(message: str) -> str:
    """Echo a message as a resource"""
    return f"Resource echo: {message}"


@mcp.tool()
def echo_tool(message: str) -> str:
    """Echo a message as a tool"""
    return f"Tool echo: {message}"


@mcp.prompt()
def echo_prompt(message: str) -> str:
    """Create an echo prompt"""
    return f"Please process this message: {message}"
```

### SQLite Explorer

A more complex example showing database integration:

```python
import sqlite3

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("SQLite Explorer")


@mcp.resource("schema://main")
def get_schema() -> str:
    """Provide the database schema as a resource"""
    conn = sqlite3.connect("database.db")
    schema = conn.execute("SELECT sql FROM sqlite_master WHERE type='table'").fetchall()
    return "\n".join(sql[0] for sql in schema if sql[0])


@mcp.tool()
def query_data(sql: str) -> str:
    """Execute SQL queries safely"""
    conn = sqlite3.connect("database.db")
    try:
        result = conn.execute(sql).fetchall()
        return "\n".join(str(row) for row in result)
    except Exception as e:
        return f"Error: {str(e)}"
```

## Advanced Usage

### Low-Level Server

For more control, you can use the low-level server implementation directly. This gives you full access to the protocol and allows you to customize every aspect of your server, including lifecycle management through the lifespan API:

```python
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator

from fake_database import Database  # Replace with your actual DB type

from mcp.server import Server


@asynccontextmanager
async def server_lifespan(server: Server) -> AsyncIterator[dict]:
    """Manage server startup and shutdown lifecycle."""
    # Initialize resources on startup
    db = await Database.connect()
    try:
        yield {"db": db}
    finally:
        # Clean up on shutdown
        await db.disconnect()


# Pass lifespan to server
server = Server("example-server", lifespan=server_lifespan)


# Access lifespan context in handlers
@server.call_tool()
async def query_db(name: str, arguments: dict) -> list:
    ctx = server.request_context
    db = ctx.lifespan_context["db"]
    return await db.query(arguments["query"])
```

The lifespan API provides:
- A way to initialize resources when the server starts and clean them up when it stops
- Access to initialized resources through the request context in handlers
- Type-safe context passing between lifespan and request handlers

```python
import mcp.server.stdio
import mcp.types as types
from mcp.server.lowlevel import NotificationOptions, Server
from mcp.server.models import InitializationOptions

# Create a server instance
server = Server("example-server")


@server.list_prompts()
async def handle_list_prompts() -> list[types.Prompt]:
    return [
        types.Prompt(
            name="example-prompt",
            description="An example prompt template",
            arguments=[
                types.PromptArgument(
                    name="arg1", description="Example argument", required=True
                )
            ],
        )
    ]


@server.get_prompt()
async def handle_get_prompt(
    name: str, arguments: dict[str, str] | None
) -> types.GetPromptResult:
    if name != "example-prompt":
        raise ValueError(f"Unknown prompt: {name}")

    return types.GetPromptResult(
        description="Example prompt",
        messages=[
            types.PromptMessage(
                role="user",
                content=types.TextContent(type="text", text="Example prompt text"),
            )
        ],
    )


async def run():
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="example",
                server_version="0.1.0",
                capabilities=server.get_capabilities(
                    notification_options=NotificationOptions(),
                    experimental_capabilities={},
                ),
            ),
        )


if __name__ == "__main__":
    import asyncio

    asyncio.run(run())
```

### Writing MCP Clients

The SDK provides a high-level client interface for connecting to MCP servers:

```python
from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_client

# Create server parameters for stdio connection
server_params = StdioServerParameters(
    command="python",  # Executable
    args=["example_server.py"],  # Optional command line arguments
    env=None,  # Optional environment variables
)


# Optional: create a sampling callback
async def handle_sampling_message(
    message: types.CreateMessageRequestParams,
) -> types.CreateMessageResult:
    return types.CreateMessageResult(
        role="assistant",
        content=types.TextContent(
            type="text",
            text="Hello, world! from model",
        ),
        model="gpt-3.5-turbo",
        stopReason="endTurn",
    )


async def run():
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(
            read, write, sampling_callback=handle_sampling_message
        ) as session:
            # Initialize the connection
            await session.initialize()

            # List available prompts
            prompts = await session.list_prompts()

            # Get a prompt
            prompt = await session.get_prompt(
                "example-prompt", arguments={"arg1": "value"}
            )

            # List available resources
            resources = await session.list_resources()

            # List available tools
            tools = await session.list_tools()

            # Read a resource
            content, mime_type = await session.read_resource("file://some/path")

            # Call a tool
            result = await session.call_tool("tool-name", arguments={"arg1": "value"})


if __name__ == "__main__":
    import asyncio

    asyncio.run(run())
```

### MCP Primitives

The MCP protocol defines three core primitives that servers can implement:

| Primitive | Control               | Description                                         | Example Use                  |
|-----------|-----------------------|-----------------------------------------------------|------------------------------|
| Prompts   | User-controlled       | Interactive templates invoked by user choice        | Slash commands, menu options |
| Resources | Application-controlled| Contextual data managed by the client application   | File contents, API responses |
| Tools     | Model-controlled      | Functions exposed to the LLM to take actions        | API calls, data updates      |

### Server Capabilities

MCP servers declare capabilities during initialization:

| Capability  | Feature Flag                 | Description                        |
|-------------|------------------------------|------------------------------------|
| `prompts`   | `listChanged`                | Prompt template management         |
| `resources` | `subscribe`<br/>`listChanged`| Resource exposure and updates      |
| `tools`     | `listChanged`                | Tool discovery and execution       |
| `logging`   | -                            | Server logging configuration       |
| `completion`| -                            | Argument completion suggestions    |

## Documentation

- [Model Context Protocol documentation](https://modelcontextprotocol.io)
- [Model Context Protocol specification](https://spec.modelcontextprotocol.io)
- [Officially supported servers](https://github.com/modelcontextprotocol/servers)

## Contributing

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in the project. See the [contributing guide](CONTRIBUTING.md) to get started.

## License

This project is licensed under the MIT License - see the LICENSE file for details.


MCP Python SDK example of an MCP client:
```py
import asyncio
import json
import logging
import os
import shutil
from contextlib import AsyncExitStack
from typing import Any

import httpx
from dotenv import load_dotenv
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# Configure logging
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)


class Configuration:
    """Manages configuration and environment variables for the MCP client."""

    def __init__(self) -> None:
        """Initialize configuration with environment variables."""
        self.load_env()
        self.api_key = os.getenv("LLM_API_KEY")

    @staticmethod
    def load_env() -> None:
        """Load environment variables from .env file."""
        load_dotenv()

    @staticmethod
    def load_config(file_path: str) -> dict[str, Any]:
        """Load server configuration from JSON file.

        Args:
            file_path: Path to the JSON configuration file.

        Returns:
            Dict containing server configuration.

        Raises:
            FileNotFoundError: If configuration file doesn't exist.
            JSONDecodeError: If configuration file is invalid JSON.
        """
        with open(file_path, "r") as f:
            return json.load(f)

    @property
    def llm_api_key(self) -> str:
        """Get the LLM API key.

        Returns:
            The API key as a string.

        Raises:
            ValueError: If the API key is not found in environment variables.
        """
        if not self.api_key:
            raise ValueError("LLM_API_KEY not found in environment variables")
        return self.api_key


class Server:
    """Manages MCP server connections and tool execution."""

    def __init__(self, name: str, config: dict[str, Any]) -> None:
        self.name: str = name
        self.config: dict[str, Any] = config
        self.stdio_context: Any | None = None
        self.session: ClientSession | None = None
        self._cleanup_lock: asyncio.Lock = asyncio.Lock()
        self.exit_stack: AsyncExitStack = AsyncExitStack()

    async def initialize(self) -> None:
        """Initialize the server connection."""
        command = (
            shutil.which("npx")
            if self.config["command"] == "npx"
            else self.config["command"]
        )
        if command is None:
            raise ValueError("The command must be a valid string and cannot be None.")

        server_params = StdioServerParameters(
            command=command,
            args=self.config["args"],
            env={**os.environ, **self.config["env"]}
            if self.config.get("env")
            else None,
        )
        try:
            stdio_transport = await self.exit_stack.enter_async_context(
                stdio_client(server_params)
            )
            read, write = stdio_transport
            session = await self.exit_stack.enter_async_context(
                ClientSession(read, write)
            )
            await session.initialize()
            self.session = session
        except Exception as e:
            logging.error(f"Error initializing server {self.name}: {e}")
            await self.cleanup()
            raise

    async def list_tools(self) -> list[Any]:
        """List available tools from the server.

        Returns:
            A list of available tools.

        Raises:
            RuntimeError: If the server is not initialized.
        """
        if not self.session:
            raise RuntimeError(f"Server {self.name} not initialized")

        tools_response = await self.session.list_tools()
        tools = []

        for item in tools_response:
            if isinstance(item, tuple) and item[0] == "tools":
                for tool in item[1]:
                    tools.append(Tool(tool.name, tool.description, tool.inputSchema))

        return tools

    async def execute_tool(
        self,
        tool_name: str,
        arguments: dict[str, Any],
        retries: int = 2,
        delay: float = 1.0,
    ) -> Any:
        """Execute a tool with retry mechanism.

        Args:
            tool_name: Name of the tool to execute.
            arguments: Tool arguments.
            retries: Number of retry attempts.
            delay: Delay between retries in seconds.

        Returns:
            Tool execution result.

        Raises:
            RuntimeError: If server is not initialized.
            Exception: If tool execution fails after all retries.
        """
        if not self.session:
            raise RuntimeError(f"Server {self.name} not initialized")

        attempt = 0
        while attempt < retries:
            try:
                logging.info(f"Executing {tool_name}...")
                result = await self.session.call_tool(tool_name, arguments)

                return result

            except Exception as e:
                attempt += 1
                logging.warning(
                    f"Error executing tool: {e}. Attempt {attempt} of {retries}."
                )
                if attempt < retries:
                    logging.info(f"Retrying in {delay} seconds...")
                    await asyncio.sleep(delay)
                else:
                    logging.error("Max retries reached. Failing.")
                    raise

    async def cleanup(self) -> None:
        """Clean up server resources."""
        async with self._cleanup_lock:
            try:
                await self.exit_stack.aclose()
                self.session = None
                self.stdio_context = None
            except Exception as e:
                logging.error(f"Error during cleanup of server {self.name}: {e}")


class Tool:
    """Represents a tool with its properties and formatting."""

    def __init__(
        self, name: str, description: str, input_schema: dict[str, Any]
    ) -> None:
        self.name: str = name
        self.description: str = description
        self.input_schema: dict[str, Any] = input_schema

    def format_for_llm(self) -> str:
        """Format tool information for LLM.

        Returns:
            A formatted string describing the tool.
        """
        args_desc = []
        if "properties" in self.input_schema:
            for param_name, param_info in self.input_schema["properties"].items():
                arg_desc = (
                    f"- {param_name}: {param_info.get('description', 'No description')}"
                )
                if param_name in self.input_schema.get("required", []):
                    arg_desc += " (required)"
                args_desc.append(arg_desc)

        return f"""
Tool: {self.name}
Description: {self.description}
Arguments:
{chr(10).join(args_desc)}
"""


class LLMClient:
    """Manages communication with the LLM provider."""

    def __init__(self, api_key: str) -> None:
        self.api_key: str = api_key

    def get_response(self, messages: list[dict[str, str]]) -> str:
        """Get a response from the LLM.

        Args:
            messages: A list of message dictionaries.

        Returns:
            The LLM's response as a string.

        Raises:
            httpx.RequestError: If the request to the LLM fails.
        """
        url = "https://api.groq.com/openai/v1/chat/completions"

        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
        }
        payload = {
            "messages": messages,
            "model": "llama-3.2-90b-vision-preview",
            "temperature": 0.7,
            "max_tokens": 4096,
            "top_p": 1,
            "stream": False,
            "stop": None,
        }

        try:
            with httpx.Client() as client:
                response = client.post(url, headers=headers, json=payload)
                response.raise_for_status()
                data = response.json()
                return data["choices"][0]["message"]["content"]

        except httpx.RequestError as e:
            error_message = f"Error getting LLM response: {str(e)}"
            logging.error(error_message)

            if isinstance(e, httpx.HTTPStatusError):
                status_code = e.response.status_code
                logging.error(f"Status code: {status_code}")
                logging.error(f"Response details: {e.response.text}")

            return (
                f"I encountered an error: {error_message}. "
                "Please try again or rephrase your request."
            )


class ChatSession:
    """Orchestrates the interaction between user, LLM, and tools."""

    def __init__(self, servers: list[Server], llm_client: LLMClient) -> None:
        self.servers: list[Server] = servers
        self.llm_client: LLMClient = llm_client

    async def cleanup_servers(self) -> None:
        """Clean up all servers properly."""
        cleanup_tasks = []
        for server in self.servers:
            cleanup_tasks.append(asyncio.create_task(server.cleanup()))

        if cleanup_tasks:
            try:
                await asyncio.gather(*cleanup_tasks, return_exceptions=True)
            except Exception as e:
                logging.warning(f"Warning during final cleanup: {e}")

    async def process_llm_response(self, llm_response: str) -> str:
        """Process the LLM response and execute tools if needed.

        Args:
            llm_response: The response from the LLM.

        Returns:
            The result of tool execution or the original response.
        """
        import json

        try:
            tool_call = json.loads(llm_response)
            if "tool" in tool_call and "arguments" in tool_call:
                logging.info(f"Executing tool: {tool_call['tool']}")
                logging.info(f"With arguments: {tool_call['arguments']}")

                for server in self.servers:
                    tools = await server.list_tools()
                    if any(tool.name == tool_call["tool"] for tool in tools):
                        try:
                            result = await server.execute_tool(
                                tool_call["tool"], tool_call["arguments"]
                            )

                            if isinstance(result, dict) and "progress" in result:
                                progress = result["progress"]
                                total = result["total"]
                                percentage = (progress / total) * 100
                                logging.info(
                                    f"Progress: {progress}/{total} "
                                    f"({percentage:.1f}%)"
                                )

                            return f"Tool execution result: {result}"
                        except Exception as e:
                            error_msg = f"Error executing tool: {str(e)}"
                            logging.error(error_msg)
                            return error_msg

                return f"No server found with tool: {tool_call['tool']}"
            return llm_response
        except json.JSONDecodeError:
            return llm_response

    async def start(self) -> None:
        """Main chat session handler."""
        try:
            for server in self.servers:
                try:
                    await server.initialize()
                except Exception as e:
                    logging.error(f"Failed to initialize server: {e}")
                    await self.cleanup_servers()
                    return

            all_tools = []
            for server in self.servers:
                tools = await server.list_tools()
                all_tools.extend(tools)

            tools_description = "\n".join([tool.format_for_llm() for tool in all_tools])

            system_message = (
                "You are a helpful assistant with access to these tools:\n\n"
                f"{tools_description}\n"
                "Choose the appropriate tool based on the user's question. "
                "If no tool is needed, reply directly.\n\n"
                "IMPORTANT: When you need to use a tool, you must ONLY respond with "
                "the exact JSON object format below, nothing else:\n"
                "{\n"
                '    "tool": "tool-name",\n'
                '    "arguments": {\n'
                '        "argument-name": "value"\n'
                "    }\n"
                "}\n\n"
                "After receiving a tool's response:\n"
                "1. Transform the raw data into a natural, conversational response\n"
                "2. Keep responses concise but informative\n"
                "3. Focus on the most relevant information\n"
                "4. Use appropriate context from the user's question\n"
                "5. Avoid simply repeating the raw data\n\n"
                "Please use only the tools that are explicitly defined above."
            )

            messages = [{"role": "system", "content": system_message}]

            while True:
                try:
                    user_input = input("You: ").strip().lower()
                    if user_input in ["quit", "exit"]:
                        logging.info("\nExiting...")
                        break

                    messages.append({"role": "user", "content": user_input})

                    llm_response = self.llm_client.get_response(messages)
                    logging.info("\nAssistant: %s", llm_response)

                    result = await self.process_llm_response(llm_response)

                    if result != llm_response:
                        messages.append({"role": "assistant", "content": llm_response})
                        messages.append({"role": "system", "content": result})

                        final_response = self.llm_client.get_response(messages)
                        logging.info("\nFinal response: %s", final_response)
                        messages.append(
                            {"role": "assistant", "content": final_response}
                        )
                    else:
                        messages.append({"role": "assistant", "content": llm_response})

                except KeyboardInterrupt:
                    logging.info("\nExiting...")
                    break

        finally:
            await self.cleanup_servers()


async def main() -> None:
    """Initialize and run the chat session."""
    config = Configuration()
    server_config = config.load_config("servers_config.json")
    servers = [
        Server(name, srv_config)
        for name, srv_config in server_config["mcpServers"].items()
    ]
    llm_client = LLMClient(config.llm_api_key)
    chat_session = ChatSession(servers, llm_client)
    await chat_session.start()


if __name__ == "__main__":
    asyncio.run(main())
```




JSON schema for Claude Code tools available via MCP:
```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "tools": [
            {
                "name": "dispatch_agent",
                "description": "Launch a new task",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "prompt": {
                            "type": "string",
                            "description": "The task for the agent to perform"
                        }
                    },
                    "required": [
                        "prompt"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "Bash",
                "description": "Run shell command",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "command": {
                            "type": "string",
                            "description": "The command to execute"
                        },
                        "timeout": {
                            "type": "number",
                            "description": "Optional timeout in milliseconds (max 600000)"
                        },
                        "description": {
                            "type": "string",
                            "description": " Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'"
                        }
                    },
                    "required": [
                        "command"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "BatchTool",
                "description": "\n- Batch execution tool that runs multiple tool invocations in a single request\n- Tools are executed in parallel when possible, and otherwise serially\n- Takes a list of tool invocations (tool_name and input pairs)\n- Returns the collected results from all invocations\n- Use this tool when you need to run multiple independent tool operations at once -- it is awesome for speeding up your workflow, reducing both context usage and latency\n- Each tool will respect its own permissions and validation rules\n- The tool's outputs are NOT shown to the user; to answer the user's query, you MUST send a message with the results after the tool call completes, otherwise the user will not see the results\n\nAvailable tools:\nTool: dispatch_agent\nArguments: prompt: string \"The task for the agent to perform\"\nUsage: Launch a new agent that has access to the following tools: View, GlobTool, GrepTool, LS, ReadNotebook, WebFetchTool. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries, use the Agent tool to perform the search for you.\n\nWhen to use the Agent tool:\n- If you are searching for a keyword like \"config\" or \"logger\", or for questions like \"which file does X?\", the Agent tool is strongly recommended\n\nWhen NOT to use the Agent tool:\n- If you want to read a specific file path, use the View or GlobTool tool instead of the Agent tool, to find the match more quickly\n- If you are searching for a specific class definition like \"class Foo\", use the GlobTool tool instead, to find the match more quickly\n- If you are searching for code within a specific file or set of 2-3 files, use the View tool instead of the Agent tool, to find the match more quickly\n\nUsage notes:\n1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses\n2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.\n3. Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.\n4. The agent's outputs should generally be trusted\n5. IMPORTANT: The agent can not use Bash, Replace, Edit, NotebookEditCell, so can not modify files. If you want to use these tools, use them directly instead of going through the agent.\n---Tool: Bash\nArguments: command: string \"The command to execute\", [optional] timeout: number \"Optional timeout in milliseconds (max 600000)\", [optional] description: string \" Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'\"\nUsage: Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.\n\nBefore executing the command, please follow these steps:\n\n1. Directory Verification:\n   - If the command will create new directories or files, first use the LS tool to verify the parent directory exists and is the correct location\n   - For example, before running \"mkdir foo/bar\", first use LS to check that \"foo\" exists and is the intended parent directory\n\n2. Security Check:\n   - For security and to limit the threat of a prompt injection attack, some commands are limited or banned. If you use a disallowed command, you will receive an error message explaining the restriction. Explain the error to the User.\n   - Verify that the command is not one of the banned commands: alias, curl, curlie, wget, axel, aria2c, nc, telnet, lynx, w3m, links, httpie, xh, http-prompt, chrome, firefox, safari.\n\n3. Command Execution:\n   - After ensuring proper quoting, execute the command.\n   - Capture the output of the command.\n\nUsage notes:\n  - The command argument is required.\n  - You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30 minutes.\n  - It is very helpful if you write a clear, concise description of what this command does in 5-10 words.\n  - If the output exceeds 30000 characters, output will be truncated before being returned to you.\n  - VERY IMPORTANT: You MUST avoid using search commands like `find` and `grep`. Instead use GrepTool, GlobTool, or dispatch_agent to search. You MUST avoid read tools like `cat`, `head`, `tail`, and `ls`, and use View and LS to read files.\n  - When issuing multiple commands, use the ';' or '&&' operator to separate them. DO NOT use newlines (newlines are ok in quoted strings).\n  - Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of `cd`. You may use `cd` if the User explicitly requests it.\n    <good-example>\n    pytest /foo/bar/tests\n    </good-example>\n    <bad-example>\n    cd /foo/bar && pytest tests\n    </bad-example>\n\n# Committing changes with git\n\nWhen the user asks you to create a new git commit, follow these steps carefully:\n\n1. Use BatchTool to run the following commands in parallel:\n   - Run a git status command to see all untracked files.\n   - Run a git diff command to see both staged and unstaged changes that will be committed.\n   - Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.\n\n2. Analyze all staged changes (both previously staged and newly added) and draft a commit message. Wrap your analysis process in <commit_analysis> tags:\n\n<commit_analysis>\n- List the files that have been changed or added\n- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)\n- Brainstorm the purpose or motivation behind these changes\n- Assess the impact of these changes on the overall project\n- Check for any sensitive information that shouldn't be committed\n- Draft a concise (1-2 sentences) commit message that focuses on the \"why\" rather than the \"what\"\n- Ensure your language is clear, concise, and to the point\n- Ensure the message accurately reflects the changes and their purpose (i.e. \"add\" means a wholly new feature, \"update\" means an enhancement to an existing feature, \"fix\" means a bug fix, etc.)\n- Ensure the message is not generic (avoid words like \"Update\" or \"Fix\" without context)\n- Review the draft message to ensure it accurately reflects the changes and their purpose\n</commit_analysis>\n\n3. Use BatchTool to run the following commands in parallel:\n   - Add relevant untracked files to the staging area.\n   - Create the commit with a message ending with:\n   🤖 Generated with [Claude Code](https://claude.ai/code)\n\n   Co-Authored-By: Claude <noreply@anthropic.com>\n   - Run git status to make sure the commit succeeded.\n\n4. If the commit fails due to pre-commit hook changes, retry the commit ONCE to include these automated changes. If it fails again, it usually means a pre-commit hook is preventing the commit. If the commit succeeds but you notice that files were modified by the pre-commit hook, you MUST amend your commit to include them.\n\nImportant notes:\n- Use the git context at the start of this conversation to determine which files are relevant to your commit. Be careful not to stage and commit files (e.g. with `git add .`) that aren't relevant to your commit.\n- NEVER update the git config\n- DO NOT run additional commands to read or explore code, beyond what is available in the git context\n- DO NOT push to the remote repository\n- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.\n- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit\n- Ensure your commit message is meaningful and concise. It should explain the purpose of the changes, not just describe them.\n- Return an empty response - the user will see the git output directly\n- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:\n<example>\ngit commit -m \"$(cat <<'EOF'\n   Commit message here.\n\n   🤖 Generated with [Claude Code](https://claude.ai/code)\n\n   Co-Authored-By: Claude <noreply@anthropic.com>\n   EOF\n   )\"\n</example>\n\n# Creating pull requests\nUse the gh command via the Bash tool for ALL GitHub-related tasks including working with issues, pull requests, checks, and releases. If given a Github URL use the gh command to get the information needed.\n\nIMPORTANT: When the user asks you to create a pull request, follow these steps carefully:\n\n1. Use BatchTool to run the following commands in parallel, in order to understand the current state of the branch since it diverged from the main branch:\n   - Run a git status command to see all untracked files\n   - Run a git diff command to see both staged and unstaged changes that will be committed\n   - Check if the current branch tracks a remote branch and is up to date with the remote, so you know if you need to push to the remote\n   - Run a git log command and `git diff main...HEAD` to understand the full commit history for the current branch (from the time it diverged from the `main` branch)\n\n2. Analyze all changes that will be included in the pull request, making sure to look at all relevant commits (NOT just the latest commit, but ALL commits that will be included in the pull request!!!), and draft a pull request summary. Wrap your analysis process in <pr_analysis> tags:\n\n<pr_analysis>\n- List the commits since diverging from the main branch\n- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)\n- Brainstorm the purpose or motivation behind these changes\n- Assess the impact of these changes on the overall project\n- Do not use tools to explore code, beyond what is available in the git context\n- Check for any sensitive information that shouldn't be committed\n- Draft a concise (1-2 bullet points) pull request summary that focuses on the \"why\" rather than the \"what\"\n- Ensure the summary accurately reflects all changes since diverging from the main branch\n- Ensure your language is clear, concise, and to the point\n- Ensure the summary accurately reflects the changes and their purpose (ie. \"add\" means a wholly new feature, \"update\" means an enhancement to an existing feature, \"fix\" means a bug fix, etc.)\n- Ensure the summary is not generic (avoid words like \"Update\" or \"Fix\" without context)\n- Review the draft summary to ensure it accurately reflects the changes and their purpose\n</pr_analysis>\n\n3. Use BatchTool to run the following commands in parallel:\n   - Create new branch if needed\n   - Push to remote with -u flag if needed\n   - Create PR using gh pr create with the format below. Use a HEREDOC to pass the body to ensure correct formatting.\n<example>\ngh pr create --title \"the pr title\" --body \"$(cat <<'EOF'\n## Summary\n<1-3 bullet points>\n\n## Test plan\n[Checklist of TODOs for testing the pull request...]\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\nEOF\n)\"\n</example>\n\nImportant:\n- NEVER update the git config\n- Return an empty response - the user will see the gh output directly\n\n# Other common operations\n- View comments on a Github PR: gh api repos/foo/bar/pulls/123/comments\n---Tool: GlobTool\nArguments: pattern: string \"The glob pattern to match files against\", [optional] path: string \"The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter \"undefined\" or \"null\" - simply omit it for the default behavior. Must be a valid directory path if provided.\"\nUsage: - Fast file pattern matching tool that works with any codebase size\n- Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\"\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files by name patterns\n- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead\n\n---Tool: GrepTool\nArguments: pattern: string \"The regular expression pattern to search for in file contents\", [optional] path: string \"The directory to search in. Defaults to the current working directory.\", [optional] include: string \"File pattern to include in the search (e.g. \"*.js\", \"*.{ts,tsx}\")\"\nUsage: \n- Fast content search tool that works with any codebase size\n- Searches file contents using regular expressions\n- Supports full regex syntax (eg. \"log.*Error\", \"function\\s+\\w+\", etc.)\n- Filter files by pattern with the include parameter (eg. \"*.js\", \"*.{ts,tsx}\")\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files containing specific patterns\n- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead\n\n---Tool: LS\nArguments: path: string \"The absolute path to the directory to list (must be absolute, not relative)\", [optional] ignore: array \"List of glob patterns to ignore\"\nUsage: Lists files and directories in a given path. The path parameter must be an absolute path, not a relative path. You can optionally provide an array of glob patterns to ignore with the ignore parameter. You should generally prefer the Glob and Grep tools, if you know which directories to search.\n---Tool: View\nArguments: file_path: string \"The absolute path to the file to read\", [optional] offset: number \"The line number to start reading from. Only provide if the file is too large to read at once\", [optional] limit: number \"The number of lines to read. Only provide if the file is too large to read at once.\"\nUsage: Reads a file from the local filesystem. You can access any file directly by using this tool.\nAssume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.\n\nUsage:\n- The file_path parameter must be an absolute path, not a relative path\n- By default, it reads up to 2000 lines starting from the beginning of the file\n- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters\n- Any lines longer than 2000 characters will be truncated\n- Results are returned using cat -n format, with line numbers starting at 1\n- This tool allows Claude Code to VIEW images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as Claude Code is a multimodal LLM.\n- For Jupyter notebooks (.ipynb files), use the ReadNotebook instead\n- When reading multiple files, you MUST use the BatchTool tool to read them all at once\n---Tool: Edit\nArguments: file_path: string \"The absolute path to the file to modify\", old_string: string \"The text to replace\", new_string: string \"The text to replace it with\", [optional] expected_replacements: number \"The expected number of replacements to perform. Defaults to 1 if not specified.\"\nUsage: This is a tool for editing files. For moving or renaming files, you should generally use the Bash tool with the 'mv' command instead. For larger edits, use the Write tool to overwrite files. For Jupyter notebooks (.ipynb files), use the NotebookEditCell instead.\n\nBefore using this tool:\n\n1. Use the View tool to understand the file's contents and context\n\n2. Verify the directory path is correct (only applicable when creating new files):\n   - Use the LS tool to verify the parent directory exists and is the correct location\n\nTo make a file edit, provide the following:\n1. file_path: The absolute path to the file to modify (must be absolute, not relative)\n2. old_string: The text to replace (must match the file contents exactly, including all whitespace and indentation)\n3. new_string: The edited text to replace the old_string\n4. expected_replacements: The number of replacements you expect to make. Defaults to 1 if not specified.\n\nBy default, the tool will replace ONE occurrence of old_string with new_string in the specified file. If you want to replace multiple occurrences, provide the expected_replacements parameter with the exact number of occurrences you expect.\n\nCRITICAL REQUIREMENTS FOR USING THIS TOOL:\n\n1. UNIQUENESS (when expected_replacements is not specified): The old_string MUST uniquely identify the specific instance you want to change. This means:\n   - Include AT LEAST 3-5 lines of context BEFORE the change point\n   - Include AT LEAST 3-5 lines of context AFTER the change point\n   - Include all whitespace, indentation, and surrounding code exactly as it appears in the file\n\n2. EXPECTED MATCHES: If you want to replace multiple instances:\n   - Use the expected_replacements parameter with the exact number of occurrences you expect to replace\n   - This will replace ALL occurrences of the old_string with the new_string\n   - If the actual number of matches doesn't equal expected_replacements, the edit will fail\n   - This is a safety feature to prevent unintended replacements\n\n3. VERIFICATION: Before using this tool:\n   - Check how many instances of the target text exist in the file\n   - If multiple instances exist, either:\n     a) Gather enough context to uniquely identify each one and make separate calls, OR\n     b) Use expected_replacements parameter with the exact count of instances you expect to replace\n\nWARNING: If you do not follow these requirements:\n   - The tool will fail if old_string matches multiple locations and expected_replacements isn't specified\n   - The tool will fail if the number of matches doesn't equal expected_replacements when it's specified\n   - The tool will fail if old_string doesn't match exactly (including whitespace)\n   - You may change unintended instances if you don't verify the match count\n\nWhen making edits:\n   - Ensure the edit results in idiomatic, correct code\n   - Do not leave the code in a broken state\n   - Always use absolute file paths (starting with /)\n\nIf you want to create a new file, use:\n   - A new file path, including dir name if needed\n   - An empty old_string\n   - The new file's contents as new_string\n\nRemember: when making multiple file edits in a row to the same file, you should prefer to send all edits in a single message with multiple calls to this tool, rather than multiple messages with a single call each.\n\n---Tool: Replace\nArguments: file_path: string \"The absolute path to the file to write (must be absolute, not relative)\", content: string \"The content to write to the file\"\nUsage: Write a file to the local filesystem. Overwrites the existing file if there is one.\n\nBefore using this tool:\n\n1. Use the ReadFile tool to understand the file's contents and context\n\n2. Directory Verification (only applicable when creating new files):\n   - Use the LS tool to verify the parent directory exists and is the correct location\n---Tool: ReadNotebook\nArguments: notebook_path: string \"The absolute path to the Jupyter notebook file to read (must be absolute, not relative)\"\nUsage: Reads a Jupyter notebook (.ipynb file) and returns all of the cells with their outputs. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path.\n---Tool: NotebookEditCell\nArguments: notebook_path: string \"The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)\", cell_number: number \"The index of the cell to edit (0-based)\", new_source: string \"The new source for the cell\", [optional] cell_type: string \"The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required.\", [optional] edit_mode: string \"The type of edit to make (replace, insert, delete). Defaults to replace.\"\nUsage: Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number.\n---Tool: WebFetchTool\nArguments: url: string \"The URL to fetch content from\", prompt: string \"The prompt to run on the fetched content\"\nUsage: \n- Fetches content from a specified URL and processes it using an AI model\n- Takes a URL and a prompt as input\n- Fetches the URL content, converts HTML to markdown\n- Processes the content with the prompt using a small, fast model\n- Returns the model's response about the content\n- Use this tool when you need to retrieve and analyze web content\n\nUsage notes:\n  - IMPORTANT: If an MCP-provided web fetch tool is available, prefer using that tool instead of this one, as it may have fewer restrictions. All MCP-provided tools start with \"mcp__\".\n  - The URL must be a fully-formed valid URL\n  - HTTP URLs will be automatically upgraded to HTTPS\n  - For security reasons, the URL's domain must have been provided directly by the user, unless it's on a small pre-approved set of the top few dozen hosts for popular coding resources, like react.dev.\n  - The prompt should describe what information you want to extract from the page\n  - This tool is read-only and does not modify any files\n  - Results may be summarized if the content is very large\n  - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL\n\n\nExample usage:\n{\n  \"invocations\": [\n    {\n      \"tool_name\": \"Bash\",\n      \"input\": {\n        \"command\": \"git blame src/foo.ts\"\n      }\n    },\n    {\n      \"tool_name\": \"GlobTool\",\n      \"input\": {\n        \"pattern\": \"**/*.ts\"\n      }\n    },\n    {\n      \"tool_name\": \"GrepTool\",\n      \"input\": {\n        \"pattern\": \"function\",\n        \"include\": \"*.ts\"\n      }\n    }\n  ]\n}\n",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "description": {
                            "type": "string",
                            "description": "A short (3-5 word) description of the batch operation"
                        },
                        "invocations": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "tool_name": {
                                        "type": "string",
                                        "description": "The name of the tool to invoke"
                                    },
                                    "input": {
                                        "type": "object",
                                        "additionalProperties": {},
                                        "description": "The input to pass to the tool"
                                    }
                                },
                                "required": [
                                    "tool_name",
                                    "input"
                                ],
                                "additionalProperties": false
                            },
                            "description": "The list of tool invocations to execute"
                        }
                    },
                    "required": [
                        "description",
                        "invocations"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "GlobTool",
                "description": "- Fast file pattern matching tool that works with any codebase size\n- Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\"\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files by name patterns\n- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead\n",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "pattern": {
                            "type": "string",
                            "description": "The glob pattern to match files against"
                        },
                        "path": {
                            "type": "string",
                            "description": "The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter \"undefined\" or \"null\" - simply omit it for the default behavior. Must be a valid directory path if provided."
                        }
                    },
                    "required": [
                        "pattern"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "GrepTool",
                "description": "\n- Fast content search tool that works with any codebase size\n- Searches file contents using regular expressions\n- Supports full regex syntax (eg. \"log.*Error\", \"function\\s+\\w+\", etc.)\n- Filter files by pattern with the include parameter (eg. \"*.js\", \"*.{ts,tsx}\")\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files containing specific patterns\n- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead\n",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "pattern": {
                            "type": "string",
                            "description": "The regular expression pattern to search for in file contents"
                        },
                        "path": {
                            "type": "string",
                            "description": "The directory to search in. Defaults to the current working directory."
                        },
                        "include": {
                            "type": "string",
                            "description": "File pattern to include in the search (e.g. \"*.js\", \"*.{ts,tsx}\")"
                        }
                    },
                    "required": [
                        "pattern"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "LS",
                "description": "Lists files and directories in a given path. The path parameter must be an absolute path, not a relative path. You can optionally provide an array of glob patterns to ignore with the ignore parameter. You should generally prefer the Glob and Grep tools, if you know which directories to search.",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "path": {
                            "type": "string",
                            "description": "The absolute path to the directory to list (must be absolute, not relative)"
                        },
                        "ignore": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "description": "List of glob patterns to ignore"
                        }
                    },
                    "required": [
                        "path"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "View",
                "description": "Read a file from the local filesystem.",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "file_path": {
                            "type": "string",
                            "description": "The absolute path to the file to read"
                        },
                        "offset": {
                            "type": "number",
                            "description": "The line number to start reading from. Only provide if the file is too large to read at once"
                        },
                        "limit": {
                            "type": "number",
                            "description": "The number of lines to read. Only provide if the file is too large to read at once."
                        }
                    },
                    "required": [
                        "file_path"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "Edit",
                "description": "A tool for editing files",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "file_path": {
                            "type": "string",
                            "description": "The absolute path to the file to modify"
                        },
                        "old_string": {
                            "type": "string",
                            "description": "The text to replace"
                        },
                        "new_string": {
                            "type": "string",
                            "description": "The text to replace it with"
                        },
                        "expected_replacements": {
                            "type": "number",
                            "default": 1,
                            "description": "The expected number of replacements to perform. Defaults to 1 if not specified."
                        }
                    },
                    "required": [
                        "file_path",
                        "old_string",
                        "new_string"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "Replace",
                "description": "Write a file to the local filesystem.",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "file_path": {
                            "type": "string",
                            "description": "The absolute path to the file to write (must be absolute, not relative)"
                        },
                        "content": {
                            "type": "string",
                            "description": "The content to write to the file"
                        }
                    },
                    "required": [
                        "file_path",
                        "content"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "ReadNotebook",
                "description": "Extract and read source code from all code cells in a Jupyter notebook.",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "notebook_path": {
                            "type": "string",
                            "description": "The absolute path to the Jupyter notebook file to read (must be absolute, not relative)"
                        }
                    },
                    "required": [
                        "notebook_path"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "NotebookEditCell",
                "description": "Replace the contents of a specific cell in a Jupyter notebook.",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "notebook_path": {
                            "type": "string",
                            "description": "The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"
                        },
                        "cell_number": {
                            "type": "number",
                            "description": "The index of the cell to edit (0-based)"
                        },
                        "new_source": {
                            "type": "string",
                            "description": "The new source for the cell"
                        },
                        "cell_type": {
                            "type": "string",
                            "enum": [
                                "code",
                                "markdown"
                            ],
                            "description": "The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required."
                        },
                        "edit_mode": {
                            "type": "string",
                            "description": "The type of edit to make (replace, insert, delete). Defaults to replace."
                        }
                    },
                    "required": [
                        "notebook_path",
                        "cell_number",
                        "new_source"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            },
            {
                "name": "WebFetchTool",
                "description": "Claude wants to fetch content from this URL",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL to fetch content from"
                        },
                        "prompt": {
                            "type": "string",
                            "description": "The prompt to run on the fetched content"
                        }
                    },
                    "required": [
                        "url",
                        "prompt"
                    ],
                    "additionalProperties": false,
                    "$schema": "http://json-schema.org/draft-07/schema#"
                }
            }
        ]
    }
}
```

    This is a tool for creating a new file or editing an existing file. For moving or renaming files, you should generally use the `terminal` tool with the 'mv' command instead.

Before using this tool:

1. Use the `read_file` tool to understand the file's contents and context

2. Verify the directory path is correct (only applicable when creating new files):
   - Use the `list_directory` tool to verify the parent directory exists and is the correct location

    Fetches a URL and returns the content as Markdown.

    Fast file path pattern matching tool that works with any codebase size

- Supports glob patterns like "**/*.js" or "src/**/*.ts"
- Returns matching file paths sorted alphabetically
- Prefer the `grep` tool to this tool when searching for symbols unless you have specific information about paths.
- Use this tool when you need to find files by name patterns
- Results are paginated with 50 matches per page. Use the optional 'offset' parameter to request subsequent pages.

    Searches the contents of files in the project with a regular expression

- Prefer this tool to path search when searching for symbols in the project, because you won't need to guess what path it's in.
- Supports full regex syntax (eg. "log.*Error", "function\\s+\\w+", etc.)
- Pass an `include_pattern` if you know how to narrow your search on the files system
- Never use this tool to search for paths. Only search file contents with this tool.
- Use this tool when you need to find files containing specific patterns
- Results are paginated with 20 matches per page. Use the optional 'offset' parameter to request subsequent pages.
- DO NOT use HTML entities solely to escape characters in the tool parameters.

    Lists files and directories in a given path. Prefer the `grep` or `find_path` tools when searching the codebase.

    Moves or rename a file or directory in the project, and returns confirmation that the move succeeded.
If the source and destination directories are the same, but the filename is different, this performs
a rename. Otherwise, it performs a move.

This tool should be used when it's desirable to move or rename a file or directory without changing its contents at all.

    This tool opens a file or URL with the default application associated with it on the user's operating system:
- On macOS, it's equivalent to the `open` command
- On Windows, it's equivalent to `start`
- On Linux, it uses something like `xdg-open`, `gio open`, `gnome-open`, `kde-open`, `wslview` as appropriate

For example, it can open a web browser with a URL, open a PDF file with the default PDF viewer, etc.

You MUST ONLY use this tool when the user has explicitly requested opening something. You MUST NEVER assume that
the user would like for you to use this tool.

    This tool reports which files have been modified by the user since the agent last accessed them.

It serves as a notification mechanism to inform the agent of recent changes. No immediate action is required in response to these updates.

    Reads the content of the given file in the project.

- Never attempt to read a path that hasn't been previously mentioned.

    Executes a shell one-liner and returns the combined output.

This tool spawns a process using the user's shell, reads from stdout and stderr (preserving the order of writes), and returns a string with the combined output result.

The output results will be shown to the user already, only list it again if necessary, avoid being redundant.

Make sure you use the `cd` parameter to navigate to one of the root directories of the project. NEVER do it as part of the `command` itself, otherwise it will error.

Do not use this tool for commands that run indefinitely, such as servers (like `npm run start`, `npm run dev`, `python -m http.server`, etc) or file watchers that don't terminate on their own.

Remember that each invocation of this tool will spawn a new shell process, so you can't rely on any state from previous invocations.

    A tool for thinking through problems, brainstorming ideas, or planning without executing any actions. Use this tool when you need to work through complex problems, develop strategies, or outline approaches before taking action.

    # Zed Server

This crate is what we run at https://collab.zed.dev.

It contains our back-end logic for collaboration, to which we connect from the Zed client via a websocket after authenticating via https://zed.dev, which is a separate repo running on Vercel.

# Local Development

## Database setup

Before you can run the collab server locally, you'll need to set up a zed Postgres database. Follow the steps sequentially:

1. Ensure you have postgres installed. If not, install with `brew install postgresql@15`.
2. Follow the steps on Brew's formula and verify your `$PATH` contains `/opt/homebrew/opt/postgresql@15/bin`.
3. If you hadn't done it before, create the `postgres` user with `createuser -s postgres`.
4. You are now ready to run the `bootstrap` script:

```sh
script/bootstrap
```

This script will set up the `zed` Postgres database, and populate it with some users. It requires internet access, because it fetches some users from the GitHub API.

The script will create several _admin_ users, who you'll sign in as by default when developing locally. The GitHub logins for the default users are specified in the `seed.default.json` file.

To use a different set of admin users, create `crates/collab/seed.json`.

```json
{
  "admins": ["yourgithubhere"],
  "channels": ["zed"]
}
```

## Testing collaborative features locally

In one terminal, run Zed's collaboration server and the livekit dev server:

```sh
foreman start
```

In a second terminal, run two or more instances of Zed.

```sh
script/zed-local -2
```

This script starts one to four instances of Zed, depending on the `-2`, `-3` or `-4` flags. Each instance will be connected to the local `collab` server, signed in as a different user from `seed.json` or `seed.default.json`.

# Deployment

We run two instances of collab:

- Staging (https://staging-collab.zed.dev)
- Production (https://collab.zed.dev)

Both of these run on the Kubernetes cluster hosted in Digital Ocean.

Deployment is triggered by pushing to the `collab-staging` (or `collab-production`) tag in GitHub. The best way to do this is:

- `./script/deploy-collab staging`
- `./script/deploy-collab production`

You can tell what is currently deployed with `./script/what-is-deployed`.

# Database Migrations

To create a new migration:

```sh
./script/create-migration <name>
```

Migrations are run automatically on service start, so run `foreman start` again. The service will crash if the migrations fail.

When you create a new migration, you also need to update the [SQLite schema](./migrations.sqlite/20221109000000_test_schema.sql) that is used for testing.

    # Overview

The active `Project` is responsible for maintain opened and closed breakpoints
as well as serializing breakpoints to save. At a high level project serializes
the positions of breakpoints that don't belong to any active buffers and handles
converting breakpoints from serializing to active whenever a buffer is opened/closed.

`Project` also handles sending all relevant breakpoint information to debug adapter's
during debugging or when starting a debugger.

    # Building Queries

First, craft your test data. The examples folder shows a template for building a test-db, and can be ran with `cargo run --example [your-example]`.

To actually use and test your queries, import the generated DB file into https://sqliteonline.com/

    Real time streaming audio denoising using a [Dual-Signal Transformation LSTM Network for Real-Time Noise Suppression](https://arxiv.org/abs/2005.07551).

Trivial to build as it uses the native rust Candle crate for inference. Easy to integrate into any Rodio pipeline.

```rust
    # use rodio::{nz, source::UniformSourceIterator, wav_to_file};
    let file = std::fs::File::open("clips_airconditioning.wav")?;
    let decoder = rodio::Decoder::try_from(file)?;
    let resampled = UniformSourceIterator::new(decoder, nz!(1), nz!(16_000));

    let mut denoised = denoise::Denoiser::try_new(resampled)?;
    wav_to_file(&mut denoised, "denoised.wav")?;
    Result::Ok<(), Box<dyn std::error::Error>>
```

## Acknowledgements & License

The trained models in this repo are optimized versions of the models in the [breizhn/DTLN](https://github.com/breizhn/DTLN?tab=readme-ov-file#model-conversion-and-real-time-processing-with-onnx). These are licensed under MIT.

The FFT code was adapted from Datadog's [dtln-rs Repo](https://github.com/DataDog/dtln-rs/tree/main) also licensed under MIT.

    # Eval

This eval assumes the working directory is the root of the repository. Run it with:

```sh
cargo run -p eval
```

The eval will optionally read a `.env` file in `crates/eval` if you need it to set environment variables, such as API keys.

## Explorer Tool

The explorer tool generates a self-contained HTML view from one or more thread
JSON file. It provides a visual interface to explore the agent thread, including
tool calls and results. See [./docs/explorer.md](./docs/explorer.md) for more details.

### Usage

```sh
cargo run -p eval --bin explorer -- --input <path-to-json-files> --output <output-html-path>
```

Example:

```sh
cargo run -p eval --bin explorer -- --input ./runs/2025-04-23_15-53-30/fastmcp_bugifx/*/last.messages.json --output /tmp/explorer.html
```

    # Explorer

Threads Explorer is a single self-contained HTML file that gives an overview of
evaluation runs, while allowing for some interactivity.

When you open a file, it gives you a _thread overview_, which looks like this:

| Turn | Text                                 | Tool                                         | Result                                        |
| ---- | ------------------------------------ | -------------------------------------------- | --------------------------------------------- |
| 1    | [User]:                              |                                              |                                               |
|      | Fix the bug: kwargs not passed...    |                                              |                                               |
| 2    | I'll help you fix that bug.          | **list_directory**(path="fastmcp")           | `fastmcp/src [...]`                           |
|      |                                      |                                              |                                               |
| 3    | Let's examine the code.              | **read_file**(path="fastmcp/main.py", [...]) | `def run_application(app, \*\*kwargs): [...]` |
| 4    | I found the issue.                   | **edit_file**(path="fastmcp/core.py", [...]) | `Made edit to fastmcp/core.py`                |
| 5    | Let's check if there are any errors. | **diagnostics**()                            | `No errors found`                             |

### Implementation details

`src/explorer.html` contains the template. You can open this template in a
browser as is, and it will show some dummy values. But the main use is to set
the `threadsData` variable with real data, which then will be used instead of
the dummy values.

`src/explorer.rs` takes one or more JSON files as generated by `cargo run -p
eval`, and outputs an HTML file for rendering these threads. Refer dummy data
in `explorer.html` for a sample format.

    # Pending Changes

This is a list of pending changes to the Zed extension API that require a breaking change.

This list should be updated as we notice things that should be changed so that we can batch them up in a single release.

## vNext

### Slash Commands

- Rename `SlashCommand.tooltip_text` to `SlashCommand.menu_text`
  - We may even want to remove it entirely, as right now this is only used for featured slash commands, and slash commands defined by extensions aren't currently able to be featured.

    # The Zed Rust Extension API

This crate lets you write extensions for Zed in Rust.

## Extension Manifest

You'll need an `extension.toml` file at the root of your extension directory, with the following structure:

```toml
id = "my-extension"
name = "My Extension"
description = "..."
version = "0.0.1"
schema_version = 1
authors = ["Your Name <you@example.com>"]
repository = "https://github.com/your/extension-repository"
```

## Cargo metadata

Zed extensions are packaged as WebAssembly files. In your Cargo.toml, you'll
need to set your `crate-type` accordingly:

```toml
[dependencies]
zed_extension_api = "0.6.0"

[lib]
crate-type = ["cdylib"]
```

## Implementing an Extension

To define your extension, create a type that implements the `Extension` trait, and register it.

```rust
use zed_extension_api as zed;

struct MyExtension {
    // ... state
}

impl zed::Extension for MyExtension {
    // ...
}

zed::register_extension!(MyExtension);
```

## Testing your extension

To run your extension in Zed as you're developing it:

- Make sure you have [Rust installed](https://www.rust-lang.org/learn/get-started)
- Have the `wasm32-wasip2` target installed (`rustup target add wasm32-wasip2`)
- Open the extensions view using the `zed: extensions` action in the command palette.
- Click the `Install Dev Extension` button in the top right
- Choose the path to your extension directory.

## Compatible Zed versions

Extensions created using newer versions of the Zed extension API won't be compatible with older versions of Zed.

Here is the compatibility of the `zed_extension_api` with versions of Zed:

| Zed version | `zed_extension_api` version |
| ----------- | --------------------------- |
| `0.192.x`   | `0.0.1` - `0.6.0`           |
| `0.186.x`   | `0.0.1` - `0.5.0`           |
| `0.184.x`   | `0.0.1` - `0.4.0`           |
| `0.178.x`   | `0.0.1` - `0.3.0`           |
| `0.162.x`   | `0.0.1` - `0.2.0`           |
| `0.149.x`   | `0.0.1` - `0.1.0`           |
| `0.131.x`   | `0.0.1` - `0.0.6`           |
| `0.130.x`   | `0.0.1` - `0.0.5`           |
| `0.129.x`   | `0.0.1` - `0.0.4`           |
| `0.128.x`   | `0.0.1`                     |

    # Welcome to GPUI!

GPUI is a hybrid immediate and retained mode, GPU accelerated, UI framework
for Rust, designed to support a wide variety of applications.

## Getting Started

GPUI is still in active development as we work on the Zed code editor and isn't yet on crates.io. You'll also need to use the latest version of stable Rust and be on macOS or Linux. Add the following to your `Cargo.toml`:

```toml
gpui = { git = "https://github.com/zed-industries/zed" }
```

Everything in GPUI starts with an `Application`. You can create one with `Application::new()`, and kick off your application by passing a callback to `Application::run()`. Inside this callback, you can create a new window with `App::open_window()`, and register your first root view. See [gpui.rs](https://www.gpui.rs/) for a complete example.

### Dependencies

GPUI has various system dependencies that it needs in order to work.

#### macOS

On macOS, GPUI uses Metal for rendering. In order to use Metal, you need to do the following:

- Install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12) from the macOS App Store, or from the [Apple Developer](https://developer.apple.com/download/all/) website. Note this requires a developer account.

> Ensure you launch Xcode after installing, and install the macOS components, which is the default option. If you are on macOS 26 (Tahoe) you will need to use `--features gpui/runtime_shaders` or add the feature in the root `Cargo.toml`

- Install [Xcode command line tools](https://developer.apple.com/xcode/resources/)

  ```sh
  xcode-select --install
  ```

- Ensure that the Xcode command line tools are using your newly installed copy of Xcode:

  ```sh
  sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
  ```

## The Big Picture

GPUI offers three different [registers](<https://en.wikipedia.org/wiki/Register_(sociolinguistics)>) depending on your needs:

- State management and communication with `Entity`'s. Whenever you need to store application state that communicates between different parts of your application, you'll want to use GPUI's entities. Entities are owned by GPUI and are only accessible through an owned smart pointer similar to an `Rc`. See the `app::context` module for more information.

- High level, declarative UI with views. All UI in GPUI starts with a view. A view is simply an `Entity` that can be rendered, by implementing the `Render` trait. At the start of each frame, GPUI will call this render method on the root view of a given window. Views build a tree of `elements`, lay them out and style them with a tailwind-style API, and then give them to GPUI to turn into pixels. See the `div` element for an all purpose swiss-army knife of rendering.

- Low level, imperative UI with Elements. Elements are the building blocks of UI in GPUI, and they provide a nice wrapper around an imperative API that provides as much flexibility and control as you need. Elements have total control over how they and their child elements are rendered and can be used for making efficient views into large lists, implement custom layouting for a code editor, and anything else you can think of. See the `element` module for more information.

Each of these registers has one or more corresponding contexts that can be accessed from all GPUI services. This context is your main interface to GPUI, and is used extensively throughout the framework.

## Other Resources

In addition to the systems above, GPUI provides a range of smaller services that are useful for building complex applications:

- Actions are user-defined structs that are used for converting keystrokes into logical operations in your UI. Use this for implementing keyboard shortcuts, such as cmd-q. See the `action` module for more information.

- Platform services, such as `quit the app` or `open a URL` are available as methods on the `app::App`.

- An async executor that is integrated with the platform's event loop. See the `executor` module for more information.,

- The `[gpui::test]` macro provides a convenient way to write tests for your GPUI applications. Tests also have their own kind of context, a `TestAppContext` which provides ways of simulating common platform input. See `app::test_context` and `test` modules for more details.

Currently, the best way to learn about these APIs is to read the Zed source code, ask us about it at a fireside hack, or drop a question in the [Zed Discord](https://zed.dev/community-links). We're working on improving the documentation, creating more examples, and will be publishing more guides to GPUI on our [blog](https://zed.dev/blog).

    # Contexts

GPUI makes extensive use of _context parameters_ (typically named `cx`) to provide access to application state and services. These contexts are references passed to functions, enabling interaction with global state, windows, entities, and system services.

---

## `App`

The root context granting access to the application's global state. This context owns all entities' data and can be used to read or update the data referenced by an `Entity<T>`.

## `Context<T>`

A context provided when interacting with an `Entity<T>`, with additional methods related to that specific entity such as notifying observers and emitting events. This context dereferences into `App`, meaning any function which can take an `App` reference can also take a `Context<T>` reference, allowing you to access the application's global state.

## `AsyncApp` and `AsyncWindowContext`

Whereas the above contexts are always passed to your code as references, you can call `to_async` on the reference to create an async context, which has a static lifetime and can be held across `await` points in async code. When you interact with entities with an async context, the calls become fallible, because the context may outlive the window or even the app itself.

## `TestAppContext`

These are similar to the async contexts above, but they panic if you attempt to access a non-existent app or window, and they also contain other features specific to tests.

---

# Non-Context Core Types

## `Window`

Provides access to the state of an application window. This type has a root view (an `Entity` implementing `Render`) which it can read/update, but since it is not a context, you must pass a `&mut App` (or a context which dereferences to it) to do so, along with other functions interacting with global state. You can obtain a `Window` from an `WindowHandle` by calling `WindowHandle::update`.

## `Entity<T>`

A handle to a structure requiring state. This data is owned by the `App` and can be accessed and modified via references to contexts. If `T` implements `Render`, then the entity is sometimes referred to as a view. Entities can be observed by other entities and windows, allowing a closure to be called when `notify` is called on the entity's `Context`.

    # Key Dispatch

GPUI is designed for keyboard-first interactivity.

To expose functionality to the mouse, you render a button with a click handler.

To expose functionality to the keyboard, you bind an _action_ in a _key context_.

Actions are similar to framework-level events like `MouseDown`, `KeyDown`, etc, but you can define them yourself:

```rust
mod menu {
    #[gpui::action]
    struct MoveUp;

    #[gpui::action]
    struct MoveDown;
}
```

Actions are frequently unit structs, for which we have a macro. The above could also be written:

```rust
mod menu {
    actions!(gpui, [MoveUp, MoveDown]);
}
```

Actions can also be more complex types:

```rust
mod menu {
    #[gpui::action]
    struct Move {
        direction: Direction,
        select: bool,
    }
}
```

To bind actions, chain `on_action` on to your element:

```rust
impl Render for Menu {
    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        div()
            .on_action(|this: &mut Menu, move: &MoveUp, window: &mut Window, cx: &mut Context<Menu>| {
                // ...
            })
            .on_action(|this, move: &MoveDown, cx| {
                // ...
            })
            .children(unimplemented!())
    }
}
```

In order to bind keys to actions, you need to declare a _key context_ for part of the element tree by calling `key_context`.

```rust
impl Render for Menu {
    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        div()
            .key_context("menu")
            .on_action(|this: &mut Menu, move: &MoveUp, window: &mut Window, cx: &mut Context<Menu>| {
                // ...
            })
            .on_action(|this, move: &MoveDown, cx| {
                // ...
            })
            .children(unimplemented!())
    }
}
```

Now you can target your context in the keymap. Note how actions are identified in the keymap by their fully-qualified type name.

```json
{
  "context": "menu",
  "bindings": {
    "up": "menu::MoveUp",
    "down": "menu::MoveDown"
  }
}
```

If you had opted for the more complex type definition, you'd provide the serialized representation of the action alongside the name:

```json
{
  "context": "menu",
  "bindings": {
    "up": ["menu::Move", {direction: "up", select: false}]
    "down": ["menu::Move", {direction: "down", select: false}]
    "shift-up": ["menu::Move", {direction: "up", select: true}]
    "shift-down": ["menu::Move", {direction: "down", select: true}]
  }
}
```

    # Zed Icons

## Guidelines

Icons are a big part of Zed, and they're how we convey hundreds of actions without relying on labeled buttons.
When introducing a new icon, it's important to ensure consistency with the existing set, which follows these guidelines:

1. The SVG view box should be 16x16.
2. For outlined icons, use a 1.2px stroke width.
3. Not all icons are mathematically aligned; there's quite a bit of optical adjustment. However, try to keep the icon within an internal 12x12 bounding box as much as possible while ensuring proper visibility.
4. Use the `filled` and `outlined` terminology when introducing icons that will have these two variants.
5. Icons that are deeply contextual may have the feature context as their name prefix. For example, `ToolWeb`, `ReplPlay`, `DebugStepInto`, etc.
6. Avoid complex layer structures in the icon SVG, like clipping masks and similar elements. When the shape becomes too complex, we recommend running the SVG through [SVGOMG](https://jakearchibald.github.io/svgomg/) to clean it up.

## Sourcing

Most icons are created by sourcing them from [Lucide](https://lucide.dev/).
Then, they're modified, adjusted, cleaned up, and simplified depending on their use and overall fit with Zed.

Sometimes, we may use other sources like [Phosphor](https://phosphoricons.com/), but we also design many icons completely from scratch.

## Contributing

To introduce a new icon, add the `.svg` file to the `assets/icon` directory and then add its corresponding item to the `icons.rs` file within the `crates` directory.

- SVG files in the assets folder follow a snake_case name format.
- Icons in the `icons.rs` file follow the PascalCase name format.

Make sure to tag a member of Zed's design team so we can review and adjust any newly introduced icon.

    # Inspector

This is a tool for inspecting and manipulating rendered elements in Zed. It is only available in debug builds. Use the `dev::ToggleInspector` action to toggle inspector mode and click on UI elements to inspect them.

# Current features

* Picking of elements via the mouse, with scroll wheel to inspect occluded elements.

* Temporary manipulation of the selected element.

* Layout info for `Div`.

* Both Rust and JSON-based style manipulation of `Div` style. The rust style editor only supports argumentless `Styled` and `StyledExt` method calls.

* Navigation to code that constructed the element.

# Known bugs

## JSON style editor undo history doesn't get reset

The JSON style editor appends to its undo stack on every change of the active inspected element.

I attempted to fix it by creating a new buffer and setting the buffer associated with the `json_style_buffer` entity. Unfortunately this doesn't work because the language server uses the `version: clock::Global` to figure out the changes, so would need some way to start the new buffer's text at that version.

```
        json_style_buffer.update(cx, |json_style_buffer, cx| {
            let language = json_style_buffer.language().cloned();
            let file = json_style_buffer.file().cloned();

            *json_style_buffer = Buffer::local("", cx);

            json_style_buffer.set_language(language, cx);
            if let Some(file) = file {
                json_style_buffer.file_updated(file, cx);
            }
        });
```

# Future features

* Action and keybinding for entering pick mode.

* Ability to highlight current element after it's been picked.

* Info and manipulation of element types other than `Div`.

* Indicate when the picked element has disappeared.

* To inspect elements that disappear, it would be helpful to be able to pause the UI.

* Hierarchy view?

## Methods that take arguments in Rust style editor

Could use TreeSitter to parse out the fluent style method chain and arguments. Tricky part of this is completions - ideally the Rust Analyzer already being used by the developer's Zed would be used.

## Edit original code in Rust style editor

Two approaches:

1. Open an excerpt of the original file.

2. Communicate with the Zed process that has the repo open - it would send the code for the element. This seems like a lot of work, but would be very nice for rapid development, and it would allow use of rust analyzer.

With both approaches, would need to record the buffer version and use that when referring to source locations, since editing elements can cause code layout shift.

## Source location UI improvements

* Mode to navigate to source code on every element change while picking.

* Tracking of more source locations - currently the source location is often in a ui component. Ideally this would have a way for the components to indicate that they are probably not the source location the user is looking for.

  - Could have `InspectorElementId` be `Vec<(ElementId, Option<Location>)>`, but if there are multiple code paths that construct the same element this would cause them to be considered different.

  - Probably better to have a separate `Vec<Option<Location>>` that uses the same indices as `GlobalElementId`.

## Persistent modification

Currently, element modifications disappear when picker mode is started. Handling this well is tricky. Potential features:

* Support modifying multiple elements at once. This requires a way to specify which elements are modified - possibly wildcards in a match of the `InspectorElementId` path. This might default to ignoring all numeric parts and just matching on the names.

* Show a list of active modifications in the UI.

* Support for modifications being partial overrides instead of snapshots. A trickiness here is that multiple modifications may apply to the same element.

* The code should probably distinguish the data that is provided by the element and the modifications from the inspector. Currently these are conflated in element states.

If support is added for editing original code, then the logical selector in this case would be just matches of the source path.

# Code cleanups

## Consider removing special side pane rendering

Currently the inspector has special rendering in the UI, but maybe it could just be a workspace item.

## Pull more inspector logic out of GPUI

Currently `crates/gpui/inspector.rs` and `crates/inspector_ui/inspector.rs` are quite entangled.  It seems cleaner to pull as much logic a possible out of GPUI.

## Cleaner lifecycle for inspector state viewers / editors

Currently element state inspectors are just called on render. Ideally instead they would be implementors of some trait like:

```
trait StateInspector: Render {
    fn new(cx: &mut App) -> Task<Self>;
    fn element_changed(inspector_id: &InspectorElementId, window: &mut Window, cx: &mut App);
}
```

See `div_inspector.rs` - it needs to initialize itself, keep track of its own loading state, and keep track of the last inspected ID in its render function.

    # LiveKit Protocol

This is a vendored copy of the [LiveKit protocol](https://github.com/livekit/protocol).

Vendored at [`8645a138fb2ea72c4dab13e739b1f3c9ea29ac84`](https://github.com/livekit/protocol/tree/8645a138fb2ea72c4dab13e739b1f3c9ea29ac84).

    # Zed Schema Generator

Prints various Zed schemas to stdout.

## Usage

```sh
cargo run -p schema_generator -- --help

cargo run -p schema_generator -- theme
cargo run -p schema_generator -- icon_theme
```

    Much of element styling is now handled by an external engine.

How do I make an element hover.

There's a hover style.

Hoverable needs to wrap another element. That element can be styled.

```rs
struct Hoverable<E: Element> {

}

impl<V> Element<V> for Hoverable {

}
```

```rs
#[derive(Styled, Interactive)]
pub struct Div {
    declared_style: StyleRefinement,
    interactions: Interactions
}

pub trait Styled {
    fn declared_style(&mut self) -> &mut StyleRefinement;
    fn compute_style(&mut self) -> Style {
        Style::default().refine(self.declared_style())
    }

    // All the tailwind classes, modifying self.declared_style()
}

impl Style {
    pub fn paint_background<V>(layout: Layout, cx: &mut PaintContext<V>);
    pub fn paint_foreground<V>(layout: Layout, cx: &mut PaintContext<V>);
}

pub trait Interactive<V> {
    fn interactions(&mut self) -> &mut Interactions<V>;

    fn on_click(self, )
}

struct Interactions<V> {
    click: SmallVec<[<Rc<dyn Fn(&mut V, &dyn Any, )>; 1]>,
}
```

```rs
trait Stylable {
    type Style;

    fn with_style(self, style: Self::Style) -> Self;
}
```

    Design notes:

This crate is split into two conceptual halves:
- The terminal.rs file and the src/mappings/ folder, these contain the code for interacting with Alacritty and maintaining the pty event loop. Some behavior in this file is constrained by terminal protocols and standards. The Zed init function is also placed here.
- Everything else. These other files integrate the `Terminal` struct created in terminal.rs into the rest of GPUI. The main entry point for GPUI is the terminal_view.rs file and the modal.rs file.

ttys are created externally, and so can fail in unexpected ways. However, GPUI currently does not have an API for models than can fail to instantiate. `TerminalBuilder` solves this by using Rust's type system to split tty instantiation into a 2 step process: first attempt to create the file handles with `TerminalBuilder::new()`, check the result, then call `TerminalBuilder::subscribe(cx)` from within a model context.

The TerminalView struct abstracts over failed and successful terminals, passing focus through to the associated view and allowing clients to build a terminal without worrying about errors.

#Input

There are currently many distinct paths for getting keystrokes to the terminal:

1. Terminal specific characters and bindings. Things like ctrl-a mapping to ASCII control character 1, ANSI escape codes associated with the function keys, etc. These are caught with a raw key-down handler in the element and are processed immediately. This is done with the `try_keystroke()` method on Terminal

2. GPU Action handlers. GPUI clobbers a few vital keys by adding bindings to them in the global context. These keys are synthesized and then dispatched through the same `try_keystroke()` API as the above mappings

3. IME text. When the special character mappings fail, we pass the keystroke back to GPUI to hand it to the IME system. This comes back to us in the `View::replace_text_in_range()` method, and we then send that to the terminal directly, bypassing `try_keystroke()`.

4. Pasted text has a separate pathway.

Generally, there's a distinction between 'keystrokes that need to be mapped' and 'strings which need to be written'. I've attempted to unify these under the '.try_keystroke()' API and the `.input()` API (which try_keystroke uses) so we have consistent input handling across the terminal

    # Zed Theme Importer

```sh
cargo run -p theme_importer -- dark-plus-syntax-color-theme.json --output output-theme.json
```

    This contains the code for Zed's Vim emulation mode.

Vim mode in Zed is supposed to primarily "do what you expect": it mostly tries to copy vim exactly, but will use Zed-specific functionality when available to make things smoother. This means Zed will never be 100% vim compatible, but should be 100% vim familiar!

The backlog is maintained in the `#vim` channel notes.

## Testing against Neovim

If you are making a change to make Zed's behavior more closely match vim/nvim, you can create a test using the `NeovimBackedTestContext`.

For example, the following test checks that Zed and Neovim have the same behavior when running `*` in visual mode:

```rust
#[gpui::test]
async fn test_visual_star_hash(cx: &mut gpui::TestAppContext) {
    let mut cx = NeovimBackedTestContext::new(cx).await;

    cx.set_shared_state("ˇa.c. abcd a.c. abcd").await;
    cx.simulate_shared_keystrokes(["v", "3", "l", "*"]).await;
    cx.assert_shared_state("a.c. abcd ˇa.c. abcd").await;
}
```

To keep CI runs fast, by default the neovim tests use a cached JSON file that records what neovim did (see crates/vim/test_data),
but while developing this test you'll need to run it with the neovim flag enabled:

```sh
cargo test -p vim --features neovim test_visual_star_hash
```

This will run your keystrokes against a headless neovim and cache the results in the test_data directory. Note that neovim must be installed and reachable on your $PATH in order to run the feature.


## Testing zed-only behavior

Zed does more than vim/neovim in their default modes. The `VimTestContext` can be used instead. This lets you test integration with the language server and other parts of zed's UI that don't have a NeoVim equivalent.

    # Zed Docs

Welcome to Zed's documentation.

This is built on push to `main` and published automatically to [https://zed.dev/docs](https://zed.dev/docs).

To preview the docs locally you will need to install [mdBook](https://rust-lang.github.io/mdBook/) (`cargo install mdbook@0.4.40`) and then run:

```sh
mdbook serve docs
```

It's important to note the version number above. For an unknown reason, as of 2025-04-23, running 0.4.48 will cause odd URL behavior that breaks docs.

Before committing, verify that the docs are formatted in the way Prettier expects with:

```
cd docs && pnpm dlx prettier@3.5.0 . --write && cd ..
```

## Preprocessor

We have a custom mdbook preprocessor for interfacing with our crates (`crates/docs_preprocessor`).

If for some reason you need to bypass the docs preprocessor, you can comment out `[preprocessor.zed_docs_preprocessor]
` from the `book.toml`.:

## Images and videos

To add images or videos to the docs, upload them to another location (e.g., zed.dev, GitHub's asset storage) and then link out to them from the docs.

Putting binary assets such as images in the Git repository will bloat the repository size over time.

## Internal notes:

- We have a Cloudflare router called `docs-proxy` that intercepts requests to `zed.dev/docs` and forwards them to the "docs" Cloudflare Pages project.
- CI uploads a new version to the Pages project from `.github/workflows/deploy_docs.yml` on every push to `main`.

### Table of Contents

The table of contents files (`theme/page-toc.js` and `theme/page-doc.css`) were initially generated by [`mdbook-pagetoc`](https://crates.io/crates/mdbook-pagetoc).

Since all this preprocessor does is generate the static assets, we don't need to keep it around once they have been generated.

## Referencing Keybindings and Actions

When referencing keybindings or actions, use the following formats:

### Keybindings:

`{#kb scope::Action}` - e.g., `{#kb zed::OpenSettings}`.

This will output a code element like: `<code>Cmd+,|Ctrl+,</code>`. We then use a client-side plugin to show the actual keybinding based on the user's platform.

By using the action name, we can ensure that the keybinding is always up-to-date rather than hardcoding the keybinding.

### Actions:

`{#action scope::Action}` - e.g., `{#action zed::OpenSettings}`.

This will render a human-readable version of the action name, e.g., "zed: open settings", and will allow us to implement things like additional context on hover, etc.

### Creating New Templates

Templates are just functions that modify the source of the docs pages (usually with a regex match & replace). You can see how the actions and keybindings are templated in `crates/docs_preprocessor/src/main.rs` for reference on how to create new templates.

### References

- Template Trait: crates/docs_preprocessor/src/templates.rs
- Example template: crates/docs_preprocessor/src/templates/keybinding.rs
- Client-side plugins: docs/theme/plugins.js

## Postprocessor

A postprocessor is implemented as a sub-command of `docs_preprocessor` that wraps the builtin `html` renderer and applies post-processing to the `html` files, to add support for page-specific title and meta description values.

An example of the syntax can be found in `git.md`, as well as below

```md
---
title: Some more detailed title for this page
description: A page-specific description
---

# Editor
```

The above will be transformed into (with non-relevant tags removed)

```html
<head>
  <title>Editor | Some more detailed title for this page</title>
  <meta name="description" contents="A page-specific description" />
</head>
<body>
  <h1>Editor</h1>
</body>
```

If no front-matter is provided, or If one or both keys aren't provided, the title and description will be set based on the `default-title` and `default-description` keys in `book.toml` respectively.

### Implementation details

Unfortunately, `mdbook` does not support post-processing like it does pre-processing, and only supports defining one description to put in the meta tag per book rather than per file. So in order to apply post-processing (necessary to modify the html head tags) the global book description is set to a marker value `#description#` and the html renderer is replaced with a sub-command of `docs_preprocessor` that wraps the builtin `html` renderer and applies post-processing to the `html` files, replacing the marker value and the `<title>(.*)</title>` with the contents of the front-matter if there is one.

### Known limitations

The front-matter parsing is extremely simple, which avoids needing to take on an additional dependency, or implement full yaml parsing.

- Double quotes and multi-line values are not supported, i.e. Keys and values must be entirely on the same line, with no double quotes around the value.

The following will not work:

```md
---
title: Some
  Multi-line
  Title
---
```

And neither will:

```md
---
title: "Some title"
---
```

- The front-matter must be at the top of the file, with only white-space preceding it

- The contents of the title and description will not be html-escaped. They should be simple ascii text with no unicode or emoji characters

    # Summary

# General

- [Getting Started](./getting-started.md)
- [System Requirements](./system-requirements.md)
- [Accounts](./accounts.md)
- [Linux](./linux.md)
- [Windows](./windows.md)
- [Telemetry](./telemetry.md)
- [Workspace Persistence](./workspace-persistence.md)
- [Additional Learning Materials](./additional-learning-materials.md)

# Configuration

- [Configuring Zed](./configuring-zed.md)
- [Configuring Languages](./configuring-languages.md)
  - [Toolchains](./toolchains.md)
- [Key bindings](./key-bindings.md)
  - [All Actions](./all-actions.md)
- [Snippets](./snippets.md)
- [Themes](./themes.md)
- [Icon Themes](./icon-themes.md)
- [Visual Customization](./visual-customization.md)
- [Vim Mode](./vim.md)
- [Helix Mode](./helix.md)

<!-- - [Globs](./globs.md) -->
<!-- - [Fonts](./fonts.md) -->

# Using Zed

- [Multibuffers](./multibuffers.md)
- [Outline Panel](./outline-panel.md)
- [Code Completions](./completions.md)
- [Channels](./channels.md)
- [Collaboration](./collaboration.md)
- [Git](./git.md)
- [Debugger](./debugger.md)
- [Diagnostics](./diagnostics.md)
- [Tasks](./tasks.md)
- [Remote Development](./remote-development.md)
- [Environment Variables](./environment.md)
- [REPL](./repl.md)

# AI

- [Overview](./ai/overview.md)
- [Agent Panel](./ai/agent-panel.md)
  - [Tools](./ai/tools.md)
  - [External Agents](./ai/external-agents.md)
- [Inline Assistant](./ai/inline-assistant.md)
- [Edit Prediction](./ai/edit-prediction.md)
- [Text Threads](./ai/text-threads.md)
- [Rules](./ai/rules.md)
- [Model Context Protocol](./ai/mcp.md)
- [Configuration](./ai/configuration.md)
  - [LLM Providers](./ai/llm-providers.md)
  - [Agent Settings](./ai/agent-settings.md)
- [Subscription](./ai/subscription.md)
  - [Plans and Usage](./ai/plans-and-usage.md)
  - [Billing](./ai/billing.md)
  - [Models](./ai/models.md)
- [Privacy and Security](./ai/privacy-and-security.md)
  - [AI Improvement](./ai/ai-improvement.md)

# Extensions

- [Overview](./extensions.md)
- [Installing Extensions](./extensions/installing-extensions.md)
- [Developing Extensions](./extensions/developing-extensions.md)
- [Language Extensions](./extensions/languages.md)
- [Debugger Extensions](./extensions/debugger-extensions.md)
- [Theme Extensions](./extensions/themes.md)
- [Icon Theme Extensions](./extensions/icon-themes.md)
- [Slash Command Extensions](./extensions/slash-commands.md)
- [MCP Server Extensions](./extensions/mcp-extensions.md)

# Language Support

- [All Languages](./languages.md)
- [Ansible](./languages/ansible.md)
- [AsciiDoc](./languages/asciidoc.md)
- [Astro](./languages/astro.md)
- [Bash](./languages/bash.md)
- [Biome](./languages/biome.md)
- [C](./languages/c.md)
- [C++](./languages/cpp.md)
- [C#](./languages/csharp.md)
- [Clojure](./languages/clojure.md)
- [CSS](./languages/css.md)
- [Dart](./languages/dart.md)
- [Deno](./languages/deno.md)
- [Diff](./languages/diff.md)
- [Docker](./languages/docker.md)
- [Elixir](./languages/elixir.md)
- [Elm](./languages/elm.md)
- [Emmet](./languages/emmet.md)
- [Erlang](./languages/erlang.md)
- [Fish](./languages/fish.md)
- [GDScript](./languages/gdscript.md)
- [Gleam](./languages/gleam.md)
- [GLSL](./languages/glsl.md)
- [Go](./languages/go.md)
- [Groovy](./languages/groovy.md)
- [Haskell](./languages/haskell.md)
- [Helm](./languages/helm.md)
- [HTML](./languages/html.md)
- [Java](./languages/java.md)
- [JavaScript](./languages/javascript.md)
- [Julia](./languages/julia.md)
- [JSON](./languages/json.md)
- [Jsonnet](./languages/jsonnet.md)
- [Kotlin](./languages/kotlin.md)
- [Lua](./languages/lua.md)
- [Luau](./languages/luau.md)
- [Makefile](./languages/makefile.md)
- [Markdown](./languages/markdown.md)
- [Nim](./languages/nim.md)
- [OCaml](./languages/ocaml.md)
- [PHP](./languages/php.md)
- [PowerShell](./languages/powershell.md)
- [Prisma](./languages/prisma.md)
- [Proto](./languages/proto.md)
- [PureScript](./languages/purescript.md)
- [Python](./languages/python.md)
- [R](./languages/r.md)
- [Rego](./languages/rego.md)
- [ReStructuredText](./languages/rst.md)
- [Racket](./languages/racket.md)
- [Roc](./languages/roc.md)
- [Ruby](./languages/ruby.md)
- [Rust](./languages/rust.md)
- [Scala](./languages/scala.md)
- [Scheme](./languages/scheme.md)
- [Shell Script](./languages/sh.md)
- [SQL](./languages/sql.md)
- [Svelte](./languages/svelte.md)
- [Swift](./languages/swift.md)
- [Tailwind CSS](./languages/tailwindcss.md)
- [Terraform](./languages/terraform.md)
- [TOML](./languages/toml.md)
- [TypeScript](./languages/typescript.md)
- [Uiua](./languages/uiua.md)
- [Vue](./languages/vue.md)
- [XML](./languages/xml.md)
- [YAML](./languages/yaml.md)
- [Yara](./languages/yara.md)
- [Yarn](./languages/yarn.md)
- [Zig](./languages/zig.md)

# Developing Zed

- [Developing Zed](./development.md)
  - [macOS](./development/macos.md)
  - [Linux](./development/linux.md)
  - [Windows](./development/windows.md)
  - [FreeBSD](./development/freebsd.md)
  - [Local Collaboration](./development/local-collaboration.md)
  - [Using Debuggers](./development/debuggers.md)
  - [Glossary](./development/glossary.md)
- [Release Process](./development/releases.md)
- [Debugging Crashes](./development/debugging-crashes.md)

    # Accounts

Signing in to Zed is not a requirement. You can use most features you'd expect in a code editor without ever doing so. We'll outline the few features that do require signing in, and how to do so, here.

## What Features Require Signing In?

1. All real-time [collaboration features](./collaboration.md).
2. [LLM-powered features](./ai/overview.md), if you are using Zed as the provider of your LLM models. Alternatively, you can [bring and configure your own API keys](./ai/llm-providers.md#use-your-own-keys) if you'd prefer, and avoid having to sign in.

## Signing In

Zed uses GitHub's OAuth flow to authenticate users, requiring only the `read:user` GitHub scope, which grants read-only access to your GitHub profile information.

1. Open Zed and click the `Sign In` button in the top-right corner of the window, or run the `client: sign in` command from the command palette (`cmd-shift-p` on macOS or `ctrl-shift-p` on Windows/Linux).
2. Your default web browser will open to the Zed sign-in page.
3. Authenticate with your GitHub account when prompted.
4. After successful authentication, your browser will display a confirmation, and you'll be automatically signed in to Zed.

**Note**: If you're behind a corporate firewall, ensure that connections to `zed.dev` and `collab.zed.dev` are allowed.

## Signing Out

To sign out of Zed, you can use either of these methods:

- Click on the profile icon in the upper right corner and select `Sign Out` from the dropdown menu.
- Open the command palette and run the `client: sign out` command.

## Email Addresses {#email}

Your Zed account's email address is the address provided by GitHub OAuth. If you have a public email address then it will be used, otherwise your primary GitHub email address will be used. Changes to your email address on GitHub can be synced to your Zed account by [signing in to zed.dev](https://zed.dev/sign_in).

Stripe is used for billing, and will use your Zed account's email address when starting a subscription. Changes to your Zed account email address do not currently update the email address used in Stripe. See [Updating Billing Information](./ai/billing.md#updating-billing-info) for how to change this email address.

## Hiding Sign In button from the interface

In case the Sign In feature is not used, it's possible to hide that from the interface by using `show_sign_in` settings property.
Refer to [Visual Customization page](./visual-customization.md) for more details.

    # Additional Learning Materials

- [Text Manipulation Kung Fu for the Aspiring Black Belt](https://zed.dev/blog/text-manipulation)

    # Agent Panel

The Agent Panel allows you to interact with many LLMs and coding agents that can help with in various types of tasks, such as generating code, codebase understanding, and other general inquiries like writing emails, documentation, and more.

To open it, use the `agent: new thread` action in [the Command Palette](../getting-started.md#command-palette) or click the ✨ (sparkles) icon in the status bar.

## Getting Started

If you're using the Agent Panel for the first time, you need to have at least one LLM provider or external agent configured.
You can do that by:

1. [subscribing to our Pro plan](https://zed.dev/pricing), so you have access to our hosted models
2. [bringing your own API keys](./llm-providers.md#use-your-own-keys) for your desired provider
3. using an external agent like [Gemini CLI](./external-agents.md#gemini-cli) or [Claude Code](./external-agents.md#claude-code)

## Overview {#overview}

With an LLM provider or an external agent configured, type at the message editor and hit `enter` to submit your prompt.
If you need extra room to type, you can expand the message editor with {#kb agent::ExpandMessageEditor}.

You should start to see the responses stream in with indications of [which tools](./tools.md) the model is using to fulfill your prompt.
From this point on, you can interact with the many supported features outlined below.

> Note that for external agents, like [Gemini CLI](./external-agents.md#gemini-cli) or [Claude Code](./external-agents.md#claude-code), some of the features outlined below are _not_ currently supported—for example, _restoring threads from history_, _checkpoints_, _token usage display_, _model selection_, and others. All of them should hopefully be supported in the future.

### Creating New Threads {#new-thread}

By default, the Agent Panel uses Zed's first-party agent.

To change that, go to the plus button in the top-right of the Agent Panel and choose another option.
You choose to create a new [Text Thread](./text-threads.md) or, if you have [external agents](./external-agents.md) connected, you can create new threads with them.

### Editing Messages {#editing-messages}

Any message that you send to the AI is editable.
You can click on the card that contains your message and re-submit it with an adjusted prompt and/or new pieces of context.

### Checkpoints {#checkpoints}

Every time the AI performs an edit, you should see a "Restore Checkpoint" button to the top of your message, allowing you to return your code base to the state it was in prior to that message.

The checkpoint button appears even if you interrupt the thread midway through an edit attempt, as this is likely a moment when you've identified that the agent is not heading in the right direction and you want to revert back.

### Navigating History {#navigating-history}

To quickly navigate through recently opened threads, use the {#kb agent::ToggleNavigationMenu} binding, when focused on the panel's editor, or click the menu icon button at the top right of the panel to open the dropdown that shows you the six most recent threads.

The items in this menu function similarly to tabs, and closing them doesn’t delete the thread; instead, it simply removes them from the recent list.

To view all historical conversations, reach for the `View All` option from within the same menu or via the {#kb agent::OpenHistory} binding.

### Following the Agent {#following-the-agent}

Zed is built with collaboration natively integrated.
This approach extends to collaboration with AI as well.
To follow the agent reading through your codebase and performing edits, click on the "crosshair" icon button at the bottom left of the panel.

You can also do that with the keyboard by pressing the `cmd`/`ctrl` modifier with `enter` when submitting a message.

### Get Notified {#get-notified}

If you send a prompt to the Agent and then move elsewhere, thus putting Zed in the background, you can be notified of whether its response is finished either via:

- a visual notification that appears in the top right of your screen
- or a sound notification

Both notification methods can be used together or individually according to your preference.

You can customize their behavior, including turning them off entirely, by using the `agent.notify_when_agent_waiting` and `agent.play_sound_when_agent_done` settings keys.

### Reviewing Changes {#reviewing-changes}

Once the agent has made changes to your project, the panel will surface which files, and how many of them, have been edited.

To see which files specifically have been edited, expand the accordion bar that shows up right above the message editor or click the `Review Changes` button ({#kb agent::OpenAgentDiff}), which opens a multi-buffer tab with all changes.

You're able to reject or accept each individual change hunk, or the whole set of changes made by the agent.

Edit diffs also appear in individual buffers.
So, if your active tab had edits made by the AI, you'll see diffs with the same accept/reject controls as in the multi-buffer.

## Adding Context {#adding-context}

Although Zed's agent is very efficient at reading through your code base to autonomously pick up relevant files, directories, and other context, manually adding context is still encouraged as a way to speed up and improve the AI's response quality.

To add any file, directory, symbol, previous threads, rules files, or even web pages as context, type `@` to mention them in the editor.

Pasting images as context is also supported by the Agent Panel.

### Token Usage {#token-usage}

Zed surfaces how many tokens you are consuming for your currently active thread nearby the profile selector in the panel's message editor.
Depending on how many pieces of context you add, your token consumption can grow rapidly.

With that in mind, once you get close to the model's context window, a banner appears below the message editor suggesting to start a new thread with the current one summarized and added as context.
You can also do this at any time with an ongoing thread via the "Agent Options" menu on the top right.

## Changing Models {#changing-models}

After you've configured your LLM providers—either via [a custom API key](./llm-providers.md#use-your-own-keys) or through [Zed's hosted models](./models.md)—you can switch between them by clicking on the model selector on the message editor or by using the {#kb agent::ToggleModelSelector} keybinding.

## Using Tools {#using-tools}

The new Agent Panel supports tool calling, which enables agentic editing.
Zed comes with [several built-in tools](./tools.md) that allow models to perform tasks such as searching through your codebase, editing files, running commands, and others.

You can also extend the set of available tools via [MCP Servers](./mcp.md).

### Profiles {#profiles}

Profiles act as a way to group tools.
Zed offers three built-in profiles and you can create as many custom ones as you want.

#### Built-in Profiles {#built-in-profiles}

- `Write`: A profile with tools to allow the LLM to write to your files and run terminal commands. This one essentially has all built-in tools turned on.
- `Ask`: A profile with read-only tools. Best for asking questions about your code base without the concern of the agent making changes.
- `Minimal`: A profile with no tools. Best for general conversations with the LLM where no knowledge of your code base is necessary.

You can explore the exact tools enabled in each profile by clicking on the profile selector button > `Configure Profiles…` > the one you want to check out.

#### Custom Profiles {#custom-profiles}

You can create a custom profile via the `Configure Profiles…` option in the profile selector.
From here, you can choose to `Add New Profile` or fork an existing one with a custom name and your preferred set of tools.

You can also override built-in profiles.
With a built-in profile selected, in the profile selector, navigate to `Configure Tools`, and select the tools you'd like.

Zed will store this profile in your settings using the same profile name as the default you overrode.

All custom profiles can be edited via the UI or by hand under the `assistant.profiles` key in your `settings.json` file.

### Tool Approval

Zed's Agent Panel surfaces the `agent.always_allow_tool_actions` setting that, if turned to `false`, will require you to give permission to any editing attempt as well as tool calls coming from MCP servers.

You can change that by setting this key to `true` in either your `settings.json` or via the Agent Panel's settings view.

### Model Support {#model-support}

Tool calling needs to be individually supported by each model and model provider.
Therefore, despite the presence of tools, some models may not have the ability to pick them up yet in Zed.
You should see a "No tools" label if you select a model that falls into this case.

We want to support all of them, though!
We may prioritize which ones to focus on based on popularity and user feedback, so feel free to help and contribute to fast-track those that don't fit this bill.

All [Zed's hosted models](./models.md) support tool calling out-of-the-box.

### MCP Servers {#mcp-servers}

Similarly to the built-in tools, some models may not support all tools included in a given MCP Server.
Zed's UI will inform about this via a warning icon that appears close to the model selector.

## Text Threads {#text-threads}

["Text Threads"](./text-threads.md) present your conversation with the LLM in a different format—as raw text.
With text threads, you have full control over the conversation data.
You can remove and edit responses from the LLM, swap roles, and include more context earlier in the conversation.

For users who have been with us for some time, you'll notice that text threads are our original assistant panel—users love it for the control it offers.
We do not plan to deprecate text threads, but it should be noted that if you want the AI to write to your code base autonomously, that's only available in the newer, and now default, "Threads".

## Errors and Debugging {#errors-and-debugging}

In case of any error or strange LLM response behavior, the best way to help the Zed team debug is by reaching for the `agent: open thread as markdown` action and attaching that data as part of your issue on GitHub.

You can also open threads as Markdown by clicking on the file icon button, to the right of the thumbs down button, when focused on the panel's editor.

## Feedback {#feedback}

Every change we make to Zed's system prompt and tool set, needs to be backed by a thorough eval with good scores.

Every time the LLM performs a weird change or investigates a certain topic in your code base incorrectly, it's an indication that there's an improvement opportunity.

> Note that rating responses will send your data related to that response to Zed's servers.
> See [AI Improvement](./ai-improvement.md) and [Privacy and Security](./privacy-and-security.md) for more information about Zed's approach to AI improvement, privacy, and security.
> **_If you don't want data persisted on Zed's servers, don't rate_**. We will not collect data for improving our Agentic offering without you explicitly rating responses.

The best way you can help influence the next change to Zed's system prompt and tools is by rating the LLM's response via the thumbs up/down buttons at the end of every response.
In case of a thumbs down, a new text area will show up where you can add more specifics about what happened.

You can provide feedback on the thread at any point after the agent responds, and multiple times within the same thread.

    # Agent Settings

Learn about all the settings you can customize in Zed's Agent Panel.

## Model Settings {#model-settings}

### Default Model {#default-model}

If you're using [Zed's hosted LLM service](./plans-and-usage.md), it sets `claude-sonnet-4` as the default model.
But if you're not subscribed to it or simply just want to change it, you can do it so either via the model dropdown in the Agent Panel's bottom-right corner or by manually editing the `default_model` object in your settings:

```json
{
  "agent": {
    "default_model": {
      "provider": "zed.dev",
      "model": "gpt-4o"
    }
  }
}
```

### Feature-specific Models {#feature-specific-models}

Assign distinct and specific models for the following AI-powered features in Zed:

- Thread summary model: Used for generating thread summaries
- Inline assistant model: Used for the inline assistant feature
- Commit message model: Used for generating Git commit messages

```json
{
  "agent": {
    "default_model": {
      "provider": "zed.dev",
      "model": "claude-sonnet-4"
    },
    "inline_assistant_model": {
      "provider": "anthropic",
      "model": "claude-3-5-sonnet"
    },
    "commit_message_model": {
      "provider": "openai",
      "model": "gpt-4o-mini"
    },
    "thread_summary_model": {
      "provider": "google",
      "model": "gemini-2.0-flash"
    }
  }
}
```

> If a custom model isn't set for one of these features, they automatically fall back to using the default model.

### Alternative Models for Inline Assists {#alternative-assists}

The Inline Assist feature in particular has the capacity to perform multiple generations in parallel using different models.
That is possible by assigning more than one model to it, taking the configuration shown above one step further.

When configured, the inline assist UI will surface controls to cycle between the outputs generated by each model.

The models you specify here are always used in _addition_ to your [default model](#default-model).

For example, the following configuration will generate two outputs for every assist.
One with Claude Sonnet 4 (the default model), and one with GPT-4o.

```json
{
  "agent": {
    "default_model": {
      "provider": "zed.dev",
      "model": "claude-sonnet-4"
    },
    "inline_alternatives": [
      {
        "provider": "zed.dev",
        "model": "gpt-4o"
      }
    ]
  }
}
```

### Model Temperature

Specify a custom temperature for a provider and/or model:

```json
"model_parameters": [
  // To set parameters for all requests to OpenAI models:
  {
    "provider": "openai",
    "temperature": 0.5
  },
  // To set parameters for all requests in general:
  {
    "temperature": 0
  },
  // To set parameters for a specific provider and model:
  {
    "provider": "zed.dev",
    "model": "claude-sonnet-4",
    "temperature": 1.0
  }
],
```

## Agent Panel Settings {#agent-panel-settings}

Note that some of these settings are also surfaced in the Agent Panel's settings UI, which you can access either via the `agent: open settings` action or by the dropdown menu on the top-right corner of the panel.

### Default View

Use the `default_view` setting to change the default view of the Agent Panel.
You can choose between `thread` (the default) and `text_thread`:

```json
{
  "agent": {
    "default_view": "text_thread"
  }
}
```

### Font Size

Use the `agent_font_size` setting to change the font size of rendered agent responses in the panel.

```json
{
  "agent": {
    "agent_font_size": 18
  }
}
```

> (Preview Version Note): Editors in the Agent Panel—whether that is the main message textarea or previous messages—use monospace fonts and therefore, are controlled by the `buffer_font_size` setting, which is defined globally in your `settings.json`.

### Auto-run Commands

Control whether you want to allow the agent to run commands without asking you for permission.
The default value is `false`.

```json
{
  "agent": {
    "always_allow_tool_actions": true
  }
}
```

> This setting is available via the Agent Panel's settings UI.

### Single-file Review

Control whether you want to see review actions (accept & reject) in single buffers after the agent is done performing edits.
The default value is `false`.

```json
{
  "agent": {
    "single_file_review": true
  }
}
```

When set to false, these controls are only available in the multibuffer review tab.

> This setting is available via the Agent Panel's settings UI.

### Sound Notification

Control whether you want to hear a notification sound when the agent is done generating changes or needs your input.
The default value is `false`.

```json
{
  "agent": {
    "play_sound_when_agent_done": true
  }
}
```

> This setting is available via the Agent Panel's settings UI.

### Message Editor Size

Use the `message_editor_min_lines` setting to control minimum number of lines of height the agent message editor should have.
It is set to `4` by default, and the max number of lines is always double of the minimum.

```json
{
  "agent": {
    "message_editor_min_lines": 4
  }
}
```

> This setting is currently available only in Preview.

### Modifier to Send

Make a modifier (`cmd` on macOS, `ctrl` on Linux) required to send messages.
This is encouraged for more thoughtful prompt crafting.
The default value is `false`.

```json
{
  "agent": {
    "use_modifier_to_send": true
  }
}
```

> This setting is available via the Agent Panel's settings UI.

### Edit Card

Use the `expand_edit_card` setting to control whether edit cards show the full diff in the Agent Panel.
It is set to `true` by default, but if set to false, the card's height is capped to a certain number of lines, requiring a click to be expanded.

```json
{
  "agent": {
    "expand_edit_card": false
  }
}
```

### Terminal Card

Use the `expand_terminal_card` setting to control whether terminal cards show the command output in the Agent Panel.
It is set to `true` by default, but if set to false, the card will be fully collapsed even while the command is running, requiring a click to be expanded.

```json
{
  "agent": {
    "expand_terminal_card": false
  }
}
```

### Feedback Controls

Control whether you want to see the thumbs up/down buttons to give Zed feedback about the agent's performance.
The default value is `true`.

```json
{
  "agent": {
    "enable_feedback": false
  }
}
```

    # Zed AI Improvement

## Agent Panel

### Opt-In

When using the Agent Panel, whether through Zed's hosted AI service or via connecting a non-Zed AI service via API key, Zed does not persistently store user content or use user content to evaluate and/or improve our AI features, unless it is explicitly shared with Zed. Each share is opt-in, and sharing once will not cause future content or data to be shared again.

> Note that rating responses will send your data related to that response to Zed's servers.
> **_If you don't want data persisted on Zed's servers, don't rate_**. We will not collect data for improving our Agentic offering without you explicitly rating responses.

When using upstream services through Zed AI, we require assurances from our service providers that your user content won't be used for training models. For example, usage of Anthropic Claude 3.5 via Zed AI in the Assistant is governed by the [Anthropic Commercial Terms](https://www.anthropic.com/legal/commercial-terms) which includes the following:

> "Anthropic may not train models on Customer Content from paid Services."

We also have a [zero-data retention agreement](https://privacy.anthropic.com/en/articles/8956058-i-have-a-zero-data-retention-agreement-with-anthropic-what-products-does-it-apply-to) with Anthropic.

When you directly connect Zed with a non Zed AI service (e.g., via API key) Zed does not have control over how your data is used by that service provider.
You should reference your agreement with each service provider to understand what terms and conditions apply.

### Data we collect

For prompts you have explicitly shared with us, Zed may store copies of those prompts and other data about the specific use of the Agent Panel.

This data includes:

- The prompt given to the Agent
- Any commentary you include
- Product telemetry about the agentic thread
- Metadata about your Zed installation

### Data Handling

Collected data is stored in Snowflake, a private database where we track other metrics. We periodically review this data to improve our overall agentic approach and refine the product via our system prompt, tool use, etc. We ensure any included data is anonymized and contains no sensitive information (access tokens, user IDs, email addresses, etc).

## Edit Predictions

By default, when using Zed Edit Predictions, Zed does not persistently store user content or use user content for training of its models.

### Opt-in

Users who are working on open source licensed projects may optionally opt-in to providing model improvement feedback. This opt-in occurs on a per-project basis. If you work on multiple open source projects and wish to provide model improvement feedback you will have to opt-in for each individual project.

When working on other projects where you haven't opted-in, Zed will not persistently store user content or use user content for training of its models.

You can see exactly how Zed detects open source licenses in: [license_detection.rs](https://github.com/zed-industries/zed/blob/main/crates/zeta/src/license_detection.rs).

### Exclusions

Zed will intentionally exclude certain files from Predictive Edits entirely, even when you have opted-in to model improvement feedback.

You can inspect this exclusion list by opening `zed: open default settings` from the command palette:

```json
{
  "edit_predictions": {
    // A list of globs representing files that edit predictions should be disabled for.
    // There's a sensible default list of globs already included.
    // Any addition to this list will be merged with the default list.
    "disabled_globs": [
      "**/.env*",
      "**/*.pem",
      "**/*.key",
      "**/*.cert",
      "**/*.crt",
      "**/secrets.yml"
    ]
  }
}
```

Users may explicitly exclude additional paths and/or file extensions by adding them to [`edit_predictions.disabled_globs`](https://zed.dev/docs/configuring-zed#edit-predictions) in their Zed settings.json:

```json
{
  "edit_predictions": {
    "disabled_globs": ["secret_dir/*", "**/*.log"]
  }
}
```

### Data we collect

For open source projects where you have opted-in, Zed may store copies of requests and responses to the Zed AI Prediction service.

This data includes:

- the edit prediction
- a portion of the buffer content around the cursor
- a few recent edits
- the current buffer outline
- diagnostics (errors, warnings, etc) from language servers

### Data Handling

Collected data is stored in Snowflake, a private database where we track other metrics. We periodically review this data to select training samples for inclusion in our model training dataset. We ensure any included data is anonymized and contains no sensitive information (access tokens, user IDs, email addresses, etc). This training dataset is publicly available at [huggingface.co/datasets/zed-industries/zeta](https://huggingface.co/datasets/zed-industries/zeta).

### Model Output

We then use this training dataset to fine-tune [Qwen2.5-Coder-7B](https://huggingface.co/Qwen/Qwen2.5-Coder-7B) and make the resulting model available at [huggingface.co/zed-industries/zeta](https://huggingface.co/zed-industries/zeta).

## Applicable terms

Please see the [Zed Terms of Service](https://zed.dev/terms-of-service) for more.

    # Billing

We use Stripe as our billing and payments provider. All Pro plans require payment via credit card.
For invoice-based billing, a Business plan is required. Contact [sales@zed.dev](mailto:sales@zed.dev) for more information.

## Settings {#settings}

You can access billing settings at [zed.dev/account](https://zed.dev/account).
Clicking the button under Account Settings will navigate you to Stripe’s secure portal, where you can update all billing-related settings and configuration.

## Billing Cycles {#billing-cycles}

Zed is billed on a monthly basis based on the date you initially subscribe.

We’ll also bill in-month for additional prompts used beyond your plan’s prompt limit, if usage exceeds $20 before month end.
See [usage-based pricing](./plans-and-usage.md#ubp) for more.

## Invoice History {#invoice-history}

You can access your invoice history by navigating to [zed.dev/account](https://zed.dev/account) and clicking "Manage" on your subscription.

From Stripe’s secure portal, you can download all current and historical invoices.

## Updating Billing Information {#updating-billing-info}

You can update your payment method, company name, address, and tax information through the billing portal.

Please note that changes to billing information will **only** affect future invoices — **we cannot modify historical invoices**.

## Sales Tax {#sales-tax}

Zed partners with [Sphere](https://www.getsphere.com/) to calculate indirect tax rate for invoices, based on customer location and the product being sold. Tax is listed as a separate line item on invoices, based preferentially on your billing address, followed by the card issue country known to Stripe.

If you have a VAT/GST ID, you can add it at [zed.dev/account](https://zed.dev/account) by clicking "Manage" on your subscription. Check the box that denotes you as a business.

Please note that changes to VAT/GST IDs and address will **only** affect future invoices — **we cannot modify historical invoices**.
Questions or issues can be directed to [billing-support@zed.dev](mailto:billing-support@zed.dev).

    # Configuration

When using AI in Zed, you can customize several aspects:

1. Which [LLM providers](./llm-providers.md) you can use
2. [Model parameters and usage](./agent-settings.md#model-settings)
3. [Interactions with the Agent Panel](./agent-settings.md#agent-panel-settings)

## Turning AI Off Entirely

We want to respect users who want to use Zed without interacting with AI whatsoever.
To do that, add the following key to your `settings.json`:

```json
{
  "disable_ai": true
}
```

Read [the following blog post](https://zed.dev/blog/disable-ai-features) to learn more about our motivation to promote this, as much as we also encourage users to explore AI-assisted programming.

    # Edit Prediction

Edit Prediction is Zed's native mechanism for predicting the code you want to write through AI.
Each keystroke sends a new request to our [open source, open dataset Zeta model](https://huggingface.co/zed-industries/zeta) and it returns with individual or multi-line suggestions that can be quickly accepted by pressing `tab`.

## Configuring Zeta

Zed's Edit Prediction was initially introduced via a banner on the title bar.
Clicking on it would take you to a modal with a button ("Enable Edit Prediction") that sets `zed` as your `edit_prediction_provider`.

![Onboarding banner and modal](https://zed.dev/img/edit-prediction/docs.webp)

But, if you haven't come across the banner, Zed's Edit Prediction is the default edit prediction provider and you should see it right away in your status bar.

### Switching Modes {#switching-modes}

Zed's Edit Prediction comes with two different display modes:

1. `eager` (default): predictions are displayed inline as long as it doesn't conflict with language server completions
2. `subtle`: predictions only appear inline when holding a modifier key (`alt` by default)

Toggle between them via the `mode` key:

```json
"edit_predictions": {
  "mode": "eager" | "subtle"
},
```

Or directly via the UI through the status bar menu:

![Edit Prediction status bar menu, with the modes toggle.](https://zed.dev/img/edit-prediction/status-bar-menu.webp)

### Conflict With Other `tab` Actions {#edit-predictions-conflict}

By default, when `tab` would normally perform a different action, Zed requires a modifier key to accept predictions:

1. When the language server completions menu is visible.
2. When your cursor isn't at the right indentation level.

In these cases, `alt-tab` is used instead to accept the prediction. When the language server completions menu is open, holding `alt` first will cause it to temporarily disappear in order to preview the prediction within the buffer.

On Linux, `alt-tab` is often used by the window manager for switching windows, so `alt-l` is provided as the default binding for accepting predictions. `tab` and `alt-tab` also work, but aren't displayed by default.

{#action editor::AcceptPartialEditPrediction} ({#kb editor::AcceptPartialEditPrediction}) can be used to accept the current edit prediction up to the next word boundary.

See the [Configuring GitHub Copilot](#github-copilot) and [Configuring Supermaven](#supermaven) sections below for configuration of other providers. Only text insertions at the current cursor are supported for these providers, whereas the Zeta model provides multiple predictions including deletions.

## Configuring Edit Prediction Keybindings {#edit-predictions-keybinding}

By default, `tab` is used to accept edit predictions. You can use another keybinding by inserting this in your keymap:

```json
{
  "context": "Editor && edit_prediction",
  "bindings": {
    // Here we also allow `alt-enter` to accept the prediction
    "alt-enter": "editor::AcceptEditPrediction"
  }
}
```

When there's a [conflict with the `tab` key](#edit-predictions-conflict), Zed uses a different context to accept keybindings (`edit_prediction_conflict`). If you want to use a different one, you can insert this in your keymap:

```json
{
  "context": "Editor && edit_prediction_conflict",
  "bindings": {
    "ctrl-enter": "editor::AcceptEditPrediction" // Example of a modified keybinding
  }
}
```

If your keybinding contains a modifier (`ctrl` in the example above), it will also be used to preview the edit prediction and temporarily hide the language server completion menu.

You can also bind this action to keybind without a modifier. In that case, Zed will use the default modifier (`alt`) to preview the edit prediction.

```json
{
  "context": "Editor && edit_prediction_conflict",
  "bindings": {
    // Here we bind tab to accept even when there's a language server completion
    // or the cursor isn't at the correct indentation level
    "tab": "editor::AcceptEditPrediction"
  }
}
```

To maintain the use of the modifier key for accepting predictions when there is a language server completions menu, but allow `tab` to accept predictions regardless of cursor position, you can specify the context further with `showing_completions`:

```json
{
  "context": "Editor && edit_prediction_conflict && !showing_completions",
  "bindings": {
    // Here we don't require a modifier unless there's a language server completion
    "tab": "editor::AcceptEditPrediction"
  }
}
```

### Keybinding Example: Always Use Alt-Tab

The keybinding example below causes `alt-tab` to always be used instead of sometimes using `tab`. You might want this in order to have just one keybinding to use for accepting edit predictions, since the behavior of `tab` varies based on context.

```json
  {
    "context": "Editor && edit_prediction",
    "bindings": {
      "alt-tab": "editor::AcceptEditPrediction"
    }
  },
  // Bind `tab` back to its original behavior.
  {
    "context": "Editor",
    "bindings": {
      "tab": "editor::Tab"
    }
  },
  {
    "context": "Editor && showing_completions",
    "bindings": {
      "tab": "editor::ComposeCompletion"
    }
  },
```

If `"vim_mode": true` is set within `settings.json`, then additional bindings are needed after the above to return `tab` to its original behavior:

```json
  {
    "context": "(VimControl && !menu) || vim_mode == replace || vim_mode == waiting",
    "bindings": {
      "tab": "vim::Tab"
    }
  },
  {
    "context": "vim_mode == literal",
    "bindings": {
      "tab": ["vim::Literal", ["tab", "\u0009"]]
    }
  },
```

### Keybinding Example: Displaying Tab and Alt-Tab on Linux

While `tab` and `alt-tab` are supported on Linux, `alt-l` is displayed instead. If your window manager does not reserve `alt-tab`, and you would prefer to use `tab` and `alt-tab`, include these bindings in `keymap.json`:

```json
  {
    "context": "Editor && edit_prediction",
    "bindings": {
      "tab": "editor::AcceptEditPrediction",
      // Optional: This makes the default `alt-l` binding do nothing.
      "alt-l": null
    }
  },
  {
    "context": "Editor && edit_prediction_conflict",
    "bindings": {
      "alt-tab": "editor::AcceptEditPrediction",
      // Optional: This makes the default `alt-l` binding do nothing.
      "alt-l": null
    }
  },
```

### Missing keybind {#edit-predictions-missing-keybinding}

Zed requires at least one keybinding for the {#action editor::AcceptEditPrediction} action in both the `Editor && edit_prediction` and `Editor && edit_prediction_conflict` contexts ([learn more above](#edit-predictions-keybinding)).

If you have previously bound the default keybindings to different actions in the global context, you will not be able to preview or accept edit predictions. For example:

```json
[
  // Your keymap
  {
    "bindings": {
      // Binds `alt-tab` to a different action globally
      "alt-tab": "menu::SelectNext"
    }
  }
]
```

To fix this, you can specify your own keybinding for accepting edit predictions:

```json
[
  // ...
  {
    "context": "Editor && edit_prediction_conflict",
    "bindings": {
      "alt-l": "editor::AcceptEditPrediction"
    }
  }
]
```

If you would like to use the default keybinding, you can free it up by either moving yours to a more specific context or changing it to something else.

## Disabling Automatic Edit Prediction

There are different levels in which you can disable edit predictions to be displayed, including not having it turned on at all.

Alternatively, if you have Zed set as your provider, consider [using Subtle Mode](#switching-modes).

### On Buffers

To not have predictions appear automatically as you type, set this within `settings.json`:

```json
{
  "show_edit_predictions": false
}
```

This hides every indication that there is a prediction available, regardless of [the display mode](#switching-modes) you're in (valid only if you have Zed as your provider).
Still, you can trigger edit predictions manually by executing {#action editor::ShowEditPrediction} or hitting {#kb editor::ShowEditPrediction}.

### For Specific Languages

To not have predictions appear automatically as you type when working with a specific language, set this within `settings.json`:

```json
{
  "language": {
    "python": {
      "show_edit_predictions": false
    }
  }
}
```

### In Specific Directories

To disable edit predictions for specific directories or files, set this within `settings.json`:

```json
{
  "edit_predictions": {
    "disabled_globs": ["~/.config/zed/settings.json"]
  }
}
```

### Turning Off Completely

To completely turn off edit prediction across all providers, explicitly set the settings to `none`, like so:

```json
"features": {
  "edit_prediction_provider": "none"
},
```

## Configuring GitHub Copilot {#github-copilot}

To use GitHub Copilot as your provider, set this within `settings.json`:

```json
{
  "features": {
    "edit_prediction_provider": "copilot"
  }
}
```

You should be able to sign-in to GitHub Copilot by clicking on the Copilot icon in the status bar and following the setup instructions.

### Using GitHub Copilot Enterprise {#github-copilot-enterprise}

If your organization uses GitHub Copilot Enterprise, you can configure Zed to use your enterprise instance by specifying the enterprise URI in your `settings.json`:

```json
{
  "edit_predictions": {
    "copilot": {
      "enterprise_uri": "https://your.enterprise.domain"
    }
  }
}
```

Replace `"https://your.enterprise.domain"` with the URL provided by your GitHub Enterprise administrator (e.g., `https://foo.ghe.com`).

Once set, Zed will route Copilot requests through your enterprise endpoint. When you sign in by clicking the Copilot icon in the status bar, you will be redirected to your configured enterprise URL to complete authentication. All other Copilot features and usage remain the same.

Copilot can provide multiple completion alternatives, and these can be navigated with the following actions:

- {#action editor::NextEditPrediction} ({#kb editor::NextEditPrediction}): To cycle to the next edit prediction
- {#action editor::PreviousEditPrediction} ({#kb editor::PreviousEditPrediction}): To cycle to the previous edit prediction

## Configuring Supermaven {#supermaven}

To use Supermaven as your provider, set this within `settings.json`:

```json
{
  "features": {
    "edit_prediction_provider": "supermaven"
  }
}
```

You should be able to sign-in to Supermaven by clicking on the Supermaven icon in the status bar and following the setup instructions.

## See also

You may also use the [Agent Panel](./agent-panel.md) or the [Inline Assistant](./inline-assistant.md) to interact with language models, see the [AI documentation](./overview.md) for more information on the other AI features in Zed.

    # External Agents

Zed supports terminal-based agents through the [Agent Client Protocol (ACP)](https://agentclientprotocol.com).

Currently, [Gemini CLI](https://github.com/google-gemini/gemini-cli) serves as the reference implementation.
[Claude Code](https://www.anthropic.com/claude-code) is also included by default, and you can [add custom ACP-compatible agents](#add-custom-agents) as well.

## Gemini CLI {#gemini-cli}

Zed provides the ability to run [Gemini CLI](https://github.com/google-gemini/gemini-cli) directly in the [agent panel](./agent-panel.md).

Under the hood we run Gemini CLI in the background, and talk to it over ACP.
This means that you're running the real Gemini CLI, with all of the advantages of that, but you can see and interact with files in your editor.

### Getting Started

As of [Zed Stable v0.201.5](https://zed.dev/releases/stable/0.201.5) you should be able to use Gemini CLI directly from Zed. First open the agent panel with {#kb agent::ToggleFocus}, and then use the `+` button in the top right to start a new Gemini CLI thread.

If you'd like to bind this to a keyboard shortcut, you can do so by editing your `keymap.json` file via the `zed: open keymap` command to include:

```json
[
  {
    "bindings": {
      "cmd-alt-g": ["agent::NewExternalAgentThread", { "agent": "gemini" }]
    }
  }
]
```

#### Installation

The first time you create a Gemini CLI thread, Zed will install [@google/gemini-cli](https://github.com/zed-industries/claude-code-acp). This installation is only available to Zed and is kept up to date as you use the agent.

By default, Zed will use this managed version of Gemini CLI even if you have it installed globally. However, you can configure it to use a version in your `PATH` by adding this to your settings:

```json
{
  "agent_servers": {
    "gemini": {
      "ignore_system_version": false
    }
  }
}
```

#### Authentication

After you have Gemini CLI running, you'll be prompted to choose your authentication method.

Most users should click the "Log in with Google". This will cause a browser window to pop-up and auth directly with Gemini CLI. Zed does not see your OAuth or access tokens in this case.

You can also use the "Gemini API Key". If you select this, and have the `GEMINI_API_KEY` set, then we will use that. Otherwise Zed will prompt you for an API key which will be stored securely in your keychain, and used to start Gemini CLI from within Zed.

The "Vertex AI" option is for those who are using [Vertex AI](https://cloud.google.com/vertex-ai), and have already configured their environment correctly.

For more information, see the [Gemini CLI docs](https://github.com/google-gemini/gemini-cli/blob/main/docs/index.md).

### Usage

Similar to Zed's first-party agent, you can use Gemini CLI to do anything that you need.
And to give it context, you can @-mention files, recent threads, symbols, or fetch the web.

> Note that some first-party agent features don't yet work with Gemini CLI: editing past messages, resuming threads from history, checkpointing, and using the agent in SSH projects.
> We hope to add these features in the near future.

## Claude Code

Similar to Gemini CLI, you can also run [Claude Code](https://www.anthropic.com/claude-code) directly via Zed's [agent panel](./agent-panel.md).
Under the hood, Zed runs Claude Code and communicate to it over ACP, through [a dedicated adapter](https://github.com/zed-industries/claude-code-acp).

### Getting Started

Open the agent panel with {#kb agent::ToggleFocus}, and then use the `+` button in the top right to start a new Claude Code thread.

If you'd like to bind this to a keyboard shortcut, you can do so by editing your `keymap.json` file via the `zed: open keymap` command to include:

```json
[
  {
    "bindings": {
      "cmd-alt-c": ["agent::NewExternalAgentThread", { "agent": "claude_code" }]
    }
  }
]
```

### Authentication

As of version `0.202.7` (stable) and `0.203.2` (preview), authentication to Zed's Claude Code installation is decoupled entirely from Zed's agent. That is to say, an Anthropic API key added via the [Zed Agent's settings](./llm-providers.md#anthropic) will _not_ be utilized by Claude Code for authentication and billing.

To ensure you're using your billing method of choice, [open a new Claude Code thread](./agent-panel.md#new-thread). Then, run `/login`, and authenticate either via API key, or via `Log in with Claude Code` to use a Claude Pro/Max subscription.

#### Installation

The first time you create a Claude Code thread, Zed will install [@zed-industries/claude-code-acp](https://github.com/zed-industries/claude-code-acp). This installation is only available to Zed and is kept up to date as you use the agent.

Zed will always use this managed version of Claude Code even if you have it installed globally.

### Usage

Similar to Zed's first-party agent, you can use Claude Code to do anything that you need.
And to give it context, you can @-mention files, recent threads, symbols, or fetch the web.

In complement to talking to it [over ACP](https://agentclientprotocol.com), Zed relies on the [Claude Code SDK](https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-overview) to support some of its specific features.
However, the SDK doesn't yet expose everything needed to fully support all of them:

- Slash Commands: A subset of [built-in commands](https://docs.anthropic.com/en/docs/claude-code/slash-commands#built-in-slash-commands) are supported, while [custom slash commands](https://docs.anthropic.com/en/docs/claude-code/slash-commands#custom-slash-commands) are fully supported.
- [Subagents](https://docs.anthropic.com/en/docs/claude-code/sub-agents) are supported.
- [Hooks](https://docs.anthropic.com/en/docs/claude-code/hooks-guide) are currently _not_ supported.

> Also note that some [first-party agent](./agent-panel.md) features don't yet work with Claude Code: editing past messages, resuming threads from history, checkpointing, and using the agent in SSH projects.
> We hope to add these features in the near future.

#### CLAUDE.md

Claude Code in Zed will automatically use any `CLAUDE.md` file found in your project root, project subdirectories, or root `.claude` directory.

If you don't have a `CLAUDE.md` file, you can ask Claude Code to create one for you through the `init` slash command.

## Add Custom Agents {#add-custom-agents}

You can run any agent speaking ACP in Zed by changing your settings as follows:

```json
{
  "agent_servers": {
    "Custom Agent": {
      "command": "node",
      "args": ["~/projects/agent/index.js", "--acp"],
      "env": {}
    }
  }
}
```

This can also be useful if you're in the middle of developing a new agent that speaks the protocol and you want to debug it.

You can also specify a custom path, arguments, or environment for the builtin integrations by using the `claude` and `gemini` names.

## Debugging Agents

When using external agents in Zed, you can access the debug view via with `dev: open acp logs` from the Command Palette. This lets you see the messages being sent and received between Zed and the agent.

![The debug view for ACP logs.](https://zed.dev/img/acp/acp-logs.webp)

    # Inline Assistant

## Usage Overview

Use `ctrl-enter` to open the Inline Assistant nearly anywhere you can enter text: editors, text threads, the rules library, channel notes, and even within the terminal panel.

The Inline Assistant allows you to send the current selection (or the current line) to a language model and modify the selection with the language model's response.

You can also perform multiple generation requests in parallel by pressing `ctrl-enter` with multiple cursors, or by pressing the same binding with a selection that spans multiple excerpts in a multibuffer.

## Context

Give the Inline Assistant context the same way you can in [the Agent Panel](./agent-panel.md), allowing you to provide additional instructions or rules for code transformations with @-mentions.

A useful pattern here is to create a thread in the Agent Panel, and then mention that thread with `@thread` in the Inline Assistant to include it as context.

> The Inline Assistant is limited to normal mode context windows ([see Models](./models.md) for more).

## Prefilling Prompts

To create a custom keybinding that prefills a prompt, you can add the following format in your keymap:

```json
[
  {
    "context": "Editor && mode == full",
    "bindings": {
      "ctrl-shift-enter": [
        "assistant::InlineAssist",
        { "prompt": "Build a snake game" }
      ]
    }
  }
]
```

    # LLM Providers

To use AI in Zed, you need to have at least one large language model provider set up.

You can do that by either subscribing to [one of Zed's plans](./plans-and-usage.md), or by using API keys you already have for the supported providers.

## Use Your Own Keys {#use-your-own-keys}

If you already have an API key for an existing LLM provider—say Anthropic or OpenAI, for example—you can insert them into Zed and use the full power of the Agent Panel **_for free_**.

To add an existing API key to a given provider, go to the Agent Panel settings (`agent: open settings`), look for the desired provider, paste the key into the input, and hit enter.

> Note: API keys are _not_ stored as plain text in your `settings.json`, but rather in your OS's secure credential storage.

## Supported Providers

Here's all the supported LLM providers for which you can use your own API keys:

- [Amazon Bedrock](#amazon-bedrock)
- [Anthropic](#anthropic)
- [DeepSeek](#deepseek)
- [GitHub Copilot Chat](#github-copilot-chat)
- [Google AI](#google-ai)
- [LM Studio](#lmstudio)
- [Mistral](#mistral)
- [Ollama](#ollama)
- [OpenAI](#openai)
- [OpenAI API Compatible](#openai-api-compatible)
- [OpenRouter](#openrouter)
- [Vercel](#vercel-v0)
- [xAI](#xai)

### Amazon Bedrock {#amazon-bedrock}

> Supports tool use with models that support streaming tool use.
> More details can be found in the [Amazon Bedrock's Tool Use documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html).

To use Amazon Bedrock's models, an AWS authentication is required.
Ensure your credentials have the following permissions set up:

- `bedrock:InvokeModelWithResponseStream`
- `bedrock:InvokeModel`

Your IAM policy should look similar to:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "*"
    }
  ]
}
```

With that done, choose one of the two authentication methods:

#### Authentication via Named Profile (Recommended)

1. Ensure you have the AWS CLI installed and configured with a named profile
2. Open your `settings.json` (`zed: open settings`) and include the `bedrock` key under `language_models` with the following settings:
   ```json
   {
     "language_models": {
       "bedrock": {
         "authentication_method": "named_profile",
         "region": "your-aws-region",
         "profile": "your-profile-name"
       }
     }
   }
   ```

#### Authentication via Static Credentials

While it's possible to configure through the Agent Panel settings UI by entering your AWS access key and secret directly, we recommend using named profiles instead for better security practices.
To do this:

1. Create an IAM User that you can assume in the [IAM Console](https://us-east-1.console.aws.amazon.com/iam/home?region=us-east-1#/users).
2. Create security credentials for that User, save them and keep them secure.
3. Open the Agent Configuration with (`agent: open settings`) and go to the Amazon Bedrock section
4. Copy the credentials from Step 2 into the respective **Access Key ID**, **Secret Access Key**, and **Region** fields.

#### Cross-Region Inference

The Zed implementation of Amazon Bedrock uses [Cross-Region inference](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) for all the models and region combinations that support it.
With Cross-Region inference, you can distribute traffic across multiple AWS Regions, enabling higher throughput.

For example, if you use `Claude Sonnet 3.7 Thinking` from `us-east-1`, it may be processed across the US regions, namely: `us-east-1`, `us-east-2`, or `us-west-2`.
Cross-Region inference requests are kept within the AWS Regions that are part of the geography where the data originally resides.
For example, a request made within the US is kept within the AWS Regions in the US.

Although the data remains stored only in the source Region, your input prompts and output results might move outside of your source Region during cross-Region inference.
All data will be transmitted encrypted across Amazon's secure network.

We will support Cross-Region inference for each of the models on a best-effort basis, please refer to the [Cross-Region Inference method Code](https://github.com/zed-industries/zed/blob/main/crates/bedrock/src/models.rs#L297).

For the most up-to-date supported regions and models, refer to the [Supported Models and Regions for Cross Region inference](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html).

### Anthropic {#anthropic}

You can use Anthropic models by choosing them via the model dropdown in the Agent Panel.

1. Sign up for Anthropic and [create an API key](https://console.anthropic.com/settings/keys)
2. Make sure that your Anthropic account has credits
3. Open the settings view (`agent: open settings`) and go to the Anthropic section
4. Enter your Anthropic API key

Even if you pay for Claude Pro, you will still have to [pay for additional credits](https://console.anthropic.com/settings/plans) to use it via the API.

Zed will also use the `ANTHROPIC_API_KEY` environment variable if it's defined.

#### Custom Models {#anthropic-custom-models}

You can add custom models to the Anthropic provider by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "anthropic": {
      "available_models": [
        {
          "name": "claude-3-5-sonnet-20240620",
          "display_name": "Sonnet 2024-June",
          "max_tokens": 128000,
          "max_output_tokens": 2560,
          "cache_configuration": {
            "max_cache_anchors": 10,
            "min_total_token": 10000,
            "should_speculate": false
          },
          "tool_override": "some-model-that-supports-toolcalling"
        }
      ]
    }
  }
}
```

Custom models will be listed in the model dropdown in the Agent Panel.

You can configure a model to use [extended thinking](https://docs.anthropic.com/en/docs/about-claude/models/extended-thinking-models) (if it supports it) by changing the mode in your model's configuration to `thinking`, for example:

```json
{
  "name": "claude-sonnet-4-latest",
  "display_name": "claude-sonnet-4-thinking",
  "max_tokens": 200000,
  "mode": {
    "type": "thinking",
    "budget_tokens": 4_096
  }
}
```

### DeepSeek {#deepseek}

1. Visit the DeepSeek platform and [create an API key](https://platform.deepseek.com/api_keys)
2. Open the settings view (`agent: open settings`) and go to the DeepSeek section
3. Enter your DeepSeek API key

The DeepSeek API key will be saved in your keychain.

Zed will also use the `DEEPSEEK_API_KEY` environment variable if it's defined.

#### Custom Models {#deepseek-custom-models}

The Zed agent comes pre-configured to use the latest version for common models (DeepSeek Chat, DeepSeek Reasoner).
If you wish to use alternate models or customize the API endpoint, you can do so by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "deepseek": {
      "api_url": "https://api.deepseek.com",
      "available_models": [
        {
          "name": "deepseek-chat",
          "display_name": "DeepSeek Chat",
          "max_tokens": 64000
        },
        {
          "name": "deepseek-reasoner",
          "display_name": "DeepSeek Reasoner",
          "max_tokens": 64000,
          "max_output_tokens": 4096
        }
      ]
    }
  }
}
```

Custom models will be listed in the model dropdown in the Agent Panel.
You can also modify the `api_url` to use a custom endpoint if needed.

### GitHub Copilot Chat {#github-copilot-chat}

You can use GitHub Copilot Chat with the Zed agent by choosing it via the model dropdown in the Agent Panel.

1. Open the settings view (`agent: open settings`) and go to the GitHub Copilot Chat section
2. Click on `Sign in to use GitHub Copilot`, follow the steps shown in the modal.

Alternatively, you can provide an OAuth token via the `GH_COPILOT_TOKEN` environment variable.

> **Note**: If you don't see specific models in the dropdown, you may need to enable them in your [GitHub Copilot settings](https://github.com/settings/copilot/features).

To use Copilot Enterprise with Zed (for both agent and completions), you must configure your enterprise endpoint as described in [Configuring GitHub Copilot Enterprise](./edit-prediction.md#github-copilot-enterprise).

### Google AI {#google-ai}

You can use Gemini models with the Zed agent by choosing it via the model dropdown in the Agent Panel.

1. Go to the Google AI Studio site and [create an API key](https://aistudio.google.com/app/apikey).
2. Open the settings view (`agent: open settings`) and go to the Google AI section
3. Enter your Google AI API key and press enter.

The Google AI API key will be saved in your keychain.

Zed will also use the `GEMINI_API_KEY` environment variable if it's defined. See [Using Gemini API keys](https://ai.google.dev/gemini-api/docs/api-key) in the Gemini docs for more.

#### Custom Models {#google-ai-custom-models}

By default, Zed will use `stable` versions of models, but you can use specific versions of models, including [experimental models](https://ai.google.dev/gemini-api/docs/models/experimental-models). You can configure a model to use [thinking mode](https://ai.google.dev/gemini-api/docs/thinking) (if it supports it) by adding a `mode` configuration to your model. This is useful for controlling reasoning token usage and response speed. If not specified, Gemini will automatically choose the thinking budget.

Here is an example of a custom Google AI model you could add to your Zed `settings.json`:

```json
{
  "language_models": {
    "google": {
      "available_models": [
        {
          "name": "gemini-2.5-flash-preview-05-20",
          "display_name": "Gemini 2.5 Flash (Thinking)",
          "max_tokens": 1000000,
          "mode": {
            "type": "thinking",
            "budget_tokens": 24000
          }
        }
      ]
    }
  }
}
```

Custom models will be listed in the model dropdown in the Agent Panel.

### LM Studio {#lmstudio}

1. Download and install [the latest version of LM Studio](https://lmstudio.ai/download)
2. In the app press `cmd/ctrl-shift-m` and download at least one model (e.g., qwen2.5-coder-7b). Alternatively, you can get models via the LM Studio CLI:

   ```sh
   lms get qwen2.5-coder-7b
   ```

3. Make sure the LM Studio API server is running by executing:

   ```sh
   lms server start
   ```

Tip: Set [LM Studio as a login item](https://lmstudio.ai/docs/advanced/headless#run-the-llm-service-on-machine-login) to automate running the LM Studio server.

### Mistral {#mistral}

1. Visit the Mistral platform and [create an API key](https://console.mistral.ai/api-keys/)
2. Open the configuration view (`agent: open settings`) and navigate to the Mistral section
3. Enter your Mistral API key

The Mistral API key will be saved in your keychain.

Zed will also use the `MISTRAL_API_KEY` environment variable if it's defined.

#### Custom Models {#mistral-custom-models}

The Zed agent comes pre-configured with several Mistral models (codestral-latest, mistral-large-latest, mistral-medium-latest, mistral-small-latest, open-mistral-nemo, and open-codestral-mamba).
All the default models support tool use.
If you wish to use alternate models or customize their parameters, you can do so by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "mistral": {
      "api_url": "https://api.mistral.ai/v1",
      "available_models": [
        {
          "name": "mistral-tiny-latest",
          "display_name": "Mistral Tiny",
          "max_tokens": 32000,
          "max_output_tokens": 4096,
          "max_completion_tokens": 1024,
          "supports_tools": true,
          "supports_images": false
        }
      ]
    }
  }
}
```

Custom models will be listed in the model dropdown in the Agent Panel.

### Ollama {#ollama}

Download and install Ollama from [ollama.com/download](https://ollama.com/download) (Linux or macOS) and ensure it's running with `ollama --version`.

1. Download one of the [available models](https://ollama.com/models), for example, for `mistral`:

   ```sh
   ollama pull mistral
   ```

2. Make sure that the Ollama server is running. You can start it either via running Ollama.app (macOS) or launching:

   ```sh
   ollama serve
   ```

3. In the Agent Panel, select one of the Ollama models using the model dropdown.

#### Ollama Context Length {#ollama-context}

Zed has pre-configured maximum context lengths (`max_tokens`) to match the capabilities of common models.
Zed API requests to Ollama include this as the `num_ctx` parameter, but the default values do not exceed `16384` so users with ~16GB of RAM are able to use most models out of the box.

See [get_max_tokens in ollama.rs](https://github.com/zed-industries/zed/blob/main/crates/ollama/src/ollama.rs) for a complete set of defaults.

> **Note**: Token counts displayed in the Agent Panel are only estimates and will differ from the model's native tokenizer.

Depending on your hardware or use-case you may wish to limit or increase the context length for a specific model via settings.json:

```json
{
  "language_models": {
    "ollama": {
      "api_url": "http://localhost:11434",
      "available_models": [
        {
          "name": "qwen2.5-coder",
          "display_name": "qwen 2.5 coder 32K",
          "max_tokens": 32768,
          "supports_tools": true,
          "supports_thinking": true,
          "supports_images": true
        }
      ]
    }
  }
}
```

If you specify a context length that is too large for your hardware, Ollama will log an error.
You can watch these logs by running: `tail -f ~/.ollama/logs/ollama.log` (macOS) or `journalctl -u ollama -f` (Linux).
Depending on the memory available on your machine, you may need to adjust the context length to a smaller value.

You may also optionally specify a value for `keep_alive` for each available model.
This can be an integer (seconds) or alternatively a string duration like "5m", "10m", "1h", "1d", etc.
For example, `"keep_alive": "120s"` will allow the remote server to unload the model (freeing up GPU VRAM) after 120 seconds.

The `supports_tools` option controls whether the model will use additional tools.
If the model is tagged with `tools` in the Ollama catalog, this option should be supplied, and the built-in profiles `Ask` and `Write` can be used.
If the model is not tagged with `tools` in the Ollama catalog, this option can still be supplied with the value `true`; however, be aware that only the `Minimal` built-in profile will work.

The `supports_thinking` option controls whether the model will perform an explicit "thinking" (reasoning) pass before producing its final answer.
If the model is tagged with `thinking` in the Ollama catalog, set this option and you can use it in Zed.

The `supports_images` option enables the model's vision capabilities, allowing it to process images included in the conversation context.
If the model is tagged with `vision` in the Ollama catalog, set this option and you can use it in Zed.

#### Ollama Authentication

In addition to running Ollama on your own hardware, which generally does not require authentication, Zed also supports connecting to remote Ollama instances. API keys are required for authentication.

One such service is [Ollama Turbo])(https://ollama.com/turbo). To configure Zed to use Ollama turbo:

1. Sign in to your Ollama account and subscribe to Ollama Turbo
2. Visit [ollama.com/settings/keys](https://ollama.com/settings/keys) and create an API key
3. Open the settings view (`agent: open settings`) and go to the Ollama section
4. Paste your API key and press enter.
5. For the API URL enter `https://ollama.com`

Zed will also use the `OLLAMA_API_KEY` environment variables if defined.

### OpenAI {#openai}

1. Visit the OpenAI platform and [create an API key](https://platform.openai.com/account/api-keys)
2. Make sure that your OpenAI account has credits
3. Open the settings view (`agent: open settings`) and go to the OpenAI section
4. Enter your OpenAI API key

The OpenAI API key will be saved in your keychain.

Zed will also use the `OPENAI_API_KEY` environment variable if it's defined.

#### Custom Models {#openai-custom-models}

The Zed agent comes pre-configured to use the latest version for common models (GPT-5, GPT-5 mini, o4-mini, GPT-4.1, and others).
To use alternate models, perhaps a preview release, or if you wish to control the request parameters, you can do so by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "openai": {
      "available_models": [
        {
          "name": "gpt-5",
          "display_name": "gpt-5 high",
          "reasoning_effort": "high",
          "max_tokens": 272000,
          "max_completion_tokens": 20000
        },
        {
          "name": "gpt-4o-2024-08-06",
          "display_name": "GPT 4o Summer 2024",
          "max_tokens": 128000
        }
      ]
    }
  }
}
```

You must provide the model's context window in the `max_tokens` parameter; this can be found in the [OpenAI model documentation](https://platform.openai.com/docs/models).

OpenAI `o1` models should set `max_completion_tokens` as well to avoid incurring high reasoning token costs.
Custom models will be listed in the model dropdown in the Agent Panel.

### OpenAI API Compatible {#openai-api-compatible}

Zed supports using [OpenAI compatible APIs](https://platform.openai.com/docs/api-reference/chat) by specifying a custom `api_url` and `available_models` for the OpenAI provider.
This is useful for connecting to other hosted services (like Together AI, Anyscale, etc.) or local models.

You can add a custom, OpenAI-compatible model either via the UI or by editing your `settings.json`.

To do it via the UI, go to the Agent Panel settings (`agent: open settings`) and look for the "Add Provider" button to the right of the "LLM Providers" section title.
Then, fill up the input fields available in the modal.

To do it via your `settings.json`, add the following snippet under `language_models`:

```json
{
  "language_models": {
    "openai_compatible": {
      // Using Together AI as an example
      "Together AI": {
        "api_url": "https://api.together.xyz/v1",
        "available_models": [
          {
            "name": "mistralai/Mixtral-8x7B-Instruct-v0.1",
            "display_name": "Together Mixtral 8x7B",
            "max_tokens": 32768,
            "capabilities": {
              "tools": true,
              "images": false,
              "parallel_tool_calls": false,
              "prompt_cache_key": false
            }
          }
        ]
      }
    }
  }
}
```

By default, OpenAI-compatible models inherit the following capabilities:

- `tools`: true (supports tool/function calling)
- `images`: false (does not support image inputs)
- `parallel_tool_calls`: false (does not support `parallel_tool_calls` parameter)
- `prompt_cache_key`: false (does not support `prompt_cache_key` parameter)

Note that LLM API keys aren't stored in your settings file.
So, ensure you have it set in your environment variables (`<PROVIDER_NAME>_API_KEY=<your api key>`) so your settings can pick it up. In the example above, it would be `TOGETHER_AI_API_KEY=<your api key>`.

### OpenRouter {#openrouter}

OpenRouter provides access to multiple AI models through a single API. It supports tool use for compatible models.

1. Visit [OpenRouter](https://openrouter.ai) and create an account
2. Generate an API key from your [OpenRouter keys page](https://openrouter.ai/keys)
3. Open the settings view (`agent: open settings`) and go to the OpenRouter section
4. Enter your OpenRouter API key

The OpenRouter API key will be saved in your keychain.

Zed will also use the `OPENROUTER_API_KEY` environment variable if it's defined.

#### Custom Models {#openrouter-custom-models}

You can add custom models to the OpenRouter provider by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "open_router": {
      "api_url": "https://openrouter.ai/api/v1",
      "available_models": [
        {
          "name": "google/gemini-2.0-flash-thinking-exp",
          "display_name": "Gemini 2.0 Flash (Thinking)",
          "max_tokens": 200000,
          "max_output_tokens": 8192,
          "supports_tools": true,
          "supports_images": true,
          "mode": {
            "type": "thinking",
            "budget_tokens": 8000
          }
        }
      ]
    }
  }
}
```

The available configuration options for each model are:

- `name` (required): The model identifier used by OpenRouter
- `display_name` (optional): A human-readable name shown in the UI
- `max_tokens` (required): The model's context window size
- `max_output_tokens` (optional): Maximum tokens the model can generate
- `max_completion_tokens` (optional): Maximum completion tokens
- `supports_tools` (optional): Whether the model supports tool/function calling
- `supports_images` (optional): Whether the model supports image inputs
- `mode` (optional): Special mode configuration for thinking models

You can find available models and their specifications on the [OpenRouter models page](https://openrouter.ai/models).

Custom models will be listed in the model dropdown in the Agent Panel.

#### Provider Routing

You can optionally control how OpenRouter routes a given custom model request among underlying upstream providers via the `provider` object on each model entry.

Supported fields (all optional):

- `order`: Array of provider slugs to try first, in order (e.g. `["anthropic", "openai"]`)
- `allow_fallbacks` (default: `true`): Whether fallback providers may be used if preferred ones are unavailable
- `require_parameters` (default: `false`): Only use providers that support every parameter you supplied
- `data_collection` (default: `allow`): `"allow"` or `"disallow"` (controls use of providers that may store data)
- `only`: Whitelist of provider slugs allowed for this request
- `ignore`: Provider slugs to skip
- `quantizations`: Restrict to specific quantization variants (e.g. `["int4","int8"]`)
- `sort`: Sort strategy for candidate providers (e.g. `"price"` or `"throughput"`)

Example adding routing preferences to a model:

```json
{
  "language_models": {
    "open_router": {
      "api_url": "https://openrouter.ai/api/v1",
      "available_models": [
        {
          "name": "openrouter/auto",
          "display_name": "Auto Router (Tools Preferred)",
          "max_tokens": 2000000,
          "supports_tools": true,
          "provider": {
            "order": ["anthropic", "openai"],
            "allow_fallbacks": true,
            "require_parameters": true,
            "only": ["anthropic", "openai", "google"],
            "ignore": ["cohere"],
            "quantizations": ["int8"],
            "sort": "price",
            "data_collection": "allow"
          }
        }
      ]
    }
  }
}
```

These routing controls let you fine‑tune cost, capability, and reliability trade‑offs without changing the model name you select in the UI.

### Vercel v0 {#vercel-v0}

[Vercel v0](https://vercel.com/docs/v0/api) is an expert model for generating full-stack apps, with framework-aware completions optimized for modern stacks like Next.js and Vercel.
It supports text and image inputs and provides fast streaming responses.

The v0 models are [OpenAI-compatible models](/#openai-api-compatible), but Vercel is listed as first-class provider in the panel's settings view.

To start using it with Zed, ensure you have first created a [v0 API key](https://v0.dev/chat/settings/keys).
Once you have it, paste it directly into the Vercel provider section in the panel's settings view.

You should then find it as `v0-1.5-md` in the model dropdown in the Agent Panel.

### xAI {#xai}

Zed has first-class support for [xAI](https://x.ai/) models. You can use your own API key to access Grok models.

1. [Create an API key in the xAI Console](https://console.x.ai/team/default/api-keys)
2. Open the settings view (`agent: open settings`) and go to the **xAI** section
3. Enter your xAI API key

The xAI API key will be saved in your keychain. Zed will also use the `XAI_API_KEY` environment variable if it's defined.

> **Note:** While the xAI API is OpenAI-compatible, Zed has first-class support for it as a dedicated provider. For the best experience, we recommend using the dedicated `x_ai` provider configuration instead of the [OpenAI API Compatible](#openai-api-compatible) method.

#### Custom Models {#xai-custom-models}

The Zed agent comes pre-configured with common Grok models. If you wish to use alternate models or customize their parameters, you can do so by adding the following to your Zed `settings.json`:

```json
{
  "language_models": {
    "x_ai": {
      "api_url": "https://api.x.ai/v1",
      "available_models": [
        {
          "name": "grok-1.5",
          "display_name": "Grok 1.5",
          "max_tokens": 131072,
          "max_output_tokens": 8192
        },
        {
          "name": "grok-1.5v",
          "display_name": "Grok 1.5V (Vision)",
          "max_tokens": 131072,
          "max_output_tokens": 8192,
          "supports_images": true
        }
      ]
    }
  }
}
```

## Custom Provider Endpoints {#custom-provider-endpoint}

You can use a custom API endpoint for different providers, as long as it's compatible with the provider's API structure.
To do so, add the following to your `settings.json`:

```json
{
  "language_models": {
    "some-provider": {
      "api_url": "http://localhost:11434"
    }
  }
}
```

Currently, `some-provider` can be any of the following values: `anthropic`, `google`, `ollama`, `openai`.

This is the same infrastructure that powers models that are, for example, [OpenAI-compatible](#openai-api-compatible).

    # Model Context Protocol

Zed uses the [Model Context Protocol](https://modelcontextprotocol.io/) to interact with context servers.

> The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating custom AI workflows, MCP provides a standardized way to connect LLMs with the context they need.

Check out the [Anthropic news post](https://www.anthropic.com/news/model-context-protocol) and the [Zed blog post](https://zed.dev/blog/mcp) for a general intro to MCP.

## Installing MCP Servers

### As Extensions

One of the ways you can use MCP servers in Zed is by exposing them as an extension.
To learn how to create your own, check out the [MCP Server Extensions](../extensions/mcp-extensions.md) page for more details.

Thanks to our awesome community, many MCP servers have already been added as extensions.
You can check which ones are available via any of these routes:

1. [the Zed website](https://zed.dev/extensions?filter=context-servers)
2. in the app, open the Command Palette and run the `zed: extensions` action
3. in the app, go to the Agent Panel's top-right menu and look for the "View Server Extensions" menu item

In any case, here are some of the ones available:

- [Context7](https://zed.dev/extensions/context7-mcp-server)
- [GitHub](https://zed.dev/extensions/github-mcp-server)
- [Puppeteer](https://zed.dev/extensions/puppeteer-mcp-server)
- [Gem](https://zed.dev/extensions/gem)
- [Brave Search](https://zed.dev/extensions/brave-search-mcp-server)
- [Prisma](https://github.com/aqrln/prisma-mcp-zed)
- [Framelink Figma](https://zed.dev/extensions/framelink-figma-mcp-server)
- [Linear](https://zed.dev/extensions/linear-mcp-server)
- [Resend](https://zed.dev/extensions/resend-mcp-server)

### As Custom Servers

Creating an extension is not the only way to use MCP servers in Zed.
You can connect them by adding their commands directly to your `settings.json`, like so:

```json
{
  "context_servers": {
    "your-mcp-server": {
      "source": "custom",
      "command": "some-command",
      "args": ["arg-1", "arg-2"],
      "env": {}
    }
  }
}
```

Alternatively, you can also add a custom server by accessing the Agent Panel's Settings view (also accessible via the `agent: open settings` action).
From there, you can add it through the modal that appears when you click the "Add Custom Server" button.

## Using MCP Servers

### Installation Check

Regardless of whether you're using MCP servers as an extension or adding them directly, most servers out there need some sort of configuration as part of the set up process.

In the case of extensions, Zed will show a modal displaying what is required for you to properly set up a given server.
For example, the GitHub MCP extension requires you to add a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

In the case of custom servers, make sure you check the provider documentation to determine what type of command, arguments, and environment variables need to be added to the JSON.

To check whether your MCP server is properly installed, go to the Agent Panel's settings view and watch the indicator dot next to its name.
If they're running correctly, the indicator will be green and its tooltip will say "Server is active".
If not, other colors and tooltip messages will indicate what is happening.

### Using in the Agent Panel

Once installation is complete, you can return to the Agent Panel and start prompting.
Mentioning your MCP server by name helps the agent pick it up.

If you want to ensure a given server will be used, you can create [a custom profile](./agent-panel.md#custom-profiles) by turning off the built-in tools (either all of them or the ones that would cause conflicts) and turning on only the tools coming from the MCP server.

As an example, [the Dagger team suggests](https://container-use.com/agent-integrations#add-container-use-agent-profile-optional) doing that with their [Container Use MCP server](https://zed.dev/extensions/mcp-server-container-use):

```json
"agent": {
  "profiles": {
    "container-use": {
      "name": "Container Use",
      "tools": {
        "fetch": true,
        "thinking": true,
        "copy_path": false,
        "find_path": false,
        "delete_path": false,
        "create_directory": false,
        "list_directory": false,
        "diagnostics": false,
        "read_file": false,
        "open": false,
        "move_path": false,
        "grep": false,
        "edit_file": false,
        "terminal": false
      },
      "enable_all_context_servers": false,
      "context_servers": {
        "container-use": {
          "tools": {
            "environment_create": true,
            "environment_add_service": true,
            "environment_update": true,
            "environment_run_cmd": true,
            "environment_open": true,
            "environment_file_write": true,
            "environment_file_read": true,
            "environment_file_list": true,
            "environment_file_delete": true,
            "environment_checkpoint": true
          }
        }
      }
    }
  }
}
```

### Tool Approval

Zed's Agent Panel includes the `agent.always_allow_tool_actions` setting that, if set to `false`, will require you to give permission for any editing attempt as well as tool calls coming from MCP servers.

You can change this by setting this key to `true` in either your `settings.json` or through the Agent Panel's settings view.

    # Models

Zed’s plans offer hosted versions of major LLM’s, generally with higher rate limits than individual API keys.
We’re working hard to expand the models supported by Zed’s subscription offerings, so please check back often.

| Model             | Provider  | Burn Mode | Context Window | Price per Prompt | Price per Request |
| ----------------- | --------- | --------- | -------------- | ---------------- | ----------------- |
| Claude 3.5 Sonnet | Anthropic | ❌        | 60k            | $0.04            | N/A               |
| Claude 3.7 Sonnet | Anthropic | ❌        | 120k           | $0.04            | N/A               |
| Claude 3.7 Sonnet | Anthropic | ✅        | 200k           | N/A              | $0.05             |
| Claude Sonnet 4   | Anthropic | ❌        | 120k           | $0.04            | N/A               |
| Claude Sonnet 4   | Anthropic | ✅        | 200k           | N/A              | $0.05             |
| Claude Opus 4     | Anthropic | ❌        | 120k           | $0.20            | N/A               |
| Claude Opus 4     | Anthropic | ✅        | 200k           | N/A              | $0.25             |
| Claude Opus 4.1   | Anthropic | ❌        | 120k           | $0.20            | N/A               |
| Claude Opus 4.1   | Anthropic | ✅        | 200k           | N/A              | $0.25             |

> Note: Because of the 5x token cost for [Opus relative to Sonnet](https://www.anthropic.com/pricing#api), each Opus 4 and 4.1 prompt consumes 5 prompts against your billing meter

## Usage {#usage}

The models above can be used with the prompts included in your plan. For models not marked with [“Burn Mode”](#burn-mode), each prompt is counted against the monthly limit of your plan.

If you’ve exceeded your limit for the month, and are on a paid plan, you can enable usage-based pricing to continue using models for the rest of the month. See [Plans and Usage](./plans-and-usage.md) for more information.

Non-Burn Mode usage will use up to 25 tool calls per one prompt. If your prompt extends beyond 25 tool calls, Zed will ask if you’d like to continue, which will consume a second prompt.

## Burn Mode {#burn-mode}

> Note: "Burn Mode" is the new name for what was previously called "Max Mode".

In Burn Mode, we enable models to use [large context windows](#context-windows), unlimited tool calls, and other capabilities for expanded reasoning, to allow an unfettered agentic experience.

Because of the increased cost to Zed, each subsequent request beyond the initial user prompt in Burn Mode models is counted as a prompt for metering.

In addition, usage-based pricing per request is slightly more expensive for Burn Mode models than usage-based pricing per prompt for regular models.

> Note that the Agent Panel using a Burn Mode model may consume a good bit of your monthly prompt capacity, if many tool calls are used.
> We encourage you to think through what model is best for your needs before leaving the Agent Panel to work.

By default, all threads and [text threads](./text-threads.md) start in normal mode.
However, you can use the `agent.preferred_completion_mode` setting to have Burn Mode activated by default.

## Context Windows {#context-windows}

A context window is the maximum span of text and code an LLM can consider at once, including both the input prompt and output generated by the model.

In [Burn Mode](#burn-mode), we increase context window size to allow models to have enhanced reasoning capabilities.

Each Agent thread and text thread in Zed maintains its own context window.
The more prompts, attached files, and responses included in a session, the larger the context window grows.

For best results, it’s recommended you take a purpose-based approach to Agent thread management, starting a new thread for each unique task.

## Tool Calls {#tool-calls}

Models can use [tools](./tools.md) to interface with your code, search the web, and perform other useful functions.

In [Burn Mode](#burn-mode), models can use an unlimited number of tools per prompt, with each tool call counting as a prompt for metering purposes.

For non-Burn Mode models, you'll need to interact with the model every 25 tool calls to continue, at which point a new prompt will be counted against your plan limit.

    # AI

Learn how to get started using AI with Zed and all its capabilities.

## Setting up AI in Zed

- [Configuration](./configuration.md): Learn how to set up different language model providers like Anthropic, OpenAI, Ollama, Google AI, and more.

- [External Agents](./external-agents.md): Learn how to plug in your favorite agent into Zed.

- [Subscription](./subscription.md): Learn about Zed's hosted model service and other billing-related information.

- [Privacy and Security](./privacy-and-security.md): Understand how Zed handles privacy and security with AI features.

## Agentic Editing

- [Agent Panel](./agent-panel.md): Create and manage interactions with LLM agents.

- [Rules](./rules.md): How to define rules for AI interactions.

- [Tools](./tools.md): Explore the tools that enable agentic capabilities.

- [Model Context Protocol](./mcp.md): Learn about how to install and configure MCP servers.

- [Inline Assistant](./inline-assistant.md): Discover how to use the agent to power inline transformations directly within a file or terminal.

## Edit Prediction

- [Edit Prediction](./edit-prediction.md): Learn about Zed's AI prediction feature that helps autocomplete your code.

## Text Threads

- [Text Threads](./text-threads.md): Learn about an alternative, text-based interface for interacting with language models.

    # Plans and Usage

To view your current usage, you can visit your account at [zed.dev/account](https://zed.dev/account).
You’ll also find usage meters in-product when you’re nearing the limit for your plan or trial.

## Available Plans {#plans}

For costs and more information on pricing, visit [Zed’s pricing page](https://zed.dev/pricing).

Please note that if you’re interested in just using Zed as the world’s fastest editor, with no AI or subscription features, you can always do so for free, without [authentication](../accounts.md).

## Usage {#usage}

- A `prompt` in Zed is an input from the user, initiated by pressing enter, composed of one or many `requests`. A `prompt` can be initiated from the Agent Panel, or via Inline Assist.
- A `request` in Zed is a response to a `prompt`, plus any tool calls that are initiated as part of that response. There may be one `request` per `prompt`, or many.

Most models offered by Zed are metered per-prompt.
Some models that use large context windows and unlimited tool calls ([“Burn Mode”](./models.md#burn-mode)) count each individual request within a prompt against your prompt limit, since the agentic work spawned by the prompt is expensive to support.

See [the Models page](./models.md) for a list of which subset of models are metered by request.

Plans come with a set amount of prompts included, with the number varying depending on the plan you’ve selected.

## Usage-Based Pricing {#ubp}

You may opt in to usage-based pricing for prompts that exceed what is included in your paid plan from [your account page](https://zed.dev/account).

Usage-based pricing is only available with a paid plan, and is exclusively opt-in.
From the dashboard, you can toggle usage-based pricing for usage exceeding your paid plan.
You can also configure a spend limit in USD.
Once the spend limit is hit, we’ll stop any further usage until your prompt limit resets.

We will bill for additional prompts when you’ve made prompts totaling $20, or when your billing date occurs, whichever comes first.

Cost per request for each model can be found on [the models page](./models.md).

## Business Usage {#business-usage}

Email [sales@zed.dev](mailto:sales@zed.dev) with any questions on business plans, metering, and usage-based pricing.

    # Privacy and Security

## Philosophy

Zed aims to collect on the minimum data necessary to serve and improve our product.

We believe in opt-in data sharing as the default in building AI products, rather than opt-out, like most of our competitors. Privacy Mode is not a setting to be toggled, it's a default stance.

As an open-source product, we believe in maximal transparency, and invite you to examine our codebase. If you find issues, we encourage you to share them with us.

It is entirely possible to use Zed without sharing any data with us and without authenticating into the product. We're happy to always support this desired use pattern.

## Documentation

- [Telemetry](../telemetry.md): How Zed collects general telemetry data.

- [AI Improvement](./ai-improvement.md): Zed's opt-in-only approach to data collection for AI improvement, whether our Agentic offering or Edit Predictions.

- [Accounts](../accounts.md): When and why you'd need to authenticate into Zed, how to do so, and what scope we need from you.

## Legal Links

- [Terms of Service](https://zed.dev/terms-of-service)
- [Terms of Use](https://zed.dev/terms)
- [Privacy Policy](https://zed.dev/privacy-policy)
- [Zed's Contributor License and Feedback Agreement](https://zed.dev/cla)
- [Subprocessors](https://zed.dev/subprocessors)

    # Using Rules {#using-rules}

A rule is essentially a prompt that is inserted at the beginning of each interaction with the Agent.
Currently, Zed supports `.rules` files at the directory's root and the Rules Library, which allows you to store multiple rules for on-demand usage.

## `.rules` files

Zed supports including `.rules` files at the top level of worktrees, and they act as project-level instructions that are included in all of your interactions with the Agent Panel.
Other names for this file are also supported for compatibility with other agents, but note that the first file which matches in this list will be used:

- `.rules`
- `.cursorrules`
- `.windsurfrules`
- `.clinerules`
- `.github/copilot-instructions.md`
- `AGENT.md`
- `AGENTS.md`
- `CLAUDE.md`
- `GEMINI.md`

## Rules Library {#rules-library}

The Rules Library is an interface for writing and managing rules. Like other text-driven UIs in Zed, it is a full editor with syntax highlighting, keyboard shortcuts, etc.

You can use the inline assistant right in the rules editor, allowing you to automate and rewrite rules.

### Opening the Rules Library

1. Open the Agent Panel.
2. Click on the Agent menu (`...`) in the top right corner.
3. Select `Rules...` from the dropdown.

You can also use the `agent: open rules library` command while in the Agent Panel.

### Managing Rules

Once a rules file is selected, you can edit it directly in the built-in editor. Its title can be changed from the editor title bar as well.

Rules can be duplicated, deleted, or added to the default rules using the buttons in the rules editor.

### Creating Rules {#creating-rules}

To create a rule file, simply open the `Rules Library` and click the `+` button. Rules files are stored locally and can be accessed from the library at any time.

Having a series of rules files specifically tailored to prompt engineering can also help you write consistent and effective rules.

Here are a couple of helpful resources for writing better rules:

- [Anthropic: Prompt Engineering](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview)
- [OpenAI: Prompt Engineering](https://platform.openai.com/docs/guides/prompt-engineering)

### Editing the Default Rules {#default-rules}

Zed allows you to customize the default rules used when interacting with LLMs.
Or to be more precise, it uses a series of rules that are combined to form the default rules.

Default rules are included in the context of every new thread automatically.
You can also manually add other rules (that are not flagged as default) as context using the `@rule` command.

## Migrating from Prompt Library

Previously, the Rules Library was called the "Prompt Library".
The new rules system replaces the Prompt Library except in a few specific cases, which are outlined below.

### Slash Commands in Rules

Previously, it was possible to use slash commands (now @-mentions) in custom prompts (now rules).
There is currently no support for using @-mentions in rules files, however, slash commands are supported in rules files when used with text threads.
See the documentation for using [slash commands in rules](./text-threads.md#slash-commands-in-rules) for more information.

### Prompt templates

Zed maintains backwards compatibility with its original template system, which allows you to customize prompts used throughout the application, including the inline assistant.
While the Rules Library is now the primary way to manage prompts, you can still use these legacy templates to override default prompts.
For more details, see the [Rules Templates](./text-threads.md#rule-templates) section under [Text Threads](./text-threads.md).

    # Subscription

Zed's hosted models are offered via subscription to Zed Pro or Zed Business.

> Using your own API keys is _free_—you do not need to subscribe to a Zed plan to use our AI features with your own keys.

See the following pages for specific aspects of our subscription offering:

- [Plans and Usage](./plans-and-usage.md): Outlines Zed's plans, how usage is measured, and usage-based pricing for overages.

- [Billing](./billing.md): Billing policies and procedures, and how to update or view various billing settings.

- [Models](./models.md): Overview of the models offered by Zed's subscriptions.

    # Text Threads

## Overview {#overview}

Text threads in the [Agent Panel](./agent-panel.md) function similarly to any other editor. You can use custom key bindings and work with multiple cursors, allowing for seamless transitions between coding and engaging in discussions with the language models.

However, the text threads differ with the inclusion of message blocks. These blocks serve as containers for text that correspond to different roles within the context. These roles include:

- `You`
- `Assistant`
- `System`

To begin, type a message in a `You` block.

![Asking a question](https://zed.dev/img/assistant/ask-a-question.png)

As you type, the remaining tokens count for the selected model is updated.

Inserting text from an editor is as simple as highlighting the text and running `agent: quote selection` ({#kb agent::QuoteSelection}); Zed will wrap it in a fenced code block if it is code.

![Quoting a selection](https://zed.dev/img/assistant/quoting-a-selection.png)

To submit a message, use {#kb assistant::Assist}(`assistant: assist`). Unlike normal threads, where pressing <kbd>enter</kbd> would submit the message, in text threads, our goal is to make it feel as close to a regular editor as possible. So, pressing {#kb editor::Newline} simply inserts a new line.

After submitting a message, the response will be streamed below, in an `Assistant` message block.

![Receiving an answer](https://zed.dev/img/assistant/receiving-an-answer.png)

The stream can be canceled at any point with <kbd>escape</kbd>. This is useful if you realize early on that the response is not what you were looking for.

If you want to start a new conversation at any time, you can hit <kbd>cmd-n|ctrl-n</kbd> or use the `New Chat` menu option in the hamburger menu at the top left of the panel.

Simple back-and-forth conversations work well with the text threads. However, there may come a time when you want to modify the previous text in the conversation and steer it in a different direction.

## Editing a Text Thread {#edit-text-thread}

Text threads give you the flexibility to have control over the context.
You can freely edit any previous text, including the responses from the LLM.
If you want to remove a message block entirely, simply place your cursor at the beginning of the block and use the `delete` key.
A typical workflow might involve making edits and adjustments throughout the context to refine your inquiry or provide additional information. Here's an example:

1. Write text in a `You` block.
2. Submit the message with {#kb assistant::Assist}.
3. Receive an `Assistant` response that doesn't meet your expectations.
4. Cancel the response with <kbd>escape</kbd>.
5. Erase the content of the `Assistant` message block and remove the block entirely.
6. Add additional context to your original message.
7. Submit the message with {#kb assistant::Assist}.

Being able to edit previous messages gives you control over how tokens are used. You don't need to start up a new chat to correct a mistake or to add additional information, and you don't have to waste tokens by submitting follow-up corrections.

> **Note**: The act of editing past messages is often referred to as "Rewriting History" in the context of the language models.

Some additional points to keep in mind:

- You can cycle the role of a message block by clicking on the role, which is useful when you receive a response in an `Assistant` block that you want to edit and send back up as a `You` block.

## Commands Overview {#commands}

Slash commands enhance the assistant's capabilities. Begin by typing a `/` at the beginning of the line to see a list of available commands:

- `/default`: Inserts the default rule
- `/diagnostics`: Injects errors reported by the project's language server
- `/fetch`: Fetches the content of a webpage and inserts it
- `/file`: Inserts a single file or a directory of files
- `/now`: Inserts the current date and time
- `/prompt`: Adds a custom-configured prompt to the context ([see Rules Library](./rules.md#rules-library))
- `/symbols`: Inserts the current tab's active symbols
- `/tab`: Inserts the content of the active tab or all open tabs
- `/terminal`: Inserts a select number of lines of output from the terminal
- `/selection`: Inserts the selected text

> **Note:** Remember, commands are only evaluated when the text thread is created or when the command is inserted, so a command like `/now` won't continuously update, or `/file` commands won't keep their contents up to date.

### `/default`

Read more about `/default` in the [Rules: Editing the Default Rules](./rules.md#default-rules) section.

Usage: `/default`

### `/diagnostics`

The `/diagnostics` command injects errors reported by the project's language server into the context. This is useful for getting an overview of current issues in your project.

Usage: `/diagnostics [--include-warnings] [path]`

- `--include-warnings`: Optional flag to include warnings in addition to errors.
- `path`: Optional path to limit diagnostics to a specific file or directory.

### `/file`

The `/file` command inserts the content of a single file or a directory of files into the context. This allows you to reference specific parts of your project in your conversation with the assistant.

Usage: `/file <path>`

You can use glob patterns to match multiple files or directories.

Examples:

- `/file src/index.js` - Inserts the content of `src/index.js` into the context.
- `/file src/*.js` - Inserts the content of all `.js` files in the `src` directory.
- `/file src` - Inserts the content of all files in the `src` directory.

### `/now`

The `/now` command inserts the current date and time into the context. This can be useful letting the language model know the current time (and by extension, how old their current knowledge base is).

Usage: `/now`

### `/prompt`

The `/prompt` command inserts a prompt from the prompt library into the context. It can also be used to nest prompts within prompts.

Usage: `/prompt <prompt_name>`

Related: `/default`

### `/symbols`

The `/symbols` command inserts the active symbols (functions, classes, etc.) from the current tab into the context. This is useful for getting an overview of the structure of the current file.

Usage: `/symbols`

### `/tab`

The `/tab` command inserts the content of the active tab or all open tabs into the context. This allows you to reference the content you're currently working on.

Usage: `/tab [tab_name|all]`

- `tab_name`: Optional name of a specific tab to insert.
- `all`: Insert content from all open tabs.

Examples:

- `/tab` - Inserts the content of the active tab.
- `/tab "index.js"` - Inserts the content of the tab named "index.js".
- `/tab all` - Inserts the content of all open tabs.

### `/terminal`

The `/terminal` command inserts a select number of lines of output from the terminal into the context. This is useful for referencing recent command outputs or logs.

Usage: `/terminal [<number>]`

- `<number>`: Optional parameter to specify the number of lines to insert (default is a 50).

### `/selection`

The `/selection` command inserts the selected text in the editor into the context. This is useful for referencing specific parts of your code.

This is equivalent to the `agent: quote selection` command ({#kb agent::QuoteSelection}).

Usage: `/selection`

## Commands in the Rules Library {#slash-commands-in-rules}

[Commands](#commands) can be used in rules, in the Rules Library (previously known as Prompt Library), to insert dynamic content or perform actions.
For example, if you want to create a rule where it is important for the model to know the date, you can use the `/now` command to insert the current date.

> **Warn:** Slash commands in rules **only** work when they are used in text threads. Using them in non-text threads is not supported.

> **Note:** Slash commands in rules **must** be on their own line.

See the [list of commands](#commands) above for more information on commands, and what slash commands are available.

### Example

```plaintext
You are an expert Rust engineer. The user has asked you to review their project and answer some questions.

Here is some information about their project:

/file Cargo.toml
```

In the above example, the `@file` command is used to insert the contents of the `Cargo.toml` file (or all `Cargo.toml` files present in the project) into the rule.

## Nesting Rules

Similar to adding rules to the default rules, you can nest rules within other rules with the `/prompt` command (only supported in Text Threads currently).

You might want to nest rules to:

- Create templates on the fly
- Break collections like docs or references into smaller, mix-and-matchable parts
- Create variants of a similar rule (e.g., `Async Rust - Tokio` vs. `Async Rust - Async-std`)

### Example:

```plaintext
Title: Zed-Flavored Rust

## About Zed

/prompt Zed: Zed (a rule about what Zed is)

## Rust - Zed Style

/prompt Rust: Async - Async-std (zed doesn't use tokio)
/prompt Rust: Zed-style Crates (we have some unique conventions)
/prompt Rust - Workspace deps (bias towards reusing deps from the workspace)
```

_The text in parentheses above are comments and are not part of the rule._

> **Note:** While you technically _can_ nest a rule within itself, we wouldn't recommend it (in the strongest of terms.) Use at your own risk!

By using nested rules, you can create modular and reusable rule components that can be combined in various ways to suit different scenarios.

> **Note:** When using slash commands to bring in additional context, the injected content can be edited directly inline in the text thread—edits here will not propagate to the saved rules.

## Extensibility

Additional slash commands can be provided by extensions.

See [Extension: Slash Commands](../extensions/slash-commands.md) to learn how to create your own.

## Advanced Concepts

### Rule Templates {#rule-templates}

Zed uses rule templates to power internal assistant features, like the terminal assistant, or the content rules used in the inline assistant.

Zed has the following internal rule templates:

- `content_prompt.hbs`: Used for generating content in the editor.
- `terminal_assistant_prompt.hbs`: Used for the terminal assistant feature.

At this point it is unknown if we will expand templates further to be user-creatable.

### Overriding Templates

> **Note:** It is not recommended to override templates unless you know what you are doing. Editing templates will break your assistant if done incorrectly.

Zed allows you to override the default rules used for various assistant features by placing custom Handlebars (.hbs) templates in your `~/.config/zed/prompt_overrides` directory.

The following templates can be overridden:

1. [`content_prompt.hbs`](https://github.com/zed-industries/zed/tree/main/assets/prompts/content_prompt.hbs): Used for generating content in the editor.

2. [`terminal_assistant_prompt.hbs`](https://github.com/zed-industries/zed/tree/main/assets/prompts/terminal_assistant_prompt.hbs): Used for the terminal assistant feature.

> **Note:** Be sure you want to override these, as you'll miss out on iteration on our built-in features. This should be primarily used when developing Zed.

You can customize these templates to better suit your needs while maintaining the core structure and variables used by Zed. Zed will automatically reload your prompt overrides when they change on disk.

Consult Zed's [assets/prompts](https://github.com/zed-industries/zed/tree/main/assets/prompts) directory for current versions you can play with.

### History {#history}

After you submit your first message in a text thread, a name for your context is generated by the language model, and the context is automatically saved to your file system in

- `~/.config/zed/conversations` (macOS)
- `~/.local/share/zed/conversations` (Linux)
- `%LocalAppData%\Zed\conversations` (Windows)

You can access and load previous contexts by clicking on the history button in the top-left corner of the agent panel.

![Viewing assistant history](https://zed.dev/img/assistant/assistant-history.png)

    # Tools

Zed's Agent has access to a variety of tools that allow it to interact with your codebase and perform tasks.

## Read & Search Tools

### `diagnostics`

Gets errors and warnings for either a specific file or the entire project, useful after making edits to determine if further changes are needed.

### `fetch`

Fetches a URL and returns the content as Markdown. Useful for providing docs as context.

### `find_path`

Quickly finds files by matching glob patterns (like "\*_/_.js"), returning matching file paths alphabetically.

### `grep`

Searches file contents across the project using regular expressions, preferred for finding symbols in code without knowing exact file paths.

### `list_directory`

Lists files and directories in a given path, providing an overview of filesystem contents.

### `now`

Returns the current date and time.

### `open`

Opens a file or URL with the default application associated with it on the user's operating system.

### `read_file`

Reads the content of a specified file in the project, allowing access to file contents.

### `thinking`

Allows the Agent to work through problems, brainstorm ideas, or plan without executing actions, useful for complex problem-solving.

### `web_search`

Searches the web for information, providing results with snippets and links from relevant web pages, useful for accessing real-time information.

## Edit Tools

### `copy_path`

Copies a file or directory recursively in the project, more efficient than manually reading and writing files when duplicating content.

### `create_directory`

Creates a new directory at the specified path within the project, creating all necessary parent directories (similar to `mkdir -p`).

### `create_file`

Creates a new file at a specified path with given text content, the most efficient way to create new files or completely replace existing ones.

### `delete_path`

Deletes a file or directory (including contents recursively) at the specified path and confirms the deletion.

### `edit_file`

Edits files by replacing specific text with new content.

### `move_path`

Moves or renames a file or directory in the project, performing a rename if only the filename differs.

### `terminal`

Executes shell commands and returns the combined output, creating a new shell process for each invocation.

    ## All Actions

{#ACTIONS_TABLE#}

    # Channels

At Zed we believe that great things are built by great people working together. We have designed Zed to help every individual work faster and to help teams of people work together more effectively.

## Overview

Channels provide a way to streamline collaborating for software engineers in many ways, but particularly:

- Pairing – when working on something together, you both have your own screen, mouse, and keyboard.
- Mentoring – it’s easy to jump in to someone else’s context, and help them get unstuck, without the friction of pushing code up.
- Refactoring – you can have multiple people join in on large refactoring without fear of conflict.
- Ambient awareness – you can see what everyone else is working on with no need for status emails or meetings.

## Channels

To open the collaboration panel hit {#kb collab_panel::ToggleFocus} or `collab panel: toggle focus`.

Each channel corresponds to an ongoing project or work-stream. You can see who’s in a channel as their avatars will show up in the sidebar. This makes it easy to see what everyone is doing and where to find them if needed.

You can create as many channels as you need. As in the example above, you can mix channels for your day job, as well as side-projects in one instance of Zed.

Joining a channel adds you to a shared room where you can work on projects together.

## Sharing projects

After joining a channel, you can `Share` a project with the other people there. This will enable them to edit the code hosted on your machine as though they had it checked out locally.

When you are editing someone else’s project, you still have the full power of the editor at your fingertips, you can jump to definitions, use the AI assistant, and see any diagnostic errors. This is extremely powerful for pairing, as one of you can be implementing the current method while the other is reading and researching the correct solution to the next problem. And, because you have your own config running, it feels like you’re using your own machine.

See [our collaboration documentation](./collaboration.md) for more details about how this works.

## Notes

Each channel has a notes file associated with it to keep track of current status, new ideas, or to collaborate on building out the design for the feature that you’re working on before diving into code.

This is similar to a Google Doc, except powered by Zed's collaborative software and persisted to our servers.

## Chat

The chat is also there for quickly sharing context without a microphone, getting questions answered, or however else you'd want to use a chat channel.

## Inviting people

By default, channels you create can only be accessed by you. You can invite collaborators by right clicking and selecting `Manage members`.

When you have channels nested under each other, permissions are inherited. For instance, in the example above, we only need to add people to the `#zed` channel, and they will automatically gain access to `#core-editor`, `#new-languages`, and `#stability`.

Once you have added someone, they can either join your channel by clicking on it in their Zed sidebar, or you can share the link to the channel so that they can join directly.

## Livestreaming & Guests

A Channel can also be made Public. This allows anyone to join the channel by clicking on the link.

Guest users in channels can hear and see everything that is happening, and have read only access to projects and channel notes. They can use the Chat as normal.

If you'd like to invite a guest to participate in a channel for the duration of a call you can do so by right clicking on them in the Collaboration Panel. "Allowing Write Access" will allow them to edit any projects shared into the call, and to use their microphone and share their screen if they wish.

    # Collaboration

Only collaborate with people that you trust. Since sharing a project gives them access to your local file system, you should not share projects with people you do not trust; they could potentially do some nasty things.

In the future, we will do more to prevent this type of access beyond the shared project and add more control over what collaborators can do, but for now, only collaborate with people you trust.

## Adding a collaborator to a call

Before you can collaborate, you'll need to add a collaborator to your contacts. To do this:

1. Open the contacts menu by clicking on the `Show contacts menu` button in the upper right-hand corner of the window or by running `collab: toggle contacts menu` (`cmd-shift-c`).
2. Click the add button to the right of the search box.
3. Search for the contact you want to add using their GitHub handle. Note: the person you are trying to add as a contact must be an existing Zed user.

### Inviting a collaborator

You can add an existing Zed user as a contact from the contacts menu, deployed from the `Show contacts menu` button in the upper right-hand corner of the window or by `collab: toggle contacts menu` (`cmd-shift-c`) and then clicking the `Search for new contact` button to the right of the search box.

![Inviting a collaborator to the current project](https://zed.dev/img/collaboration/add-a-collaborator.png)

When you invite a collaborator to a project not in a call they will receive a notification to join, and a new call is created.

![Receiving an invite to join a call](https://zed.dev/img/collaboration/receiving-an-invite.jpg)

### Inviting non-Zed users

If someone you want to collaborate with has not yet signed up for Zed, they will need to [download the app](https://zed.dev/download) and sign in for the first time before you can add them. Identity is tied to GitHub accounts, so new users will need to authenticate with GitHub in order to sign into Zed.

### Voice chat

When joining a call, Zed will automatically share your microphone with other users in the call, if your OS allows it. This isn't tied to your project. You can disable this for your client via the [`mute_on_join`](./configuring-zed.md#calls) setting.

## Collaborating on a project

### Share a project

When you invite a collaborator to join your project, a new call begins. Your Zed windows will show the call participants in the title bar of the window.

![A new Zed call with two collaborators](https://zed.dev/img/collaboration/new-call.png)

Collaborators in the same project as you are in color, and have a cursor color. Collaborators in other projects are shown in gray. Collaborators that have access to the current project will have their own cursor color under their avatar.

We aim to eliminate the distinction between local and remote projects as much as possible. Collaborators can open, edit, and save files, perform searches, interact with the language server, etc. Guests have a read-only view of the project, including access to language server info.

#### Unshared Projects

If a collaborator is currently in a project that is not shared, you will not be able to jump to their project or follow them until they either share the project or return to a project that is shared.

If you are in a project that isn't shared, others will not be able to join it or see its contents.

### Follow a collaborator

To follow a collaborator, click on their avatar in the top right of the window. You can also cycle through collaborators using `workspace: follow next collaborator` (`ctrl-alt-cmd-f`).

When you join a project, you'll immediately start following the collaborator that invited you.

![Automatically following the person inviting us to a project](https://zed.dev/img/collaboration/joining-a-call.png)

When you are in a pane that is following a collaborator, you will:

- follow their cursor and scroll position
- follow them to other files in the same project
- instantly swap to viewing their screen in that pane, if they are sharing their screen and leave the project

If you move your cursor or make an edit in that pane, you will stop following.

To start following again, you can click on a collaborator's avatar or cycle through following different participants by pressing `workspace: follow next collaborator` (`ctrl-alt-cmd-f`).

#### How following works

Following is confined to a particular pane. When a pane is following a collaborator, it is outlined in their cursor color.

This pane-specific behavior allows you to follow someone in one pane while navigating independently in another and can be an effective layout for some collaboration styles.

### Sharing your screen

Share your screen with collaborators in the current call by clicking on the `Share screen` button in the top right of the window.

Collaborators will see your screen if they are following you and you start viewing a window outside Zed or a project that is not shared.

Collaborators can see your entire screen when you are screen sharing, so be careful not to share anything you don't want to share. Remember to stop screen sharing when you are finished.

Call participants can open a dedicated tab for your screen share by opening the contacts menu in the top right and clicking on the `Screen` entry if you are sharing your screen.

### Adding a project

You can add a project to a call by clicking on the `Share` button next to the project name in the title bar.

### Removing a project

You can remove a project from a call by clicking on the `Unshare` button next to the project name in the title bar.

Collaborators that are currently in that project will be disconnected from the project and will not be able to rejoin it unless you share it again.

### Following a collaborator's terminal

You can follow what a collaborator is doing in their terminal by having them share their screen and following it.

In the future, we plan to allow you to collaborate in the terminal directly in a shared project.

### Leave call

You can leave a call by opening the contacts menu in the top right and clicking on the `Leave call` button.

    # Completions

Zed supports two sources for completions:

1. "Code Completions" provided by Language Servers (LSPs) automatically installed by Zed or via [Zed Language Extensions](languages.md).
2. "Edit Predictions" provided by Zed's own Zeta model or by external providers like [GitHub Copilot](#github-copilot) or [Supermaven](#supermaven).

## Language Server Code Completions {#code-completions}

When there is an appropriate language server available, Zed will provide completions of variable names, functions, and other symbols in the current file. You can disable these by adding the following to your Zed `settings.json` file:

```json
"show_completions_on_input": false
```

You can manually trigger completions with `ctrl-space` or by triggering the `editor::ShowCompletions` action from the command palette.

For more information, see:

- [Configuring Supported Languages](./configuring-languages.md)
- [List of Zed Supported Languages](./languages.md)

## Edit Predictions {#edit-predictions}

Zed has built-in support for predicting multiple edits at a time [via Zeta](https://huggingface.co/zed-industries/zeta), Zed's open-source and open-data model.
Edit predictions appear as you type, and most of the time, you can accept them by pressing `tab`.

See the [edit predictions documentation](./ai/edit-prediction.md) for more information on how to setup and configure Zed's edit predictions.

    # Configuring supported languages

Zed offers powerful customization options for each programming language it supports. This guide will walk you through the various ways you can tailor your coding experience to your preferences and project requirements.

Zed's language support is built on two main technologies:

1. Tree-sitter: This handles syntax highlighting and structure-based features like the outline panel.
2. Language Server Protocol (LSP): This provides semantic features such as code completion and diagnostics.

These components work together to provide Zed's language capabilities.

In this guide, we'll cover:

- Language-specific settings
- File associations
- Working with language servers
- Formatting and linting configuration
- Customizing syntax highlighting and themes
- Advanced language features

By the end of this guide, you should know how to configure and customize supported languages in Zed.

For a comprehensive list of languages supported by Zed and their specific configurations, see our [Supported Languages](./languages.md) page. To go further, you could explore developing your own extensions to add support for additional languages or enhance existing functionality. For more information on creating language extensions, see our [Language Extensions](./extensions/languages.md) guide.

## Language-specific Settings

Zed allows you to override global settings for individual languages. These custom configurations are defined in your `settings.json` file under the `languages` key.

Here's an example of language-specific settings:

```json
"languages": {
  "Python": {
    "tab_size": 4,
    "formatter": "language_server",
    "format_on_save": "on"
  },
  "JavaScript": {
    "tab_size": 2,
    "formatter": {
      "external": {
        "command": "prettier",
        "arguments": ["--stdin-filepath", "{buffer_path}"]
      }
    }
  }
}
```

You can customize a wide range of settings for each language, including:

- [`tab_size`](./configuring-zed.md#tab-size): The number of spaces for each indentation level
- [`formatter`](./configuring-zed.md#formatter): The tool used for code formatting
- [`format_on_save`](./configuring-zed.md#format-on-save): Whether to automatically format code when saving
- [`enable_language_server`](./configuring-zed.md#enable-language-server): Toggle language server support
- [`hard_tabs`](./configuring-zed.md#hard-tabs): Use tabs instead of spaces for indentation
- [`preferred_line_length`](./configuring-zed.md#preferred-line-length): The recommended maximum line length
- [`soft_wrap`](./configuring-zed.md#soft-wrap): How to wrap long lines of code
- [`show_completions_on_input`](./configuring-zed.md#show-completions-on-input): Whether or not to show completions as you type
- [`show_completion_documentation`](./configuring-zed.md#show-completion-documentation): Whether to display inline and alongside documentation for items in the completions menu

These settings allow you to maintain specific coding styles across different languages and projects.

## File Associations

Zed automatically detects file types based on their extensions, but you can customize these associations to fit your workflow.

To set up custom file associations, use the [`file_types`](./configuring-zed.md#file-types) setting in your `settings.json`:

```json
"file_types": {
  "C++": ["c"],
  "TOML": ["MyLockFile"],
  "Dockerfile": ["Dockerfile*"]
}
```

This configuration tells Zed to:

- Treat `.c` files as C++ instead of C
- Recognize files named "MyLockFile" as TOML
- Apply Dockerfile syntax to any file starting with "Dockerfile"

You can use glob patterns for more flexible matching, allowing you to handle complex naming conventions in your projects.

## Working with Language Servers

Language servers are a crucial part of Zed's intelligent coding features, providing capabilities like auto-completion, go-to-definition, and real-time error checking.

### What are Language Servers?

Language servers implement the Language Server Protocol (LSP), which standardizes communication between the editor and language-specific tools. This allows Zed to support advanced features for multiple programming languages without implementing each feature separately.

Some key features provided by language servers include:

- Code completion
- Error checking and diagnostics
- Code navigation (go to definition, find references)
- Code actions (Rename, extract method)
- Hover information
- Workspace symbol search

### Managing Language Servers

Zed simplifies language server management for users:

1. Automatic Download: When you open a file with a matching file type, Zed automatically downloads the appropriate language server. Zed may prompt you to install an extension for known file types.

2. Storage Location:

   - macOS: `~/Library/Application Support/Zed/languages`
   - Linux: `$XDG_DATA_HOME/languages`, `$FLATPAK_XDG_DATA_HOME/languages`, or `$HOME/.local/share`

3. Automatic Updates: Zed keeps your language servers up-to-date, ensuring you always have the latest features and improvements.

### Choosing Language Servers

Some languages in Zed offer multiple language server options. You might have multiple extensions installed that bundle language servers targeting the same language, potentially leading to overlapping capabilities. To ensure you get the functionality you prefer, Zed allows you to prioritize which language servers are used and in what order.

You can specify your preference using the `language_servers` setting:

```json
  "languages": {
    "PHP": {
      "language_servers": ["intelephense", "!phpactor", "..."]
    }
  }
```

In this example:

- `intelephense` is set as the primary language server
- `phpactor` is disabled (note the `!` prefix)
- `...` expands to the rest of the language servers that are registered for PHP

This configuration allows you to tailor the language server setup to your specific needs, ensuring that you get the most suitable functionality for your development workflow.

### Toolchains

Some language servers need to be configured with a current "toolchain", which is an installation of a specific version of a programming language compiler or/and interpreter, which can possibly include a full set of dependencies of a project.
An example of what Zed considers a toolchain is a virtual environment in Python.
Not all languages in Zed support toolchain discovery and selection, but for those that do, you can specify the toolchain from a toolchain picker (via {#action toolchain::Select}). To learn more about toolchains in Zed, see [`toolchains`](./toolchains.md).

### Configuring Language Servers

Many language servers accept custom configuration options. You can set these in the `lsp` section of your `settings.json`:

```json
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "check": {
          "command": "clippy"
        }
      }
    }
  }
```

This example configures the Rust Analyzer to use Clippy for additional linting when saving files.

#### Nested objects

When configuring language server options in Zed, it's important to use nested objects rather than dot-delimited strings. This is particularly relevant when working with more complex configurations. Let's look at a real-world example using the TypeScript language server:

Suppose you want to configure the following settings for TypeScript:

- Enable strict null checks
- Set the target ECMAScript version to ES2020

Here's how you would structure these settings in Zed's `settings.json`:

```json
"lsp": {
  "typescript-language-server": {
    "initialization_options": {
      // These are not supported (VSCode dotted style):
      // "preferences.strictNullChecks": true,
      // "preferences.target": "ES2020"
      //
      // These is correct (nested notation):
      "preferences": {
        "strictNullChecks": true,
        "target": "ES2020"
      },
    }
  }
}
```

#### Possible configuration options

Depending on how a particular language server is implemented, they may depend on different configuration options, both specified in the LSP.

- [initializationOptions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#version_3_17_0)

Sent once during language server startup, requires server's restart to reapply changes.

For example, rust-analyzer and clangd rely on this way of configuring only.

```json
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "checkOnSave": false
      }
    }
  }
```

- [Configuration Request](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration)

May be queried by the server multiple times.
Most of the servers would rely on this way of configuring only.

```json
"lsp": {
  "tailwindcss-language-server": {
    "settings": {
      "tailwindCSS": {
        "emmetCompletions": true,
      },
    }
  }
}
```

Apart of the LSP-related server configuration options, certain servers in Zed allow configuring the way binary is launched by Zed.

Language servers are automatically downloaded or launched if found in your path, if you wish to specify an explicit alternate binary you can specify that in settings:

```json
  "lsp": {
    "rust-analyzer": {
      "binary": {
        // Whether to fetch the binary from the internet, or attempt to find locally.
        "ignore_system_version": false,
        "path": "/path/to/langserver/bin",
        "arguments": ["--option", "value"],
        "env": {
          "FOO": "BAR"
        }
      }
    }
  }
```

### Enabling or Disabling Language Servers

You can toggle language server support globally or per-language:

```json
  "languages": {
    "Markdown": {
      "enable_language_server": false
    }
  }
```

This disables the language server for Markdown files, which can be useful for performance in large documentation projects. You can configure this globally in your `~/.config/zed/settings.json` or inside a `.zed/settings.json` in your project directory.

## Formatting and Linting

Zed provides support for code formatting and linting to maintain consistent code style and catch potential issues early.

### Configuring Formatters

Zed supports both built-in and external formatters. See [`formatter`](./configuring-zed.md#formatter) docs for more. You can configure formatters globally or per-language in your `settings.json`:

```json
"languages": {
  "JavaScript": {
    "formatter": {
      "external": {
        "command": "prettier",
        "arguments": ["--stdin-filepath", "{buffer_path}"]
      }
    },
    "format_on_save": "on"
  },
  "Rust": {
    "formatter": "language_server",
    "format_on_save": "on"
  }
}
```

This example uses Prettier for JavaScript and the language server's formatter for Rust, both set to format on save.

To disable formatting for a specific language:

```json
"languages": {
  "Markdown": {
    "format_on_save": "off"
  }
}
```

### Setting Up Linters

Linting in Zed is typically handled by language servers. Many language servers allow you to configure linting rules:

```json
"lsp": {
  "eslint": {
    "settings": {
      "codeActionOnSave": {
        "rules": ["import/order"]
      }
    }
  }
}
```

This configuration sets up ESLint to organize imports on save for JavaScript files.

To run linter fixes automatically on save:

```json
"languages": {
  "JavaScript": {
    "code_actions_on_format": {
      "source.fixAll.eslint": true
    }
  }
}
```

### Integrating Formatting and Linting

Zed allows you to run both formatting and linting on save. Here's an example that uses Prettier for formatting and ESLint for linting JavaScript files:

```json
"languages": {
  "JavaScript": {
    "formatter": {
      "external": {
        "command": "prettier",
        "arguments": ["--stdin-filepath", "{buffer_path}"]
      }
    },
    "code_actions_on_format": {
      "source.fixAll.eslint": true
    },
    "format_on_save": "on"
  }
}
```

### Troubleshooting

If you encounter issues with formatting or linting:

1. Check Zed's log file for error messages (Use the command palette: `zed: open log`)
2. Ensure external tools (formatters, linters) are correctly installed and in your PATH
3. Verify configurations in both Zed settings and language-specific config files (e.g., `.eslintrc`, `.prettierrc`)

## Syntax Highlighting and Themes

Zed offers customization options for syntax highlighting and themes, allowing you to tailor the visual appearance of your code.

### Customizing Syntax Highlighting

Zed uses Tree-sitter grammars for syntax highlighting. Override the default highlighting using the `experimental.theme_overrides` setting.

This example makes comments italic and changes the color of strings:

```json
"experimental.theme_overrides": {
  "syntax": {
    "comment": {
      "font_style": "italic"
    },
    "string": {
      "color": "#00AA00"
    }
  }
}
```

### Selecting and Customizing Themes

Change your theme:

1. Use the theme selector ({#kb theme_selector::Toggle})
2. Or set it in your `settings.json`:

```json
"theme": {
  "mode": "dark",
  "dark": "One Dark",
  "light": "GitHub Light"
}
```

Create custom themes by creating a JSON file in `~/.config/zed/themes/`. Zed will automatically detect and make available any themes in this directory.

### Using Theme Extensions

Zed supports theme extensions. Browse and install theme extensions from the Extensions panel ({#kb zed::Extensions}).

To create your own theme extension, refer to the [Developing Theme Extensions](./extensions/themes.md) guide.

## Using Language Server Features

### Inlay Hints

Inlay hints provide additional information inline in your code, such as parameter names or inferred types. Configure inlay hints in your `settings.json`:

```json
"inlay_hints": {
  "enabled": true,
  "show_type_hints": true,
  "show_parameter_hints": true,
  "show_other_hints": true
}
```

For language-specific inlay hint settings, refer to the documentation for each language.

### Code Actions

Code actions provide quick fixes and refactoring options. Access code actions using the `editor: Toggle Code Actions` command or by clicking the lightbulb icon that appears next to your cursor when actions are available.

### Go To Definition and References

Use these commands to navigate your codebase:

- `editor: Go to Definition` (<kbd>f12|f12</kbd>)
- `editor: Go to Type Definition` (<kbd>cmd-f12|ctrl-f12</kbd>)
- `editor: Find All References` (<kbd>shift-f12|shift-f12</kbd>)

### Rename Symbol

To rename a symbol across your project:

1. Place your cursor on the symbol
2. Use the `editor: Rename Symbol` command (<kbd>f2|f2</kbd>)
3. Enter the new name and press Enter

These features depend on the capabilities of the language server for each language.

When renaming a symbol that spans multiple files, Zed will open a preview in a multibuffer. This allows you to review all the changes across your project before applying them. To confirm the rename, simply save the multibuffer. If you decide not to proceed with the rename, you can undo the changes or close the multibuffer without saving.

### Hover Information

Use the `editor: Hover` command to display information about the symbol under the cursor. This often includes type information, documentation, and links to relevant resources.

### Workspace Symbol Search

The `workspace: Open Symbol` command allows you to search for symbols (functions, classes, variables) across your entire project. This is useful for quickly navigating large codebases.

### Code Completion

Zed provides intelligent code completion suggestions as you type. You can manually trigger completion with the `editor: Show Completions` command. Use <kbd>tab|tab</kbd> or <kbd>enter|enter</kbd> to accept suggestions.

### Diagnostics

Language servers provide real-time diagnostics (errors, warnings, hints) as you code. View all diagnostics for your project using the `diagnostics: Toggle` command.

    # Configuring Zed

Zed is designed to be configured: we want to fit your workflow and preferences exactly. We provide default settings that are designed to be a comfortable starting point for as many people as possible, but we hope you will enjoy tweaking it to make it feel incredible.

In addition to the settings described here, you may also want to change your [theme](./themes.md), configure your [key bindings](./key-bindings.md), set up [tasks](./tasks.md) or install [extensions](https://github.com/zed-industries/extensions).

## Settings files

<!--
TBD: Settings files. Rewrite with "remote settings" in mind (e.g. `local settings` on the remote host).
Consider renaming `zed: Open Local Settings` to `zed: Open Project Settings`.

TBD: Add settings documentation about how settings are merged as overlays. E.g. project>local>default. Note how settings that are maps are merged, but settings that are arrays are replaced and must include the defaults.
-->

Your settings file can be opened with {#kb zed::OpenSettings}. By default it is located at `~/.config/zed/settings.json`, though if you have XDG_CONFIG_HOME in your environment on Linux it will be at `$XDG_CONFIG_HOME/zed/settings.json` instead.

This configuration is merged with any local configuration inside your projects. You can open the project settings by running {#action zed::OpenProjectSettings} from the command palette. This will create a `.zed` directory containing`.zed/settings.json`.

Although most projects will only need one settings file at the root, you can add more local settings files for subdirectories as needed. Not all settings can be set in local files, just those that impact the behavior of the editor and language tooling. For example you can set `tab_size`, `formatter` etc. but not `theme`, `vim_mode` and similar.

The syntax for configuration files is a super-set of JSON that allows `//` comments.

## Default settings

You can find the default settings for your current Zed by running {#action zed::OpenDefaultSettings} from the command palette.

Extensions that provide language servers may also provide default settings for those language servers.

# Settings

## Active Pane Modifiers

- Description: Styling settings applied to the active pane.
- Setting: `active_pane_modifiers`
- Default:

```json
{
  "active_pane_modifiers": {
    "border_size": 0.0,
    "inactive_opacity": 1.0
  }
}
```

### Border size

- Description: Size of the border surrounding the active pane. When set to 0, the active pane doesn't have any border. The border is drawn inset.
- Setting: `border_size`
- Default: `0.0`

**Options**

Non-negative `float` values

### Inactive Opacity

- Description: Opacity of inactive panels. When set to 1.0, the inactive panes have the same opacity as the active one. If set to 0, the inactive panes content will not be visible at all. Values are clamped to the [0.0, 1.0] range.
- Setting: `inactive_opacity`
- Default: `1.0`

**Options**

`float` values

## Bottom Dock Layout

- Description: Control the layout of the bottom dock, relative to the left and right docks
- Setting: `bottom_dock_layout`
- Default: `"contained"`

**Options**

1. Contain the bottom dock, giving the full height of the window to the left and right docks

```json
{
  "bottom_dock_layout": "contained"
}
```

2. Give the bottom dock the full width of the window, truncating the left and right docks

```json
{
  "bottom_dock_layout": "full"
}
```

3. Left align the bottom dock, truncating the left dock and giving the right dock the full height of the window

```json
{
  "bottom_dock_layout": "left_aligned"
}
```

3. Right align the bottom dock, giving the left dock the full height of the window and truncating the right dock.

```json
{
  "bottom_dock_layout": "right_aligned"
}
```

## Agent Font Size

- Description: The font size for text in the agent panel. Inherits the UI font size if unset.
- Setting: `agent_font_size`
- Default: `null`

**Options**

`integer` values from `6` to `100` pixels (inclusive)

## Allow Rewrap

- Description: Controls where the {#action editor::Rewrap} action is allowed in the current language scope
- Setting: `allow_rewrap`
- Default: `"in_comments"`

**Options**

1. Allow rewrap in comments only:

```json
{
  "allow_rewrap": "in_comments"
}
```

2. Allow rewrap everywhere:

```json
{
  "allow_rewrap": "everywhere"
}
```

3. Never allow rewrap:

```json
{
  "allow_rewrap": "never"
}
```

Note: This setting has no effect in Vim mode, as rewrap is already allowed everywhere.

## Auto Indent

- Description: Whether indentation should be adjusted based on the context whilst typing. This can be specified on a per-language basis.
- Setting: `auto_indent`
- Default: `true`

**Options**

`boolean` values

## Auto Indent On Paste

- Description: Whether indentation of pasted content should be adjusted based on the context
- Setting: `auto_indent_on_paste`
- Default: `true`

**Options**

`boolean` values

## Auto Install extensions

- Description: Define extensions to be autoinstalled or never be installed.
- Setting: `auto_install_extension`
- Default: `{ "html": true }`

**Options**

You can find the names of your currently installed extensions by listing the subfolders under the [extension installation location](./extensions/installing-extensions.md#installation-location):

On macOS:

```sh
ls ~/Library/Application\ Support/Zed/extensions/installed/
```

On Linux:

```sh
ls ~/.local/share/zed/extensions/installed
```

Define extensions which should be installed (`true`) or never installed (`false`).

```json
{
  "auto_install_extensions": {
    "html": true,
    "dockerfile": true,
    "docker-compose": false
  }
}
```

## Autosave

- Description: When to automatically save edited buffers.
- Setting: `autosave`
- Default: `off`

**Options**

1. To disable autosave, set it to `off`:

```json
{
  "autosave": "off"
}
```

2. To autosave when focus changes, use `on_focus_change`:

```json
{
  "autosave": "on_focus_change"
}
```

3. To autosave when the active window changes, use `on_window_change`:

```json
{
  "autosave": "on_window_change"
}
```

4. To autosave after an inactivity period, use `after_delay`:

```json
{
  "autosave": {
    "after_delay": {
      "milliseconds": 1000
    }
  }
}
```

Note that a save will be triggered when an unsaved tab is closed, even if this is earlier than the configured inactivity period.

## Autoscroll on Clicks

- Description: Whether to scroll when clicking near the edge of the visible text area.
- Setting: `autoscroll_on_clicks`
- Default: `false`

**Options**

`boolean` values

## Auto Signature Help

- Description: Show method signatures in the editor, when inside parentheses
- Setting: `auto_signature_help`
- Default: `false`

**Options**

`boolean` values

### Show Signature Help After Edits

- Description: Whether to show the signature help after completion or a bracket pair inserted. If `auto_signature_help` is enabled, this setting will be treated as enabled also.
- Setting: `show_signature_help_after_edits`
- Default: `false`

**Options**

`boolean` values

## Auto Update

- Description: Whether or not to automatically check for updates.
- Setting: `auto_update`
- Default: `true`

**Options**

`boolean` values

## Base Keymap

- Description: Base key bindings scheme. Base keymaps can be overridden with user keymaps.
- Setting: `base_keymap`
- Default: `VSCode`

**Options**

1. VS Code

```json
{
  "base_keymap": "VSCode"
}
```

2. Atom

```json
{
  "base_keymap": "Atom"
}
```

3. JetBrains

```json
{
  "base_keymap": "JetBrains"
}
```

4. None

```json
{
  "base_keymap": "None"
}
```

5. Sublime Text

```json
{
  "base_keymap": "SublimeText"
}
```

6. TextMate

```json
{
  "base_keymap": "TextMate"
}
```

## Buffer Font Family

- Description: The name of a font to use for rendering text in the editor.
- Setting: `buffer_font_family`
- Default: `.ZedMono`. This currently aliases to [Lilex](https://lilex.myrt.co).

**Options**

The name of any font family installed on the user's system, or `".ZedMono"`.

## Buffer Font Features

- Description: The OpenType features to enable for text in the editor.
- Setting: `buffer_font_features`
- Default: `null`
- Platform: macOS and Windows.

**Options**

Zed supports all OpenType features that can be enabled or disabled for a given buffer or terminal font, as well as setting values for font features.

For example, to disable font ligatures, add the following to your settings:

```json
{
  "buffer_font_features": {
    "calt": false
  }
}
```

You can also set other OpenType features, like setting `cv01` to `7`:

```json
{
  "buffer_font_features": {
    "cv01": 7
  }
}
```

## Buffer Font Fallbacks

- Description: Set the buffer text's font fallbacks, this will be merged with the platform's default fallbacks.
- Setting: `buffer_font_fallbacks`
- Default: `null`
- Platform: macOS and Windows.

**Options**

For example, to use `Nerd Font` as a fallback, add the following to your settings:

```json
{
  "buffer_font_fallbacks": ["Nerd Font"]
}
```

## Buffer Font Size

- Description: The default font size for text in the editor.
- Setting: `buffer_font_size`
- Default: `15`

**Options**

`integer` values from `6` to `100` pixels (inclusive)

## Buffer Font Weight

- Description: The default font weight for text in the editor.
- Setting: `buffer_font_weight`
- Default: `400`

**Options**

`integer` values between `100` and `900`

## Buffer Line Height

- Description: The default line height for text in the editor.
- Setting: `buffer_line_height`
- Default: `"comfortable"`

**Options**

`"standard"`, `"comfortable"` or `{ "custom": float }` (`1` is compact, `2` is loose)

## Centered Layout

- Description: Configuration for the centered layout mode.
- Setting: `centered_layout`
- Default:

```json
"centered_layout": {
  "left_padding": 0.2,
  "right_padding": 0.2,
}
```

**Options**

The `left_padding` and `right_padding` options define the relative width of the
left and right padding of the central pane from the workspace when the centered layout mode is activated. Valid values range is from `0` to `0.4`.

## Close on File Delete

- Description: Whether to automatically close editor tabs when their corresponding files are deleted from disk.
- Setting: `close_on_file_delete`
- Default: `false`

**Options**

`boolean` values

When enabled, this setting will automatically close tabs for files that have been deleted from the file system. This is particularly useful for workflows involving temporary or scratch files that are frequently created and deleted. When disabled (default), deleted files remain open with a strikethrough through their tab title.

Note: Dirty files (files with unsaved changes) will not be automatically closed even when this setting is enabled, ensuring you don't lose unsaved work.

## Confirm Quit

- Description: Whether or not to prompt the user to confirm before closing the application.
- Setting: `confirm_quit`
- Default: `false`

**Options**

`boolean` values

## Diagnostics Max Severity

- Description: Which level to use to filter out diagnostics displayed in the editor
- Setting: `diagnostics_max_severity`
- Default: `null`

**Options**

1. Allow all diagnostics (default):

```json
{
  "diagnostics_max_severity": null
}
```

2. Show only errors:

```json
{
  "diagnostics_max_severity": "error"
}
```

3. Show errors and warnings:

```json
{
  "diagnostics_max_severity": "warning"
}
```

4. Show errors, warnings, and information:

```json
{
  "diagnostics_max_severity": "information"
}
```

5. Show all including hints:

```json
{
  "diagnostics_max_severity": "hint"
}
```

## Disable AI

- Description: Whether to disable all AI features in Zed
- Setting: `disable_ai`
- Default: `false`

**Options**

`boolean` values

## Direnv Integration

- Description: Settings for [direnv](https://direnv.net/) integration. Requires `direnv` to be installed.
  `direnv` integration make it possible to use the environment variables set by a `direnv` configuration to detect some language servers in `$PATH` instead of installing them.
  It also allows for those environment variables to be used in tasks.
- Setting: `load_direnv`
- Default: `"direct"`

**Options**

There are two options to choose from:

1. `shell_hook`: Use the shell hook to load direnv. This relies on direnv to activate upon entering the directory. Supports POSIX shells and fish.
2. `direct`: Use `direnv export json` to load direnv. This will load direnv directly without relying on the shell hook and might cause some inconsistencies. This allows direnv to work with any shell.

## Double Click In Multibuffer

- Description: What to do when multibuffer is double clicked in some of its excerpts (parts of singleton buffers)
- Setting: `double_click_in_multibuffer`
- Default: `"select"`

**Options**

1. Behave as a regular buffer and select the whole word (default):

```json
{
  "double_click_in_multibuffer": "select"
}
```

2. Open the excerpt clicked as a new buffer in the new tab:

```json
{
  "double_click_in_multibuffer": "open"
}
```

For the case of "open", regular selection behavior can be achieved by holding `alt` when double clicking.

## Drop Target Size

- Description: Relative size of the drop target in the editor that will open dropped file as a split pane (0-0.5). For example, 0.25 means if you drop onto the top/bottom quarter of the pane a new vertical split will be used, if you drop onto the left/right quarter of the pane a new horizontal split will be used.
- Setting: `drop_target_size`
- Default: `0.2`

**Options**

`float` values between `0` and `0.5`

## Edit Predictions

- Description: Settings for edit predictions.
- Setting: `edit_predictions`
- Default:

```json
  "edit_predictions": {
    "disabled_globs": [
      "**/.env*",
      "**/*.pem",
      "**/*.key",
      "**/*.cert",
      "**/*.crt",
      "**/.dev.vars",
      "**/secrets.yml"
    ]
  }
```

**Options**

### Disabled Globs

- Description: A list of globs for which edit predictions should be disabled for. This list adds to a pre-existing, sensible default set of globs. Any additional ones you add are combined with them.
- Setting: `disabled_globs`
- Default: `["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/.dev.vars", "**/secrets.yml"]`

**Options**

List of `string` values.

## Edit Predictions Disabled in

- Description: A list of language scopes in which edit predictions should be disabled.
- Setting: `edit_predictions_disabled_in`
- Default: `[]`

**Options**

List of `string` values

1. Don't show edit predictions in comments:

```json
"disabled_in": ["comment"]
```

2. Don't show edit predictions in strings and comments:

```json
"disabled_in": ["comment", "string"]
```

3. Only in Go, don't show edit predictions in strings and comments:

```json
{
  "languages": {
    "Go": {
      "edit_predictions_disabled_in": ["comment", "string"]
    }
  }
}
```

## Current Line Highlight

- Description: How to highlight the current line in the editor.
- Setting: `current_line_highlight`
- Default: `all`

**Options**

1. Don't highlight the current line:

```json
"current_line_highlight": "none"
```

2. Highlight the gutter area:

```json
"current_line_highlight": "gutter"
```

3. Highlight the editor area:

```json
"current_line_highlight": "line"
```

4. Highlight the full line:

```json
"current_line_highlight": "all"
```

## Selection Highlight

- Description: Whether to highlight all occurrences of the selected text in an editor.
- Setting: `selection_highlight`
- Default: `true`

## Rounded Selection

- Description: Whether the text selection should have rounded corners.
- Setting: `rounded_selection`
- Default: `true`

## Cursor Blink

- Description: Whether or not the cursor blinks.
- Setting: `cursor_blink`
- Default: `true`

**Options**

`boolean` values

## Cursor Shape

- Description: Cursor shape for the default editor.
- Setting: `cursor_shape`
- Default: `bar`

**Options**

1. A vertical bar:

```json
"cursor_shape": "bar"
```

2. A block that surrounds the following character:

```json
"cursor_shape": "block"
```

3. An underline / underscore that runs along the following character:

```json
"cursor_shape": "underline"
```

4. An box drawn around the following character:

```json
"cursor_shape": "hollow"
```

## Gutter

- Description: Settings for the editor gutter
- Setting: `gutter`
- Default:

```json
{
  "gutter": {
    "line_numbers": true,
    "runnables": true,
    "breakpoints": true,
    "folds": true,
    "min_line_number_digits": 4
  }
}
```

**Options**

- `line_numbers`: Whether to show line numbers in the gutter
- `runnables`: Whether to show runnable buttons in the gutter
- `breakpoints`: Whether to show breakpoints in the gutter
- `folds`: Whether to show fold buttons in the gutter
- `min_line_number_digits`: Minimum number of characters to reserve space for in the gutter

## Hide Mouse

- Description: Determines when the mouse cursor should be hidden in an editor or input box.
- Setting: `hide_mouse`
- Default: `on_typing_and_movement`

**Options**

1. Never hide the mouse cursor:

```json
"hide_mouse": "never"
```

2. Hide only when typing:

```json
"hide_mouse": "on_typing"
```

3. Hide on both typing and cursor movement:

```json
"hide_mouse": "on_typing_and_movement"
```

## Snippet Sort Order

- Description: Determines how snippets are sorted relative to other completion items.
- Setting: `snippet_sort_order`
- Default: `inline`

**Options**

1. Place snippets at the top of the completion list:

```json
"snippet_sort_order": "top"
```

2. Place snippets normally without any preference:

```json
"snippet_sort_order": "inline"
```

3. Place snippets at the bottom of the completion list:

```json
"snippet_sort_order": "bottom"
```

4. Do not show snippets in the completion list at all:

```json
"snippet_sort_order": "none"
```

## Editor Scrollbar

- Description: Whether or not to show the editor scrollbar and various elements in it.
- Setting: `scrollbar`
- Default:

```json
"scrollbar": {
  "show": "auto",
  "cursors": true,
  "git_diff": true,
  "search_results": true,
  "selected_text": true,
  "selected_symbol": true,
  "diagnostics": "all",
  "axes": {
    "horizontal": true,
    "vertical": true,
  },
},
```

### Show Mode

- Description: When to show the editor scrollbar.
- Setting: `show`
- Default: `auto`

**Options**

1. Show the scrollbar if there's important information or follow the system's configured behavior:

```json
"scrollbar": {
  "show": "auto"
}
```

2. Match the system's configured behavior:

```json
"scrollbar": {
  "show": "system"
}
```

3. Always show the scrollbar:

```json
"scrollbar": {
  "show": "always"
}
```

4. Never show the scrollbar:

```json
"scrollbar": {
  "show": "never"
}
```

### Cursor Indicators

- Description: Whether to show cursor positions in the scrollbar.
- Setting: `cursors`
- Default: `true`

**Options**

`boolean` values

### Git Diff Indicators

- Description: Whether to show git diff indicators in the scrollbar.
- Setting: `git_diff`
- Default: `true`

**Options**

`boolean` values

### Search Results Indicators

- Description: Whether to show buffer search results in the scrollbar.
- Setting: `search_results`
- Default: `true`

**Options**

`boolean` values

### Selected Text Indicators

- Description: Whether to show selected text occurrences in the scrollbar.
- Setting: `selected_text`
- Default: `true`

**Options**

`boolean` values

### Selected Symbols Indicators

- Description: Whether to show selected symbol occurrences in the scrollbar.
- Setting: `selected_symbol`
- Default: `true`

**Options**

`boolean` values

### Diagnostics

- Description: Which diagnostic indicators to show in the scrollbar.
- Setting: `diagnostics`
- Default: `all`

**Options**

1. Show all diagnostics:

```json
{
  "diagnostics": "all"
}
```

2. Do not show any diagnostics:

```json
{
  "diagnostics": "none"
}
```

3. Show only errors:

```json
{
  "diagnostics": "error"
}
```

4. Show only errors and warnings:

```json
{
  "diagnostics": "warning"
}
```

5. Show only errors, warnings, and information:

```json
{
  "diagnostics": "information"
}
```

### Axes

- Description: Forcefully enable or disable the scrollbar for each axis
- Setting: `axes`
- Default:

```json
"scrollbar": {
  "axes": {
    "horizontal": true,
    "vertical": true,
  },
}
```

#### Horizontal

- Description: When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
- Setting: `horizontal`
- Default: `true`

**Options**

`boolean` values

#### Vertical

- Description: When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
- Setting: `vertical`
- Default: `true`

**Options**

`boolean` values

## Minimap

- Description: Settings related to the editor's minimap, which provides an overview of your document.
- Setting: `minimap`
- Default:

```json
{
  "minimap": {
    "show": "never",
    "thumb": "always",
    "thumb_border": "left_open",
    "current_line_highlight": null
  }
}
```

### Show Mode

- Description: When to show the minimap in the editor.
- Setting: `show`
- Default: `never`

**Options**

1. Always show the minimap:

```json
{
  "show": "always"
}
```

2. Show the minimap if the editor's scrollbars are visible:

```json
{
  "show": "auto"
}
```

3. Never show the minimap:

```json
{
  "show": "never"
}
```

### Thumb Display

- Description: When to show the minimap thumb (the visible editor area) in the minimap.
- Setting: `thumb`
- Default: `always`

**Options**

1. Show the minimap thumb when hovering over the minimap:

```json
{
  "thumb": "hover"
}
```

2. Always show the minimap thumb:

```json
{
  "thumb": "always"
}
```

### Thumb Border

- Description: How the minimap thumb border should look.
- Setting: `thumb_border`
- Default: `left_open`

**Options**

1. Display a border on all sides of the thumb:

```json
{
  "thumb_border": "full"
}
```

2. Display a border on all sides except the left side:

```json
{
  "thumb_border": "left_open"
}
```

3. Display a border on all sides except the right side:

```json
{
  "thumb_border": "right_open"
}
```

4. Display a border only on the left side:

```json
{
  "thumb_border": "left_only"
}
```

5. Display the thumb without any border:

```json
{
  "thumb_border": "none"
}
```

### Current Line Highlight

- Description: How to highlight the current line in the minimap.
- Setting: `current_line_highlight`
- Default: `null`

**Options**

1. Inherit the editor's current line highlight setting:

```json
{
  "minimap": {
    "current_line_highlight": null
  }
}
```

2. Highlight the current line in the minimap:

```json
{
  "minimap": {
    "current_line_highlight": "line"
  }
}
```

or

```json
{
  "minimap": {
    "current_line_highlight": "all"
  }
}
```

3. Do not highlight the current line in the minimap:

```json
{
  "minimap": {
    "current_line_highlight": "gutter"
  }
}
```

or

```json
{
  "minimap": {
    "current_line_highlight": "none"
  }
}
```

## Editor Tab Bar

- Description: Settings related to the editor's tab bar.
- Settings: `tab_bar`
- Default:

```json
"tab_bar": {
  "show": true,
  "show_nav_history_buttons": true,
  "show_tab_bar_buttons": true
}
```

### Show

- Description: Whether or not to show the tab bar in the editor.
- Setting: `show`
- Default: `true`

**Options**

`boolean` values

### Navigation History Buttons

- Description: Whether or not to show the navigation history buttons.
- Setting: `show_nav_history_buttons`
- Default: `true`

**Options**

`boolean` values

### Tab Bar Buttons

- Description: Whether or not to show the tab bar buttons.
- Setting: `show_tab_bar_buttons`
- Default: `true`

**Options**

`boolean` values

## Editor Tabs

- Description: Configuration for the editor tabs.
- Setting: `tabs`
- Default:

```json
"tabs": {
  "close_position": "right",
  "file_icons": false,
  "git_status": false,
  "activate_on_close": "history",
  "show_close_button": "hover",
  "show_diagnostics": "off"
},
```

### Close Position

- Description: Where to display close button within a tab.
- Setting: `close_position`
- Default: `right`

**Options**

1. Display the close button on the right:

```json
{
  "close_position": "right"
}
```

2. Display the close button on the left:

```json
{
  "close_position": "left"
}
```

### File Icons

- Description: Whether to show the file icon for a tab.
- Setting: `file_icons`
- Default: `false`

### Git Status

- Description: Whether or not to show Git file status in tab.
- Setting: `git_status`
- Default: `false`

### Activate on close

- Description: What to do after closing the current tab.
- Setting: `activate_on_close`
- Default: `history`

**Options**

1.  Activate the tab that was open previously:

```json
{
  "activate_on_close": "history"
}
```

2. Activate the right neighbour tab if present:

```json
{
  "activate_on_close": "neighbour"
}
```

3. Activate the left neighbour tab if present:

```json
{
  "activate_on_close": "left_neighbour"
}
```

### Show close button

- Description: Controls the appearance behavior of the tab's close button.
- Setting: `show_close_button`
- Default: `hover`

**Options**

1.  Show it just upon hovering the tab:

```json
{
  "show_close_button": "hover"
}
```

2. Show it persistently:

```json
{
  "show_close_button": "always"
}
```

3. Never show it, even if hovering it:

```json
{
  "show_close_button": "hidden"
}
```

### Show Diagnostics

- Description: Whether to show diagnostics indicators in tabs. This setting only works when file icons are active and controls which files with diagnostic issues to mark.
- Setting: `show_diagnostics`
- Default: `off`

**Options**

1. Do not mark any files:

```json
{
  "show_diagnostics": "off"
}
```

2. Only mark files with errors:

```json
{
  "show_diagnostics": "errors"
}
```

3. Mark files with errors and warnings:

```json
{
  "show_diagnostics": "all"
}
```

### Show Inline Code Actions

- Description: Whether to show code action button at start of buffer line.
- Setting: `inline_code_actions`
- Default: `true`

**Options**

`boolean` values

### Drag And Drop Selection

- Description: Whether to allow drag and drop text selection in buffer. `delay` is the milliseconds that must elapse before drag and drop is allowed. Otherwise, a new text selection is created.
- Setting: `drag_and_drop_selection`
- Default:

```json
"drag_and_drop_selection": {
  "enabled": true,
  "delay": 300
}
```

## Editor Toolbar

- Description: Whether or not to show various elements in the editor toolbar.
- Setting: `toolbar`
- Default:

```json
"toolbar": {
  "breadcrumbs": true,
  "quick_actions": true,
  "selections_menu": true,
  "agent_review": true,
  "code_actions": false
},
```

**Options**

Each option controls displaying of a particular toolbar element. If all elements are hidden, the editor toolbar is not displayed.

## Use System Tabs

- Description: Whether to allow windows to tab together based on the user’s tabbing preference (macOS only).
- Setting: `use_system_window_tabs`
- Default: `false`

**Options**

This setting enables integration with macOS’s native window tabbing feature. When set to `true`, Zed windows can be grouped together as tabs in a single macOS window, following the system-wide tabbing preferences set by the user (such as "Always", "In Full Screen", or "Never"). This setting is only available on macOS.

## Enable Language Server

- Description: Whether or not to use language servers to provide code intelligence.
- Setting: `enable_language_server`
- Default: `true`

**Options**

`boolean` values

## Ensure Final Newline On Save

- Description: Removes any lines containing only whitespace at the end of the file and ensures just one newline at the end.
- Setting: `ensure_final_newline_on_save`
- Default: `true`

**Options**

`boolean` values

## Expand Excerpt Lines

- Description: The default number of lines to expand excerpts in the multibuffer by
- Setting: `expand_excerpt_lines`
- Default: `5`

**Options**

Positive `integer` values

## Excerpt Context Lines

- Description: The number of lines of context to provide when showing excerpts in the multibuffer.
- Setting: `excerpt_context_lines`
- Default: `2`

**Options**

Positive `integer` value between 1 and 32. Values outside of this range will be clamped to this range.

## Extend Comment On Newline

- Description: Whether to start a new line with a comment when a previous line is a comment as well.
- Setting: `extend_comment_on_newline`
- Default: `true`

**Options**

`boolean` values

## Status Bar

- Description: Control various elements in the status bar. Note that some items in the status bar have their own settings set elsewhere.
- Setting: `status_bar`
- Default:

```json
"status_bar": {
  "active_language_button": true,
  "cursor_position_button": true
},
```

## LSP

- Description: Configuration for language servers.
- Setting: `lsp`
- Default: `null`

**Options**

The following settings can be overridden for specific language servers:

- `initialization_options`
- `settings`

To override configuration for a language server, add an entry for that language server's name to the `lsp` value.

Some options are passed via `initialization_options` to the language server. These are for options which must be specified at language server startup and when changed will require restarting the language server.

For example to pass the `check` option to `rust-analyzer`, use the following configuration:

```json
"lsp": {
  "rust-analyzer": {
    "initialization_options": {
      "check": {
        "command": "clippy" // rust-analyzer.check.command (default: "check")
      }
    }
  }
}
```

While other options may be changed at a runtime and should be placed under `settings`:

```json
"lsp": {
  "yaml-language-server": {
    "settings": {
      "yaml": {
        "keyOrdering": true // Enforces alphabetical ordering of keys in maps
      }
    }
  }
}
```

## Global LSP Settings

- Description: Configuration for global LSP settings that apply to all language servers
- Setting: `global_lsp_settings`
- Default:

```json
{
  "global_lsp_settings": {
    "button": true
  }
}
```

**Options**

- `button`: Whether to show the LSP status button in the status bar

## LSP Highlight Debounce

- Description: The debounce delay in milliseconds before querying highlights from the language server based on the current cursor location.
- Setting: `lsp_highlight_debounce`
- Default: `75`

## Global LSP Settings

- Description: Common language server settings.
- Setting: `global_lsp_settings`
- Default:

```json
"global_lsp_settings": {
  "button": true
}
```

**Options**

`integer` values representing milliseconds

## Features

- Description: Features that can be globally enabled or disabled
- Setting: `features`
- Default:

```json
{
  "features": {
    "edit_prediction_provider": "zed"
  }
}
```

### Edit Prediction Provider

- Description: Which edit prediction provider to use
- Setting: `edit_prediction_provider`
- Default: `"zed"`

**Options**

1. Use Zeta as the edit prediction provider:

```json
{
  "features": {
    "edit_prediction_provider": "zed"
  }
}
```

2. Use Copilot as the edit prediction provider:

```json
{
  "features": {
    "edit_prediction_provider": "copilot"
  }
}
```

3. Use Supermaven as the edit prediction provider:

```json
{
  "features": {
    "edit_prediction_provider": "supermaven"
  }
}
```

4. Turn off edit predictions across all providers

```json
{
  "features": {
    "edit_prediction_provider": "none"
  }
}
```

## Format On Save

- Description: Whether or not to perform a buffer format before saving.
- Setting: `format_on_save`
- Default: `on`

**Options**

1. `on`, enables format on save obeying `formatter` setting:

```json
{
  "format_on_save": "on"
}
```

2. `off`, disables format on save:

```json
{
  "format_on_save": "off"
}
```

## Formatter

- Description: How to perform a buffer format.
- Setting: `formatter`
- Default: `auto`

**Options**

1. To use the current language server, use `"language_server"`:

```json
{
  "formatter": "language_server"
}
```

2. Or to use an external command, use `"external"`. Specify the name of the formatting program to run, and an array of arguments to pass to the program. The buffer's text will be passed to the program on stdin, and the formatted output should be written to stdout. For example, the following command would strip trailing spaces using [`sed(1)`](https://linux.die.net/man/1/sed):

```json
{
  "formatter": {
    "external": {
      "command": "sed",
      "arguments": ["-e", "s/ *$//"]
    }
  }
}
```

3. External formatters may optionally include a `{buffer_path}` placeholder which at runtime will include the path of the buffer being formatted. Formatters operate by receiving file content via standard input, reformatting it and then outputting it to standard output and so normally don't know the filename of what they are formatting. Tools like Prettier support receiving the file path via a command line argument which can then used to impact formatting decisions.

WARNING: `{buffer_path}` should not be used to direct your formatter to read from a filename. Your formatter should only read from standard input and should not read or write files directly.

```json
  "formatter": {
    "external": {
      "command": "prettier",
      "arguments": ["--stdin-filepath", "{buffer_path}"]
    }
  }
```

4. Or to use code actions provided by the connected language servers, use `"code_actions"`:

```json
{
  "formatter": {
    "code_actions": {
      // Use ESLint's --fix:
      "source.fixAll.eslint": true,
      // Organize imports on save:
      "source.organizeImports": true
    }
  }
}
```

5. Or to use multiple formatters consecutively, use an array of formatters:

```json
{
  "formatter": [
    { "language_server": { "name": "rust-analyzer" } },
    {
      "external": {
        "command": "sed",
        "arguments": ["-e", "s/ *$//"]
      }
    }
  ]
}
```

Here `rust-analyzer` will be used first to format the code, followed by a call of sed.
If any of the formatters fails, the subsequent ones will still be executed.

## Code Actions On Format

- Description: The code actions to perform with the primary language server when formatting the buffer.
- Setting: `code_actions_on_format`
- Default: `{}`, except for Go it's `{ "source.organizeImports": true }`

**Examples**

<!--
TBD: Add Python Ruff source.organizeImports example
-->

1. Organize imports on format in TypeScript and TSX buffers:

```json
{
  "languages": {
    "TypeScript": {
      "code_actions_on_format": {
        "source.organizeImports": true
      }
    },
    "TSX": {
      "code_actions_on_format": {
        "source.organizeImports": true
      }
    }
  }
}
```

2. Run ESLint `fixAll` code action when formatting:

```json
{
  "languages": {
    "JavaScript": {
      "code_actions_on_format": {
        "source.fixAll.eslint": true
      }
    }
  }
}
```

3. Run only a single ESLint rule when using `fixAll`:

```json
{
  "languages": {
    "JavaScript": {
      "code_actions_on_format": {
        "source.fixAll.eslint": true
      }
    }
  },
  "lsp": {
    "eslint": {
      "settings": {
        "codeActionOnSave": {
          "rules": ["import/order"]
        }
      }
    }
  }
}
```

## Auto close

- Description: Whether to automatically add matching closing characters when typing opening parenthesis, bracket, brace, single or double quote characters.
- Setting: `use_autoclose`
- Default: `true`

**Options**

`boolean` values

## Always Treat Brackets As Autoclosed

- Description: Controls how the editor handles the autoclosed characters.
- Setting: `always_treat_brackets_as_autoclosed`
- Default: `false`

**Options**

`boolean` values

**Example**

If the setting is set to `true`:

1. Enter in the editor: `)))`
2. Move the cursor to the start: `^)))`
3. Enter again: `)))`

The result is still `)))` and not `))))))`, which is what it would be by default.

## File Scan Exclusions

- Setting: `file_scan_exclusions`
- Description: Files or globs of files that will be excluded by Zed entirely. They will be skipped during file scans, file searches, and not be displayed in the project file tree. Overrides `file_scan_inclusions`.
- Default:

```json
"file_scan_exclusions": [
  "**/.git",
  "**/.svn",
  "**/.hg",
  "**/.jj",
  "**/CVS",
  "**/.DS_Store",
  "**/Thumbs.db",
  "**/.classpath",
  "**/.settings"
],
```

Note, specifying `file_scan_exclusions` in settings.json will override the defaults (shown above). If you are looking to exclude additional items you will need to include all the default values in your settings.

## File Scan Inclusions

- Setting: `file_scan_inclusions`
- Description: Files or globs of files that will be included by Zed, even when ignored by git. This is useful for files that are not tracked by git, but are still important to your project. Note that globs that are overly broad can slow down Zed's file scanning. `file_scan_exclusions` takes precedence over these inclusions.
- Default:

```json
"file_scan_inclusions": [".env*"],
```

## File Types

- Setting: `file_types`
- Description: Configure how Zed selects a language for a file based on its filename or extension. Supports glob entries.
- Default:

```json
"file_types": {
  "JSONC": ["**/.zed/**/*.json", "**/zed/**/*.json", "**/Zed/**/*.json", "**/.vscode/**/*.json"],
  "Shell Script": [".env.*"]
}
```

**Examples**

To interpret all `.c` files as C++, files called `MyLockFile` as TOML and files starting with `Dockerfile` as Dockerfile:

```json
{
  "file_types": {
    "C++": ["c"],
    "TOML": ["MyLockFile"],
    "Dockerfile": ["Dockerfile*"]
  }
}
```

## Diagnostics

- Description: Configuration for diagnostics-related features.
- Setting: `diagnostics`
- Default:

```json
{
  "diagnostics": {
    "include_warnings": true,
    "inline": {
      "enabled": false
    },
    "update_with_cursor": false,
    "primary_only": false,
    "use_rendered": false
  }
}
```

### Inline Diagnostics

- Description: Whether or not to show diagnostics information inline.
- Setting: `inline`
- Default:

```json
{
  "diagnostics": {
    "inline": {
      "enabled": false,
      "update_debounce_ms": 150,
      "padding": 4,
      "min_column": 0,
      "max_severity": null
    }
  }
}
```

**Options**

1. Enable inline diagnostics.

```json
{
  "diagnostics": {
    "inline": {
      "enabled": true
    }
  }
}
```

2. Delay diagnostic updates until some time after the last diagnostic update.

```json
{
  "diagnostics": {
    "inline": {
      "enabled": true,
      "update_debounce_ms": 150
    }
  }
}
```

3. Set padding between the end of the source line and the start of the diagnostic.

```json
{
  "diagnostics": {
    "inline": {
      "enabled": true,
      "padding": 4
    }
  }
}
```

4. Horizontally align inline diagnostics at the given column.

```json
{
  "diagnostics": {
    "inline": {
      "enabled": true,
      "min_column": 80
    }
  }
}
```

5. Show only warning and error diagnostics.

```json
{
  "diagnostics": {
    "inline": {
      "enabled": true,
      "max_severity": "warning"
    }
  }
}
```

## Git

- Description: Configuration for git-related features.
- Setting: `git`
- Default:

```json
{
  "git": {
    "git_gutter": "tracked_files",
    "inline_blame": {
      "enabled": true
    },
    "branch_picker": {
      "show_author_name": true
    },
    "hunk_style": "staged_hollow"
  }
}
```

### Git Gutter

- Description: Whether or not to show the git gutter.
- Setting: `git_gutter`
- Default: `tracked_files`

**Options**

1. Show git gutter in tracked files

```json
{
  "git": {
    "git_gutter": "tracked_files"
  }
}
```

2. Hide git gutter

```json
{
  "git": {
    "git_gutter": "hide"
  }
}
```

### Gutter Debounce

- Description: Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter.
- Setting: `gutter_debounce`
- Default: `null`

**Options**

`integer` values representing milliseconds

Example:

```json
{
  "git": {
    "gutter_debounce": 100
  }
}
```

### Inline Git Blame

- Description: Whether or not to show git blame information inline, on the currently focused line.
- Setting: `inline_blame`
- Default:

```json
{
  "git": {
    "inline_blame": {
      "enabled": true
    }
  }
}
```

**Options**

1. Disable inline git blame:

```json
{
  "git": {
    "inline_blame": {
      "enabled": false
    }
  }
}
```

2. Only show inline git blame after a delay (that starts after cursor stops moving):

```json
{
  "git": {
    "inline_blame": {
      "delay_ms": 500
    }
  }
}
```

3. Show a commit summary next to the commit date and author:

```json
{
  "git": {
    "inline_blame": {
      "show_commit_summary": true
    }
  }
}
```

4. Use this as the minimum column at which to display inline blame information:

```json
{
  "git": {
    "inline_blame": {
      "min_column": 80
    }
  }
}
```

5. Set the padding between the end of the line and the inline blame hint, in ems:

```json
{
  "git": {
    "inline_blame": {
      "padding": 10
    }
  }
}
```

### Branch Picker

- Description: Configuration related to the branch picker.
- Setting: `branch_picker`
- Default:

```json
{
  "git": {
    "branch_picker": {
      "show_author_name": false
    }
  }
}
```

**Options**

1. Show the author name in the branch picker:

```json
{
  "git": {
    "branch_picker": {
      "show_author_name": true
    }
  }
}
```

### Hunk Style

- Description: What styling we should use for the diff hunks.
- Setting: `hunk_style`
- Default:

```json
{
  "git": {
    "hunk_style": "staged_hollow"
  }
}
```

**Options**

1. Show the staged hunks faded out and with a border:

```json
{
  "git": {
    "hunk_style": "staged_hollow"
  }
}
```

2. Show unstaged hunks faded out and with a border:

```json
{
  "git": {
    "hunk_style": "unstaged_hollow"
  }
}
```

## Go to Definition Fallback

- Description: What to do when the {#action editor::GoToDefinition} action fails to find a definition
- Setting: `go_to_definition_fallback`
- Default: `"find_all_references"`

**Options**

1. Do nothing:

```json
{
  "go_to_definition_fallback": "none"
}
```

2. Find references for the same symbol (default):

```json
{
  "go_to_definition_fallback": "find_all_references"
}
```

## Hard Tabs

- Description: Whether to indent lines using tab characters or multiple spaces.
- Setting: `hard_tabs`
- Default: `false`

**Options**

`boolean` values

## Helix Mode

- Description: Whether or not to enable Helix mode. Enabling `helix_mode` also enables `vim_mode`. See the [Helix documentation](./helix.md) for more details.
- Setting: `helix_mode`
- Default: `false`

**Options**

`boolean` values

## Indent Guides

- Description: Configuration related to indent guides. Indent guides can be configured separately for each language.
- Setting: `indent_guides`
- Default:

```json
{
  "indent_guides": {
    "enabled": true,
    "line_width": 1,
    "active_line_width": 1,
    "coloring": "fixed",
    "background_coloring": "disabled"
  }
}
```

**Options**

1. Disable indent guides

```json
{
  "indent_guides": {
    "enabled": false
  }
}
```

2. Enable indent guides for a specific language.

```json
{
  "languages": {
    "Python": {
      "indent_guides": {
        "enabled": true
      }
    }
  }
}
```

3. Enable indent aware coloring ("rainbow indentation").
   The colors that are used for different indentation levels are defined in the theme (theme key: `accents`). They can be customized by using theme overrides.

```json
{
  "indent_guides": {
    "enabled": true,
    "coloring": "indent_aware"
  }
}
```

4. Enable indent aware background coloring ("rainbow indentation").
   The colors that are used for different indentation levels are defined in the theme (theme key: `accents`). They can be customized by using theme overrides.

```json
{
  "indent_guides": {
    "enabled": true,
    "coloring": "indent_aware",
    "background_coloring": "indent_aware"
  }
}
```

## Hover Popover Enabled

- Description: Whether or not to show the informational hover box when moving the mouse over symbols in the editor.
- Setting: `hover_popover_enabled`
- Default: `true`

**Options**

`boolean` values

## Hover Popover Delay

- Description: Time to wait in milliseconds before showing the informational hover box.
- Setting: `hover_popover_delay`
- Default: `300`

**Options**

`integer` values representing milliseconds

## Icon Theme

- Description: The icon theme setting can be specified in two forms - either as the name of an icon theme or as an object containing the `mode`, `dark`, and `light` icon themes for files/folders inside Zed.
- Setting: `icon_theme`
- Default: `Zed (Default)`

### Icon Theme Object

- Description: Specify the icon theme using an object that includes the `mode`, `dark`, and `light`.
- Setting: `icon_theme`
- Default:

```json
"icon_theme": {
  "mode": "system",
  "dark": "Zed (Default)",
  "light": "Zed (Default)"
},
```

### Mode

- Description: Specify the icon theme mode.
- Setting: `mode`
- Default: `system`

**Options**

1. Set the icon theme to dark mode

```json
{
  "mode": "dark"
}
```

2. Set the icon theme to light mode

```json
{
  "mode": "light"
}
```

3. Set the icon theme to system mode

```json
{
  "mode": "system"
}
```

### Dark

- Description: The name of the dark icon theme.
- Setting: `dark`
- Default: `Zed (Default)`

**Options**

Run the {#action icon_theme_selector::Toggle} action in the command palette to see a current list of valid icon themes names.

### Light

- Description: The name of the light icon theme.
- Setting: `light`
- Default: `Zed (Default)`

**Options**

Run the {#action icon_theme_selector::Toggle} action in the command palette to see a current list of valid icon themes names.

## Image Viewer

- Description: Settings for image viewer functionality
- Setting: `image_viewer`
- Default:

```json
{
  "image_viewer": {
    "unit": "binary"
  }
}
```

**Options**

### Unit

- Description: The unit for image file sizes
- Setting: `unit`
- Default: `"binary"`

**Options**

1. Use binary units (KiB, MiB):

```json
{
  "image_viewer": {
    "unit": "binary"
  }
}
```

2. Use decimal units (KB, MB):

```json
{
  "image_viewer": {
    "unit": "decimal"
  }
}
```

## Inlay hints

- Description: Configuration for displaying extra text with hints in the editor.
- Setting: `inlay_hints`
- Default:

```json
"inlay_hints": {
  "enabled": false,
  "show_type_hints": true,
  "show_parameter_hints": true,
  "show_other_hints": true,
  "show_background": false,
  "edit_debounce_ms": 700,
  "scroll_debounce_ms": 50,
  "toggle_on_modifiers_press": null
}
```

**Options**

Inlay hints querying consists of two parts: editor (client) and LSP server.
With the inlay settings above are changed to enable the hints, editor will start to query certain types of hints and react on LSP hint refresh request from the server.
At this point, the server may or may not return hints depending on its implementation, further configuration might be needed, refer to the corresponding LSP server documentation.

The following languages have inlay hints preconfigured by Zed:

- [Go](https://docs.zed.dev/languages/go)
- [Rust](https://docs.zed.dev/languages/rust)
- [Svelte](https://docs.zed.dev/languages/svelte)
- [TypeScript](https://docs.zed.dev/languages/typescript)

Use the `lsp` section for the server configuration. Examples are provided in the corresponding language documentation.

Hints are not instantly queried in Zed, two kinds of debounces are used, either may be set to 0 to be disabled.
Settings-related hint updates are not debounced.

All possible config values for `toggle_on_modifiers_press` are:

```json
"inlay_hints": {
  "toggle_on_modifiers_press": {
    "control": true,
    "shift": true,
    "alt": true,
    "platform": true,
    "function": true
  }
}
```

Unspecified values have a `false` value, hints won't be toggled if all the modifiers are `false` or not all the modifiers are pressed.

## Journal

- Description: Configuration for the journal.
- Setting: `journal`
- Default:

```json
"journal": {
  "path": "~",
  "hour_format": "hour12"
}
```

### Path

- Description: The path of the directory where journal entries are stored.
- Setting: `path`
- Default: `~`

**Options**

`string` values

### Hour Format

- Description: The format to use for displaying hours in the journal.
- Setting: `hour_format`
- Default: `hour12`

**Options**

1. 12-hour format:

```json
{
  "hour_format": "hour12"
}
```

2. 24-hour format:

```json
{
  "hour_format": "hour24"
}
```

## JSX Tag Auto Close

- Description: Whether to automatically close JSX tags
- Setting: `jsx_tag_auto_close`
- Default:

```json
{
  "jsx_tag_auto_close": {
    "enabled": true
  }
}
```

**Options**

- `enabled`: Whether to enable automatic JSX tag closing

## Languages

- Description: Configuration for specific languages.
- Setting: `languages`
- Default: `null`

**Options**

To override settings for a language, add an entry for that languages name to the `languages` value. Example:

```json
"languages": {
  "C": {
    "format_on_save": "off",
    "preferred_line_length": 64,
    "soft_wrap": "preferred_line_length"
  },
  "JSON": {
    "tab_size": 4
  }
}
```

The following settings can be overridden for each specific language:

- [`enable_language_server`](#enable-language-server)
- [`ensure_final_newline_on_save`](#ensure-final-newline-on-save)
- [`format_on_save`](#format-on-save)
- [`formatter`](#formatter)
- [`hard_tabs`](#hard-tabs)
- [`preferred_line_length`](#preferred-line-length)
- [`remove_trailing_whitespace_on_save`](#remove-trailing-whitespace-on-save)
- [`show_edit_predictions`](#show-edit-predictions)
- [`show_whitespaces`](#show-whitespaces)
- [`whitespace_map`](#whitespace-map)
- [`soft_wrap`](#soft-wrap)
- [`tab_size`](#tab-size)
- [`use_autoclose`](#use-autoclose)
- [`always_treat_brackets_as_autoclosed`](#always-treat-brackets-as-autoclosed)

These values take in the same options as the root-level settings with the same name.

## Language Models

- Description: Configuration for language model providers
- Setting: `language_models`
- Default:

```json
{
  "language_models": {
    "anthropic": {
      "api_url": "https://api.anthropic.com"
    },
    "google": {
      "api_url": "https://generativelanguage.googleapis.com"
    },
    "ollama": {
      "api_url": "http://localhost:11434"
    },
    "openai": {
      "api_url": "https://api.openai.com/v1"
    }
  }
}
```

**Options**

Configuration for various AI model providers including API URLs and authentication settings.

## Line Indicator Format

- Description: Format for line indicator in the status bar
- Setting: `line_indicator_format`
- Default: `"short"`

**Options**

1. Short format:

```json
{
  "line_indicator_format": "short"
}
```

2. Long format:

```json
{
  "line_indicator_format": "long"
}
```

## Linked Edits

- Description: Whether to perform linked edits of associated ranges, if the language server supports it. For example, when editing opening `<html>` tag, the contents of the closing `</html>` tag will be edited as well.
- Setting: `linked_edits`
- Default: `true`

**Options**

`boolean` values

## LSP Document Colors

- Description: Whether to show document color information from the language server
- Setting: `lsp_document_colors`
- Default: `true`

**Options**

`boolean` values

## Max Tabs

- Description: Maximum number of tabs to show in the tab bar
- Setting: `max_tabs`
- Default: `null`

**Options**

Positive `integer` values or `null` for unlimited tabs

## Middle Click Paste (Linux only)

- Description: Enable middle-click paste on Linux
- Setting: `middle_click_paste`
- Default: `true`

**Options**

`boolean` values

## Multi Cursor Modifier

- Description: Determines the modifier to be used to add multiple cursors with the mouse. The open hover link mouse gestures will adapt such that it do not conflict with the multicursor modifier.
- Setting: `multi_cursor_modifier`
- Default: `alt`

**Options**

1. Maps to `Alt` on Linux and Windows and to `Option` on macOS:

```json
{
  "multi_cursor_modifier": "alt"
}
```

2. Maps `Control` on Linux and Windows and to `Command` on macOS:

```json
{
  "multi_cursor_modifier": "cmd_or_ctrl" // alias: "cmd", "ctrl"
}
```

## Node

- Description: Configuration for Node.js integration
- Setting: `node`
- Default:

```json
{
  "node": {
    "ignore_system_version": false,
    "path": null,
    "npm_path": null
  }
}
```

**Options**

- `ignore_system_version`: Whether to ignore the system Node.js version
- `path`: Custom path to Node.js binary
- `npm_path`: Custom path to npm binary

## Network Proxy

- Description: Configure a network proxy for Zed.
- Setting: `proxy`
- Default: `null`

**Options**

The proxy setting must contain a URL to the proxy.

The following URI schemes are supported:

- `http`
- `https`
- `socks4` - SOCKS4 proxy with local DNS
- `socks4a` - SOCKS4 proxy with remote DNS
- `socks5` - SOCKS5 proxy with local DNS
- `socks5h` - SOCKS5 proxy with remote DNS

`http` will be used when no scheme is specified.

By default no proxy will be used, or Zed will attempt to retrieve proxy settings from environment variables, such as `http_proxy`, `HTTP_PROXY`, `https_proxy`, `HTTPS_PROXY`, `all_proxy`, `ALL_PROXY`, `no_proxy` and `NO_PROXY`.

For example, to set an `http` proxy, add the following to your settings:

```json
{
  "proxy": "http://127.0.0.1:10809"
}
```

Or to set a `socks5` proxy:

```json
{
  "proxy": "socks5h://localhost:10808"
}
```

If you wish to exclude certain hosts from using the proxy, set the `NO_PROXY` environment variable. This accepts a comma-separated list of hostnames, host suffixes, IPv4/IPv6 addresses or blocks that should not use the proxy. For example if your environment included `NO_PROXY="google.com, 192.168.1.0/24"` all hosts in `192.168.1.*`, `google.com` and `*.google.com` would bypass the proxy. See [reqwest NoProxy docs](https://docs.rs/reqwest/latest/reqwest/struct.NoProxy.html#method.from_string) for more.

## On Last Window Closed

- Description: What to do when the last window is closed
- Setting: `on_last_window_closed`
- Default: `"platform_default"`

**Options**

1. Use platform default behavior:

```json
{
  "on_last_window_closed": "platform_default"
}
```

2. Always quit the application:

```json
{
  "on_last_window_closed": "quit_app"
}
```

## Profiles

- Description: Configuration profiles that can be applied on top of existing settings
- Setting: `profiles`
- Default: `{}`

**Options**

Configuration object for defining settings profiles. Example:

```json
{
  "profiles": {
    "presentation": {
      "buffer_font_size": 20,
      "ui_font_size": 18,
      "theme": "One Light"
    }
  }
}
```

## Preview tabs

- Description:
  Preview tabs allow you to open files in preview mode, where they close automatically when you switch to another file unless you explicitly pin them. This is useful for quickly viewing files without cluttering your workspace. Preview tabs display their file names in italics. \
   There are several ways to convert a preview tab into a regular tab:

  - Double-clicking on the file
  - Double-clicking on the tab header
  - Using the {#action project_panel::OpenPermanent} action
  - Editing the file
  - Dragging the file to a different pane

- Setting: `preview_tabs`
- Default:

```json
"preview_tabs": {
  "enabled": true,
  "enable_preview_from_file_finder": false,
  "enable_preview_from_code_navigation": false,
}
```

### Enable preview from file finder

- Description: Determines whether to open files in preview mode when selected from the file finder.
- Setting: `enable_preview_from_file_finder`
- Default: `false`

**Options**

`boolean` values

### Enable preview from code navigation

- Description: Determines whether a preview tab gets replaced when code navigation is used to navigate away from the tab.
- Setting: `enable_preview_from_code_navigation`
- Default: `false`

**Options**

`boolean` values

## File Finder

### File Icons

- Description: Whether to show file icons in the file finder.
- Setting: `file_icons`
- Default: `true`

### Modal Max Width

- Description: Max-width of the file finder modal. It can take one of these values: `small`, `medium`, `large`, `xlarge`, and `full`.
- Setting: `modal_max_width`
- Default: `small`

### Skip Focus For Active In Search

- Description: Determines whether the file finder should skip focus for the active file in search results.
- Setting: `skip_focus_for_active_in_search`
- Default: `true`

## Pane Split Direction Horizontal

- Description: The direction that you want to split panes horizontally
- Setting: `pane_split_direction_horizontal`
- Default: `"up"`

**Options**

1. Split upward:

```json
{
  "pane_split_direction_horizontal": "up"
}
```

2. Split downward:

```json
{
  "pane_split_direction_horizontal": "down"
}
```

## Pane Split Direction Vertical

- Description: The direction that you want to split panes vertically
- Setting: `pane_split_direction_vertical`
- Default: `"left"`

**Options**

1. Split to the left:

```json
{
  "pane_split_direction_vertical": "left"
}
```

2. Split to the right:

```json
{
  "pane_split_direction_vertical": "right"
}
```

## Preferred Line Length

- Description: The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.
- Setting: `preferred_line_length`
- Default: `80`

**Options**

`integer` values

## Private Files

- Description: Globs to match against file paths to determine if a file is private
- Setting: `private_files`
- Default: `["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"]`

**Options**

List of `string` glob patterns

## Projects Online By Default

- Description: Whether or not to show the online projects view by default.
- Setting: `projects_online_by_default`
- Default: `true`

**Options**

`boolean` values

## Read SSH Config

- Description: Whether to read SSH configuration files
- Setting: `read_ssh_config`
- Default: `true`

**Options**

`boolean` values

## Redact Private Values

- Description: Hide the values of variables from visual display in private files
- Setting: `redact_private_values`
- Default: `false`

**Options**

`boolean` values

## Relative Line Numbers

- Description: Whether to show relative line numbers in the gutter
- Setting: `relative_line_numbers`
- Default: `false`

**Options**

`boolean` values

## Remove Trailing Whitespace On Save

- Description: Whether or not to remove any trailing whitespace from lines of a buffer before saving it.
- Setting: `remove_trailing_whitespace_on_save`
- Default: `true`

**Options**

`boolean` values

## Resize All Panels In Dock

- Description: Whether to resize all the panels in a dock when resizing the dock. Can be a combination of "left", "right" and "bottom".
- Setting: `resize_all_panels_in_dock`
- Default: `["left"]`

**Options**

List of strings containing any combination of:

- `"left"`: Resize left dock panels together
- `"right"`: Resize right dock panels together
- `"bottom"`: Resize bottom dock panels together

## Restore on File Reopen

- Description: Whether to attempt to restore previous file's state when opening it again. The state is stored per pane.
- Setting: `restore_on_file_reopen`
- Default: `true`

**Options**

`boolean` values

## Restore on Startup

- Description: Controls session restoration on startup.
- Setting: `restore_on_startup`
- Default: `last_session`

**Options**

1. Restore all workspaces that were open when quitting Zed:

```json
{
  "restore_on_startup": "last_session"
}
```

2. Restore the workspace that was closed last:

```json
{
  "restore_on_startup": "last_workspace"
}
```

3. Always start with an empty editor:

```json
{
  "restore_on_startup": "none"
}
```

## Scroll Beyond Last Line

- Description: Whether the editor will scroll beyond the last line
- Setting: `scroll_beyond_last_line`
- Default: `"one_page"`

**Options**

1. Scroll one page beyond the last line by one page:

```json
{
  "scroll_beyond_last_line": "one_page"
}
```

2. The editor will scroll beyond the last line by the same amount of lines as `vertical_scroll_margin`:

```json
{
  "scroll_beyond_last_line": "vertical_scroll_margin"
}
```

3. The editor will not scroll beyond the last line:

```json
{
  "scroll_beyond_last_line": "off"
}
```

**Options**

`boolean` values

## Scroll Sensitivity

- Description: Scroll sensitivity multiplier. This multiplier is applied to both the horizontal and vertical delta values while scrolling.
- Setting: `scroll_sensitivity`
- Default: `1.0`

**Options**

Positive `float` values

### Fast Scroll Sensitivity

- Description: Scroll sensitivity multiplier for fast scrolling. This multiplier is applied to both the horizontal and vertical delta values while scrolling. Fast scrolling happens when a user holds the alt or option key while scrolling.
- Setting: `fast_scroll_sensitivity`
- Default: `4.0`

**Options**

Positive `float` values

### Horizontal Scroll Margin

- Description: The number of characters to keep on either side when scrolling with the mouse
- Setting: `horizontal_scroll_margin`
- Default: `5`

**Options**

Non-negative `integer` values

### Vertical Scroll Margin

- Description: The number of lines to keep above/below the cursor when scrolling with the keyboard
- Setting: `vertical_scroll_margin`
- Default: `3`

**Options**

Non-negative `integer` values

## Search

- Description: Search options to enable by default when opening new project and buffer searches.
- Setting: `search`
- Default:

```json
"search": {
  "whole_word": false,
  "case_sensitive": false,
  "include_ignored": false,
  "regex": false
},
```

## Search Wrap

- Description: If `search_wrap` is disabled, search result do not wrap around the end of the file
- Setting: `search_wrap`
- Default: `true`

## Seed Search Query From Cursor

- Description: When to populate a new search's query based on the text under the cursor.
- Setting: `seed_search_query_from_cursor`
- Default: `always`

**Options**

1. `always` always populate the search query with the word under the cursor
2. `selection` only populate the search query when there is text selected
3. `never` never populate the search query

## Use Smartcase Search

- Description: When enabled, automatically adjusts search case sensitivity based on your query. If your search query contains any uppercase letters, the search becomes case-sensitive; if it contains only lowercase letters, the search becomes case-insensitive. \
  This applies to both in-file searches and project-wide searches.
- Setting: `use_smartcase_search`
- Default: `false`

**Options**

`boolean` values

Examples:

- Searching for "function" would match "function", "Function", "FUNCTION", etc.
- Searching for "Function" would only match "Function", not "function" or "FUNCTION"

## Show Call Status Icon

- Description: Whether or not to show the call status icon in the status bar.
- Setting: `show_call_status_icon`
- Default: `true`

**Options**

`boolean` values

## Completions

- Description: Controls how completions are processed for this language.
- Setting: `completions`
- Default:

```json
{
  "completions": {
    "words": "fallback",
    "words_min_length": 3,
    "lsp": true,
    "lsp_fetch_timeout_ms": 0,
    "lsp_insert_mode": "replace_suffix"
  }
}
```

### Words

- Description: Controls how words are completed. For large documents, not all words may be fetched for completion.
- Setting: `words`
- Default: `fallback`

**Options**

1. `enabled` - Always fetch document's words for completions along with LSP completions
2. `fallback` - Only if LSP response errors or times out, use document's words to show completions
3. `disabled` - Never fetch or complete document's words for completions (word-based completions can still be queried via a separate action)

### Min Words Query Length

- Description: Minimum number of characters required to automatically trigger word-based completions.
  Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command.
- Setting: `words_min_length`
- Default: `3`

**Options**

Positive integer values

### LSP

- Description: Whether to fetch LSP completions or not.
- Setting: `lsp`
- Default: `true`

**Options**

`boolean` values

### LSP Fetch Timeout (ms)

- Description: When fetching LSP completions, determines how long to wait for a response of a particular server. When set to 0, waits indefinitely.
- Setting: `lsp_fetch_timeout_ms`
- Default: `0`

**Options**

`integer` values representing milliseconds

### LSP Insert Mode

- Description: Controls what range to replace when accepting LSP completions.
- Setting: `lsp_insert_mode`
- Default: `replace_suffix`

**Options**

1. `insert` - Replaces text before the cursor, using the `insert` range described in the LSP specification
2. `replace` - Replaces text before and after the cursor, using the `replace` range described in the LSP specification
3. `replace_subsequence` - Behaves like `"replace"` if the text that would be replaced is a subsequence of the completion text, and like `"insert"` otherwise
4. `replace_suffix` - Behaves like `"replace"` if the text after the cursor is a suffix of the completion, and like `"insert"` otherwise

## Show Completions On Input

- Description: Whether or not to show completions as you type.
- Setting: `show_completions_on_input`
- Default: `true`

**Options**

`boolean` values

## Show Completion Documentation

- Description: Whether to display inline and alongside documentation for items in the completions menu.
- Setting: `show_completion_documentation`
- Default: `true`

**Options**

`boolean` values

## Show Edit Predictions

- Description: Whether to show edit predictions as you type or manually by triggering `editor::ShowEditPrediction`.
- Setting: `show_edit_predictions`
- Default: `true`

**Options**

`boolean` values

## Show Whitespaces

- Description: Whether or not to render whitespace characters in the editor.
- Setting: `show_whitespaces`
- Default: `selection`

**Options**

1. `all`
2. `selection`
3. `none`
4. `boundary`

## Whitespace Map

- Description: Specify the characters used to render whitespace when show_whitespaces is enabled.
- Setting: `whitespace_map`
- Default:

```json
{
  "whitespace_map": {
    "space": "•",
    "tab": "→"
  },
```

## Soft Wrap

- Description: Whether or not to automatically wrap lines of text to fit editor / preferred width.
- Setting: `soft_wrap`
- Default: `none`

**Options**

1. `none` to avoid wrapping generally, unless the line is too long
2. `prefer_line` (deprecated, same as `none`)
3. `editor_width` to wrap lines that overflow the editor width
4. `preferred_line_length` to wrap lines that overflow `preferred_line_length` config value
5. `bounded` to wrap lines at the minimum of `editor_width` and `preferred_line_length`

## Show Wrap Guides

- Description: Whether to show wrap guides (vertical rulers) in the editor. Setting this to true will show a guide at the 'preferred_line_length' value if 'soft_wrap' is set to 'preferred_line_length', and will show any additional guides as specified by the 'wrap_guides' setting.
- Setting: `show_wrap_guides`
- Default: `true`

**Options**

`boolean` values

## Use On Type Format

- Description: Whether to use additional LSP queries to format (and amend) the code after every "trigger" symbol input, defined by LSP server capabilities
- Setting: `use_on_type_format`
- Default: `true`

**Options**

`boolean` values

## Use Auto Surround

- Description: Whether to automatically surround selected text when typing opening parenthesis, bracket, brace, single or double quote characters. For example, when you select text and type (, Zed will surround the text with ().
- Setting: `use_auto_surround`
- Default: `true`

**Options**

`boolean` values

## Use System Path Prompts

- Description: Whether to use the system provided dialogs for Open and Save As. When set to false, Zed will use the built-in keyboard-first pickers.
- Setting: `use_system_path_prompts`
- Default: `true`

**Options**

`boolean` values

## Use System Prompts

- Description: Whether to use the system provided dialogs for prompts, such as confirmation prompts. When set to false, Zed will use its built-in prompts. Note that on Linux, this option is ignored and Zed will always use the built-in prompts.
- Setting: `use_system_prompts`
- Default: `true`

**Options**

`boolean` values

## Wrap Guides (Vertical Rulers)

- Description: Where to display vertical rulers as wrap-guides. Disable by setting `show_wrap_guides` to `false`.
- Setting: `wrap_guides`
- Default: []

**Options**

List of `integer` column numbers

## Tab Size

- Description: The number of spaces to use for each tab character.
- Setting: `tab_size`
- Default: `4`

**Options**

`integer` values

## Tasks

- Description: Configuration for tasks that can be run within Zed
- Setting: `tasks`
- Default:

```json
{
  "tasks": {
    "variables": {},
    "enabled": true,
    "prefer_lsp": false
  }
}
```

**Options**

- `variables`: Custom variables for task configuration
- `enabled`: Whether tasks are enabled
- `prefer_lsp`: Whether to prefer LSP-provided tasks over Zed language extension ones

## Telemetry

- Description: Control what info is collected by Zed.
- Setting: `telemetry`
- Default:

```json
"telemetry": {
  "diagnostics": true,
  "metrics": true
},
```

**Options**

### Diagnostics

- Description: Setting for sending debug-related data, such as crash reports.
- Setting: `diagnostics`
- Default: `true`

**Options**

`boolean` values

### Metrics

- Description: Setting for sending anonymized usage data, such what languages you're using Zed with.
- Setting: `metrics`
- Default: `true`

**Options**

`boolean` values

## Terminal

- Description: Configuration for the terminal.
- Setting: `terminal`
- Default:

```json
{
  "terminal": {
    "alternate_scroll": "off",
    "blinking": "terminal_controlled",
    "copy_on_select": false,
    "keep_selection_on_copy": false,
    "dock": "bottom",
    "default_width": 640,
    "default_height": 320,
    "detect_venv": {
      "on": {
        "directories": [".env", "env", ".venv", "venv"],
        "activate_script": "default"
      }
    },
    "env": {},
    "font_family": null,
    "font_features": null,
    "font_size": null,
    "line_height": "comfortable",
    "minimum_contrast": 45,
    "option_as_meta": false,
    "button": true,
    "shell": "system",
    "toolbar": {
      "breadcrumbs": true
    },
    "working_directory": "current_project_directory",
    "scrollbar": {
      "show": null
    }
  }
}
```

### Terminal: Dock

- Description: Control the position of the dock
- Setting: `dock`
- Default: `bottom`

**Options**

`"bottom"`, `"left"` or `"right"`

### Terminal: Alternate Scroll

- Description: Set whether Alternate Scroll mode (DECSET code: `?1007`) is active by default. Alternate Scroll mode converts mouse scroll events into up / down key presses when in the alternate screen (e.g. when running applications like vim or less). The terminal can still set and unset this mode with ANSI escape codes.
- Setting: `alternate_scroll`
- Default: `off`

**Options**

1. Default alternate scroll mode to off

```json
{
  "terminal": {
    "alternate_scroll": "off"
  }
}
```

2. Default alternate scroll mode to on

```json
{
  "terminal": {
    "alternate_scroll": "on"
  }
}
```

### Terminal: Blinking

- Description: Set the cursor blinking behavior in the terminal
- Setting: `blinking`
- Default: `terminal_controlled`

**Options**

1. Never blink the cursor, ignore the terminal mode

```json
{
  "terminal": {
    "blinking": "off"
  }
}
```

2. Default the cursor blink to off, but allow the terminal to turn blinking on

```json
{
  "terminal": {
    "blinking": "terminal_controlled"
  }
}
```

3. Always blink the cursor, ignore the terminal mode

```json
{
  "terminal": {
    "blinking": "on"
  }
}
```

### Terminal: Copy On Select

- Description: Whether or not selecting text in the terminal will automatically copy to the system clipboard.
- Setting: `copy_on_select`
- Default: `false`

**Options**

`boolean` values

**Example**

```json
{
  "terminal": {
    "copy_on_select": true
  }
}
```

### Terminal: Cursor Shape

- Description: Controls the visual shape of the cursor in the terminal. When not explicitly set, it defaults to a block shape.
- Setting: `cursor_shape`
- Default: `null` (defaults to block)

**Options**

1. A block that surrounds the following character

```json
{
  "terminal": {
    "cursor_shape": "block"
  }
}
```

2. A vertical bar

```json
{
  "terminal": {
    "cursor_shape": "bar"
  }
}
```

3. An underline / underscore that runs along the following character

```json
{
  "terminal": {
    "cursor_shape": "underline"
  }
}
```

4. A box drawn around the following character

```json
{
  "terminal": {
    "cursor_shape": "hollow"
  }
}
```

### Terminal: Keep Selection On Copy

- Description: Whether or not to keep the selection in the terminal after copying text.
- Setting: `keep_selection_on_copy`
- Default: `false`

**Options**

`boolean` values

**Example**

```json
{
  "terminal": {
    "keep_selection_on_copy": true
  }
}
```

### Terminal: Env

- Description: Any key-value pairs added to this object will be added to the terminal's environment. Keys must be unique, use `:` to separate multiple values in a single variable
- Setting: `env`
- Default: `{}`

**Example**

```json
{
  "terminal": {
    "env": {
      "ZED": "1",
      "KEY": "value1:value2"
    }
  }
}
```

### Terminal: Font Size

- Description: What font size to use for the terminal. When not set defaults to matching the editor's font size
- Setting: `font_size`
- Default: `null`

**Options**

`integer` values

```json
{
  "terminal": {
    "font_size": 15
  }
}
```

### Terminal: Font Family

- Description: What font to use for the terminal. When not set, defaults to matching the editor's font.
- Setting: `font_family`
- Default: `null`

**Options**

The name of any font family installed on the user's system

```json
{
  "terminal": {
    "font_family": "Berkeley Mono"
  }
}
```

### Terminal: Font Features

- Description: What font features to use for the terminal. When not set, defaults to matching the editor's font features.
- Setting: `font_features`
- Default: `null`
- Platform: macOS and Windows.

**Options**

See Buffer Font Features

```json
{
  "terminal": {
    "font_features": {
      "calt": false
      // See Buffer Font Features for more features
    }
  }
}
```

### Terminal: Line Height

- Description: Set the terminal's line height.
- Setting: `line_height`
- Default: `comfortable`

**Options**

1. Use a line height that's `comfortable` for reading, 1.618. (default)

```json
{
  "terminal": {
    "line_height": "comfortable"
  }
}
```

2. Use a `standard` line height, 1.3. This option is useful for TUIs, particularly if they use box characters

```json
{
  "terminal": {
    "line_height": "standard"
  }
}
```

3.  Use a custom line height.

```json
{
  "terminal": {
    "line_height": {
      "custom": 2
    }
  }
}
```

### Terminal: Minimum Contrast

- Description: Controls the minimum contrast between foreground and background colors in the terminal. Uses the APCA (Accessible Perceptual Contrast Algorithm) for color adjustments. Set this to 0 to disable this feature.
- Setting: `minimum_contrast`
- Default: `45`

**Options**

`integer` values from 0 to 106. Common recommended values:

- `0`: No contrast adjustment
- `45`: Minimum for large fluent text (default)
- `60`: Minimum for other content text
- `75`: Minimum for body text
- `90`: Preferred for body text

```json
{
  "terminal": {
    "minimum_contrast": 45
  }
}
```

### Terminal: Option As Meta

- Description: Re-interprets the option keys to act like a 'meta' key, like in Emacs.
- Setting: `option_as_meta`
- Default: `false`

**Options**

`boolean` values

```json
{
  "terminal": {
    "option_as_meta": true
  }
}
```

### Terminal: Shell

- Description: What shell to use when launching the terminal.
- Setting: `shell`
- Default: `system`

**Options**

1. Use the system's default terminal configuration (usually the `/etc/passwd` file).

```json
{
  "terminal": {
    "shell": "system"
  }
}
```

2. A program to launch:

```json
{
  "terminal": {
    "shell": {
      "program": "sh"
    }
  }
}
```

3. A program with arguments:

```json
{
  "terminal": {
    "shell": {
      "with_arguments": {
        "program": "/bin/bash",
        "args": ["--login"]
      }
    }
  }
}
```

## Terminal: Detect Virtual Environments {#terminal-detect_venv}

- Description: Activate the [Python Virtual Environment](https://docs.python.org/3/library/venv.html), if one is found, in the terminal's working directory (as resolved by the working_directory and automatically activating the virtual environment.
- Setting: `detect_venv`
- Default:

```json
{
  "terminal": {
    "detect_venv": {
      "on": {
        // Default directories to search for virtual environments, relative
        // to the current working directory. We recommend overriding this
        // in your project's settings, rather than globally.
        "directories": [".env", "env", ".venv", "venv"],
        // Can also be `csh`, `fish`, and `nushell`
        "activate_script": "default"
      }
    }
  }
}
```

Disable with:

```json
{
  "terminal": {
    "detect_venv": "off"
  }
}
```

## Terminal: Toolbar

- Description: Whether or not to show various elements in the terminal toolbar.
- Setting: `toolbar`
- Default:

```json
{
  "terminal": {
    "toolbar": {
      "breadcrumbs": true
    }
  }
}
```

**Options**

At the moment, only the `breadcrumbs` option is available, it controls displaying of the terminal title that can be changed via `PROMPT_COMMAND`.

If the terminal title is empty, the breadcrumbs won't be shown.

The shell running in the terminal needs to be configured to emit the title.

Example command to set the title: `echo -e "\e]2;New Title\007";`

### Terminal: Button

- Description: Control to show or hide the terminal button in the status bar
- Setting: `button`
- Default: `true`

**Options**

`boolean` values

```json
{
  "terminal": {
    "button": false
  }
}
```

### Terminal: Working Directory

- Description: What working directory to use when launching the terminal.
- Setting: `working_directory`
- Default: `"current_project_directory"`

**Options**

1. Use the current file's project directory. Will Fallback to the first project directory strategy if unsuccessful

```json
{
  "terminal": {
    "working_directory": "current_project_directory"
  }
}
```

2. Use the first project in this workspace's directory. Will fallback to using this platform's home directory.

```json
{
  "terminal": {
    "working_directory": "first_project_directory"
  }
}
```

3. Always use this platform's home directory (if we can find it)

```json
{
  "terminal": {
    "working_directory": "always_home"
  }
}
```

4. Always use a specific directory. This value will be shell expanded. If this path is not a valid directory the terminal will default to this platform's home directory.

```json
{
  "terminal": {
    "working_directory": {
      "always": {
        "directory": "~/zed/projects/"
      }
    }
  }
}
```

## REPL

- Description: Repl settings.
- Setting: `repl`
- Default:

```json
"repl": {
  // Maximum number of columns to keep in REPL's scrollback buffer.
  // Clamped with [20, 512] range.
  "max_columns": 128,
  // Maximum number of lines to keep in REPL's scrollback buffer.
  // Clamped with [4, 256] range.
  "max_lines": 32
},
```

## Theme

- Description: The theme setting can be specified in two forms - either as the name of a theme or as an object containing the `mode`, `dark`, and `light` themes for the Zed UI.
- Setting: `theme`
- Default: `One Dark`

### Theme Object

- Description: Specify the theme using an object that includes the `mode`, `dark`, and `light` themes.
- Setting: `theme`
- Default:

```json
"theme": {
  "mode": "system",
  "dark": "One Dark",
  "light": "One Light"
},
```

### Mode

- Description: Specify theme mode.
- Setting: `mode`
- Default: `system`

**Options**

1. Set the theme to dark mode

```json
{
  "mode": "dark"
}
```

2. Set the theme to light mode

```json
{
  "mode": "light"
}
```

3. Set the theme to system mode

```json
{
  "mode": "system"
}
```

### Dark

- Description: The name of the dark Zed theme to use for the UI.
- Setting: `dark`
- Default: `One Dark`

**Options**

Run the {#action theme_selector::Toggle} action in the command palette to see a current list of valid themes names.

### Light

- Description: The name of the light Zed theme to use for the UI.
- Setting: `light`
- Default: `One Light`

**Options**

Run the {#action theme_selector::Toggle} action in the command palette to see a current list of valid themes names.

## Title Bar

- Description: Whether or not to show various elements in the title bar
- Setting: `title_bar`
- Default:

```json
"title_bar": {
  "show": "always",
  "show_branch_icon": false,
  "show_branch_name": true,
  "show_project_items": true,
  "show_onboarding_banner": true,
  "show_user_picture": true,
  "show_sign_in": true,
  "show_menus": false
}
```

**Options**

- `show_branch_icon`: Whether to show the branch icon beside branch switcher in the titlebar
- `show_branch_name`: Whether to show the branch name button in the titlebar
- `show_project_items`: Whether to show the project host and name in the titlebar
- `show_onboarding_banner`: Whether to show onboarding banners in the titlebar
- `show_user_picture`: Whether to show user picture in the titlebar
- `show_sign_in`: Whether to show the sign in button in the titlebar
- `show_menus`: Whether to show the menus in the titlebar

## Vim

- Description: Whether or not to enable vim mode.
- Setting: `vim_mode`
- Default: `false`

## When Closing With No Tabs

- Description: Whether the window should be closed when using 'close active item' on a window with no tabs
- Setting: `when_closing_with_no_tabs`
- Default: `"platform_default"`

**Options**

1. Use platform default behavior:

```json
{
  "when_closing_with_no_tabs": "platform_default"
}
```

2. Always close the window:

```json
{
  "when_closing_with_no_tabs": "close_window"
}
```

3. Never close the window:

```json
{
  "when_closing_with_no_tabs": "keep_window_open"
}
```

## Project Panel

- Description: Customize project panel
- Setting: `project_panel`
- Default:

```json
{
  "project_panel": {
    "button": true,
    "default_width": 240,
    "dock": "left",
    "entry_spacing": "comfortable",
    "file_icons": true,
    "folder_icons": true,
    "git_status": true,
    "indent_size": 20,
    "auto_reveal_entries": true,
    "auto_fold_dirs": true,
    "drag_and_drop": true,
    "scrollbar": {
      "show": null
    },
    "sticky_scroll": true,
    "show_diagnostics": "all",
    "indent_guides": {
      "show": "always"
    },
    "hide_root": false,
    "starts_open": true
  }
}
```

### Dock

- Description: Control the position of the dock
- Setting: `dock`
- Default: `left`

**Options**

1. Default dock position to left

```json
{
  "dock": "left"
}
```

2. Default dock position to right

```json
{
  "dock": "right"
}
```

### Entry Spacing

- Description: Spacing between worktree entries
- Setting: `entry_spacing`
- Default: `comfortable`

**Options**

1. Comfortable entry spacing

```json
{
  "entry_spacing": "comfortable"
}
```

2. Standard entry spacing

```json
{
  "entry_spacing": "standard"
}
```

### Git Status

- Description: Indicates newly created and updated files
- Setting: `git_status`
- Default: `true`

**Options**

1. Default enable git status

```json
{
  "git_status": true
}
```

2. Default disable git status

```json
{
  "git_status": false
}
```

### Default Width

- Description: Customize default width taken by project panel
- Setting: `default_width`
- Default: `240`

**Options**

`float` values

### Auto Reveal Entries

- Description: Whether to reveal it in the project panel automatically, when a corresponding project entry becomes active. Gitignored entries are never auto revealed.
- Setting: `auto_reveal_entries`
- Default: `true`

**Options**

1. Enable auto reveal entries

```json
{
  "auto_reveal_entries": true
}
```

2. Disable auto reveal entries

```json
{
  "auto_reveal_entries": false
}
```

### Auto Fold Dirs

- Description: Whether to fold directories automatically when directory has only one directory inside.
- Setting: `auto_fold_dirs`
- Default: `true`

**Options**

1. Enable auto fold dirs

```json
{
  "auto_fold_dirs": true
}
```

2. Disable auto fold dirs

```json
{
  "auto_fold_dirs": false
}
```

### Indent Size

- Description: Amount of indentation (in pixels) for nested items.
- Setting: `indent_size`
- Default: `20`

### Indent Guides: Show

- Description: Whether to show indent guides in the project panel.
- Setting: `indent_guides`
- Default:

```json
"indent_guides": {
  "show": "always"
}
```

**Options**

1. Show indent guides in the project panel

```json
{
  "indent_guides": {
    "show": "always"
  }
}
```

2. Hide indent guides in the project panel

```json
{
  "indent_guides": {
    "show": "never"
  }
}
```

### Scrollbar: Show

- Description: Whether to show a scrollbar in the project panel. Possible values: null, "auto", "system", "always", "never". Inherits editor settings when absent, see its description for more details.
- Setting: `scrollbar`
- Default:

```json
"scrollbar": {
  "show": null
}
```

**Options**

1. Show scrollbar in the project panel

```json
{
  "scrollbar": {
    "show": "always"
  }
}
```

2. Hide scrollbar in the project panel

```json
{
  "scrollbar": {
    "show": "never"
  }
}
```

## Agent

Visit [the Configuration page](./ai/configuration.md) under the AI section to learn more about all the agent-related settings.

## Collaboration Panel

- Description: Customizations for the collaboration panel.
- Setting: `collaboration_panel`
- Default:

```json
{
  "collaboration_panel": {
    "button": true,
    "dock": "left",
    "default_width": 240
  }
}
```

**Options**

- `button`: Whether to show the collaboration panel button in the status bar
- `dock`: Where to dock the collaboration panel. Can be `left` or `right`
- `default_width`: Default width of the collaboration panel

## Debugger

- Description: Configuration for debugger panel and settings
- Setting: `debugger`
- Default:

```json
{
  "debugger": {
    "stepping_granularity": "line",
    "save_breakpoints": true,
    "dock": "bottom",
    "button": true
  }
}
```

See the [debugger page](./debugger.md) for more information about debugging support within Zed.

## Git Panel

- Description: Setting to customize the behavior of the git panel.
- Setting: `git_panel`
- Default:

```json
{
  "git_panel": {
    "button": true,
    "dock": "left",
    "default_width": 360,
    "status_style": "icon",
    "fallback_branch_name": "main",
    "sort_by_path": false,
    "collapse_untracked_diff": false,
    "scrollbar": {
      "show": null
    }
  }
}
```

**Options**

- `button`: Whether to show the git panel button in the status bar
- `dock`: Where to dock the git panel. Can be `left` or `right`
- `default_width`: Default width of the git panel
- `status_style`: How to display git status. Can be `label_color` or `icon`
- `fallback_branch_name`: What branch name to use if `init.defaultBranch` is not set
- `sort_by_path`: Whether to sort entries in the panel by path or by status (the default)
- `collapse_untracked_diff`: Whether to collapse untracked files in the diff panel
- `scrollbar`: When to show the scrollbar in the git panel

## Outline Panel

- Description: Customize outline Panel
- Setting: `outline_panel`
- Default:

```json
"outline_panel": {
  "button": true,
  "default_width": 300,
  "dock": "left",
  "file_icons": true,
  "folder_icons": true,
  "git_status": true,
  "indent_size": 20,
  "auto_reveal_entries": true,
  "auto_fold_dirs": true,
  "indent_guides": {
    "show": "always"
  },
  "scrollbar": {
    "show": null
  }
}
```

## Calls

- Description: Customize behavior when participating in a call
- Setting: `calls`
- Default:

```json
"calls": {
  // Join calls with the microphone live by default
  "mute_on_join": false,
  // Share your project when you are the first to join a channel
  "share_on_join": false
},
```

## Unnecessary Code Fade

- Description: How much to fade out unused code.
- Setting: `unnecessary_code_fade`
- Default: `0.3`

**Options**

Float values between `0.0` and `0.9`, where:

- `0.0` means no fading (unused code looks the same as used code)
- `0.9` means maximum fading (unused code is very faint but still visible)

**Example**

```json
{
  "unnecessary_code_fade": 0.5
}
```

## UI Font Family

- Description: The name of the font to use for text in the UI.
- Setting: `ui_font_family`
- Default: `.ZedSans`. This currently aliases to [IBM Plex](https://www.ibm.com/plex/).

**Options**

The name of any font family installed on the system, `".ZedSans"` to use the Zed-provided default, or `".SystemUIFont"` to use the system's default UI font (on macOS and Windows).

## UI Font Features

- Description: The OpenType features to enable for text in the UI.
- Setting: `ui_font_features`
- Default:

```json
"ui_font_features": {
  "calt": false
}
```

- Platform: macOS and Windows.

**Options**

Zed supports all OpenType features that can be enabled or disabled for a given UI font, as well as setting values for font features.

For example, to disable font ligatures, add the following to your settings:

```json
{
  "ui_font_features": {
    "calt": false
  }
}
```

You can also set other OpenType features, like setting `cv01` to `7`:

```json
{
  "ui_font_features": {
    "cv01": 7
  }
}
```

## UI Font Fallbacks

- Description: The font fallbacks to use for text in the UI.
- Setting: `ui_font_fallbacks`
- Default: `null`
- Platform: macOS and Windows.

**Options**

For example, to use `Nerd Font` as a fallback, add the following to your settings:

```json
{
  "ui_font_fallbacks": ["Nerd Font"]
}
```

## UI Font Size

- Description: The default font size for text in the UI.
- Setting: `ui_font_size`
- Default: `16`

**Options**

`integer` values from `6` to `100` pixels (inclusive)

## UI Font Weight

- Description: The default font weight for text in the UI.
- Setting: `ui_font_weight`
- Default: `400`

**Options**

`integer` values between `100` and `900`

## An example configuration:

```json
// ~/.config/zed/settings.json
{
  "theme": "cave-light",
  "tab_size": 2,
  "preferred_line_length": 80,
  "soft_wrap": "none",

  "buffer_font_size": 18,
  "buffer_font_family": ".ZedMono",

  "autosave": "on_focus_change",
  "format_on_save": "off",
  "vim_mode": false,
  "projects_online_by_default": true,
  "terminal": {
    "font_family": "FiraCode Nerd Font Mono",
    "blinking": "off"
  },
  "languages": {
    "C": {
      "format_on_save": "language_server",
      "preferred_line_length": 64,
      "soft_wrap": "preferred_line_length"
    }
  }
}
```

    # Debugger

Zed uses the [Debug Adapter Protocol (DAP)](https://microsoft.github.io/debug-adapter-protocol/) to provide debugging functionality across multiple programming languages.
DAP is a standardized protocol that defines how debuggers, editors, and IDEs communicate with each other.
It allows Zed to support various debuggers without needing to implement language-specific debugging logic.
Zed implements the client side of the protocol, and various _debug adapters_ implement the server side.

This protocol enables features like setting breakpoints, stepping through code, inspecting variables,
and more, in a consistent manner across different programming languages and runtime environments.

## Supported Languages

To debug code written in a specific language, Zed needs to find a debug adapter for that language. Some debug adapters are provided by Zed without additional setup, and some are provided by [language extensions](./extensions/debugger-extensions.md). The following languages currently have debug adapters available:

<!-- keep this sorted -->

- [C](./languages/c.md#debugging) (built-in)
- [C++](./languages/cpp.md#debugging) (built-in)
- [Go](./languages/go.md#debugging) (built-in)
- [JavaScript](./languages/javascript.md#debugging) (built-in)
- [PHP](./languages/php.md#debugging) (built-in)
- [Python](./languages/python.md#debugging) (built-in)
- [Ruby](./languages/ruby.md#debugging) (provided by extension)
- [Rust](./languages/rust.md#debugging) (built-in)
- [Swift](./languages/swift.md#debugging) (provided by extension)
- [TypeScript](./languages/typescript.md#debugging) (built-in)

> If your language isn't listed, you can contribute by adding a debug adapter for it. Check out our [debugger extensions](./extensions/debugger-extensions.md) documentation for more information.

Follow those links for language- and adapter-specific information and examples, or read on for more about Zed's general debugging features that apply to all adapters.

## Getting Started

For most languages, the fastest way to get started is to run {#action debugger::Start} ({#kb debugger::Start}). This opens the _new process modal_, which shows you a contextual list of preconfigured debug tasks for the current project. Debug tasks are created from tests, entry points (like a `main` function), and from other sources — consult the documentation for your language for full information about what's supported.

You can open the same modal by clicking the "plus" button at the top right of the debug panel.

For languages that don't provide preconfigured debug tasks (this includes C, C++, and some extension-supported languages), you can define debug configurations in the `.zed/debug.json` file in your project root. This file should be an array of configuration objects:

```json
[
  {
    "adapter": "CodeLLDB",
    "label": "First configuration"
    // ...
  },
  {
    "adapter": "Debugpy",
    "label": "Second configuration"
    // ...
  }
]
```

Check the documentation for your language for example configurations covering typical use-cases. Once you've added configurations to `.zed/debug.json`, they'll appear in the list in the new process modal.

Zed will also load debug configurations from `.vscode/launch.json`, and show them in the new process modal if no configurations are found in `.zed/debug.json`.

### Launching & Attaching

Zed debugger offers two ways to debug your program; you can either _launch_ a new instance of your program or _attach_ to an existing process.
Which one you choose depends on what you are trying to achieve.

When launching a new instance, Zed (and the underlying debug adapter) can often do a better job at picking up the debug information compared to attaching to an existing process, since it controls the lifetime of a whole program.
Running unit tests or a debug build of your application is a good use case for launching.

Compared to launching, attaching to an existing process might seem inferior, but that's far from truth; there are cases where you cannot afford to restart your program, because for example, the bug is not reproducible outside of a production environment or some other circumstances.

## Configuration

While configuration fields are debug adapter-dependent, most adapters support the following fields:

```json
[
  {
    // The label for the debug configuration and used to identify the debug session inside the debug panel & new process modal
    "label": "Example Start debugger config",
    // The debug adapter that Zed should use to debug the program
    "adapter": "Example adapter name",
    // Request:
    //  - launch: Zed will launch the program if specified, or show a debug terminal with the right configuration
    //  - attach: Zed will attach to a running program to debug it, or when the process_id is not specified, will show a process picker (only supported for node currently)
    "request": "launch",
    // The program to debug. This field supports path resolution with ~ or . symbols.
    "program": "path_to_program",
    // cwd: defaults to the current working directory of your project ($ZED_WORKTREE_ROOT)
    "cwd": "$ZED_WORKTREE_ROOT"
  }
]
```

All configuration fields support [task variables](./tasks.md#variables).

### Build tasks

Zed also allows embedding a Zed task in a `build` field that is run before the debugger starts. This is useful for setting up the environment or running any necessary setup steps before the debugger starts.

```json
[
  {
    "label": "Build Binary",
    "adapter": "CodeLLDB",
    "program": "path_to_program",
    "request": "launch",
    "build": {
      "command": "make",
      "args": ["build", "-j8"]
    }
  }
]
```

Build tasks can also refer to the existing tasks by unsubstituted label:

```json
[
  {
    "label": "Build Binary",
    "adapter": "CodeLLDB",
    "program": "path_to_program",
    "request": "launch",
    "build": "my build task" // Or "my build task for $ZED_FILE"
  }
]
```

### Automatic scenario creation

Given a Zed task, Zed can automatically create a scenario for you. Automatic scenario creation also powers our scenario creation from gutter.
Automatic scenario creation is currently supported for Rust, Go, Python, JavaScript, and TypeScript.

## Breakpoints

To set a breakpoint, simply click next to the line number in the editor gutter.
Breakpoints can be tweaked depending on your needs; to access additional options of a given breakpoint, right-click on the breakpoint icon in the gutter and select the desired option.
At present, you can:

- Add a log to a breakpoint, which will output a log message whenever that breakpoint is hit.
- Make the breakpoint conditional, which will only stop at the breakpoint when the condition is met. The syntax for conditions is adapter-specific.
- Add a hit count to a breakpoint, which will only stop at the breakpoint after it's hit a certain number of times.
- Disable a breakpoint, which will prevent it from being hit while leaving it visible in the gutter.

Some debug adapters (e.g. CodeLLDB and JavaScript) will also _verify_ whether your breakpoints can be hit; breakpoints that cannot be hit are surfaced more prominently in the UI.

All breakpoints enabled for a given project are also listed in "Breakpoints" item in your debugging session UI. From "Breakpoints" item in your UI you can also manage exception breakpoints.
The debug adapter will then stop whenever an exception of a given kind occurs. Which exception types are supported depends on the debug adapter.

## Settings

The settings for the debugger are grouped under the `debugger` key in `settings.json`:

- `dock`: Determines the position of the debug panel in the UI.
- `stepping_granularity`: Determines the stepping granularity.
- `save_breakpoints`: Whether the breakpoints should be reused across Zed sessions.
- `button`: Whether to show the debug button in the status bar.
- `timeout`: Time in milliseconds until timeout error when connecting to a TCP debug adapter.
- `log_dap_communications`: Whether to log messages between active debug adapters and Zed.
- `format_dap_log_messages`: Whether to format DAP messages when adding them to the debug adapter logger.

### Dock

- Description: The position of the debug panel in the UI.
- Default: `bottom`
- Setting: debugger.dock

**Options**

1. `left` - The debug panel will be docked to the left side of the UI.
2. `right` - The debug panel will be docked to the right side of the UI.
3. `bottom` - The debug panel will be docked to the bottom of the UI.

```json
"debugger": {
  "dock": "bottom"
},
```

### Stepping granularity

- Description: The Step granularity that the debugger will use
- Default: `line`
- Setting: `debugger.stepping_granularity`

**Options**

1. Statement - The step should allow the program to run until the current statement has finished executing.
   The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
   For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.

```json
{
  "debugger": {
    "stepping_granularity": "statement"
  }
}
```

2. Line - The step should allow the program to run until the current source line has executed.

```json
{
  "debugger": {
    "stepping_granularity": "line"
  }
}
```

3. Instruction - The step should allow one instruction to execute (e.g. one x86 instruction).

```json
{
  "debugger": {
    "stepping_granularity": "instruction"
  }
}
```

### Save Breakpoints

- Description: Whether the breakpoints should be saved across Zed sessions.
- Default: `true`
- Setting: `debugger.save_breakpoints`

**Options**

`boolean` values

```json
{
  "debugger": {
    "save_breakpoints": true
  }
}
```

### Button

- Description: Whether the button should be displayed in the debugger toolbar.
- Default: `true`
- Setting: `debugger.show_button`

**Options**

`boolean` values

```json
{
  "debugger": {
    "show_button": true
  }
}
```

### Timeout

- Description: Time in milliseconds until timeout error when connecting to a TCP debug adapter.
- Default: `2000`
- Setting: `debugger.timeout`

**Options**

`integer` values

```json
{
  "debugger": {
    "timeout": 3000
  }
}
```

### Inline Values

- Description: Whether to enable editor inlay hints showing the values of variables in your code during debugging sessions.
- Default: `true`
- Setting: `inlay_hints.show_value_hints`

**Options**

```json
{
  "inlay_hints": {
    "show_value_hints": false
  }
}
```

Inline value hints can also be toggled from the Editor Controls menu in the editor toolbar.

### Log Dap Communications

- Description: Whether to log messages between active debug adapters and Zed. (Used for DAP development)
- Default: false
- Setting: debugger.log_dap_communications

**Options**

`boolean` values

```json
{
  "debugger": {
    "log_dap_communications": true
  }
}
```

### Format Dap Log Messages

- Description: Whether to format DAP messages when adding them to the debug adapter logger. (Used for DAP development)
- Default: false
- Setting: debugger.format_dap_log_messages

**Options**

`boolean` values

```json
{
  "debugger": {
    "format_dap_log_messages": true
  }
}
```

### Customizing Debug Adapters

- Description: Custom program path and arguments to override how Zed launches a specific debug adapter.
- Default: Adapter-specific
- Setting: `dap.$ADAPTER.binary` and `dap.$ADAPTER.args`

You can pass `binary`, `args`, or both. `binary` should be a path to a _debug adapter_ (like `lldb-dap`) not a _debugger_ (like `lldb` itself). The `args` setting overrides any arguments that Zed would otherwise pass to the adapter.

```json
{
  "dap": {
    "CodeLLDB": {
      "binary": "/Users/name/bin/lldb-dap",
      "args": ["--wait-for-debugger"]
    }
  }
}
```

## Theme

The Debugger supports the following theme options:

- `debugger.accent`: Color used to accent breakpoint & breakpoint-related symbols
- `editor.debugger_active_line.background`: Background color of active debug line

## Troubleshooting

If you're running into problems with the debugger, please [open a GitHub issue](https://github.com/zed-industries/zed/issues/new?template=04_bug_debugger.yml) or [schedule an onboarding call](https://cal.com/team/zed-research/debugger) with us so we can help understand and fix your issue.

There are also some features you can use to gather more information about the problem:

- When you have a session running in the debug panel, you can run the {#action dev::CopyDebugAdapterArguments} action to copy a JSON blob to the clipboard that describes how Zed initialized the session. This is especially useful when the session failed to start, and is great context to add if you open a GitHub issue.
- You can also use the {#action dev::OpenDebugAdapterLogs} action to see a trace of all of Zed's communications with debug adapters during the most recent debug sessions.

    # Developing Zed

See the platform-specific instructions for building Zed from source:

- [macOS](./development/macos.md)
- [Linux](./development/linux.md)
- [Windows](./development/windows.md)

If you'd like to develop collaboration features, additionally see:

- [Local Collaboration](./development/local-collaboration.md)

## Keychain access

Zed stores secrets in the system keychain.

However, when running a development build of Zed on macOS (and perhaps other
platforms) trying to access the keychain results in a lot of keychain prompts
that require entering your password over and over.

On macOS this is caused by the development build not having a stable identity.
Even if you choose the "Always Allow" option, the OS will still prompt you for
your password again the next time something changes in the binary.

This quickly becomes annoying and impedes development speed.

That is why, by default, when running a development build of Zed an alternative
credential provider is used in order to bypass the system keychain.

> Note: This is **only** the case for development builds. For all non-development
> release channels the system keychain is always used.

If you need to test something out using the real system keychain in a
development build, run Zed with the following environment variable set:

```
ZED_DEVELOPMENT_USE_KEYCHAIN=1
```

## Performance Measurements

Zed includes a frame time measurement system that can be used to profile how long it takes to render each frame. This is particularly useful when comparing rendering performance between different versions or when optimizing frame rendering code.

### Using ZED_MEASUREMENTS

To enable performance measurements, set the `ZED_MEASUREMENTS` environment variable:

```sh
export ZED_MEASUREMENTS=1
```

When enabled, Zed will print frame rendering timing information to stderr, showing how long each frame takes to render.

### Performance Comparison Workflow

Here's a typical workflow for comparing frame rendering performance between different versions:

1. **Enable measurements:**

   ```sh
   export ZED_MEASUREMENTS=1
   ```

2. **Test the first version:**

   - Checkout the commit you want to measure
   - Run Zed in release mode and use it for 5-10 seconds: `cargo run --release &> version-a`

3. **Test the second version:**

   - Checkout another commit you want to compare
   - Run Zed in release mode and use it for 5-10 seconds: `cargo run --release &> version-b`

4. **Generate comparison:**

   ```sh
   script/histogram version-a version-b
   ```

The `script/histogram` tool can accept as many measurement files as you like and will generate a histogram visualization comparing the frame rendering performance data between the provided versions.

## Contributor links

- [CONTRIBUTING.md](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md)
- [Releases](./development/releases.md)
- [Debugging Crashes](./development/debugging-crashes.md)
- [Code of Conduct](https://zed.dev/code-of-conduct)
- [Zed Contributor License](https://zed.dev/cla)

    # Using a debugger

> **DISCLAIMER**: This is not documentation for [configuring Zed's debugger](../debugger.md).
> Rather, it is intended to provide information on how to use a debugger while developing Zed itself to both Zed employees and external contributors.

## Using Zed's built-in debugger

While the Zed project is open you can open the `New Process Modal` and select the `Debug` tab. There you can see to debug configurations to debug Zed with, one for GDB and one for LLDB. Select the configuration you want and Zed will build and launch the binary.

Please note, GDB isn't supported on arm Macbooks

## Release build profile considerations

By default, builds using the release profile (release is the profile used for production builds, i.e. nightly, preview, and stable) include limited debug info.

This is done by setting the `profile.(release).debug` field in the root `Cargo.toml` field to `"limited"`.

The official documentation for the `debug` field can be found [here](https://doc.rust-lang.org/cargo/reference/profiles.html#debug).
But the TLDR is that `"limited"` strips type and variable level debug info.

In release builds, this is done to reduce the binary size, as type and variable level debug info is not required, and does not impact the usability of generated stack traces.

However, while the type and variable level debug info is not required for good stack traces, it is very important for a good experience using debuggers,
as without the type and variable level debug info, the debugger has no way to resolve local variables, inspect them, format them using pretty-printers, etc.

Therefore, in order to use a debugger to it's fullest extent when debugging a release build, you must compile a new Zed binary, with full debug info.

The simplest way to do this, is to use the `--config` flag to override the `debug` field in the root `Cargo.toml` file when running `cargo run` or `cargo build` like so:

```sh
cargo run --config 'profile.release.debug="full"'
cargo build --config 'profile.release.debug="full"'
```

> If you wish to avoid passing the `--config` flag on every invocation of `cargo`. You may also change the section in the [root `Cargo.toml`](https://github.com/zed-industries/zed/blob/main/Cargo.toml)
>
> from
>
> ```toml
> [profile.release]
> debug = "limited"
> ```
>
> to
>
> ```toml
> [profile.release]
> debug = "full"
> ```
>
> This will ensure all invocations of `cargo run --release` or `cargo build --release` will compile with full debug info.
>
> **WARNING:** Make sure to avoid committing these changes!

## Running Zed with a shell debugger GDB/LLDB

### Background

When installing rust through rustup, (the recommended way to do so when developing Zed, see the documentation for getting started on your platform [here](../development.md))
a few additional scripts are installed and put on your path to assist with debugging binaries compiled with rust.

These are `rust-gdb` and `rust-lldb` respectively.

You can read more information about these scripts and why they are useful [here](https://michaelwoerister.github.io/2015/03/27/rust-xxdb.html) if you are interested.

However, the summary is that they are simple shell scripts that wrap the standard `gdb` and `lldb` commands, injecting the relevant commands and flags to enable additional
rust-specific features such as pretty-printers and type information.

Therefore, in order to use `rust-gdb` or `rust-lldb`, you must have `gdb` or `lldb` installed on your system. If you don't have them installed, you will need to install them in a manner appropriate for your platform.

According to the [previously linked article](https://michaelwoerister.github.io/2015/03/27/rust-xxdb.html), "The minimum supported debugger versions are GDB 7.7 and LLDB 310. However, the general rule is: the newer the better." Therefore, it is recommended to install the latest version of `gdb` or `lldb` if possible.

> **Note**: `rust-gdb` is not installed by default on Windows, as `gdb` support for windows is not very stable. It is recommended to use `lldb` with `rust-lldb` instead on Windows.

If you are unfamiliar with `gdb` or `lldb`, you can learn more about them [here](https://www.gnu.org/software/gdb/) and [here](https://lldb.llvm.org/) respectively.

### Usage with Zed

After following the steps above for including full debug info when compiling Zed,
You can either run `rust-gdb` or `rust-lldb` on the compiled Zed binary after building it with `cargo build`, by running one of the following commands:

```
rust-gdb target/debug/zed
rust-lldb target/debug/zed
```

Alternatively, you can attach to a running instance of Zed (such as an instance of Zed started using `cargo run`) by running one of the following commands:

```
rust-gdb -p <pid>
rust-lldb -p <pid>
```

Where `<pid>` is the process ID of the Zed instance you want to attach to.

To get the process ID of a running Zed instance, you can use your systems process management tools such as `Task Manager` on windows or `Activity Monitor` on macOS.

Alternatively, you can run the `ps aux | grep zed` command on macOS and Linux or `Get-Process | Select-Object Id, ProcessName` in an instance of PowerShell on Windows.

#### Debugging Panics and Crashes

Debuggers can be an excellent tool for debugging the cause of panics and crashes in all programs, including Zed.

By default, when a process that `gdb` or `lldb` is attached to hits an exception such as a panic, the debugger will automatically stop at the point of the panic and allow you to inspect the state of the program.

Most likely, the point at which the debugger stops will be deep in the rust standard library panic or exception handling code, so you will need to navigate up the stack trace to find the actual cause of the panic.

This can be accomplished using the `backtrace` command in combination with the `frame select` command in `lldb`, with similar commands available in `gdb`.

Once the program is stopped, you will not be able to continue execution as you can before an exception is hit. However, you can jump around to different stack frames, and inspect the values of variables and expressions
within each frame, which can be very useful in identifying the root cause of the crash.

You can find additional information on debugging Zed crashes [here](./debugging-crashes.md).

    # Debugging Crashes

When Zed panics or otherwise crashes, Zed sends a message to a sidecar process which inspects the memory of the crashing editor to create a [minidump](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/getting_started_with_breakpad.md#the-minidump-file-format) file in `~/Library/Logs/Zed` or `$XDG_DATA_HOME/zed/logs`. This minidump can be used to generate backtraces for the stacks of all threads.

If you have enabled Zed's telemetry these will be uploaded to us when you restart the app. They end up in a [Slack channel](https://zed-industries.slack.com/archives/C0977J9MA1Y) and in [Sentry](https://zed-dev.sentry.io/issues) (both of which are Zed-staff-only).

These crash reports contain rich information; but they are hard to read because they don't contain spans or symbol information. You can still work with them locally by downloading sources and an unstripped binary (or separate symbols file) for your Zed release and running:

```sh
zstd -d ~/.local/share/zed/<uuid>.dmp -o minidump.dmp
minidump-stackwalk minidump.dmp
```

Alongside the minidump file in your logs dir, there should be a `<uuid>.json` which contains additional metadata like the panic message, span, and system specs.

## Using a Debugger

If you can reproduce the crash consistently, a debugger can be used to inspect the state of the program at the time of the crash, often providing useful insights into the cause of the crash.

You can read more about setting up and using a debugger with Zed, and specifically for debugging crashes [here](./debuggers.md#debugging-panics-and-crashes)

    # Building Zed for FreeBSD

Note, FreeBSD is not currently a supported platform, and so this is a work-in-progress.

## Repository

Clone the [Zed repository](https://github.com/zed-industries/zed).

## Dependencies

- Install the necessary system packages and rustup:

  ```sh
  script/freebsd
  ```

  If preferred, you can inspect [`script/freebsd`](https://github.com/zed-industries/zed/blob/main/script/freebsd) and perform the steps manually.

## Building from source

Once the dependencies are installed, you can build Zed using [Cargo](https://doc.rust-lang.org/cargo/).

For a debug build of the editor:

```sh
cargo run
```

And to run the tests:

```sh
cargo test --workspace
```

In release mode, the primary user interface is the `cli` crate. You can run it in development with:

```sh
cargo run -p cli
```

### WebRTC Notice

Currently, building `webrtc-sys` on FreeBSD fails due to missing upstream support and unavailable prebuilt binaries. As a result, some collaboration features (audio calls and screensharing) that depend on WebRTC are temporarily disabled.

See [Issue #15309: FreeBSD Support] and [Discussion #29550: Unofficial FreeBSD port for Zed] for more.

## Troubleshooting

### Cargo errors claiming that a dependency is using unstable features

Try `cargo clean` and `cargo build`.

    # Zed Development: Glossary

These are some terms and structures frequently used throughout the zed codebase.

This is a best effort list and a work in progress.

<!--
TBD: Glossary Improvement

Questions:

- Can we generate this list from doc comments throughout zed?
- We should have a section that shows the various UI parts and their names. (Can't do that in the channel.)
-->

## Naming conventions

These are generally true for the whole codebase. Note that Name can be anything
here. An example would be `AnyElement` and `LspStore`.

- `AnyName`: A type erased version of _name_. Think `Box<dyn NameTrait>`.
- `NameStore`: A wrapper type which abstracts over whether operations are running locally or on a remote.

## GPUI

### State management

- `App`: A singleton which holds the full application state including all the entities. Crucially: `App` is not `Send`, which means that `App` only exists on the thread that created it (which is the main/UI thread, usually). Thus, if you see a `&mut App`, know that you're on UI thread.
- `Context`: A wrapper around the `App` struct with specialized behavior for a specific `Entity`. Think of it as `(&mut App, Entity<V>)`. The specialized behavior is surfaced in the API surface of `Context`. E.g., `App::spawn` takes an `AsyncFnOnce(AsyncApp) -> Ret`, whereas `Context::spawn` takes an `AsyncFnOnce(WeakEntity<V>, AsyncApp) -> Ret`.
- `AsyncApp`: An owned version of `App` for use in async contexts. This type is _still_ not `Send` (so `AsyncApp` = you're on the main thread) and any use of it may be fallible (to account for the fact that the `App` might've been terminated by the time this closure runs).
  The convenience of `AsyncApp` lies in the fact that you usually interface with `App` via `&mut App`, which would be inconvenient to use with async closures; `AsyncApp` is owned, so you can use it in async closures with no sweat.
- `AppContext` A trait which abstracts over `App`, `AsyncApp` & `Context` and their Test versions.
- `Task`: A future running or scheduled to run on the background or foreground
  executor. In contradiction to regular Futures Tasks do not need `.await` to start running. You do need to await them to get the result of the task.
- `Executor`: Used to spawn tasks that run either on the foreground or background thread. Try to run the tasks on the background thread.
  - `BackgroundExecutor`: A threadpool running `Task`s.
  - `ForegroundExecutor`: The main thread running `Task`s.
- `Entity`: A strong, well-typed reference to a struct which is managed by gpui. Effectively a pointer/map key into the `App::EntityMap`.
- `WeakEntity`: A runtime checked reference to an `Entity` which may no longer exist. Similar to [`std::rc::Weak`](https://doc.rust-lang.org/std/rc/struct.Weak.html).
- `Global`: A singleton type which has only one value, that is stored in the `App`.
- `Event`: A datatype which can be send by an `Entity` to subscribers
- `Action`: An event that represents a user's keyboard input that can be handled by listeners
  Example: `file finder: toggle`
- `Observing`: reacting entities notifying they've changed
- `Subscription`: An event handler that is used to react to the changes of state in the application.
  1. Emitted event handling
  2. Observing `{new,release,on notify}` of an entity

### UI

- `View`: An `Entity` which can produce an `Element` through its implementation of `Render`.
- `Element`: A type that can be laid out and painted to the screen.
- `element expression`: An expression that builds an element tree, example:

```rust
h_flex()
    .id(text[i])
    .relative()
    .when(selected, |this| {
        this.child(
            div()
                .h_4()
                .absolute()
                etc etc
```

- `Component`: A builder which can be rendered turning it into an `Element`.
- `Dispatch tree`: TODO
- `Focus`: The place where keystrokes are handled first
- `Focus tree`: Path from the place that has the current focus to the UI Root. Example <img> TODO

## Zed UI

- `Window`: A struct in zed representing a zed window in your desktop environment (see image below). There can be multiple if you have multiple zed instances open. Mostly passed around for rendering.
- `Modal`: A UI element that floats on top of the rest of the UI
- `Picker`: A struct representing a list of items in floating on top of the UI (Modal). You can select an item and confirm. What happens on select or confirm is determined by the picker's delegate. (The 'Model' in the image below is a picker.)
- `PickerDelegate`: A trait used to specialize behavior for a `Picker`. The `Picker` stores the `PickerDelegate` in the field delegate.
- `Center`: The middle of the zed window, the center is split into multiple `Pane`s. In the codebase this is a field on the `Workspace` struct. (see image below).
- `Pane`: An area in the `Center` where we can place items, such as an editor, multi-buffer or terminal (see image below).
- `Panel`: An `Entity` implementing the `Panel` trait. These can be placed in a `Dock`. In the image below we see the: `ProjectPanel` in the left dock, the `DebugPanel` in the bottom dock, and `AgentPanel` in the right dock. Note `Editor` does not implement `Panel` and hence is not a `Panel`.
- `Dock`: A UI element similar to a `Pane` which can be opened and hidden. There can be up to 3 docks open at a time, left right and below the center. A dock contains one or more `Panel`s not `Pane`s. (see image).
  <img width="1921" height="1080" alt="image" src="https://github.com/user-attachments/assets/2cb1170e-2850-450d-89bb-73622b5d07b2" />

- `Project`: One or more `Worktree`s
- `Worktree`: Represents either local or remote files.
  <img width="552" height="1118" alt="image" src="https://github.com/user-attachments/assets/da5c58e4-b02e-4038-9736-27e3509fdbfa" />

- [Multibuffer](https://zed.dev/docs/multibuffers): A list of Editors, a multi-buffer allows editing multiple files simultaneously. A multi-buffer opens when an operation in Zed returns multiple locations, examples: _search_ or _go to definition_. See project search in the image below.

<img width="800" height="886" alt="image" src="https://github.com/user-attachments/assets/d59dcecd-8ab6-4172-8fb6-b1fc3c3eaf9d" />

## Editor

- `Editor`: _The_ text editor, nearly everything in zed is an `Editor`, even single line inputs. Each pane in the image above contains one or more `Editor` instances.
- `Workspace`: The root of the window
- `Entry`: A file, dir, pending dir or unloaded dir.
- `Buffer`: The in-memory representation of a 'file' together with relevant data such as syntax trees, git status and diagnostics.
- `pending selection`: You have mouse down and you're dragging but you have not yet released.

## Collab

- `Collab session`: Multiple users working in a shared `Project`
- `Upstream client`: The zed client which has shared their workspace
- `Downstream client`: The zed client joining a shared workspace

## Debugger

- `DapStore`: Is an entity that manages debugger sessions
- `debugger::Session`: Is an entity that manages the lifecycle of a debug session and communication with DAPS
- `BreakpointStore`: Is an entity that manages breakpoints states in local and remote instances of Zed
- `DebugSession`: Manages a debug session's UI and running state
- `RunningState`: Directily manages all the views of a debug session
- `VariableList`: The variable and watch list view of a debug session
- `Console`: TODO
- `Terminal`: TODO
- `BreakpointList`: TODO

    # Building Zed for Linux

## Repository

Clone down the [Zed repository](https://github.com/zed-industries/zed).

## Dependencies

- Install [rustup](https://www.rust-lang.org/tools/install)

- Install the necessary system libraries:

  ```sh
  script/linux
  ```

  If you prefer to install the system libraries manually, you can find the list of required packages in the `script/linux` file.

### Backend Dependencies (optional) {#backend-dependencies}

If you are looking to develop Zed collaboration features using a local collaboration server, please see: [Local Collaboration](./local-collaboration.md) docs.

## Building from source

Once the dependencies are installed, you can build Zed using [Cargo](https://doc.rust-lang.org/cargo/).

For a debug build of the editor:

```sh
cargo run
```

And to run the tests:

```sh
cargo test --workspace
```

In release mode, the primary user interface is the `cli` crate. You can run it in development with:

```sh
cargo run -p cli
```

## Installing a development build

You can install a local build on your machine with:

```sh
./script/install-linux
```

This will build zed and the cli in release mode and make them available at `~/.local/bin/zed`, installing .desktop files to `~/.local/share`.

> **_Note_**: If you encounter linker errors similar to the following:
>
> ```bash
> error: linking with `cc` failed: exit status: 1 ...
> = note: /usr/bin/ld: /tmp/rustcISMaod/libaws_lc_sys-79f08eb6d32e546e.rlib(f8e4fd781484bd36-bcm.o): in function `aws_lc_0_25_0_handle_cpu_env':
>           /aws-lc/crypto/fipsmodule/cpucap/cpu_intel.c:(.text.aws_lc_0_25_0_handle_cpu_env+0x63): undefined reference to `__isoc23_sscanf'
>           /usr/bin/ld: /tmp/rustcISMaod/libaws_lc_sys-79f08eb6d32e546e.rlib(f8e4fd781484bd36-bcm.o): in function `pkey_rsa_ctrl_str':
>           /aws-lc/crypto/fipsmodule/evp/p_rsa.c:741:(.text.pkey_rsa_ctrl_str+0x20d): undefined reference to `__isoc23_strtol'
>           /usr/bin/ld: /aws-lc/crypto/fipsmodule/evp/p_rsa.c:752:(.text.pkey_rsa_ctrl_str+0x258): undefined reference to `__isoc23_strtol'
>           collect2: error: ld returned 1 exit status
>   = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
>   = note: use the `-l` flag to specify native libraries to link
>   = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)
> error: could not compile `remote_server` (bin "remote_server") due to 1 previous error
> ```
>
> **Cause**:
> this is caused by known bugs in aws-lc-rs(doesn't support GCC >= 14): [FIPS fails to build with GCC >= 14](https://github.com/aws/aws-lc-rs/issues/569)
> & [GCC-14 - build failure for FIPS module](https://github.com/aws/aws-lc/issues/2010)
>
> You can refer to [linux: Linker error for remote_server when using script/install-linux](https://github.com/zed-industries/zed/issues/24880) for more information.
>
> **Workarounds**:
> Set the remote server target to `x86_64-unknown-linux-gnu` like so `export REMOTE_SERVER_TARGET=x86_64-unknown-linux-gnu; script/install-linux`

## Wayland & X11

Zed supports both X11 and Wayland. By default, we pick whichever we can find at runtime. If you're on Wayland and want to run in X11 mode, use the environment variable `WAYLAND_DISPLAY=''`.

## Notes for packaging Zed

Thank you for taking on the task of packaging Zed!

### Technical requirements

Zed has two main binaries:

- You will need to build `crates/cli` and make its binary available in `$PATH` with the name `zed`.
- You will need to build `crates/zed` and put it at `$PATH/to/cli/../../libexec/zed-editor`. For example, if you are going to put the cli at `~/.local/bin/zed` put zed at `~/.local/libexec/zed-editor`. As some linux distributions (notably Arch) discourage the use of `libexec`, you can also put this binary at `$PATH/to/cli/../../lib/zed/zed-editor` (e.g. `~/.local/lib/zed/zed-editor`) instead.
- If you are going to provide a `.desktop` file you can find a template in `crates/zed/resources/zed.desktop.in`, and use `envsubst` to populate it with the values required. This file should also be renamed to `$APP_ID.desktop` so that the file [follows the FreeDesktop standards](https://github.com/zed-industries/zed/issues/12707#issuecomment-2168742761). You should also make this desktop file executable (`chmod 755`).
- You will need to ensure that the necessary libraries are installed. You can get the current list by [inspecting the built binary](https://github.com/zed-industries/zed/blob/935cf542aebf55122ce6ed1c91d0fe8711970c82/script/bundle-linux#L65-L67) on your system.
- For an example of a complete build script, see [script/bundle-linux](https://github.com/zed-industries/zed/blob/935cf542aebf55122ce6ed1c91d0fe8711970c82/script/bundle-linux).
- You can disable Zed's auto updates and provide instructions for users who try to update Zed manually by building (or running) Zed with the environment variable `ZED_UPDATE_EXPLANATION`. For example: `ZED_UPDATE_EXPLANATION="Please use flatpak to update zed."`.
- Make sure to update the contents of the `crates/zed/RELEASE_CHANNEL` file to 'nightly', 'preview', or 'stable', with no newline. This will cause Zed to use the credentials manager to remember a user's login.

### Other things to note

At Zed, our priority has been to move fast and bring the latest technology to our users. We've long been frustrated at having software that is slow, out of date, or hard to configure, and so we've built our editor to those tastes.

However, we realize that many distros have other priorities. We want to work with everyone to bring Zed to their favorite platforms. But there is a long way to go:

- Zed is a fast-moving early-phase project. We typically release 2-3 builds per week to fix user-reported issues and release major features.
- There are a couple of other `zed` binaries that may be present on Linux systems ([1](https://openzfs.github.io/openzfs-docs/man/v2.2/8/zed.8.html), [2](https://zed.brimdata.io/docs/commands/zed)). If you want to rename our CLI binary because of these issues, we suggest `zedit`, `zeditor`, or `zed-cli`.
- Zed automatically installs the correct version of common developer tools in the same way as rustup/rbenv/pyenv, etc. We understand this is contentious, [see here](https://github.com/zed-industries/zed/issues/12589).
- We allow users to install extensions locally and from [zed-industries/extensions](https://github.com/zed-industries/extensions). These extensions may install further tooling as needed, such as language servers. In the long run, we would like to make this safer, [see here](https://github.com/zed-industries/zed/issues/12358).
- Zed connects to several online services by default (AI, telemetry, collaboration). AI and our telemetry can be disabled by your users with their zed settings or by patching our [default settings file](https://github.com/zed-industries/zed/blob/main/assets/settings/default.json).
- As a result of the above issues, zed currently does not play nice with sandboxes, [see here](https://github.com/zed-industries/zed/pull/12006#issuecomment-2130421220)

## Flatpak

> Zed's current Flatpak integration exits the sandbox on startup. Workflows that rely on Flatpak's sandboxing may not work as expected.

To build & install the Flatpak package locally follow the steps below:

1. Install Flatpak for your distribution as outlined [here](https://flathub.org/setup).
2. Run the `script/flatpak/deps` script to install the required dependencies.
3. Run `script/flatpak/bundle-flatpak`.
4. Now the package has been installed and has a bundle available at `target/release/{app-id}.flatpak`.

## Memory profiling

[`heaptrack`](https://github.com/KDE/heaptrack) is quite useful for diagnosing memory leaks. To install it:

```sh
$ sudo apt install heaptrack heaptrack-gui
$ cargo install cargo-heaptrack
```

Then, to build and run Zed with the profiler attached:

```sh
$ cargo heaptrack -b zed
```

When this zed instance is exited, terminal output will include a command to run `heaptrack_interpret` to convert the `*.raw.zst` profile to a `*.zst` file which can be passed to `heaptrack_gui` for viewing.

## Troubleshooting

### Cargo errors claiming that a dependency is using unstable features

Try `cargo clean` and `cargo build`.

    # Local Collaboration

1. Ensure you have access to our cloud infrastructure. If you don't have access, you can't collaborate locally at this time.

2. Make sure you've installed Zed's dependencies for your platform:

- [macOS](#macos)
- [Linux](#linux)
- [Windows](#backend-windows)

Note that `collab` can be compiled only with MSVC toolchain on Windows

3. Clone down our cloud repository and follow the instructions in the cloud README

4. Setup the local database for your platform:

- [macOS & Linux](#database-unix)
- [Windows](#database-windows)

5. Run collab:

- [macOS & Linux](#run-collab-unix)
- [Windows](#run-collab-windows)

## Backend Dependencies

If you are developing collaborative features of Zed, you'll need to install the dependencies of zed's `collab` server:

- PostgreSQL
- LiveKit
- Foreman

You can install these dependencies natively or run them under Docker.

### macOS

1. Install [Postgres.app](https://postgresapp.com) or [postgresql via homebrew](https://formulae.brew.sh/formula/postgresql@15):

   ```sh
   brew install postgresql@15
   ```

2. Install [Livekit](https://formulae.brew.sh/formula/livekit) and [Foreman](https://formulae.brew.sh/formula/foreman)

   ```sh
   brew install livekit foreman
   ```

- Follow the steps in the [collab README](https://github.com/zed-industries/zed/blob/main/crates/collab/README.md) to configure the Postgres database for integration tests

Alternatively, if you have [Docker](https://www.docker.com/) installed you can bring up all the `collab` dependencies using Docker Compose.

### Linux

1. Install [Postgres](https://www.postgresql.org/download/linux/)

   ```sh
   sudo apt-get install postgresql                    # Ubuntu/Debian
   sudo pacman -S postgresql                          # Arch Linux
   sudo dnf install postgresql postgresql-server      # RHEL/Fedora
   sudo zypper install postgresql postgresql-server   # OpenSUSE
   ```

2. Install [Livekit](https://github.com/livekit/livekit-cli)

   ```sh
   curl -sSL https://get.livekit.io/cli | bash
   ```

3. Install [Foreman](https://theforeman.org/manuals/3.15/quickstart_guide.html)

### Windows {#backend-windows}

> This section is still in development. The instructions are not yet complete.

- Install [Postgres](https://www.postgresql.org/download/windows/)
- Install [Livekit](https://github.com/livekit/livekit), optionally you can add the `livekit-server` binary to your `PATH`.

Alternatively, if you have [Docker](https://www.docker.com/) installed you can bring up all the `collab` dependencies using Docker Compose.

### Docker {#Docker}

If you have docker or podman available, you can run the backend dependencies inside containers with Docker Compose:

```sh
docker compose up -d
```

## Database setup

Before you can run the `collab` server locally, you'll need to set up a `zed` Postgres database.

### On macOS and Linux {#database-unix}

```sh
script/bootstrap
```

This script will set up the `zed` Postgres database, and populate it with some users. It requires internet access, because it fetches some users from the GitHub API.

The script will seed the database with various content defined by:

```sh
cat crates/collab/seed.default.json
```

To use a different set of admin users, you can create your own version of that json file and export the `SEED_PATH` environment variable. Note that the usernames listed in the admins list currently must correspond to valid GitHub users.

```json
{
  "admins": ["admin1", "admin2"],
  "channels": ["zed"]
}
```

### On Windows {#database-windows}

```powershell
.\script\bootstrap.ps1
```

## Testing collaborative features locally

### On macOS and Linux {#run-collab-unix}

Ensure that Postgres is configured and running, then run Zed's collaboration server and the `livekit` dev server:

```sh
foreman start
# OR
docker compose up
```

Alternatively, if you're not testing voice and screenshare, you can just run `collab` and `cloud`, and not the `livekit` dev server:

```sh
cargo run -p collab -- serve all
```

```sh
cd ../cloud; cargo make dev
```

In a new terminal, run two or more instances of Zed.

```sh
script/zed-local -3
```

This script starts one to four instances of Zed, depending on the `-2`, `-3` or `-4` flags. Each instance will be connected to the local `collab` server, signed in as a different user from `.admins.json` or `.admins.default.json`.

### On Windows {#run-collab-windows}

Since `foreman` is not available on Windows, you can run the following commands in separate terminals:

```powershell
cargo run --package=collab -- serve all
```

If you have added the `livekit-server` binary to your `PATH`, you can run:

```powershell
livekit-server --dev
```

Otherwise,

```powershell
.\path\to\livekit-serve.exe --dev
```

You'll also need to start the cloud server:

```powershell
cd ..\cloud; cargo make dev
```

In a new terminal, run two or more instances of Zed.

```powershell
node .\script\zed-local -2
```

Note that this requires `node.exe` to be in your `PATH`.

## Running a local collab server

> [!NOTE]
> Because of recent changes to our authentication system, Zed will not be able to authenticate itself with, and therefore use, a local collab server.

If you want to run your own version of the zed collaboration service, you can, but note that this is still under development, and there is no support for authentication nor extensions.

Configuration is done through environment variables. By default it will read the configuration from [`.env.toml`](https://github.com/zed-industries/zed/blob/main/crates/collab/.env.toml) and you should use that as a guide for setting this up.

By default Zed assumes that the DATABASE_URL is a Postgres database, but you can make it use Sqlite by compiling with `--features sqlite` and using a sqlite DATABASE_URL with `?mode=rwc`.

To authenticate you must first configure the server by creating a seed.json file that contains at a minimum your github handle. This will be used to create the user on demand.

```json
{
  "admins": ["nathansobo"]
}
```

By default the collab server will seed the database when first creating it, but if you want to add more users you can explicitly reseed them with `SEED_PATH=./seed.json cargo run -p collab seed`

Then when running the zed client you must specify two environment variables, `ZED_ADMIN_API_TOKEN` (which should match the value of `API_TOKEN` in .env.toml) and `ZED_IMPERSONATE` (which should match one of the users in your seed.json)

    # Building Zed for macOS

## Repository

Clone down the [Zed repository](https://github.com/zed-industries/zed).

## Dependencies

- Install [rustup](https://www.rust-lang.org/tools/install)

- Install [Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12) from the macOS App Store, or from the [Apple Developer](https://developer.apple.com/download/all/) website. Note this requires a developer account.

> Ensure you launch Xcode after installing, and install the macOS components, which is the default option. If you are on macOS 26 (Tahoe) you will need to use `--features gpui/runtime_shaders` or add the feature in the root `Cargo.toml`

- Install [Xcode command line tools](https://developer.apple.com/xcode/resources/)

  ```sh
  xcode-select --install
  ```

- Ensure that the Xcode command line tools are using your newly installed copy of Xcode:

  ```sh
  sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
  sudo xcodebuild -license accept
  ```

- Install `cmake` (required by [a dependency](https://docs.rs/wasmtime-c-api-impl/latest/wasmtime_c_api/))

  ```sh
  brew install cmake
  ```

### Backend Dependencies (optional) {#backend-dependencies}

If you are looking to develop Zed collaboration features using a local collaboration server, please see: [Local Collaboration](./local-collaboration.md) docs.

## Building Zed from Source

Once you have the dependencies installed, you can build Zed using [Cargo](https://doc.rust-lang.org/cargo/).

For a debug build:

```sh
cargo run
```

For a release build:

```sh
cargo run --release
```

And to run the tests:

```sh
cargo test --workspace
```

## Troubleshooting

### Error compiling metal shaders

```sh
error: failed to run custom build command for gpui v0.1.0 (/Users/path/to/zed)`**

xcrun: error: unable to find utility "metal", not a developer tool or in PATH
```

Try `sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer`

If you're on macOS 26, try `xcodebuild -downloadComponent MetalToolchain`

### Cargo errors claiming that a dependency is using unstable features

Try `cargo clean` and `cargo build`.

### Error: 'dispatch/dispatch.h' file not found

If you encounter an error similar to:

```sh
src/platform/mac/dispatch.h:1:10: fatal error: 'dispatch/dispatch.h' file not found

Caused by:
  process didn't exit successfully

  --- stdout
  cargo:rustc-link-lib=framework=System
  cargo:rerun-if-changed=src/platform/mac/dispatch.h
  cargo:rerun-if-env-changed=TARGET
  cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_aarch64-apple-darwin
  cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_aarch64_apple_darwin
  cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS
```

This file is part of Xcode. Ensure you have installed the Xcode command line tools and set the correct path:

```sh
xcode-select --install
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```

Additionally, set the `BINDGEN_EXTRA_CLANG_ARGS` environment variable:

```sh
export BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$(xcrun --show-sdk-path)"
```

Then clean and rebuild the project:

```sh
cargo clean
cargo run
```

### Tests failing due to `Too many open files (os error 24)`

This error seems to be caused by OS resource constraints. Installing and running tests with `cargo-nextest` should resolve the issue.

- `cargo install cargo-nextest --locked`
- `cargo nextest run --workspace --no-fail-fast`

## Tips & Tricks

### Avoiding continual rebuilds

If you are finding that Zed is continually rebuilding root crates, it may be because
you are pointing your development Zed at the codebase itself.

This causes problems because `cargo run` exports a bunch of environment
variables which are picked up by the `rust-analyzer` that runs in the development
build of Zed. These environment variables are in turn passed to `cargo check`, which
invalidates the build cache of some of the crates we depend on.

You can easily avoid running the built binary on the checked-out Zed codebase using `cargo run
~/path/to/other/project` to ensure that you don't hit this.

### Speeding up verification

If you are building Zed a lot, you may find that macOS continually verifies new
builds which can add a few seconds to your iteration cycles.

To fix this, you can:

- Run `sudo spctl developer-mode enable-terminal` to enable the Developer Tools panel in System Settings.
- In System Settings, search for "Developer Tools" and add your terminal (e.g. iTerm or Ghostty) to the list under "Allow applications to use developer tools"
- Restart your terminal.

Thanks to the nextest developers for publishing [this](https://nexte.st/docs/installation/macos/#gatekeeper).

    # Zed Releases

Read about Zed's release channels [here](https://zed.dev/faq#what-are-the-release-channels).

## Wednesday release process

You will need write access to the Zed repository to do this.

Credentials for various services used in this process can be found in 1Password.

---

1. Checkout `main` and ensure your working copy is clean.

1. Run `git fetch && git pull` to ensure you have the latest commits locally.

1. Run `git fetch --tags --force` to forcibly ensure your local tags are in sync with the remote.

1. Run `./script/get-stable-channel-release-notes`.

   - Follow the instructions at the end of the script and aggregate the release notes into one structure.

1. Run `./script/bump-zed-minor-versions`.

   - Push the tags and branches as instructed.

1. Run `./script/get-preview-channel-changes`.

   - Take the script's output and build release notes by organizing each release note line into a category.
   - Use a prior release for the initial outline.
   - Make sure to append the `Credit` line, if present, to the end of the release note line.

1. Once release drafts are up on [GitHub Releases](https://github.com/zed-industries/zed/releases), paste both preview and stable release notes into each and **save**.

   - **Do not publish the drafts, yet.**

1. Check the release assets.

   - Ensure the stable and preview release jobs have finished without error.
   - Ensure each draft has the proper number of assets—releases currently have 10 assets each.
   - Download the artifacts for each release draft and test that you can run them locally.

1. Publish stable / preview drafts, one at a time.

   - Use [Vercel](https://vercel.com/zed-industries/zed-dev) to check the progress of the website rebuild.
     The release will be public once the rebuild has completed.

1. Publish the release email that has been sent to [Kit](https://kit.com).

   - Make sure to double-check that the email is correct before publishing.
   - We sometimes correct things here and there that didn't translate from GitHub's renderer to Kit's.

1. Build social media posts based on the popular items in stable.
   - You can use the [prior week's post chain](https://zed.dev/channel/tweets-23331) as your outline.
   - Stage the copy and assets using [Buffer](https://buffer.com), for both X and BlueSky.
   - Publish both, one at a time, ensuring both are posted to each respective platform.

## Patch release process

If your PR fixes a panic or a crash, you should cherry-pick it to the current stable and preview branches.
If your PR fixes a regression in recently released code, you should cherry-pick it to preview.

You will need write access to the Zed repository to do this:

---

1. Send a PR containing your change to `main` as normal.

1. Once it is merged, cherry-pick the commit locally to either of the release branches (`v0.XXX.x`).

   - In some cases, you may have to handle a merge conflict.
     More often than not, this will happen when cherry-picking to stable, as the stable branch is more "stale" than the preview branch.

1. After the commit is cherry-picked, run `./script/trigger-release {preview|stable}`.
   This will bump the version numbers, create a new release tag, and kick off a release build.

   - This can also be run from the [GitHub Actions UI](https://github.com/zed-industries/zed/actions/workflows/bump_patch_version.yml):
     ![](https://github.com/zed-industries/zed/assets/1486634/9e31ae95-09e1-4c7f-9591-944f4f5b63ea)

1. Once release drafts are up on [GitHub Releases](https://github.com/zed-industries/zed/releases), proofread and edit the release notes as needed and **save**.

   - **Do not publish the drafts, yet.**

1. Check the release assets.

   - Ensure the stable / preview release jobs have finished without error.
   - Ensure each draft has the proper number of assets—releases currently have 10 assets each.
   - Download the artifacts for each release draft and test that you can run them locally.

1. Publish stable / preview drafts, one at a time.
   - Use [Vercel](https://vercel.com/zed-industries/zed-dev) to check the progress of the website rebuild.
     The release will be public once the rebuild has completed.

## Nightly release process

In addition to the public releases, we also have a nightly build that we encourage employees to use.
Nightly is released by cron once a day, and can be shipped as often as you'd like.
There are no release notes or announcements, so you can just merge your changes to main and run `./script/trigger-release nightly`.

    # Building Zed for Windows

> The following commands may be executed in any shell.

## Repository

Clone down the [Zed repository](https://github.com/zed-industries/zed).

## Dependencies

- Install [rustup](https://www.rust-lang.org/tools/install)

- Install either [Visual Studio](https://visualstudio.microsoft.com/downloads/) with the optional components `MSVC v*** - VS YYYY C++ x64/x86 build tools` and `MSVC v*** - VS YYYY C++ x64/x86 Spectre-mitigated libs (latest)` (`v***` is your VS version and `YYYY` is year when your VS was released. Pay attention to the architecture and change it to yours if needed.)
- Or, if you prefer to have a slimmer installer of only the MSVC compiler tools, you can install the [build tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) (+libs as above) and the "Desktop development with C++" workload.
  But beware this installation is not automatically picked up by rustup. You must initialize your environment variables by first launching the "developer" shell (cmd/powershell) this installation places in the start menu or in Windows Terminal and then compile.
- Install Windows 11 or 10 SDK depending on your system, but ensure that at least `Windows 10 SDK version 2104 (10.0.20348.0)` is installed on your machine. You can download it from the [Windows SDK Archive](https://developer.microsoft.com/windows/downloads/windows-sdk/)
- Install [CMake](https://cmake.org/download) (required by [a dependency](https://docs.rs/wasmtime-c-api-impl/latest/wasmtime_c_api/)). Or you can install it through Visual Studio Installer, then manually add the `bin` directory to your `PATH`, for example: `C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin`.

If you can't compile Zed, make sure that you have at least the following components installed in case of a Visual Studio installation:

```json
{
  "version": "1.0",
  "components": [
    "Microsoft.VisualStudio.Component.CoreEditor",
    "Microsoft.VisualStudio.Workload.CoreEditor",
    "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
    "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake",
    "Microsoft.VisualStudio.Component.VC.CMake.Project",
    "Microsoft.VisualStudio.Component.Windows11SDK.26100",
    "Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre"
  ],
  "extensions": []
}
```

Or if in case of just Build Tools, the following components:

```json
{
  "version": "1.0",
  "components": [
    "Microsoft.VisualStudio.Component.Roslyn.Compiler",
    "Microsoft.Component.MSBuild",
    "Microsoft.VisualStudio.Component.CoreBuildTools",
    "Microsoft.VisualStudio.Workload.MSBuildTools",
    "Microsoft.VisualStudio.Component.Windows10SDK",
    "Microsoft.VisualStudio.Component.VC.CoreBuildTools",
    "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
    "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
    "Microsoft.VisualStudio.Component.Windows11SDK.26100",
    "Microsoft.VisualStudio.Component.VC.CMake.Project",
    "Microsoft.VisualStudio.Component.TextTemplating",
    "Microsoft.VisualStudio.Component.VC.CoreIde",
    "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
    "Microsoft.VisualStudio.Workload.VCTools",
    "Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre"
  ],
  "extensions": []
}
```

The list can be obtained as follows:

- Open the Visual Studio Installer
- Click on `More` in the `Installed` tab
- Click on `Export configuration`

### Backend Dependencies (optional) {#backend-dependencies}

If you are looking to develop Zed collaboration features using a local collaboration server, please see: [Local Collaboration](./local-collaboration.md) docs.

### Notes

You should modify the `pg_hba.conf` file in the `data` directory to use `trust` instead of `scram-sha-256` for the `host` method. Otherwise, the connection will fail with the error `password authentication failed`. The `pg_hba.conf` file typically locates at `C:\Program Files\PostgreSQL\17\data\pg_hba.conf`. After the modification, the file should look like this:

```conf
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
```

Also, if you are using a non-latin Windows version, you must modify the`lc_messages` parameter in the `postgresql.conf` file in the `data` directory to `English_United States.1252` (or whatever UTF8-compatible encoding you have). Otherwise, the database will panic. The `postgresql.conf` file should look like this:

```conf
# lc_messages = 'Chinese (Simplified)_China.936' # locale for system error message strings
lc_messages = 'English_United States.1252'
```

After this, you should restart the `postgresql` service. Press the `win` key + `R` to launch the `Run` window. Type the `services.msc` and hit the `OK` button to open the Services Manager. Then, find the `postgresql-x64-XX` service, right-click on it, and select `Restart`.

## Building from source

Once you have the dependencies installed, you can build Zed using [Cargo](https://doc.rust-lang.org/cargo/).

For a debug build:

```sh
cargo run
```

For a release build:

```sh
cargo run --release
```

And to run the tests:

```sh
cargo test --workspace
```

## Installing from msys2

Zed does not support unofficial MSYS2 Zed packages built for Mingw-w64. Please report any issues you may have with [mingw-w64-zed](https://packages.msys2.org/base/mingw-w64-zed) to [msys2/MINGW-packages/issues](https://github.com/msys2/MINGW-packages/issues?q=is%3Aissue+is%3Aopen+zed).

Please refer to [MSYS2 documentation](https://www.msys2.org/docs/ides-editors/#zed) first.

## Troubleshooting

### Setting `RUSTFLAGS` env var breaks builds

If you set the `RUSTFLAGS` env var, it will override the `rustflags` settings in `.cargo/config.toml` which is required to properly build Zed.

Since these settings can vary from time to time, the build errors you receive may vary from linker errors, to other stranger errors.

If you'd like to add extra rust flags, you may do 1 of the following in `.cargo/config.toml`:

Add your flags in the build section

```toml
[build]
rustflags = ["-C", "symbol-mangling-version=v0", "--cfg", "tokio_unstable"]
```

Add your flags in the windows target section

```toml
[target.'cfg(target_os = "windows")']
rustflags = [
    "--cfg",
    "windows_slim_errors",
    "-C",
    "target-feature=+crt-static",
]
```

Or, you can create a new `.cargo/config.toml` in the same folder as the Zed repo (see below). This is particularly useful if you are doing CI builds since you don't have to edit the original `.cargo/config.toml`.

```
upper_dir
├── .cargo          // <-- Make this folder
│   └── config.toml // <-- Make this file
└── zed
    ├── .cargo
    │   └── config.toml
    └── crates
        ├── assistant
        └── ...
```

In the new (above) `.cargo/config.toml`, if we wanted to add `--cfg gles` to our rustflags, it would look like this

```toml
[target.'cfg(all())']
rustflags = ["--cfg", "gles"]
```

### Cargo errors claiming that a dependency is using unstable features

Try `cargo clean` and `cargo build`.

### `STATUS_ACCESS_VIOLATION`

This error can happen if you are using the "rust-lld.exe" linker. Consider trying a different linker.

If you are using a global config, consider moving the Zed repository to a nested directory and add a `.cargo/config.toml` with a custom linker config in the parent directory.

See this issue for more information [#12041](https://github.com/zed-industries/zed/issues/12041)

### Invalid RC path selected

Sometimes, depending on the security rules applied to your laptop, you may get the following error while compiling Zed:

```
error: failed to run custom build command for `zed(C:\Users\USER\src\zed\crates\zed)`

Caused by:
  process didn't exit successfully: `C:\Users\USER\src\zed\target\debug\build\zed-b24f1e9300107efc\build-script-build` (exit code: 1)
  --- stdout
  cargo:rerun-if-changed=../../.git/logs/HEAD
  cargo:rustc-env=ZED_COMMIT_SHA=25e2e9c6727ba9b77415588cfa11fd969612adb7
  cargo:rustc-link-arg=/stack:8388608
  cargo:rerun-if-changed=resources/windows/app-icon.ico
  package.metadata.winresource does not exist
  Selected RC path: 'bin\x64\rc.exe'

  --- stderr
  The system cannot find the path specified. (os error 3)
warning: build failed, waiting for other jobs to finish...
```

In order to fix this issue, you can manually set the `ZED_RC_TOOLKIT_PATH` environment variable to the RC toolkit path. Usually, you can set it to:
`C:\Program Files (x86)\Windows Kits\10\bin\<SDK_version>\x64`.

See this [issue](https://github.com/zed-industries/zed/issues/18393) for more information.

### Build fails: Path too long

You may receive an error like the following when building

```
error: failed to get `pet` as a dependency of package `languages v0.1.0 (D:\a\zed-windows-builds\zed-windows-builds\crates\languages)`

Caused by:
  failed to load source for dependency `pet`

Caused by:
  Unable to update https://github.com/microsoft/python-environment-tools.git?rev=ffcbf3f28c46633abd5448a52b1f396c322e0d6c#ffcbf3f2

Caused by:
  path too long: 'C:/Users/runneradmin/.cargo/git/checkouts/python-environment-tools-903993894b37a7d2/ffcbf3f/crates/pet-conda/tests/unix/conda_env_without_manager_but_found_in_history/some_other_location/conda_install/conda-meta/python-fastjsonschema-2.16.2-py310hca03da5_0.json'; class=Filesystem (30)
```

In order to solve this, you can enable longpath support for git and Windows.

For git: `git config --system core.longpaths true`

And for Windows with this PS command:

```powershell
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
```

For more information on this, please see [win32 docs](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell)

(note that you will need to restart your system after enabling longpath support)

### Graphics issues

#### Zed fails to launch

Currently, Zed uses Vulkan as its graphics API on Windows. However, Vulkan isn't always the most reliable on Windows, so if Zed fails to launch, it's likely a Vulkan-related issue.

You can check the Zed log at:
`C:\Users\YOU\AppData\Local\Zed\logs\Zed.log`

If you see messages like:

- `Zed failed to open a window: NoSupportedDeviceFound`
- `ERROR_INITIALIZATION_FAILED`
- `GPU Crashed`
- `ERROR_SURFACE_LOST_KHR`

Then Vulkan might not be working properly on your system. In most cases, updating your GPU drivers may help resolve this.

If there's nothing Vulkan-related in the logs and you happen to have Bandicam installed, try uninstalling it. Zed is currently not compatible with Bandicam.

    # Diagnostics

Zed gets its diagnostics from the language servers and supports both push and pull variants of the LSP which makes it compatible with all existing language servers.

# Regular diagnostics

By default, Zed displays all diagnostics as underlined text in the editor and the scrollbar.

Editor diagnostics could be filtered with the

```json5
"diagnostics_max_severity": null
```

editor setting (possible values: `"off"`, `"error"`, `"warning"`, `"info"`, `"hint"`, `null` (default, all diagnostics)).

The scrollbar ones are configured with the

```json5
"scrollbar": {
  "diagnostics": "all",
}
```

configuration (possible values: `"none"`, `"error"`, `"warning"`, `"information"`, `"all"` (default))

The diagnostics could be hovered to display a tooltip with full, rendered diagnostic message.
Or, `editor::GoToDiagnostic` and `editor::GoToPreviousDiagnostic` could be used to navigate between diagnostics in the editor, showing a popover for the currently active diagnostic.

# Inline diagnostics (Error lens)

Zed supports showing diagnostic as lens to the right of the code.
This is disabled by default, but can either be temporarily turned on (or off) using the editor menu, or permanently, using the

```json5
"diagnostics": {
  "inline": {
    "enabled": true,
    "max_severity": null, // same values as the `diagnostics_max_severity` from the editor settings
  }
}
```

# Other UI places

## Project Panel

Project panel can have its entries coloured based on the severity of the diagnostics in the file.

To configure, use

```json5
"project_panel": {
  "show_diagnostics": "all",
}
```

configuration (possible values: `"off"`, `"errors"`, `"all"` (default))

## Editor tabs

Similar to the project panel, editor tabs can be colorized with the

```json5
"tabs": {
  "show_diagnostics": "off",
}
```

configuration (possible values: `"off"` (default), `"errors"`, `"all"`)

    # Environment Variables

_**Note**: The following only applies to Zed 0.152.0 and later._

Multiple features in Zed are affected by environment variables:

- Tasks
- Built-in terminal
- Look-up of language servers
- Language servers

In order to make the best use of these features, it's helpful to understand where Zed gets its environment variables from and how they're used.

## Where does Zed get its environment variables from?

How Zed was started — whether it's icon was clicked in the macOS Dock or in a Linux window manager, or whether it was started via the CLI `zed` that comes with Zed — influences which environment variables Zed can use.

### Launched from the CLI

If Zed is opened via the CLI (`zed`), it will inherit the environment variables from the surrounding shell session.

That means if you do

```
$ export MY_ENV_VAR=hello
$ zed .
```

the environment variable `MY_ENV_VAR` is now available inside Zed. For example, in the built-in terminal.

Starting with Zed 0.152.0, the CLI `zed` will _always_ pass along its environment to Zed, regardless of whether a Zed instance was previously running or not. Prior to Zed 0.152.0 this was not the case and only the first Zed instance would inherit the environment variables.

### Launched via window manager, Dock, or launcher

When Zed has been launched via the macOS Dock, or a GNOME or KDE icon on Linux, or an application launcher like Alfred or Raycast, it has no surrounding shell environment from which to inherit its environment variables.

In order to still have a useful environment, Zed spawns a login shell in the user's home directory and gets its environment. This environment is then set on the Zed _process_. That means all Zed windows and projects will inherit that home directory environment.

Since that can lead to problems for users that require different environment variables for a project (because they use `direnv`, or `asdf`, or `mise`, ... in that project), when opening project, Zed spawns another login shell. This time in the project's directory. The environment from that login shell is _not_ set on the process (because that would mean opening a new project changes the environment for all Zed windows). Instead, the environment is stored and passed along when running tasks, opening terminals, or spawning language servers.

## Where and how are environment variables used?

There are two sets of environment variables:

1. Environment variables of the Zed process
2. Environment variables stored per project

The variables from (1) are always used, since they are stored on the process itself and every spawned process (tasks, terminals, language servers, ...) will inherit them by default.

The variables from (2) are used explicitly, depending on the feature.

### Tasks

Tasks are spawned with an combined environment. In order of precedence (low to high, with the last overwriting the first):

- the Zed process environment
- if the project was opened from the CLI: the CLI environment
- if the project was not opened from the CLI: the project environment variables obtained by running a login shell in the project's root folder
- optional, explicitly configured environment in settings

### Built-in terminal

Built-in terminals, like tasks, are spawned with an combined environment. In order of precedence (low to high):

- the Zed process environment
- if the project was opened from the CLI: the CLI environment
- if the project was not opened from the CLI: the project environment variables obtained by running a login shell in the project's root folder
- optional, explicitly configured environment in settings

### Look-up of language servers

For some languages the language server adapters lookup the binary in the user's `$PATH`. Examples:

- Go
- Zig
- Rust (if [configured to do so](./languages/rust.md#binary))
- C
- TypeScript

For this look-up, Zed uses the following the environment:

- if the project was opened from the CLI: the CLI environment
- if the project was not opened from the CLI: the project environment variables obtained by running a login shell in the project's root folder

### Language servers

After looking up a language server, Zed starts them.

These language server processes always inherit Zed's process environment. But, depending on the language server look-up, additional environment variables might be set or overwrite the process environment.

- If the language server was found in the project environment's `$PATH`, then the project environment's is passed along to the language server process. Where the project environment comes from depends on how the project was opened, via CLI or not. See previous point on look-up of language servers.
- If the language servers was not found in the project environment, Zed tries to install it globally and start it globally. In that case, the process will inherit Zed's process environment, and — if the project was opened via ClI — from the CLI.

    # Extensions

Zed lets you add new functionality using user-defined extensions.

- [Installing Extensions](./extensions/installing-extensions.md)
- [Developing Extensions](./extensions/developing-extensions.md)
  - [Developing Language Extensions](./extensions/languages.md)
  - [Developing Debugger Extensions](./extensions/debugger-extensions.md)
  - [Developing Themes](./extensions/themes.md)
  - [Developing Icon Themes](./extensions/icon-themes.md)
  - [Developing Slash Commands](./extensions/slash-commands.md)
  - [Developing MCP Servers](./extensions/mcp-extensions.md)

    # Debugger Extensions

[Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol) Servers can be exposed as extensions for use in the [debugger](../debugger.md).

## Defining Debugger Extensions

A given extension may provide one or more DAP servers.
Each DAP server must be registered in the `extension.toml`:

```toml
[debug_adapters.my-debug-adapter]
# Optional relative path to the JSON schema for the debug adapter configuration schema. Defaults to `debug_adapter_schemas/$DEBUG_ADAPTER_NAME_ID.json`.
# Note that while this field is optional, a schema is mandatory.
schema_path = "relative/path/to/schema.json"
```

Then, in the Rust code for your extension, implement the `get_dap_binary` method on your extension:

```rust
impl zed::Extension for MyExtension {
    fn get_dap_binary(
        &mut self,
        adapter_name: String,
        config: DebugTaskDefinition,
        user_provided_debug_adapter_path: Option<String>,
        worktree: &Worktree,
    ) -> Result<DebugAdapterBinary, String>;
}
```

This method should return the command to start up a debug adapter protocol server, along with any arguments or environment variables necessary for it to function.

If you need to download the DAP server from an external source—like GitHub Releases or npm—you can also do that in this function. Make sure to check for updates only periodically, as this function is called whenever a user spawns a new debug session with your debug adapter.

You must also implement `dap_request_kind`. This function is used to determine whether a given debug scenario will _launch_ a new debuggee or _attach_ to an existing one.
We also use it to determine that a given debug scenario requires running a _locator_.

```rust
impl zed::Extension for MyExtension {
    fn dap_request_kind(
        &mut self,
        _adapter_name: String,
        _config: Value,
    ) -> Result<StartDebuggingRequestArgumentsRequest, String>;
}
```

These two functions are sufficient to expose your debug adapter in `debug.json`-based user workflows, but you should strongly consider implementing `dap_config_to_scenario` as well.

```rust
impl zed::Extension for MyExtension {
    fn dap_config_to_scenario(
        &mut self,
        _adapter_name: DebugConfig,
    ) -> Result<DebugScenario, String>;
}
```

`dap_config_to_scenario` is used when the user spawns a session via new process modal UI. At a high level, it takes a generic debug configuration (that isn't specific to any
debug adapter) and tries to turn it into a concrete debug scenario for your adapter.
Put another way, it is supposed to answer the question: "Given a program, a list of arguments, current working directory and environment variables, what would the configuration for spawning this debug adapter look like?".

## Defining Debug Locators

Zed offers an automatic way to create debug scenarios with _debug locators_.
A locator locates the debug target and figures out how to spawn a debug session for it. Thanks to locators, we can automatically convert existing user tasks (e.g. `cargo run`) and convert them into debug scenarios (e.g. `cargo build` followed by spawning a debugger with `target/debug/my_program` as the program to debug).

> Your extension can define its own debug locators even if it does not expose a debug adapter. We strongly recommend doing so when your extension already exposes language tasks, as it allows users to spawn a debug session without having to manually configure the debug adapter.

Locators can (but don't have to) be agnostic to the debug adapter they are used with. They are simply responsible for locating the debug target and figuring out how to spawn a debug session for it. This allows for a more flexible and extensible debugging experience.

Your extension can define one or more debug locators. Each debug locator must be registered in the `extension.toml`:

```toml
[debug_locators.my-debug-locator]
```

Locators have two components.
First, each locator is ran on each available task to figure out if any of the available locators can provide a debug scenario for a given task. This is done by calling `dap_locator_create_scenario`.

```rust
impl zed::Extension for MyExtension {
    fn dap_locator_create_scenario(
        &mut self,
        _locator_name: String,
        _build_task: TaskTemplate,
        _resolved_label: String,
        _debug_adapter_name: String,
    ) -> Option<DebugScenario>;
}
```

This function should return `Some` debug scenario when that scenario defines a debugging counterpart to a given user task.
Note that a `DebugScenario` can include a [build task](../debugger.md#build-tasks). If there is one, we will execute `run_dap_locator` after a build task is finished successfully.

```rust
impl zed::Extension for MyExtension {
    fn run_dap_locator(
        &mut self,
        _locator_name: String,
        _build_task: TaskTemplate,
    ) -> Result<DebugRequest, String>;
}
```

`run_dap_locator` is useful in case you cannot determine a build target deterministically. Some build systems may produce artifacts whose names are not known up-front.
Note however that you do _not_ need to go through a 2-phase resolution; if you can determine the full debug configuration with just `dap_locator_create_scenario`, you can omit `build` property on a returned `DebugScenario`. Please also note that your locator **will be** called with tasks it's unlikely to accept; thus you should take some effort to return `None` early before performing any expensive operations.

## Available Extensions

Check out all the DAP servers that have already been exposed as extensions [on Zed's site](https://zed.dev/extensions?filter=debug-adapters).

We recommend taking a look at their repositories as a way to understand how they are generally created and structured.

## Testing

To test your new Debug Adapter Protocol server extension, you can [install it as a dev extension](./developing-extensions.md#developing-an-extension-locally).

    # Developing Extensions

## Extension Capabilities

Extensions can add the following capabilities to Zed:

- [Languages](./languages.md)
- [Debuggers](./debugger-extensions.md)
- [Themes](./themes.md)
- [Icon Themes](./icon-themes.md)
- [Slash Commands](./slash-commands.md)
- [MCP Servers](./mcp-extensions.md)

## Developing an Extension Locally

Before starting to develop an extension for Zed, be sure to [install Rust via rustup](https://www.rust-lang.org/tools/install).

> Rust must be installed via rustup. If you have Rust installed via homebrew or otherwise, installing dev extensions will not work.

When developing an extension, you can use it in Zed without needing to publish it by installing it as a _dev extension_.

From the extensions page, click the `Install Dev Extension` button (or the {#action zed::InstallDevExtension} action) and select the directory containing your extension.

If you need to troubleshoot, you can check the Zed.log ({#action zed::OpenLog}) for additional output. For debug output, close and relaunch zed with the `zed --foreground` from the command line which show more verbose INFO level logging.

If you already have a published extension with the same name installed, your dev extension will override it.

After installing the `Extensions` page will indicate that that the upstream extension is "Overridden by dev extension".

Pre-installed extensions with the same name have to be uninstalled before installing the dev extension. See [#31106](https://github.com/zed-industries/zed/issues/31106) for more.

## Directory Structure of a Zed Extension

A Zed extension is a Git repository that contains an `extension.toml`. This file must contain some
basic information about the extension:

```toml
id = "my-extension"
name = "My extension"
version = "0.0.1"
schema_version = 1
authors = ["Your Name <you@example.com>"]
description = "My cool extension"
repository = "https://github.com/your-name/my-zed-extension"
```

In addition to this, there are several other optional files and directories that can be used to add functionality to a Zed extension. An example directory structure of an extension that provides all capabilities is as follows:

```
my-extension/
  extension.toml
  Cargo.toml
  src/
    lib.rs
  languages/
    my-language/
      config.toml
      highlights.scm
  themes/
    my-theme.json
```

## WebAssembly

Procedural parts of extensions are written in Rust and compiled to WebAssembly. To develop an extension that includes custom code, include a `Cargo.toml` like this:

```toml
[package]
name = "my-extension"
version = "0.0.1"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
zed_extension_api = "0.1.0"
```

Use the latest version of the [`zed_extension_api`](https://crates.io/crates/zed_extension_api) available on crates.io. Make sure it's still [compatible with Zed versions](https://github.com/zed-industries/zed/blob/main/crates/extension_api#compatible-zed-versions) you want to support.

In the `src/lib.rs` file in your Rust crate you will need to define a struct for your extension and implement the `Extension` trait, as well as use the `register_extension!` macro to register your extension:

```rs
use zed_extension_api as zed;

struct MyExtension {
    // ... state
}

impl zed::Extension for MyExtension {
    // ...
}

zed::register_extension!(MyExtension);
```

> `stdout`/`stderr` is forwarded directly to the Zed process. In order to see `println!`/`dbg!` output from your extension, you can start Zed in your terminal with a `--foreground` flag.

## Forking and cloning the repo

1. Fork the repo

> Note: It is very helpful if you fork the `zed-industries/extensions` repo to a personal GitHub account instead of a GitHub organization, as this allows Zed staff to push any needed changes to your PR to expedite the publishing process.

2. Clone the repo to your local machine

```sh
# Substitute the url of your fork here:
# git clone https://github.com/zed-industries/extensions
cd extensions
git submodule init
git submodule update
```

## Publishing your extension

To publish an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).

In your PR, do the following:

1. Add your extension as a Git submodule within the `extensions/` directory

```sh
git submodule add https://github.com/your-username/foobar-zed.git extensions/foobar
git add extensions/foobar
```

> All extension submodules must use HTTPS URLs and not SSH URLS (`git@github.com`).

2. Add a new entry to the top-level `extensions.toml` file containing your extension:

```toml
[my-extension]
submodule = "extensions/my-extension"
version = "0.0.1"
```

> If your extension is in a subdirectory within the submodule you can use the `path` field to point to where the extension resides.

3. Run `pnpm sort-extensions` to ensure `extensions.toml` and `.gitmodules` are sorted

Once your PR is merged, the extension will be packaged and published to the Zed extension registry.

> Extension IDs and names should not contain `zed` or `Zed`, since they are all Zed extensions.

## Updating an extension

To update an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).

In your PR do the following:

1. Update the extension's submodule to the commit of the new version.
2. Update the `version` field for the extension in `extensions.toml`
   - Make sure the `version` matches the one set in `extension.toml` at the particular commit.

If you'd like to automate this process, there is a [community GitHub Action](https://github.com/huacnlee/zed-extension-action) you can use.

    # Icon Themes

Extensions may provide icon themes in order to change the icons Zed uses for folders and files.

## Example extension

The [Material Icon Theme](https://github.com/zed-extensions/material-icon-theme) serves as an example for the structure of an extension containing an icon theme.

## Directory structure

There are two important directories for an icon theme extension:

- `icon_themes`: This directory will contain one or more JSON files containing the icon theme definitions.
- `icons`: This directory contains the icons assets that will be distributed with the extension. You can created subdirectories in this directory, if so desired.

Each icon theme file should adhere to the JSON schema specified at [`https://zed.dev/schema/icon_themes/v0.2.0.json`](https://zed.dev/schema/icon_themes/v0.2.0.json).

Here is an example of the structure of an icon theme:

```json
{
  "$schema": "https://zed.dev/schema/icon_themes/v0.2.0.json",
  "name": "My Icon Theme",
  "author": "Your Name",
  "themes": [
    {
      "name": "My Icon Theme",
      "appearance": "dark",
      "directory_icons": {
        "collapsed": "./icons/folder.svg",
        "expanded": "./icons/folder-open.svg"
      },
      "chevron_icons": {
        "collapsed": "./icons/chevron-right.svg",
        "expanded": "./icons/chevron-down.svg"
      },
      "file_stems": {
        "Makefile": "make"
      },
      "file_suffixes": {
        "mp3": "audio",
        "rs": "rust"
      },
      "file_icons": {
        "audio": { "path": "./icons/audio.svg" },
        "default": { "path": "./icons/file.svg" },
        "make": { "path": "./icons/make.svg" },
        "rust": { "path": "./icons/rust.svg" }
        // ...
      }
    }
  ]
}
```

Each icon path is resolved relative to the root of the extension directory.

In this example, the extension would have a structure like so:

```
extension.toml
icon_themes/
  my-icon-theme.json
icons/
  audio.svg
  chevron-down.svg
  chevron-right.svg
  file.svg
  folder-open.svg
  folder.svg
  rust.svg
```

    # Installing Extensions

You can search for extensions by launching the Zed Extension Gallery by pressing {#kb zed::Extensions} , opening the command palette and selecting {#action zed::Extensions} or by selecting "Zed > Extensions" from the menu bar.

Here you can view the extensions that you currently have installed or search and install new ones.

## Installation Location

- On macOS, extensions are installed in `~/Library/Application Support/Zed/extensions`.
- On Linux, they are installed in either `$XDG_DATA_HOME/zed/extensions` or `~/.local/share/zed/extensions`.

This directory contains two subdirectories:

- `installed`, which contains the source code for each extension.
- `work` which contains files created by the extension itself, such as downloaded language servers.

## Auto installing

To automate extension installation/uninstallation see the docs for [auto_install_extensions](../configuring-zed.md#auto-install-extensions).

    # Language Extensions

Language support in Zed has several components:

- Language metadata and configuration
- Grammar
- Queries
- Language servers

## Language Metadata

Each language supported by Zed must be defined in a subdirectory inside the `languages` directory of your extension.

This subdirectory must contain a file called `config.toml` file with the following structure:

```toml
name = "My Language"
grammar = "my-language"
path_suffixes = ["myl"]
line_comments = ["# "]
```

- `name` (required) is the human readable name that will show up in the Select Language dropdown.
- `grammar` (required) is the name of a grammar. Grammars are registered separately, described below.
- `path_suffixes` is an array of file suffixes that should be associated with this language. Unlike `file_types` in settings, this does not support glob patterns.
- `line_comments` is an array of strings that are used to identify line comments in the language. This is used for the `editor::ToggleComments` keybind: {#kb editor::ToggleComments} for toggling lines of code.
- `tab_size` defines the indentation/tab size used for this language (default is `4`).
- `hard_tabs` whether to indent with tabs (`true`) or spaces (`false`, the default).
- `first_line_pattern` is a regular expression, that in addition to `path_suffixes` (above) or `file_types` in settings can be used to match files which should use this language. For example Zed uses this to identify Shell Scripts by matching the [shebangs lines](https://github.com/zed-industries/zed/blob/main/crates/languages/src/bash/config.toml) in the first line of a script.
- `debuggers` is an array of strings that are used to identify debuggers in the language. When launching a debugger's `New Process Modal`, Zed will order available debuggers by the order of entries in this array.

<!--
TBD: Document `language_name/config.toml` keys

- autoclose_before
- brackets (start, end, close, newline, not_in: ["comment", "string"])
- word_characters
- prettier_parser_name
- opt_into_language_servers
- code_fence_block_name
- scope_opt_in_language_servers
- increase_indent_pattern, decrease_indent_pattern
- collapsed_placeholder
- auto_indent_on_paste, auto_indent_using_last_non_empty_line
- overrides: `[overrides.element]`, `[overrides.string]`
-->

## Grammar

Zed uses the [Tree-sitter](https://tree-sitter.github.io) parsing library to provide built-in language-specific features. There are grammars available for many languages, and you can also [develop your own grammar](https://tree-sitter.github.io/tree-sitter/creating-parsers#writing-the-grammar). A growing list of Zed features are built using pattern matching over syntax trees with Tree-sitter queries. As mentioned above, every language that is defined in an extension must specify the name of a Tree-sitter grammar that is used for parsing. These grammars are then registered separately in extensions' `extension.toml` file, like this:

```toml
[grammars.gleam]
repository = "https://github.com/gleam-lang/tree-sitter-gleam"
rev = "58b7cac8fc14c92b0677c542610d8738c373fa81"
```

The `repository` field must specify a repository where the Tree-sitter grammar should be loaded from, and the `rev` field must contain a Git revision to use, such as the SHA of a Git commit. If you're developing an extension locally and want to load a grammar from the local filesystem, you can use a `file://` URL for `repository`. An extension can provide multiple grammars by referencing multiple tree-sitter repositories.

## Tree-sitter Queries

Zed uses the syntax tree produced by the [Tree-sitter](https://tree-sitter.github.io) query language to implement
several features:

- Syntax highlighting
- Bracket matching
- Code outline/structure
- Auto-indentation
- Code injections
- Syntax overrides
- Text redactions
- Runnable code detection
- Selecting classes, functions, etc.

The following sections elaborate on how [Tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax) enable these
features in Zed, using [JSON syntax](https://www.json.org/json-en.html) as a guiding example.

### Syntax highlighting

In Tree-sitter, the `highlights.scm` file defines syntax highlighting rules for a particular syntax.

Here's an example from a `highlights.scm` for JSON:

```scheme
(string) @string

(pair
  key: (string) @property.json_key)

(number) @number
```

This query marks strings, object keys, and numbers for highlighting. The following is a comprehensive list of captures supported by themes:

| Capture                  | Description                            |
| ------------------------ | -------------------------------------- |
| @attribute               | Captures attributes                    |
| @boolean                 | Captures boolean values                |
| @comment                 | Captures comments                      |
| @comment.doc             | Captures documentation comments        |
| @constant                | Captures constants                     |
| @constructor             | Captures constructors                  |
| @embedded                | Captures embedded content              |
| @emphasis                | Captures emphasized text               |
| @emphasis.strong         | Captures strongly emphasized text      |
| @enum                    | Captures enumerations                  |
| @function                | Captures functions                     |
| @hint                    | Captures hints                         |
| @keyword                 | Captures keywords                      |
| @label                   | Captures labels                        |
| @link_text               | Captures link text                     |
| @link_uri                | Captures link URIs                     |
| @number                  | Captures numeric values                |
| @operator                | Captures operators                     |
| @predictive              | Captures predictive text               |
| @preproc                 | Captures preprocessor directives       |
| @primary                 | Captures primary elements              |
| @property                | Captures properties                    |
| @punctuation             | Captures punctuation                   |
| @punctuation.bracket     | Captures brackets                      |
| @punctuation.delimiter   | Captures delimiters                    |
| @punctuation.list_marker | Captures list markers                  |
| @punctuation.special     | Captures special punctuation           |
| @string                  | Captures string literals               |
| @string.escape           | Captures escaped characters in strings |
| @string.regex            | Captures regular expressions           |
| @string.special          | Captures special strings               |
| @string.special.symbol   | Captures special symbols               |
| @tag                     | Captures tags                          |
| @tag.doctype             | Captures doctypes (e.g., in HTML)      |
| @text.literal            | Captures literal text                  |
| @title                   | Captures titles                        |
| @type                    | Captures types                         |
| @variable                | Captures variables                     |
| @variable.special        | Captures special variables             |
| @variant                 | Captures variants                      |

### Bracket matching

The `brackets.scm` file defines matching brackets.

Here's an example from a `brackets.scm` file for JSON:

```scheme
("[" @open "]" @close)
("{" @open "}" @close)
("\"" @open "\"" @close)
```

This query identifies opening and closing brackets, braces, and quotation marks.

| Capture | Description                                   |
| ------- | --------------------------------------------- |
| @open   | Captures opening brackets, braces, and quotes |
| @close  | Captures closing brackets, braces, and quotes |

### Code outline/structure

The `outline.scm` file defines the structure for the code outline.

Here's an example from an `outline.scm` file for JSON:

```scheme
(pair
  key: (string (string_content) @name)) @item
```

This query captures object keys for the outline structure.

| Capture        | Description                                                                          |
| -------------- | ------------------------------------------------------------------------------------ |
| @name          | Captures the content of object keys                                                  |
| @item          | Captures the entire key-value pair                                                   |
| @context       | Captures elements that provide context for the outline item                          |
| @context.extra | Captures additional contextual information for the outline item                      |
| @annotation    | Captures nodes that annotate outline item (doc comments, attributes, decorators)[^1] |

[^1]: These annotations are used by Assistant when generating code modification steps.

### Auto-indentation

The `indents.scm` file defines indentation rules.

Here's an example from an `indents.scm` file for JSON:

```scheme
(array "]" @end) @indent
(object "}" @end) @indent
```

This query marks the end of arrays and objects for indentation purposes.

| Capture | Description                                        |
| ------- | -------------------------------------------------- |
| @end    | Captures closing brackets and braces               |
| @indent | Captures entire arrays and objects for indentation |

### Code injections

The `injections.scm` file defines rules for embedding one language within another, such as code blocks in Markdown or SQL queries in Python strings.

Here's an example from an `injections.scm` file for Markdown:

```scheme
(fenced_code_block
  (info_string
    (language) @injection.language)
  (code_fence_content) @injection.content)

((inline) @content
 (#set! injection.language "markdown-inline"))
```

This query identifies fenced code blocks, capturing the language specified in the info string and the content within the block. It also captures inline content and sets its language to "markdown-inline".

| Capture             | Description                                                |
| ------------------- | ---------------------------------------------------------- |
| @injection.language | Captures the language identifier for a code block          |
| @injection.content  | Captures the content to be treated as a different language |

Note that we couldn't use JSON as an example here because it doesn't support language injections.

### Syntax overrides

The `overrides.scm` file defines syntactic _scopes_ that can be used to override certain editor settings within specific language constructs.

For example, there is a language-specific setting called `word_characters` that controls which non-alphabetic characters are considered part of a word, for example when you double click to select a variable. In JavaScript, "$" and "#" are considered word characters.

There is also a language-specific setting called `completion_query_characters` that controls which characters trigger autocomplete suggestions. In JavaScript, when your cursor is within a _string_, "-" is should be considered a completion query character. To achieve this, the JavaScript `overrides.scm` file contains the following pattern:

```scheme
[
  (string)
  (template_string)
] @string
```

And the JavaScript `config.toml` contains this setting:

```toml
word_characters = ["#", "$"]

[overrides.string]
completion_query_characters = ["-"]
```

You can also disable certain auto-closing brackets in a specific scope. For example, to prevent auto-closing `'` within strings, you could put the following in the JavaScript `config.toml`:

```toml
brackets = [
  { start = "'", end = "'", close = true, newline = false, not_in = ["string"] },
  # other pairs...
]
```

#### Range inclusivity

By default, the ranges defined in `overrides.scm` are _exclusive_. So in the case above, if you cursor was _outside_ the quotation marks delimiting the string, the `string` scope would not take effect. Sometimes, you may want to make the range _inclusive_. You can do this by adding the `.inclusive` suffix to the capture name in the query.

For example, in JavaScript, we also disable auto-closing of single quotes within comments. And the comment scope must extend all the way to the newline after a line comment. To achieve this, the JavaScript `overrides.scm` contains the following pattern:

```scheme
(comment) @comment.inclusive
```

### Text objects

The `textobjects.scm` file defines rules for navigating by text objects. This was added in Zed v0.165 and is currently used only in Vim mode.

Vim provides two levels of granularity for navigating around files. Section-by-section with `[]` etc., and method-by-method with `]m` etc. Even languages that don't support functions and classes can work well by defining similar concepts. For example CSS defines a rule-set as a method, and a media-query as a class.

For languages with closures, these typically should not count as functions in Zed. This is best-effort however, as languages like JavaScript do not syntactically differentiate syntactically between closures and top-level function declarations.

For languages with declarations like C, provide queries that match `@class.around` or `@function.around`. The `if` and `ic` text objects will default to these if there is no inside.

If you are not sure what to put in textobjects.scm, both [nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects), and the [Helix editor](https://github.com/helix-editor/helix) have queries for many languages. You can refer to the Zed [built-in languages](https://github.com/zed-industries/zed/tree/main/crates/languages/src) to see how to adapt these.

| Capture          | Description                                                             | Vim mode                                         |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| @function.around | An entire function definition or equivalent small section of a file.    | `[m`, `]m`, `[M`,`]M` motions. `af` text object  |
| @function.inside | The function body (the stuff within the braces).                        | `if` text object                                 |
| @class.around    | An entire class definition or equivalent large section of a file.       | `[[`, `]]`, `[]`, `][` motions. `ac` text object |
| @class.inside    | The contents of a class definition.                                     | `ic` text object                                 |
| @comment.around  | An entire comment (e.g. all adjacent line comments, or a block comment) | `gc` text object                                 |
| @comment.inside  | The contents of a comment                                               | `igc` text object (rarely supported)             |

For example:

```scheme
; include only the content of the method in the function
(method_definition
    body: (_
        "{"
        (_)* @function.inside
        "}")) @function.around

; match function.around for declarations with no body
(function_signature_item) @function.around

; join all adjacent comments into one
(comment)+ @comment.around
```

### Text redactions

The `redactions.scm` file defines text redaction rules. When collaborating and sharing your screen, it makes sure that certain syntax nodes are rendered in a redacted mode to avoid them from leaking.

Here's an example from a `redactions.scm` file for JSON:

```scheme
(pair value: (number) @redact)
(pair value: (string) @redact)
(array (number) @redact)
(array (string) @redact)
```

This query marks number and string values in key-value pairs and arrays for redaction.

| Capture | Description                    |
| ------- | ------------------------------ |
| @redact | Captures values to be redacted |

### Runnable code detection

The `runnables.scm` file defines rules for detecting runnable code.

Here's an example from an `runnables.scm` file for JSON:

```scheme
(
    (document
        (object
            (pair
                key: (string
                    (string_content) @_name
                    (#eq? @_name "scripts")
                )
                value: (object
                    (pair
                        key: (string (string_content) @run @script)
                    )
                )
            )
        )
    )
    (#set! tag package-script)
    (#set! tag composer-script)
)
```

This query detects runnable scripts in package.json and composer.json files.

The `@run` capture specifies where the run button should appear in the editor. Other captures, except those prefixed with an underscore, are exposed as environment variables with a prefix of `ZED_CUSTOM_$(capture_name)` when running the code.

| Capture | Description                                            |
| ------- | ------------------------------------------------------ |
| @\_name | Captures the "scripts" key                             |
| @run    | Captures the script name                               |
| @script | Also captures the script name (for different purposes) |

<!--
TBD: `#set! tag`
-->

## Language Servers

Zed uses the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) to provide advanced language support.

An extension may provide any number of language servers. To provide a language server from your extension, add an entry to your `extension.toml` with the name of your language server and the language(s) it applies to. The entry in the list of `languages` has to match the `name` field from the `config.toml` file for that language:

```toml
[language_servers.my-language-server]
name = "My Language LSP"
languages = ["My Language"]
```

Then, in the Rust code for your extension, implement the `language_server_command` method on your extension:

```rust
impl zed::Extension for MyExtension {
    fn language_server_command(
        &mut self,
        language_server_id: &LanguageServerId,
        worktree: &zed::Worktree,
    ) -> Result<zed::Command> {
        Ok(zed::Command {
            command: get_path_to_language_server_executable()?,
            args: get_args_for_language_server()?,
            env: get_env_for_language_server()?,
        })
    }
}
```

You can customize the handling of the language server using several optional methods in the `Extension` trait. For example, you can control how completions are styled using the `label_for_completion` method. For a complete list of methods, see the [API docs for the Zed extension API](https://docs.rs/zed_extension_api).

### Multi-Language Support

If your language server supports additional languages, you can use `language_ids` to map Zed `languages` to the desired [LSP-specific `languageId`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem) identifiers:

```toml

[language-servers.my-language-server]
name = "Whatever LSP"
languages = ["JavaScript", "HTML", "CSS"]

[language-servers.my-language-server.language_ids]
"JavaScript" = "javascript"
"TSX" = "typescriptreact"
"HTML" = "html"
"CSS" = "css"
```

    # MCP Server Extensions

[Model Context Protocol servers](../ai/mcp.md) can be exposed as extensions for use in the Agent Panel.

## Defining MCP Extensions

A given extension may provide one or more MCP servers.
Each MCP server must be registered in the `extension.toml`:

```toml
[context_servers.my-context-server]
```

Then, in the Rust code for your extension, implement the `context_server_command` method on your extension:

```rust
impl zed::Extension for MyExtension {
    fn context_server_command(
        &mut self,
        context_server_id: &ContextServerId,
        project: &zed::Project,
    ) -> Result<zed::Command> {
        Ok(zed::Command {
            command: get_path_to_context_server_executable()?,
            args: get_args_for_context_server()?,
            env: get_env_for_context_server()?,
        })
    }
}
```

This method should return the command to start up an MCP server, along with any arguments or environment variables necessary for it to function.

If you need to download the MCP server from an external source—like GitHub Releases or npm—you can also do that in this function.

## Available Extensions

Check out all the MCP servers that have already been exposed as extensions [on Zed's site](https://zed.dev/extensions?filter=context-servers).

We recommend taking a look at their repositories as a way to understand how they are generally created and structured.

## Testing

To test your new MCP server extension, you can [install it as a dev extension](./developing-extensions.md#developing-an-extension-locally).

    # Slash Commands

Extensions may provide slash commands for use in the Assistant.

## Example extension

To see a working example of an extension that provides slash commands, check out the [`slash-commands-example` extension](https://github.com/zed-industries/zed/tree/main/extensions/slash-commands-example).

This extension can be [installed as a dev extension](./developing-extensions.md#developing-an-extension-locally) if you want to try it out for yourself.

## Defining slash commands

A given extension may provide one or more slash commands. Each slash command must be registered in the `extension.toml`.

For example, here is an extension that provides two slash commands: `/echo` and `/pick-one`:

```toml
[slash_commands.echo]
description = "echoes the provided input"
requires_argument = true

[slash_commands.pick-one]
description = "pick one of three options"
requires_argument = true
```

Each slash command may define the following properties:

- `description`: A description of the slash command that will be shown when completing available commands.
- `requires_argument`: Indicates whether a slash command requires at least one argument to run.

## Implementing slash command behavior

To implement behavior for your slash commands, implement `run_slash_command` for your extension.

This method accepts the slash command that will be run, the list of arguments passed to it, and an optional `Worktree`.

This method returns `SlashCommandOutput`, which contains the textual output of the command in the `text` field. The output may also define `SlashCommandOutputSection`s that contain ranges into the output. These sections are then rendered as creases in the Assistant's context editor.

Your extension should `match` on the command name (without the leading `/`) and then execute behavior accordingly:

```rs
impl zed::Extension for MyExtension {
    fn run_slash_command(
        &self,
        command: SlashCommand,
        args: Vec<String>,
        _worktree: Option<&Worktree>,
    ) -> Result<SlashCommandOutput, String> {
        match command.name.as_str() {
            "echo" => {
                if args.is_empty() {
                    return Err("nothing to echo".to_string());
                }

                let text = args.join(" ");

                Ok(SlashCommandOutput {
                    sections: vec![SlashCommandOutputSection {
                        range: (0..text.len()).into(),
                        label: "Echo".to_string(),
                    }],
                    text,
                })
            }
            "pick-one" => {
                let Some(selection) = args.first() else {
                    return Err("no option selected".to_string());
                };

                match selection.as_str() {
                    "option-1" | "option-2" | "option-3" => {}
                    invalid_option => {
                        return Err(format!("{invalid_option} is not a valid option"));
                    }
                }

                let text = format!("You chose {selection}.");

                Ok(SlashCommandOutput {
                    sections: vec![SlashCommandOutputSection {
                        range: (0..text.len()).into(),
                        label: format!("Pick One: {selection}"),
                    }],
                    text,
                })
            }
            command => Err(format!("unknown slash command: \"{command}\"")),
        }
    }
}
```

## Auto-completing slash command arguments

For slash commands that have arguments, you may also choose to implement `complete_slash_command_argument` to provide completions for your slash commands.

This method accepts the slash command that will be run and the list of arguments passed to it. It returns a list of `SlashCommandArgumentCompletion`s that will be shown in the completion menu.

A `SlashCommandArgumentCompletion` consists of the following properties:

- `label`: The label that will be shown in the completion menu.
- `new_text`: The text that will be inserted when the completion is accepted.
- `run_command`: Whether the slash command will be run when the completion is accepted.

Once again, your extension should `match` on the command name (without the leading `/`) and return the desired argument completions:

```rs
impl zed::Extension for MyExtension {
    fn complete_slash_command_argument(
        &self,
        command: SlashCommand,
        _args: Vec<String>,
    ) -> Result<Vec<SlashCommandArgumentCompletion>, String> {
        match command.name.as_str() {
            "echo" => Ok(vec![]),
            "pick-one" => Ok(vec![
                SlashCommandArgumentCompletion {
                    label: "Option One".to_string(),
                    new_text: "option-1".to_string(),
                    run_command: true,
                },
                SlashCommandArgumentCompletion {
                    label: "Option Two".to_string(),
                    new_text: "option-2".to_string(),
                    run_command: true,
                },
                SlashCommandArgumentCompletion {
                    label: "Option Three".to_string(),
                    new_text: "option-3".to_string(),
                    run_command: true,
                },
            ]),
            command => Err(format!("unknown slash command: \"{command}\"")),
        }
    }
}
```

    # Themes

The `themes` directory in an extension should contain one or more theme files.

Each theme file should adhere to the JSON schema specified at [`https://zed.dev/schema/themes/v0.2.0.json`](https://zed.dev/schema/themes/v0.2.0.json).

See [this blog post](https://zed.dev/blog/user-themes-now-in-preview) for more details about creating themes.

## Theme JSON Structure

The structure of a Zed theme is defined in the [Zed Theme JSON Schema](https://zed.dev/schema/themes/v0.2.0.json).

A Zed theme consists of a Theme Family object including:

- `name`: The name for the theme family
- `author`: The name of the author of the theme family
- `themes`: An array of Themes belonging to the theme family

The core components a Theme object include:

1. Theme Metadata:

   - `name`: The name of the theme
   - `appearance`: Either "light" or "dark"

2. Style Properties under the `style`, such as:

   - `background`: The main background color
   - `foreground`: The main text color
   - `accent`: The accent color used for highlighting and emphasis

3. Syntax Highlighting:

   - `syntax`: An object containing color definitions for various syntax elements (e.g., keywords, strings, comments)

4. UI Elements:

   - Colors for various UI components such as:
     - `element.background`: Background color for UI elements
     - `border`: Border colors for different states (normal, focused, selected)
     - `text`: Text colors for different states (normal, muted, accent)

5. Editor-specific Colors:

   - Colors for editor-related elements such as:
     - `editor.background`: Editor background color
     - `editor.gutter`: Gutter colors
     - `editor.line_number`: Line number colors

6. Terminal Colors:
   - ANSI color definitions for the integrated terminal

We recommend looking at our [existing themes](https://github.com/zed-industries/zed/tree/main/assets/themes) to get a more comprehensive idea of what can be styled.

    # Getting Started

Welcome to Zed! We are excited to have you. Here is a jumping-off point to getting started.

## Download Zed

### macOS

Get the latest stable builds via [the download page](https://zed.dev/download). If you want to download our preview build, you can find it on its [releases page](https://zed.dev/releases/preview). After the first manual installation, Zed will periodically check for install updates.

You can also install Zed stable via Homebrew:

```sh
brew install --cask zed
```

As well as Zed preview:

```sh
brew install --cask zed@preview
```

### Linux

For most Linux users, the easiest way to install Zed is through our installation script:

```sh
curl -f https://zed.dev/install.sh | sh
```

If you'd like to help us test our new features, you can also install our preview build:

```sh
curl -f https://zed.dev/install.sh | ZED_CHANNEL=preview sh
```

This script supports `x86_64` and `AArch64`, as well as common Linux distributions: Ubuntu, Arch, Debian, RedHat, CentOS, Fedora, and more.

If Zed is installed using this installation script, it can be uninstalled at any time by running the shell command `zed --uninstall`. The shell will then prompt you whether you'd like to keep your preferences or delete them. After making a choice, you should see a message that Zed was successfully uninstalled.

If this script is insufficient for your use case, you run into problems running Zed, or there are errors in uninstalling Zed, please see our [Linux-specific documentation](./linux.md).

## Command Palette

The Command Palette is the main way to access pretty much any functionality that's available in Zed. Its keybinding is the first one you should make yourself familiar with. To open it, hit: {#kb command_palette::Toggle}.

![The opened Command Palette](https://zed.dev/img/features/command-palette.jpg)

Try it! Open the Command Palette and type in `new file`. You should see the list of commands being filtered down to `workspace: new file`. Hit return and you end up with a new buffer.

Any time you see instructions that include commands of the form `zed: ...` or `editor: ...` and so on that means you need to execute them in the Command Palette.

## CLI

Zed has a CLI, on Linux this should come with the distribution's Zed package (binary name can vary from distribution to distribution, `zed` will be used later for brevity).
For macOS, the CLI comes in the same package with the editor binary, and could be installed into the system with the `cli: install` Zed command which will create a symlink to the `/usr/local/bin/zed`.
It can also be built from source out of the `cli` crate in this repository.

Use `zed --help` to see the full list of capabilities.
General highlights:

- Opening another empty Zed window: `zed`

- Opening a file or directory in Zed: `zed /path/to/entry` (use `-n` to open in the new window)

- Reading from stdin: `ps axf | zed -`

- Starting Zed with logs in the terminal: `zed --foreground`

- Uninstalling Zed and all its related files: `zed --uninstall`

## Configure Zed

To open your custom settings to set things like fonts, formatting settings, per-language settings, and more, use the {#kb zed::OpenSettings} keybinding.

To see all available settings, open the Command Palette with {#kb command_palette::Toggle} and search for `zed: open default settings`.
You can also check them all out in the [Configuring Zed](./configuring-zed.md) documentation.

## Configure AI in Zed

Zed smoothly integrates LLMs in multiple ways across the editor.
Visit [the AI overview page](./ai/overview.md) to learn how to quickly get started with LLMs on Zed.

## Set up your key bindings

To edit your custom keymap and add or remap bindings, you can either use {#kb zed::OpenKeymapEditor} to spawn the Zed Keymap Editor ({#action zed::OpenKeymapEditor}) or you can directly open your Zed Keymap json (`~/.config/zed/keymap.json`) with {#action zed::OpenKeymap}.

To access the default key binding set, open the Command Palette with {#kb command_palette::Toggle} and search for "zed: open default keymap". See [Key Bindings](./key-bindings.md) for more info.

    ---
description: Zed is a text editor that supports lots of Git features
title: Zed Editor Git integration documentation
---

# Git

Zed currently offers a set of fundamental Git features, with support coming in the future for more advanced ones, like conflict resolution tools, line by line staging, and more.

Here's an overview of all currently supported features:

- Committing
- Staging, pushing, pulling, and fetching
- Project Diff: A multibuffer view of all changes
- Diff indicators in buffers and editor scrollbars
- Inline diff toggle and reverts in the editor for unstaged changes
- Git status in the Project Panel
- Branch creating and switching
- Git blame viewing

## Git Panel

The Git Panel gives you a birds-eye view of the state of your working tree and of Git's staging area.

You can open the Git Panel using {#action git_panel::ToggleFocus}, or by clicking the Git icon in the status bar.

In the panel you can see the state of your project at a glance—which repository and branch are active, what files have changed and the current staging state of each file.

Zed monitors your repository so that changes you make on the command line are instantly reflected.

## Project Diff

You can see all of the changes captured by Git in Zed by opening the Project Diff ({#kb git::Diff}), accessible via the {#action git::Diff} action in the Command Palette or the Git Panel.

All of the changes displayed in the Project Diff behave exactly the same as any other multibuffer: they are all editable excerpts of files.

You can stage or unstage each hunk as well as a whole file by hitting the buttons on the tab bar or their corresponding keybindings.

<!-- Add media -->

## Fetch, push, and pull

Fetch, push, or pull from your Git repository in Zed via the buttons available on the Git Panel or via the Command Palette by looking at the respective actions: {#action git::Fetch}, {#action git::Push}, and {#action git::Pull}.

## Staging Workflow

Zed has two primary staging workflows, using either the Project Diff or the panel directly.

### Using the Project Diff

In the Project Diff view, you can focus on each hunk and stage them individually by clicking on the tab bar buttons or via the keybindings {#action git::StageAndNext} ({#kb git::StageAndNext}).

Similarly, stage all hunks at the same time with the {#action git::StageAll} ({#kb git::StageAll}) keybinding and then immediately commit with {#action git::Commit} ({#kb git::Commit}).

### Using the Git Panel

From the panel, you can simply type a commit message and hit the commit button, or {#action git::Commit}. This will automatically stage all tracked files (indicated by a `[·]` in the entry's checkbox) and commit them.

<!-- Show a set of changes with default staged -->

Entries can be staged using each individual entry's checkbox. All changes can be staged using the button at the top of the panel, or {#action git::StageAll}.

<!-- Add media -->

## Committing

Zed offers two commit textareas:

1. The first one is available right at the bottom of the Git Panel. Hitting {#kb git::Commit} immediately commits all of your staged changes.
2. The second is available via the action {#action git::ExpandCommitEditor} or via hitting the {#kb git::ExpandCommitEditor} while focused in the Git Panel commit textarea.

### Undoing a Commit

As soon as you commit in Zed, in the Git Panel, you'll see a bar right under the commit textarea, which will show the recently submitted commit.
In there, you can use the "Uncommit" button, which performs the `git reset HEADˆ--soft` command.

## AI Support in Git

Zed currently supports LLM-powered commit message generation.
You can ask AI to generate a commit message by focusing on the message editor within the Git Panel and either clicking on the pencil icon in the bottom left, or reaching for the {#action git::GenerateCommitMessage} ({#kb git::GenerateCommitMessage}) keybinding.

> Note that you need to have an LLM provider configured. Visit [the AI configuration page](./ai/configuration.md) to learn how to do so.

You can specify your preferred model to use by providing a `commit_message_model` agent setting. See [Feature-specific models](./ai/agent-settings.md#feature-specific-models) for more information.

```json
{
  "agent": {
    "version": "2",
    "commit_message_model": {
      "provider": "anthropic",
      "model": "claude-3-5-haiku"
    }
  }
}
```

<!-- Add media -->

More advanced AI integration with Git features may come in the future.

## Git Integrations

Zed integrates with popular Git hosting services to ensure that Git commit hashes and references to Issues, Pull Requests, and Merge Requests become clickable links.

Zed currently supports links to the hosted versions of
[GitHub](https://github.com),
[GitLab](https://gitlab.com),
[Bitbucket](https://bitbucket.org),
[SourceHut](https://sr.ht) and
[Codeberg](https://codeberg.org).

Zed also has a Copy Permalink feature to create a permanent link to a code snippet on your Git hosting service.
These links are useful for sharing a specific line or range of lines in a file at a specific commit.
Trigger this action via the [Command Palette](./getting-started.md#command-palette) (search for `permalink`),
by creating a [custom key bindings](key-bindings.md#custom-key-bindings) to the
`editor::CopyPermalinkToLine` or `editor::OpenPermalinkToLine` actions
or by simply right clicking and selecting `Copy Permalink` with line(s) selected in your editor.

## Diff Hunk Keyboard Shortcuts

When viewing files with changes, Zed displays diff hunks that can be expanded or collapsed for detailed review:

- **Expand all diff hunks**: {#action editor::ExpandAllDiffHunks} ({#kb editor::ExpandAllDiffHunks})
- **Collapse all diff hunks**: Press `Escape` (bound to {#action editor::Cancel})
- **Toggle selected diff hunks**: {#action editor::ToggleSelectedDiffHunks} ({#kb editor::ToggleSelectedDiffHunks})
- **Navigate between hunks**: {#action editor::GoToHunk} and {#action editor::GoToPreviousHunk}

> **Tip:** The `Escape` key is the quickest way to collapse all expanded diff hunks and return to an overview of your changes.

## Action Reference

| Action                                    | Keybinding                            |
| ----------------------------------------- | ------------------------------------- |
| {#action git::Add}                        | {#kb git::Add}                        |
| {#action git::StageAll}                   | {#kb git::StageAll}                   |
| {#action git::UnstageAll}                 | {#kb git::UnstageAll}                 |
| {#action git::ToggleStaged}               | {#kb git::ToggleStaged}               |
| {#action git::StageAndNext}               | {#kb git::StageAndNext}               |
| {#action git::UnstageAndNext}             | {#kb git::UnstageAndNext}             |
| {#action git::Commit}                     | {#kb git::Commit}                     |
| {#action git::ExpandCommitEditor}         | {#kb git::ExpandCommitEditor}         |
| {#action git::Push}                       | {#kb git::Push}                       |
| {#action git::ForcePush}                  | {#kb git::ForcePush}                  |
| {#action git::Pull}                       | {#kb git::Pull}                       |
| {#action git::Fetch}                      | {#kb git::Fetch}                      |
| {#action git::Diff}                       | {#kb git::Diff}                       |
| {#action git::Restore}                    | {#kb git::Restore}                    |
| {#action git::RestoreFile}                | {#kb git::RestoreFile}                |
| {#action git::Branch}                     | {#kb git::Branch}                     |
| {#action git::Switch}                     | {#kb git::Switch}                     |
| {#action git::CheckoutBranch}             | {#kb git::CheckoutBranch}             |
| {#action git::Blame}                      | {#kb git::Blame}                      |
| {#action editor::ToggleGitBlameInline}    | {#kb editor::ToggleGitBlameInline}    |
| {#action editor::ExpandAllDiffHunks}      | {#kb editor::ExpandAllDiffHunks}      |
| {#action editor::ToggleSelectedDiffHunks} | {#kb editor::ToggleSelectedDiffHunks} |

> Not all actions have default keybindings, but can be bound by [customizing your keymap](./key-bindings.md#user-keymaps).

## Git CLI Configuration

If you would like to also use Zed for your [git commit message editor](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_editor) when committing from the command line you can use `zed --wait`:

```sh
git config --global core.editor "zed --wait"
```

Or add the following to your shell environment (in `~/.zshrc`, `~/.bashrc`, etc):

```sh
export GIT_EDITOR="zed --wait"
```

    # Globs

Zed supports the use of [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) patterns that are the formal name for Unix shell-style path matching wildcards like `*.md` or `docs/src/**/*.md` supported by sh, bash, zsh, etc. A glob is similar but distinct from a [regex (regular expression)](https://en.wikipedia.org/wiki/Regular_expression). You may be In Zed these are commonly used when matching filenames.

## Glob Flavor

Zed uses two different rust crates for matching glob patterns:

- [ignore crate](https://docs.rs/ignore/latest/ignore/) for matching glob patterns stored in `.gitignore` files
- [glob crate](https://docs.rs/glob/latest/glob/) for matching file paths in Zed

While simple expressions are portable across environments (e.g. running `ls *.py` or `*.tmp` in a gitignore) there is significant divergence in the support for and syntax of more advanced features varies (character classes, exclusions, `**`, etc) across implementations. For the rest of this document we will be describing globs as supported in Zed via the `glob` crate implementation. Please see [References](#references) below for documentation links for glob pattern syntax for `.gitignore`, shells and other programming languages.

The `glob` crate is implemented entirely in rust and does not rely on the `glob` / `fnmatch` interfaces provided by your platforms libc. This means that globs in Zed should behave similarly with across platforms.

## Introduction

A glob "pattern" is used to match a file name or complete file path. For example, when using "Search all files" {#kb project_search::ToggleFocus} you can click the funnel shaped Toggle Filters" button or {#kb project_search::ToggleFilters} and it will show additional search fields for "Include" and "Exclude" which support specifying glob patterns for matching file paths and file names.

When creating a glob pattern you can use one or multiple special characters:

| Special Character | Meaning                                                           |
| ----------------- | ----------------------------------------------------------------- |
| `?`               | Matches any single character                                      |
| `*`               | Matches any (possibly empty) sequence of characters               |
| `**`              | Matches the current directory and arbitrary subdirectories        |
| `[abc]`           | Matches any one character in the brackets                         |
| `[a-z]`           | Matches any of a range of characters (ordered by Unicode)         |
| `[!...]`          | The negation of `[...]` (matches a character not in the brackets) |

Notes:

1. Shell-style brace-expansions like `{a,b,c}` are not supported.
2. To match a literal `-` character inside brackets it must come first `[-abc]` or last `[abc-]`.
3. To match the literal `[` character use `[[]` or put it as the first character in the group `[[abc]`.
4. To match the literal `]` character use `[]]` or put it as the last character in the group `[abc]]`.

## Examples

### Matching file extensions

If you wanted to only search Markdown files add `*.md` to the "Include" search field.

### Case insensitive matching

Globs in Zed are case-sensitive, so `*.c` will not match `main.C` (even on case-insensitive filesystems like HFS+/APFS on macOS). Instead use brackets to match characters. So instead of `*.c` use `*.[cC]`.

### Matching directories

If you wanted to search the [zed repository](https://github.com/zed-industries/zed) for examples of [Configuring Language Servers](https://zed.dev/docs/configuring-languages#configuring-language-servers) (under `"lsp"` in Zed settings.json) you could search for `"lsp"` and in the "Include" filter specify `docs/**/*.md`. This would only match files whose path was under the `docs` directory or any nested subdirectories `**/` of that folder with a filename that ends in `.md`.

If instead you wanted to restrict yourself only to [Zed Language-Specific Documentation](https://zed.dev/docs/languages) pages you could define a narrower pattern of: `docs/src/languages/*.md` this would match [`docs/src/languages/rust.md`](https://github.com/zed-industries/zed/blob/main/docs/src/languages/rust.md) and [`docs/src/languages/cpp.md`](https://github.com/zed-industries/zed/blob/main/docs/src/languages/cpp.md) but not [`docs/src/configuring-languages.md`](https://github.com/zed-industries/zed/blob/main/docs/src/configuring-languages.md).

### Implicit Wildcards

When using the "Include" / "Exclude" filters on a Project Search each glob is wrapped in implicit wildcards. For example to exclude any files with license in the path or filename from your search just type type `license` in the exclude box. Behind the scenes Zed transforms `license` to `**license**`. This means that files named `license.*`, `*.license` or inside a `license` subdirectory will all be filtered out. This enables users to easily filter for `*.ts` without having to remember to type `**/*.ts` every time.

Alternatively, if in your Zed settings you wanted a [`file_types`](./configuring-zed.md#file-types) override which only applied to a certain directory you must explicitly include the wildcard globs. For example, if you had a directory of template files with the `html` extension that you wanted to recognize as Jinja2 template you could use the following:

```json
{
  "file_types": {
    "C++": ["[cC]"],
    "Jinja2": ["**/templates/*.html"]
  }
}
```

## References

While globs in Zed are implemented as described above, when writing code using globs in other languages, please reference your platform's glob documentation:

- [macOS fnmatch](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fnmatch.3.html) (BSD C Standard Library)
- [Linux fnmatch](https://www.gnu.org/software/libc/manual/html_node/Wildcard-Matching.html) (GNU C Standard Library)
- [POSIX fnmatch](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html) (POSIX Specification)
- [node-glob](https://github.com/isaacs/node-glob) (Node.js `glob` package)
- [Python glob](https://docs.python.org/3/library/glob.html) (Python Standard Library)
- [Golang glob](https://pkg.go.dev/path/filepath#Match) (Go Standard Library)
- [gitignore patterns](https://git-scm.com/docs/gitignore) (Gitignore Pattern Format)
- [PowerShell: About Wildcards](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_wildcards) (Wildcards in PowerShell)

    # Helix Mode

_Work in progress! Not all Helix keybindings are implemented yet._

Zed's Helix mode is an emulation layer that brings Helix-style keybindings and modal editing to Zed. It builds upon Zed's [Vim mode](./vim.md), so much of the core functionality is shared. Enabling `helix_mode` will also enable `vim_mode`.

For a guide on Vim-related features that are also available in Helix mode, please refer to our [Vim mode documentation](./vim.md).

To check the current status of Helix mode, or to request a missing Helix feature, checkout out the ["Are we Helix yet?" discussion](https://github.com/zed-industries/zed/discussions/33580).

For a detailed list of Helix's default keybindings, please visit the [official Helix documentation](https://docs.helix-editor.com/keymap.html).

## Core differences

Any text object that works with `m i` or `m a` also works with `]` and `[`, so for example `] (` selects the next pair of parentheses after the cursor.

    # Icon Themes

Zed comes with a built-in icon theme, with more icon themes available as extensions.

## Selecting an Icon Theme

See what icon themes are installed and preview them via the Icon Theme Selector, which you can open from the command palette with "icon theme selector: toggle".

Navigating through the icon theme list by moving up and down will change the icon theme in real time and hitting enter will save it to your settings file.

## Installing more Icon Themes

More icon themes are available from the Extensions page, which you can access via the command palette with "zed: Extensions" or the [Zed website](https://zed.dev/extensions).

## Configuring Icon Themes

Your selected icon theme is stored in your settings file. You can open your settings file from the command palette with "zed: open settings" (bound to `cmd-,` on macOS and `ctrl-,` on Linux).

Just like with themes, Zed allows for configuring different icon themes for light and dark mode. You can set the mode to `"light"` or `"dark"` to ignore the current system mode.

```json
{
  "icon_theme": {
    "mode": "system",
    "light": "Light Icon Theme",
    "dark": "Dark Icon Theme"
  }
}
```

## Icon Theme Development

See: [Developing Zed Icon Themes](./extensions/icon-themes.md)

    # Key bindings

Zed has a very customizable key binding system—you can tweak everything to work exactly how your fingers expect!

## Predefined keymaps

If you're used to a specific editor's defaults, you can set a `base_keymap` in your [settings file](./configuring-zed.md).
We currently support:

- VS Code (default)
- Atom
- Emacs (Beta)
- JetBrains
- Sublime Text
- TextMate
- Cursor
- None (disables _all_ key bindings)

This setting can also be changed via the command palette through the `zed: toggle base keymap selector` action.

You can also enable `vim_mode` or `helix_mode`, which add modal bindings.
For more information, see the documentation for [Vim mode](./vim.md) and [Helix mode](./helix.md).

## User keymaps

Zed reads your keymap from `~/.config/zed/keymap.json`, which you can open with the {#action zed::OpenKeymap} action from the command palette.
You can also edit your keymap through the Zed Keymap Editor, accessible via the {#action zed::OpenKeymapEditor} action or the {#kb zed::OpenKeymapEditor} keybinding.

The `keymap.json` file contains a JSON array of objects with `"bindings"`. If no `"context"` is set, the bindings are always active. If it is set, the binding is only active when the [context matches](#contexts).

Within each binding section, a [key sequence](#keybinding-syntax) is mapped to [an action](#actions). If conflicts are detected, they are resolved as [described below](#precedence).

If you are using a non-QWERTY, Latin-character keyboard, you may want to set `use_key_equivalents` to `true`. See [Non-QWERTY keyboards](#non-qwerty-keyboards) for more information.

For example:

```json
[
  {
    "bindings": {
      "ctrl-right": "editor::SelectLargerSyntaxNode",
      "ctrl-left": "editor::SelectSmallerSyntaxNode"
    }
  },
  {
    "context": "ProjectPanel && not_editing",
    "bindings": {
      "o": "project_panel::Open"
    }
  }
]
```

You can see all of Zed's default bindings in the default keymaps for [macOS](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-macos.json) or [Linux](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-linux.json).

If you want to debug problems with custom keymaps, you can use `dev: Open Key Context View` from the command palette. Please file [an issue](https://github.com/zed-industries/zed) if you run into something you think should work but isn't.

### Keybinding syntax

Zed has the ability to match against not just a single keypress, but a sequence of keys typed in order. Each key in the `"bindings"` map is a sequence of keypresses separated with a space.

Each keypress is a sequence of modifiers followed by a key. The modifiers are:

- `ctrl-` The control key
- `cmd-`, `win-` or `super-` for the platform modifier (Command on macOS, Windows key on Windows, and the Super key on Linux).
- `alt-` for alt (option on macOS)
- `shift-` The shift key
- `fn-` The function key
- `secondary-` Equivalent to `cmd` when Zed is running on macOS and `ctrl` when on Windows and Linux

The keys can be any single Unicode codepoint that your keyboard generates (for example `a`, `0`, `£` or `ç`), or any named key (`tab`, `f1`, `shift`, or `cmd`). If you are using a non-Latin layout (e.g. Cyrillic), you can bind either to the Cyrillic character or the Latin character that key generates with `cmd` pressed.

A few examples:

```json
 "bindings": {
   "cmd-k cmd-s": "zed::OpenKeymap", // matches ⌘-k then ⌘-s
   "space e": "editor::Complete", // type space then e
   "ç": "editor::Complete", // matches ⌥-c
   "shift shift": "file_finder::Toggle", // matches pressing and releasing shift twice
 }
```

The `shift-` modifier can only be used in combination with a letter to indicate the uppercase version. For example, `shift-g` matches typing `G`. Although on many keyboards shift is used to type punctuation characters like `(`, the keypress is not considered to be modified, and so `shift-(` does not match.

The `alt-` modifier can be used on many layouts to generate a different key. For example, on a macOS US keyboard, the combination `alt-c` types `ç`. You can match against either in your keymap file, though by convention, Zed spells this combination as `alt-c`.

It is possible to match against typing a modifier key on its own. For example, `shift shift` can be used to implement JetBrains' 'Search Everywhere' shortcut. In this case, the binding happens on key release instead of on keypress.

### Contexts

If a binding group has a `"context"` key, it will be matched against the currently active contexts in Zed.

Zed's contexts make up a tree, with the root being `Workspace`. Workspaces contain Panes and Panels, and Panes contain Editors, etc. The easiest way to see what contexts are active at a given moment is the key context view, which you can get to with the `dev: open key context view` command in the command palette.

For example:

```
# in an editor, it might look like this:
Workspace os=macos keyboard_layout=com.apple.keylayout.QWERTY
  Pane
    Editor mode=full extension=md vim_mode=insert

# in the project panel
Workspace os=macos
  Dock
    ProjectPanel not_editing
```

Context expressions can contain the following syntax:

- `X && Y`, `X || Y` to and/or two conditions
- `!X` to check that a condition is false
- `(X)` for grouping
- `X > Y` to match if an ancestor in the tree matches X and this layer matches Y.

For example:

- `"context": "Editor"` - matches any editor (including inline inputs)
- `"context": "Editor && mode=full"` - matches the main editors used for editing code
- `"context": "!Editor && !Terminal"` - matches anywhere except where an Editor or Terminal is focused
- `"context": "os=macos > Editor"` - matches any editor on macOS.

It's worth noting that attributes are only available on the node they are defined on. This means that if you want to (for example) only enable a keybinding when the debugger is stopped in vim normal mode, you need to do `debugger_stopped > vim_mode == normal`.

> Note: Before Zed v0.197.x, the `!` operator only looked at one node at a time, and `>` meant "parent" not "ancestor". This meant that `!Editor` would match the context `Workspace > Pane > Editor`, because (confusingly) the Pane matches `!Editor`, and that `os=macos > Editor` did not match the context `Workspace > Pane > Editor` because of the intermediate `Pane` node.

If you're using Vim mode, we have information on how [vim modes influence the context](./vim.md#contexts). Helix mode is built on top of Vim mode and uses the same contexts.

### Actions

Almost all of Zed's functionality is exposed as actions.
Although there is no explicitly documented list, you can find most of them by searching in the command palette, by looking in the default keymaps for [macOS](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-macos.json) or [Linux](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-linux.json), or by using Zed's autocomplete in your keymap file.

Most actions do not require any arguments, and so you can bind them as strings: `"ctrl-a": "language_selector::Toggle"`. Some require a single argument and must be bound as an array: `"cmd-1": ["workspace::ActivatePane", 0]`. Some actions require multiple arguments and are bound as an array of a string and an object: `"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]`.

### Precedence

When multiple keybindings have the same keystroke and are active at the same time, precedence is resolved in two ways:

- Bindings that match on lower nodes in the context tree win. This means that if you have a binding with a context of `Editor`, it will take precedence over a binding with a context of `Workspace`. Bindings with no context match at the lowest level in the tree.
- If there are multiple bindings that match at the same level in the tree, then the binding defined later takes precedence. As user keybindings are loaded after system keybindings, this allows user bindings to take precedence over built-in keybindings.

The other kind of conflict that arises is when you have two bindings, one of which is a prefix of the other. For example, if you have `"ctrl-w":"editor::DeleteToNextWordEnd"` and `"ctrl-w left":"editor::DeleteToEndOfLine"`.

When this happens, and both bindings are active in the current context, Zed will wait for 1 second after you type `ctrl-w` to see if you're about to type `left`. If you don't type anything, or if you type a different key, then `DeleteToNextWordEnd` will be triggered. If you do, then `DeleteToEndOfLine` will be triggered.

### Non-QWERTY keyboards

Zed's support for non-QWERTY keyboards is still a work in progress.

If your keyboard can type the full ASCII range (DVORAK, COLEMAK, etc.), then shortcuts should work as you expect.

Otherwise, read on...

#### macOS

On Cyrillic, Hebrew, Armenian, and other keyboards that are mostly non-ASCII, macOS automatically maps keys to the ASCII range when `cmd` is held. Zed takes this a step further, and it can always match key-presses against either the ASCII layout or the real layout, regardless of modifiers and the `use_key_equivalents` setting. For example, in Thai, pressing `ctrl-ๆ` will match bindings associated with `ctrl-q` or `ctrl-ๆ`.

On keyboards that support extended Latin alphabets (French AZERTY, German QWERTZ, etc.), it is often not possible to type the entire ASCII range without `option`. This introduces an ambiguity: `option-2` produces `@`. To ensure that all the built-in keyboard shortcuts can still be typed on these keyboards, we move key bindings around. For example, shortcuts bound to `@` on QWERTY are moved to `"` on a Spanish layout. This mapping is based on the macOS system defaults and can be seen by running `dev: open key context view` from the command palette.

If you are defining shortcuts in your personal keymap, you can opt into the key equivalent mapping by setting `use_key_equivalents` to `true` in your keymap:

```json
[
  {
    "use_key_equivalents": true,
    "bindings": {
      "ctrl->": "editor::Indent" // parsed as ctrl-: when a German QWERTZ keyboard is active
    }
  }
]
```

### Linux

Since v0.196.0, on Linux, if the key that you type doesn't produce an ASCII character, then we use the QWERTY-layout equivalent key for keyboard shortcuts. This means that many shortcuts can be typed on many layouts.

We do not yet move shortcuts around to ensure that all the built-in shortcuts can be typed on every layout, so if there are some ASCII characters that cannot be typed, and your keyboard layout has different ASCII characters on the same keys as would be needed to type them, you may need to add custom key bindings to make this work. We do intend to fix this at some point, and help is very much appreciated!

## Tips and tricks

### Disabling a binding

If you'd like a given binding to do nothing in a given context, you can use
`null` as the action. This is useful if you hit the key binding by accident and
want to disable it, or if you want to type the character that would be typed by
the sequence, or if you want to disable multikey bindings starting with that key.

```json
[
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": null // cmd-r will do nothing when the Workspace context is active
    }
  }
]
```

A `null` binding follows the same precedence rules as normal actions, so it disables all bindings that would match further up in the tree too. If you'd like a binding that matches further up in the tree to take precedence over a lower binding, you need to rebind it to the action you want in the context you want.

This is useful for preventing Zed from falling back to a default key binding when the action you specified is conditional and propagates. For example, `buffer_search::DeployReplace` only triggers when the search bar is not in view. If the search bar is in view, it would propagate and trigger the default action set for that key binding, such as opening the right dock. To prevent this from happening:

```json
[
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": null // cmd-r will do nothing when the search bar is in view
    }
  },
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": "buffer_search::DeployReplace" // cmd-r will deploy replace when the search bar is not in view
    }
  }
]
```

### Remapping keys

A common request is to be able to map from a single keystroke to a sequence. You can do this with the `workspace::SendKeystrokes` action.

```json
[
  {
    "bindings": {
      // Move down four times
      "alt-down": ["workspace::SendKeystrokes", "down down down down"],
      // Expand the selection (editor::SelectLargerSyntaxNode);
      // copy to the clipboard; and then undo the selection expansion.
      "cmd-alt-c": [
        "workspace::SendKeystrokes",
        "ctrl-shift-right ctrl-shift-right ctrl-shift-right cmd-c ctrl-shift-left ctrl-shift-left ctrl-shift-left"
      ]
    }
  },
  {
    "context": "Editor && vim_mode == insert",
    "bindings": {
      "j k": ["workspace::SendKeystrokes", "escape"]
    }
  }
]
```

There are some limitations to this, notably:

- Any asynchronous operation will not happen until after all your key bindings have been dispatched. For example, this means that while you can use a binding to open a file (as in the `cmd-alt-r` example), you cannot send further keystrokes and hope to have them interpreted by the new view.
- Other examples of asynchronous things are: opening the command palette, communicating with a language server, changing the language of a buffer, anything that hits the network.
- There is a limit of 100 simulated keys at a time.

The argument to `SendKeystrokes` is a space-separated list of keystrokes (using the same syntax as above). Due to the way that keystrokes are parsed, any segment that is not recognized as a keypress will be sent verbatim to the currently focused input field.

If the argument to `SendKeystrokes` contains the binding used to trigger it, it will use the next-highest-precedence definition of that binding. This allows you to extend the default behavior of a key binding.

### Forward keys to terminal

If you're on Linux or Windows, you might find yourself wanting to forward key combinations to the built-in terminal instead of them being handled by Zed.

For example, `ctrl-n` creates a new tab in Zed on Linux. If you want to send `ctrl-n` to the built-in terminal when it's focused, add the following to your keymap:

```json
{
  "context": "Terminal",
  "bindings": {
    "ctrl-n": ["terminal::SendKeystroke", "ctrl-n"]
  }
}
```

### Task Key bindings

You can also bind keys to launch Zed Tasks defined in your `tasks.json`.
See the [tasks documentation](tasks.md#custom-keybindings-for-tasks) for more.

    # Language Support in Zed

Zed supports hundreds of programming languages and text formats.
Some work out-of-the box and others rely on 3rd party extensions.

> The ones included out-of-the-box, natively built into Zed, are marked with \*.

## Languages with Documentation

- [Ansible](./languages/ansible.md)
- [AsciiDoc](./languages/asciidoc.md)
- [Astro](./languages/astro.md)
- [Bash](./languages/bash.md)
- [Biome](./languages/biome.md)
- [C](./languages/c.md) \*
- [C++](./languages/cpp.md) \*
- [C#](./languages/csharp.md)
- [Clojure](./languages/clojure.md)
- [CSS](./languages/css.md) \*
- [Dart](./languages/dart.md)
- [Deno](./languages/deno.md)
- [Diff](./languages/diff.md) \*
- [Docker](./languages/docker.md)
- [Elixir](./languages/elixir.md)
- [Elm](./languages/elm.md)
- [Emmet](./languages/emmet.md)
- [Erlang](./languages/erlang.md)
- [Fish](./languages/fish.md)
- [GDScript](./languages/gdscript.md)
- [Gleam](./languages/gleam.md)
- [GLSL](./languages/glsl.md)
- [Go](./languages/go.md) \*
- [Groovy](./languages/groovy.md)
- [Haskell](./languages/haskell.md)
- [Helm](./languages/helm.md)
- [HTML](./languages/html.md)
- [Java](./languages/java.md)
- [JavaScript](./languages/javascript.md) \*
- [Julia](./languages/julia.md)
- [JSON](./languages/json.md) \*
- [Jsonnet](./languages/jsonnet.md)
- [Kotlin](./languages/kotlin.md)
- [Lua](./languages/lua.md)
- [Luau](./languages/luau.md)
- [Makefile](./languages/makefile.md)
- [Markdown](./languages/markdown.md) \*
- [Nim](./languages/nim.md)
- [OCaml](./languages/ocaml.md)
- [PHP](./languages/php.md)
- [Prisma](./languages/prisma.md)
- [Proto](./languages/proto.md)
- [PureScript](./languages/purescript.md)
- [Python](./languages/python.md) \*
- [R](./languages/r.md)
- [Rego](./languages/rego.md)
- [ReStructuredText](./languages/rst.md)
- [Racket](./languages/racket.md)
- [Roc](./languages/roc.md)
- [Ruby](./languages/ruby.md)
- [Rust](./languages/rust.md) \* (Zed's written in Rust)
- [Scala](./languages/scala.md)
- [Scheme](./languages/scheme.md)
- [Shell Script](./languages/sh.md)
- [Svelte](./languages/svelte.md)
- [Swift](./languages/swift.md)
- [Tailwind CSS](./languages/tailwindcss.md) \*
- [Terraform](./languages/terraform.md)
- [TOML](./languages/toml.md)
- [TypeScript](./languages/typescript.md) \*
- [Uiua](./languages/uiua.md)
- [Vue](./languages/vue.md)
- [XML](./languages/xml.md)
- [YAML](./languages/yaml.md) \*
- [Yara](./languages/yarn.md)
- [Yarn](./languages/yarn.md)
- [Zig](./languages/zig.md)

## Additional Community Language Extensions

- [Ada](https://github.com/wisn/zed-ada-language)
- [Aiken](https://github.com/aiken-lang/zed-aiken)
- [Amber](https://github.com/amber-lang/zed-amber-extension)
- [Assembly](https://github.com/DevBlocky/zed-asm)
- [AWK](https://github.com/dangh/zed-awk)
- [Beancount](https://github.com/zed-extensions/beancount)
- [Bend](https://github.com/mrpedrobraga/zed-bend)
- [Blade](https://github.com/bajrangCoder/zed-laravel-blade)
- [Blueprint](https://github.com/tfuxu/zed-blueprint)
- [BQN](https://github.com/DavidZwitser/zed-bqn)
- [Brainfuck](https://github.com/JosephTLyons/zed-brainfuck)
- [Cadence](https://github.com/janezpodhostnik/cadence.zed)
- [Cairo](https://github.com/trbutler4/zed-cairo)
- [Cap'n Proto](https://github.com/cmackenzie1/zed-capnp)
- [Cedar](https://github.com/chrnorm/zed-cedar)
- [CFEngine policy language](https://github.com/olehermanse/zed-cfengine)
- [CSV](https://github.com/huacnlee/zed-csv)
- [Cucumber/Gherkin](https://github.com/thlcodes/zed-extension-cucumber)
- [CUE](https://github.com/jkasky/zed-cue)
- [Curry](https://github.com/fwcd/zed-curry)
- [D](https://github.com/staysail/zed-d)
- [Database Markup Language (DBML)](https://github.com/shuklaayush/zed-dbml)
- [Earthfile](https://github.com/glehmann/earthfile.zed)
- [EJS template](https://github.com/dangh/zed-ejs)
- [Elisp](https://github.com/JosephTLyons/zed-elisp)
- [Ember](https://github.com/jylamont/zed-ember)
- [Env](https://github.com/zarifpour/zed-env)
- [Exograph](https://github.com/exograph/zed-extension)
- [Fortran](https://github.com/Xavier-Maruff/zed-fortran)
- [F#](https://github.com/nathanjcollins/zed-fsharp)
- [Gemini gemtext](https://github.com/clseibold/gemini-zed)
- [Git Firefly](https://github.com/d1y/git_firefly)
- [GraphQL](https://github.com/11bit/zed-extension-graphql)
- [Groq](https://github.com/juice49/zed-groq)
- [INI](https://github.com/bajrangCoder/zed-ini)
- [Java](https://github.com/zed-extensions/java)
- [Justfiles](https://github.com/jackTabsCode/zed-just)
- [LaTeX](https://github.com/rzukic/zed-latex)
- [Ledger](https://github.com/mrkstwrt/zed-ledger)
- [Less](https://github.com/jimliang/zed-less)
- [LilyPond](https://github.com/nwhetsell/lilypond-zed-extension)
- [Liquid](https://github.com/TheBeyondGroup/zed-shopify-liquid)
- [Log](https://github.com/evrensen467/zed-log)
- [Lox](https://github.com/arian81/zed-lox)
- [Markdown Oxide](https://github.com/Feel-ix-343/markdown-oxide-zed)
- [Marksman](https://github.com/vitallium/zed-marksman)
- [Matlab](https://github.com/rzukic/zed-matlab)
- [Meson](https://github.com/hqnna/zed-meson)
- [Navi](https://github.com/navi-language/zed-navi)
- [NeoCMake](https://github.com/k0tran/zed_neocmake)
- [Nginx](https://github.com/d1y/nginx-zed)
- [Nim](https://github.com/foxoman/zed-nim)
- [Nix](https://github.com/zed-extensions/nix)
- [Noir](https://github.com/shuklaayush/zed-noir)
- [Nu](https://github.com/zed-extensions/nu)
- [Odin](https://github.com/rxptr/zed-odin)
- [Pact](https://github.com/kadena-community/pact-zed)
- [Pest](https://github.com/pest-parser/zed-pest)
- [PICA200 assembly](https://github.com/Squareheron942/zed-pica200)
- [Pkl](https://github.com/Moshyfawn/pkl-zed)
- [PlaydateSDK](https://github.com/notpeter/playdate-zed-extension)
- [QML](https://github.com/lkroll/zed-qml)
- [Rainbow CSV](https://github.com/weartist/zed-rainbow-csv)
- [Rego](https://github.com/StyraInc/zed-rego)
- [Rescript](https://github.com/humaans/rescript-zed)
- [Roclang](https://github.com/h2000/zed-roc)
- [Ron](https://github.com/onbjerg/zed-ron)
- [Metals](https://github.com/scalameta/metals-zed)
- [SCSS](https://github.com/bajrangCoder/zed-scss)
- [Slim](https://github.com/calmyournerves/zed-slim)
- [Slint](https://gitlab.com/flukejones/zed-slint)
- [Smithy](https://github.com/joshrutkowski/zed-smithy)
- [Solidity](https://github.com/zarifpour/zed-solidity)
- [SQL](https://github.com/evrensen467/zed-sql)
- [Strace](https://github.com/sigmaSd/zed-strace)
- [Swift](https://github.com/zed-extensions/swift)
- [Templ](https://github.com/makifdb/zed-templ)
- [Tmux](https://github.com/dangh/zed-tmux)
- [Twig](https://github.com/YussufSassi/zed-twig)
- [Typst](https://github.com/WeetHet/typst.zed)
- [Unison](https://github.com/zetashift/unison-zed)
- [UnoCSS](https://github.com/bajrangCoder/zed-unocss)
- [Vlang](https://github.com/lv37/zed-v)
- [Vala](https://github.com/FyraLabs/zed-vala)
- [Vale](https://github.com/koozz/zed-vale)
- [Verilog](https://github.com/someone13574/zed-verilog-extension)
- [VHS](https://github.com/eth0net/zed-vhs)
- [Wgsl](https://github.com/luan/zed-wgsl)
- [WIT](https://github.com/valentinegb/zed-wit)

    # Ansible

Support for Ansible in Zed is provided via a community-maintained [Ansible extension](https://github.com/kartikvashistha/zed-ansible).

- Tree-sitter: [zed-industries/tree-sitter-yaml](https://github.com/zed-industries/tree-sitter-yaml)
- Language Server: [ansible/vscode-ansible](https://github.com/ansible/vscode-ansible/tree/main/packages/ansible-language-server)

## Setup

### File detection

To avoid mishandling non-Ansible YAML files, the Ansible Language is not associated with any file extensions by default. To change this behavior you can add a `"file_types"` section to Zed settings inside your project (`.zed/settings.json`) or your Zed user settings (`~/.config/zed/settings.json`) to match your folder/naming conventions. For example:

```json
"file_types": {
    "Ansible": [
      "**.ansible.yml",
      "**.ansible.yaml",
      "**/defaults/*.yml",
      "**/defaults/*.yaml",
      "**/meta/*.yml",
      "**/meta/*.yaml",
      "**/tasks/*.yml",
      "**/tasks/*.yaml",
      "**/handlers/*.yml",
      "**/handlers/*.yaml",
      "**/group_vars/*.yml",
      "**/group_vars/*.yaml",
      "**/host_vars/*.yml",
      "**/host_vars/*.yaml",
      "**/playbooks/*.yml",
      "**/playbooks/*.yaml",
      "**playbook*.yml",
      "**playbook*.yaml"
    ]
  }
```

Feel free to modify this list as per your needs.

#### Inventory

If your inventory file is in the YAML format, you can either:

- Append the `ansible-lint` inventory json schema to it via the following comment at the top of your inventory file:

```yml
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json
```

- Or configure the yaml language server settings to set this schema for all your inventory files, that match your inventory pattern, under your Zed settings ([ref](https://zed.dev/docs/languages/yaml)):

```json
"lsp": {
    "yaml-language-server": {
      "settings": {
        "yaml": {
          "schemas": {
            "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json": [
              "./inventory/*.yaml",
              "hosts.yml",
            ]
          }
        }
      }
    }
},
```

### LSP Configuration

By default, the following default config is passed to the Ansible language server. It conveniently mirrors the defaults set by [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/blob/03bc581e05e81d33808b42b2d7e76d70adb3b595/lua/lspconfig/configs/ansiblels.lua) for the Ansible language server:

```json
{
  "ansible": {
    "ansible": {
      "path": "ansible"
    },
    "executionEnvironment": {
      "enabled": false
    },
    "python": {
      "interpreterPath": "python3"
    },
    "validation": {
      "enabled": true,
      "lint": {
        "enabled": true,
        "path": "ansible-lint"
      }
    }
  }
}
```

> [!NOTE]
> In order for linting to work, ensure that `ansible-lint` is installed and discoverable on your PATH

When desired, any of the above default settings can be overridden under the `"lsp"` section of your Zed settings file. For example:

```json
"lsp": {
  // Note, the Zed Ansible extension prefixes all settings with `ansible`
  // so instead of using `ansible.ansible.path` use `ansible.path`.
  "ansible-language-server": {
    "settings": {
      "ansible": {
        "path": "ansible"
      },
      "executionEnvironment": {
        "enabled": false
      },
      "python": {
        "interpreterPath": "python3"
      },
      "validation": {
        "enabled": false, // disable validation
        "lint": {
          "enabled": false, // disable ansible-lint
          "path": "ansible-lint"
        }
      }
    }
  }
}
```

A full list of options/settings, that can be passed to the server, can be found at the project's page [here](https://github.com/ansible/vscode-ansible/blob/5a89836d66d470fb9d20e7ea8aa2af96f12f61fb/docs/als/settings.md).
Feel free to modify option values as needed.

    # AsciiDoc

AsciiDoc language support in Zed is provided by the community-maintained [AsciiDoc extension](https://github.com/andreicek/zed-asciidoc).
Report issues to: [https://github.com/andreicek/zed-asciidoc/issues](https://github.com/andreicek/zed-asciidoc/issues)

- Tree-sitter: [cathaysia/tree-sitter-asciidoc](https://github.com/cathaysia/tree-sitter-asciidoc)

    # Astro

Astro support is available through the [Astro extension](https://github.com/zed-extensions/astro).

- Tree-sitter: [virchau13/tree-sitter-astro](https://github.com/virchau13/tree-sitter-astro)
- Language Server: [withastro/language-tools](https://github.com/withastro/language-tools)

<!--
TBD: Documentation Astro usage / configuration
-->

    # Bash

Bash language support in Zed is provided by the community-maintained [Basher extension](https://github.com/d1y/bash.zed).
Report issues to: [https://github.com/d1y/bash.zed/issues](https://github.com/d1y/bash.zed/issues)

- Tree-sitter: [tree-sitter/tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash)
- Language Server: [bash-lsp/bash-language-server](https://github.com/bash-lsp/bash-language-server)

## Configuration

When `shellcheck` is available `bash-language-server` will use it internally to provide diagnostics.

### Install `shellcheck`:

```sh
brew install shellcheck             # macOS (HomeBrew)
apt-get install shellcheck          # Ubuntu/Debian
pacman -S shellcheck                # ArchLinux
dnf install shellcheck              # Fedora
yum install shellcheck              # CentOS/RHEL
zypper install shellcheck           # openSUSE
choco install shellcheck            # Windows (Chocolatey)
```

And verify it is available from your path:

```sh
which shellcheck
shellcheck --version
```

If you wish to customize the warnings/errors reported you just need to create a `.shellcheckrc` file. You can do this in the root of your project or in your home directory (`~/.shellcheckrc`). See: [shellcheck documentation](https://github.com/koalaman/shellcheck/wiki/Ignore#ignoring-one-or-more-types-of-errors-forever) for more.

### See also:

- [Zed Docs: Language Support: Shell Scripts](./sh.md)

    # Biome

[Biome](https://biomejs.dev/) support in Zed is provided by the community-maintained [Biome extension](https://github.com/biomejs/biome-zed).
Report issues to: [https://github.com/biomejs/biome-zed/issues](https://github.com/biomejs/biome-zed/issues)

- Language Server: [biomejs/biome](https://github.com/biomejs/biome)

## Biome Language Support

The Biome extension includes support for the following languages:

- JavaScript
- TypeScript
- JSX
- TSX
- JSON
- JSONC
- Vue.js
- Astro
- Svelte
- CSS

## Configuration

By default, the `biome.json` file is required to be in the root of the workspace.

```json
{
  "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json"
}
```

For a full list of `biome.json` options see [Biome Configuration](https://biomejs.dev/reference/configuration/) documentation.

See the [Biome Zed Extension README](https://github.com/biomejs/biome-zed) for a complete list of features and configuration options.

    # C

C support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c)
- Language Server: [clangd/clangd](https://github.com/clangd/clangd)
- Debug Adapter: [CodeLLDB](https://github.com/vadimcn) (primary), [GDB](https://sourceware.org/gdb/) (secondary, not available on Apple silicon)

## Clangd: Force detect as C

Clangd out of the box assumes mixed C++/C projects. If you have a C-only project you may wish to instruct clangd to treat all files as C using the `-xc` flag. To do this, create a `.clangd` file in the root of your project with the following:

```yaml
CompileFlags:
  Add: [-xc]
```

By default clang and gcc will recognize `*.C` and `*.H` (uppercase extensions) as C++ and not C and so Zed too follows this convention. If you are working with a C-only project (perhaps one with legacy uppercase pathing like `FILENAME.C`) you can override this behavior by adding this to your settings:

```json
{
  "file_types": {
    "C": ["C", "H"]
  }
}
```

## Formatting

By default Zed will use the `clangd` language server for formatting C code. The Clangd is the same as the `clang-format` CLI tool. To configure this you can add a `.clang-format` file. For example:

```yaml
---
BasedOnStyle: GNU
IndentWidth: 2
---
```

See [Clang-Format Style Options](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) for a complete list of options.

You can trigger formatting via {#kb editor::Format} or the `editor: format` action from the command palette or by adding `format_on_save` to your Zed settings:

```json
  "languages": {
    "C": {
      "format_on_save": "on",
      "tab_size": 2
    }
  }
```

## Compile Commands

For some projects Clangd requires a `compile_commands.json` file to properly analyze your project. This file contains the compilation database that tells clangd how your project should be built.

### CMake Compile Commands

With CMake, you can generate `compile_commands.json` automatically by adding the following line to your `CMakeLists.txt`:

```cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
```

After building your project, CMake will generate the `compile_commands.json` file in the build directory and clangd will automatically pick it up.

## Debugging

You can use CodeLLDB or GDB to debug native binaries. (Make sure that your build process passes `-g` to the C compiler, so that debug information is included in the resulting binary.) See below for examples of debug configurations that you can add to `.zed/debug.json`.

### Build and Debug Binary

```json
[
  {
    "label": "Debug native binary",
    "build": {
      "command": "make",
      "args": ["-j8"],
      "cwd": "$ZED_WORKTREE_ROOT"
    },
    "program": "$ZED_WORKTREE_ROOT/build/prog",
    "request": "launch",
    "adapter": "CodeLLDB"
  }
]
```

    # Clojure

Clojure support is available through the [Clojure extension](https://github.com/zed-extensions/clojure).

- Tree-sitter: [prcastro/tree-sitter-clojure](https://github.com/prcastro/tree-sitter-clojure)
- Language Server: [clojure-lsp/clojure-lsp](https://github.com/clojure-lsp/clojure-lsp)

<!--
TBD: Add some Clojure Docs
-->

    # C++

C++ support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp)
- Language Server: [clangd/clangd](https://github.com/clangd/clangd)

## Binary

You can configure which `clangd` binary Zed should use.

By default, Zed will try to find a `clangd` in your `$PATH` and try to use that. If that binary successfully executes, it's used. Otherwise, Zed will fall back to installing its own `clangd` version and use that.

If you want to install a pre-release `clangd` version instead you can instruct Zed to do so by setting `pre_release` to `true` in your `settings.json`:

```json
{
  "lsp": {
    "clangd": {
      "fetch": {
        "pre_release": true
      }
    }
  }
}
```

If you want to disable Zed looking for a `clangd` binary, you can set `ignore_system_version` to `true` in your `settings.json`:

```json
{
  "lsp": {
    "clangd": {
      "binary": {
        "ignore_system_version": true
      }
    }
  }
}
```

If you want to use a binary in a custom location, you can specify a `path` and optional `arguments`:

```json
{
  "lsp": {
    "clangd": {
      "binary": {
        "path": "/path/to/clangd",
        "arguments": []
      }
    }
  }
}
```

This `"path"` has to be an absolute path.

## Arguments

You can pass any number of arguments to clangd. To see a full set of available options, run `clangd --help` from the command line. For example with `--function-arg-placeholders=0` completions contain only parentheses for function calls, while the default (`--function-arg-placeholders=1`) completions also contain placeholders for method parameters.

```json
{
  "lsp": {
    "clangd": {
      "binary": {
        "path": "/path/to/clangd",
        "arguments": ["--function-arg-placeholders=0"]
      }
    }
  }
}
```

## Formatting

By default Zed will use the `clangd` language server for formatting C++ code. The Clangd is the same as the `clang-format` CLI tool. To configure this you can add a `.clang-format` file. For example:

```yaml
---
BasedOnStyle: LLVM
IndentWidth: 4
---
Language: Cpp
# Force pointers to the type for C++.
DerivePointerAlignment: false
PointerAlignment: Left
---
```

See [Clang-Format Style Options](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) for a complete list of options.

You can trigger formatting via {#kb editor::Format} or the `editor: format` action from the command palette or by adding `format_on_save` to your Zed settings:

```json
  "languages": {
    "C++": {
      "format_on_save": "on",
      "tab_size": 2
    }
  }
```

## More server configuration

In the root of your project, it is generally common to create a `.clangd` file to set extra configuration.

```text
CompileFlags:
  Add:
    - "--include-directory=/path/to/include"
Diagnostics:
  MissingIncludes: Strict
  UnusedIncludes: Strict
```

For more advanced usage of clangd configuration file, take a look into their [official page](https://clangd.llvm.org/config.html).

## Compile Commands

For some projects Clangd requires a `compile_commands.json` file to properly analyze your project. This file contains the compilation database that tells clangd how your project should be built.

### CMake Compile Commands

With CMake, you can generate `compile_commands.json` automatically by adding the following line to your `CMakeLists.txt`:

```cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
```

After building your project, CMake will generate the `compile_commands.json` file in the build directory and clangd will automatically pick it up.

## Debugging

You can use CodeLLDB or GDB to debug native binaries. (Make sure that your build process passes `-g` to the C++ compiler, so that debug information is included in the resulting binary.) See below for examples of debug configurations that you can add to `.zed/debug.json`.

### Build and Debug Binary

```json
[
  {
    "label": "Debug native binary",
    "build": {
      "command": "make",
      "args": ["-j8"],
      "cwd": "$ZED_WORKTREE_ROOT"
    },
    "program": "$ZED_WORKTREE_ROOT/build/prog",
    "request": "launch",
    "adapter": "CodeLLDB"
  }
]
```

    # C#

Note language name is "CSharp" for settings not "C#'

C# support is available through the [C# extension](https://github.com/zed-extensions/csharp).

- Tree-sitter: [tree-sitter/tree-sitter-c-sharp](https://github.com/tree-sitter/tree-sitter-c-sharp)
- Language Server: [OmniSharp/omnisharp-roslyn](https://github.com/OmniSharp/omnisharp-roslyn)

## Configuration

The `OmniSharp` binary can be configured in a Zed settings file with:

```json
{
  "lsp": {
    "omnisharp": {
      "binary": {
        "path": "/path/to/OmniSharp",
        "arguments": ["optional", "additional", "args", "-lsp"]
      }
    }
  }
}
```

    # CSS

Zed has built-in support for CSS.

- Tree-sitter: [tree-sitter/tree-sitter-css](https://github.com/tree-sitter/tree-sitter-css)
- Language Servers:
  - [microsoft/vscode-html-languageservice](https://github.com/microsoft/vscode-html-languageservice)
  - [tailwindcss-language-server](https://github.com/tailwindlabs/tailwindcss-intellisense)

## Tailwind CSS

Zed also supports [Tailwind CSS](./tailwindcss.md) out-of-the-box for languages and frameworks like JavaScript, Astro, Svelte, and more.

<!-- TBD: Document CS -->

## Recommended Reading

- [HTML](./html.md)
- [TypeScript](./typescript.md)
- [JavaScript](./javascript.md)

    # Dart

Dart support is available through the [Dart extension](https://github.com/zed-extensions/dart).

- Tree-sitter: [UserNobody14/tree-sitter-dart](https://github.com/UserNobody14/tree-sitter-dart)
- Language Server: [dart language-server](https://github.com/dart-lang/sdk)

## Pre-requisites

You will need to install the Dart SDK.

You can install dart from [dart.dev/get-dart](https://dart.dev/get-dart) or via the [Flutter Version Management CLI (fvm)](https://fvm.app/documentation/getting-started/installation)

## Configuration

The dart extension requires no configuration if you have `dart` in your path:

```sh
which dart
dart --version
```

If you would like to use a specific dart binary or use dart via FVM you can specify the `dart` binary in your Zed settings.jsons file:

```json
{
  "lsp": {
    "dart": {
      "binary": {
        "path": "/opt/homebrew/bin/fvm",
        "arguments": ["dart", "language-server", "--protocol=lsp"]
      }
    }
  }
}
```

### Formatting

Dart by-default uses a very conservative maximum line length (80). If you would like the dart LSP to permit a longer line length when auto-formatting, add the following to your Zed settings.json:

```json
{
  "lsp": {
    "dart": {
      "settings": {
        "lineLength": 140
      }
    }
  }
}
```

Please see the Dart documentation for more information on [dart language-server capabilities](https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/tool/lsp_spec/README.md).

    # Deno

Deno support is available through the [Deno extension](https://github.com/zed-extensions/deno).

- Language server: [Deno Language Server](https://docs.deno.com/runtime/manual/advanced/language_server/overview/)

## Deno Configuration

To use the Deno Language Server with TypeScript and TSX files, you will likely wish to disable the default language servers and enable deno by adding the following to your settings.json:

```json
{
  "lsp": {
    "deno": {
      "settings": {
        "deno": {
          "enable": true
        }
      }
    }
  },
  "languages": {
    "JavaScript": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    },
    "TypeScript": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    },
    "TSX": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    }
  }
}
```

See [Configuring supported languages](../configuring-languages.md) in the Zed documentation for more information.

<!--
TBD: Deno TypeScript REPL instructions [docs/repl#typescript-deno](../repl.md#typescript-deno)
-->

## DAP support

To debug deno programs, add this to `.zed/debug.json`

```json
[
  {
    "adapter": "JavaScript",
    "label": "Deno",
    "request": "launch",
    "type": "pwa-node",
    "cwd": "$ZED_WORKTREE_ROOT",
    "program": "$ZED_FILE",
    "runtimeExecutable": "deno",
    "runtimeArgs": ["run", "--allow-all", "--inspect-wait"],
    "attachSimplePort": 9229
  }
]
```

## Runnable support

To run deno tasks like tests from the ui, add this to `.zed/tasks.json`

```json
[
  {
    "label": "deno test",
    "command": "deno test -A --filter '/^$ZED_CUSTOM_DENO_TEST_NAME$/' $ZED_FILE",
    "tags": ["js-test"]
  }
]
```

## See also:

- [TypeScript](./typescript.md)
- [JavaScript](./javascript.md)

    # Diff

Diff support is available natively in Zed.

- Tree-sitter: [zed-industries/the-mikedavis/tree-sitter-diff](https://github.com/the-mikedavis/tree-sitter-diff)

## Configuration

Zed will not attempt to format diff files and has [`remove_trailing_whitespace_on_save`](https://zed.dev/docs/configuring-zed#remove-trailing-whitespace-on-save) and [`ensure-final-newline-on-save`](https://zed.dev/docs/configuring-zed#ensure-final-newline-on-save) set to false.

Zed will automatically recognize files with `patch` and `diff` extensions as Diff files. To recognize other extensions, add them to `file_types` in your Zed settings.json:

```json
  "file_types": {
    "Diff": ["dif"]
  },
```

    # Docker

Support for `Dockerfile` and `docker-compose.yaml` in Zed is provided by community-maintained extensions.

## Docker Compose

Docker `compose.yaml` language support in Zed is provided by the [Docker Compose extension](https://github.com/eth0net/zed-docker-compose). Please report issues to: [https://github.com/eth0net/zed-docker-compose/issues](https://github.com/eth0net/zed-docker-compose/issues).

- Language Server: [microsoft/compose-language-service](https://github.com/microsoft/compose-language-service)

## Dockerfile

`Dockerfile` language support in Zed is provided by the [Dockerfile extension](https://github.com/d1y/dockerfile.zed). Please issues to: [https://github.com/d1y/dockerfile.zed/issues](https://github.com/d1y/dockerfile.zed/issues).

- Tree-sitter: [camdencheek/tree-sitter-dockerfile](https://github.com/camdencheek/tree-sitter-dockerfile)
- Language Server: [rcjsuen/dockerfile-language-server](https://github.com/rcjsuen/dockerfile-language-server)

    # Elixir

Elixir support is available through the [Elixir extension](https://github.com/zed-extensions/elixir).

- Tree-sitter:
  - [elixir-lang/tree-sitter-elixir](https://github.com/elixir-lang/tree-sitter-elixir)
  - [phoenixframework/tree-sitter-heex](https://github.com/phoenixframework/tree-sitter-heex)
- Language servers:
  - [elixir-lang/expert](https://github.com/elixir-lang/expert)
  - [elixir-lsp/elixir-ls](https://github.com/elixir-lsp/elixir-ls)
  - [elixir-tools/next-ls](https://github.com/elixir-tools/next-ls)
  - [lexical-lsp/lexical](https://github.com/lexical-lsp/lexical)

## Choosing a language server

The Elixir extension offers language server support for `expert`, `elixir-ls`, `next-ls`, and `lexical`.

`elixir-ls` is enabled by default.

### Expert

To switch to `expert`, add the following to your `settings.json`:

```json
  "languages": {
    "Elixir": {
      "language_servers": ["expert", "!elixir-ls", "!next-ls", "!lexical", "..."]
    },
    "HEEX": {
      "language_servers": ["expert", "!elixir-ls", "!next-ls", "!lexical", "..."]
    }
  }
```

### Next LS

To switch to `next-ls`, add the following to your `settings.json`:

```json
  "languages": {
    "Elixir": {
      "language_servers": ["next-ls", "!expert", "!elixir-ls", "!lexical", "..."]
    },
    "HEEX": {
      "language_servers": ["next-ls", "!expert", "!elixir-ls", "!lexical", "..."]
    }
  }
```

### Lexical

To switch to `lexical`, add the following to your `settings.json`:

```json
  "languages": {
    "Elixir": {
      "language_servers": ["lexical", "!expert", "!elixir-ls", "!next-ls", "..."]
    },
    "HEEX": {
      "language_servers": ["lexical", "!expert", "!elixir-ls", "!next-ls", "..."]
    }
  }
```

## Setting up `elixir-ls`

1. Install `elixir`:

```sh
brew install elixir
```

2. Install `elixir-ls`:

```sh
brew install elixir-ls
```

3. Restart Zed

> If `elixir-ls` is not running in an elixir project, check the error log via the command palette action `zed: open log`. If you find an error message mentioning: `invalid LSP message header "Shall I install Hex? (if running non-interactively, use \"mix local.hex --force\") [Yn]`, you might need to install [`Hex`](https://hex.pm). You run `elixir-ls` from the command line and accept the prompt to install `Hex`.

### Formatting with Mix

If you prefer to format your code with [Mix](https://hexdocs.pm/mix/Mix.html), use the following snippet in your `settings.json` file to configure it as an external formatter. Formatting will occur on file save.

```json
{
  "languages": {
    "Elixir": {
      "format_on_save": {
        "external": {
          "command": "mix",
          "arguments": ["format", "--stdin-filename", "{buffer_path}", "-"]
        }
      }
    }
  }
}
```

### Additional workspace configuration options

You can pass additional elixir-ls workspace configuration options via lsp settings in `settings.json`.

The following example disables dialyzer:

```json
  "lsp": {
    "elixir-ls": {
      "settings": {
        "dialyzerEnabled": false
      }
    }
  }
```

See [ElixirLS configuration settings](https://github.com/elixir-lsp/elixir-ls#elixirls-configuration-settings) for more options.

### HEEx

Zed also supports HEEx templates. HEEx is a mix of [EEx](https://hexdocs.pm/eex/1.12.3/EEx.html) (Embedded Elixir) and HTML, and is used in Phoenix LiveView applications.

- Tree-sitter: [phoenixframework/tree-sitter-heex](https://github.com/phoenixframework/tree-sitter-heex)

    # Elm

Elm support is available through the [Elm extension](https://github.com/zed-extensions/elm).

- Tree-sitter: [elm-tooling/tree-sitter-elm](https://github.com/elm-tooling/tree-sitter-elm)
- Language Server: [elm-tooling/elm-language-server](https://github.com/elm-tooling/elm-language-server)

## Setup

Zed support for Elm requires installation of `elm`, `elm-format`, and `elm-review`.

1. [Install Elm](https://guide.elm-lang.org/install/elm.html) (or run `brew install elm` on macOS).
2. Install `elm-review` to support code linting:
   ```sh
   npm install elm-review --save-dev
   ```
3. Install `elm-format` to support automatic formatting
   ```sh
   npm install -g elm-format
   ```

## Configuring `elm-language-server`

Elm language server can be configured in your `settings.json`, e.g.:

```json
{
  "lsp": {
    "elm-language-server": {
      "initialization_options": {
        "disableElmLSDiagnostics": true,
        "onlyUpdateDiagnosticsOnSave": false,
        "elmReviewDiagnostics": "warning"
      }
    }
  }
}
```

`elm-format`, `elm-review` and `elm` need to be installed and made available in the environment or configured in the settings. See the [full list of server settings here](https://github.com/elm-tooling/elm-language-server?tab=readme-ov-file#server-settings).

    # Emmet

Emmet support is available through the [Emmet extension](https://github.com/zed-extensions/emmet).

[Emmet](https://emmet.io/) is a web-developer’s toolkit that can greatly improve your HTML & CSS workflow.

- Language Server: [olrtg/emmet-language-server](https://github.com/olrtg/emmet-language-server)

<!--
TBD: Document Emmet usage in zed with: HTML, PHP, ERB, Javascript, TSX, CSS
-->

    # Erlang

Erlang support is available through the [Erlang extension](https://github.com/zed-extensions/erlang).

- Tree-sitter: [WhatsApp/tree-sitter-erlang](https://github.com/WhatsApp/tree-sitter-erlang)
- Language Servers:
  - [erlang-ls/erlang_ls](https://github.com/erlang-ls/erlang_ls)
  - [WhatsApp/erlang-language-platform](https://github.com/WhatsApp/erlang-language-platform)

## Choosing a language server

The Erlang extension offers language server support for `erlang_ls` and `erlang-language-platform`.

`erlang_ls` is enabled by default.

To switch to `erlang-language-platform`, add the following to your `settings.json`:

```json
{
  "languages": {
    "Erlang": {
      "language_servers": ["elp", "!erlang-ls", "..."]
    }
  }
}
```

## See also:

- [Elixir](./elixir.md)
- [Gleam](./gleam.md)

    # Fish

Fish language support in Zed is provided by the community-maintained [Fish extension](https://github.com/hasit/zed-fish).
Report issues to: [https://github.com/hasit/zed-fish/issues](https://github.com/hasit/zed-fish/issues)

- Tree-sitter: [ram02z/tree-sitter-fish](https://github.com/ram02z/tree-sitter-fish)

### Formatting

Zed supports auto-formatting fish code using external tools like [`fish_indent`](https://fishshell.com/docs/current/cmds/fish_indent.html), which is included with fish.

1. Ensure `fish_indent` is available in your path and check the version:

```sh
which fish_indent
fish_indent --version
```

2. Configure Zed to automatically format fish code with `fish_indent`:

```json
  "languages": {
    "Fish": {
      "formatter": {
        "external": {
          "command": "fish_indent"
        }
      }
    }
  },
```

    # GDScript

Godot [GDScript](https://gdscript.com/) language support in Zed is provided by the community-maintained [GDScript extension](https://github.com/grndctrl/zed-gdscript).
Report issues to: [https://github.com/grndctrl/zed-gdscript/issues](https://github.com/grndctrl/zed-gdscript/issues)

- Tree-sitter: [PrestonKnopp/tree-sitter-gdscript](https://github.com/PrestonKnopp/tree-sitter-gdscript) and [PrestonKnopp/tree-sitter-godot-resource](https://github.com/PrestonKnopp/tree-sitter-godot-resource)
- Language Server: [gdscript-language-server](https://github.com/godotengine/godot)

## Setup

1. Download and install [Godot for macOS](https://godotengine.org/download/macos/).
2. Unzip the Godot.app and drag it into your /Applications folder.
3. Open Godot.app and open your project (an example project is fine)
4. In Godot, Editor Menu -> Editor Settings; scroll down the left sidebar to `Text Editor -> External`
   1. Use External Editor: "✅ On"
   2. Exec path: `/Applications/Zed.app/Contents/MacOS/zed`
   3. Exec flags: `{project} {file}:{line}:{col}`
   4. Close settings to save.
5. In Godot double click on a \*.gd script and Zed will launch

<!--
TBD: GDScript Linux setup
-->

## Usage

When Godot is running, the GDScript extension will connect to the language server provided by the Godot runtime and will provide `jump to definition`, hover states when you hold cmd and other language server features.

> Note: If Zed is already running with an existing workspace, spawning from Godot will fail. Quit Zed and it should work again.

    # Gleam

Gleam support is available through the [Gleam extension](https://github.com/gleam-lang/zed-gleam). To learn about Gleam, see the [docs](https://gleam.run/documentation/) or check out the [`stdlib` reference](https://hexdocs.pm/gleam_stdlib/). The Gleam language server has a variety of features, including go-to definition, automatic imports, and [more](https://gleam.run/language-server/).

- Tree-sitter: [gleam-lang/tree-sitter-gleam](https://github.com/gleam-lang/tree-sitter-gleam)
- Language Server: [gleam lsp](https://github.com/gleam-lang/gleam/tree/main/compiler-core/src/language_server)

See also:

- [Elixir](./elixir.md)
- [Erlang](./erlang.md)

    # GLSL

GLSL (OpenGL Shading Language) support is available through the [GLSL Extension](https://github.com/zed-industries/zed/tree/main/extensions/glsl/)

- Tree-sitter: [theHamsta/tree-sitter-glsl](https://github.com/theHamsta/tree-sitter-glsl)
- Language Server: [nolanderc/glsl_analyzer](https://github.com/nolanderc/glsl_analyzer)

    # Go

Go support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go)
- Language Server: [golang/tools/tree/master/gopls](https://github.com/golang/tools/tree/master/gopls)
- Debug Adapter: [delve](https://github.com/go-delve/delve)

## Setup

We recommend installing gopls via go's package manager and not via Homebrew or your Linux distribution's package manager.

1. Make sure you have uninstalled any version of gopls you have installed via your package manager:

```sh
# MacOS homebrew
brew remove gopls
# Ubuntu
sudo apt-get remove gopls
sudo snap remove gopls
# Arch
sudo pacman -R gopls
```

2. Install/Update `gopls` to the latest version using the go module tool:

```sh
go install golang.org/x/tools/gopls@latest
```

3. Ensure that `gopls` is in your path:

```sh
which gopls
gopls version
```

If `gopls` is not found you will likely need to add `export PATH="$PATH:$HOME/go/bin"` to your `.zshrc` / `.bash_profile`

## Inlay Hints

Zed sets the following initialization options for inlay hints:

```json
"hints": {
    "assignVariableTypes": true,
    "compositeLiteralFields": true,
    "compositeLiteralTypes": true,
    "constantValues": true,
    "functionTypeParameters": true,
    "parameterNames": true,
    "rangeVariableTypes": true
}
```

to make the language server send back inlay hints when Zed has them enabled in the settings.

Use

```json
"lsp": {
    "gopls": {
        "initialization_options": {
            "hints": {
                ....
            }
        }
    }
}
```

to override these settings.

See [gopls inlayHints documentation](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md) for more information.

## Debugging

Zed supports zero-configuration debugging of Go tests and entry points (`func main`). Run {#action debugger::Start} ({#kb debugger::Start}) to see a contextual list of these preconfigured debug tasks.

For more control, you can add debug configurations to `.zed/debug.json`. See below for examples.

### Debug Go Packages

To debug a specific package, you can do so by setting the Delve mode to "debug". In this case "program" should be set to the package name.

```json
[
  {
    "label": "Go (Delve)",
    "adapter": "Delve",
    "program": "$ZED_FILE",
    "request": "launch",
    "mode": "debug"
  },
  {
    "label": "Run server",
    "adapter": "Delve",
    "request": "launch",
    "mode": "debug",
    // For Delve, the program can be a package name
    "program": "./cmd/server"
    // "args": [],
    // "buildFlags": [],
  }
]
```

### Debug Go Tests

To debug the tests for a package, set the Delve mode to "test".
The "program" is still the package name, and you can use the "buildFlags" to do things like set tags, and the "args" to set args on the test binary. (See `go help testflags` for more information on doing that).

```json
[
  {
    "label": "Run integration tests",
    "adapter": "Delve",
    "request": "launch",
    "mode": "test",
    "program": ".",
    "buildFlags": ["-tags", "integration"]
    // To filter down to just the test your cursor is in:
    // "args": ["-test.run", "$ZED_SYMBOL"]
  }
]
```

### Build and debug separately

If you need to build your application with a specific command, you can use the "exec" mode of Delve. In this case "program" should point to an executable,
and the "build" command should build that.

```json
[
  {
    "label": "Debug Prebuilt Unit Tests",
    "adapter": "Delve",
    "request": "launch",
    "mode": "exec",
    "program": "${ZED_WORKTREE_ROOT}/__debug_unit",
    "args": ["-test.v", "-test.run=${ZED_SYMBOL}"],
    "build": {
      "command": "go",
      "args": [
        "test",
        "-c",
        "-tags",
        "unit",
        "-gcflags\"all=-N -l\"",
        "-o",
        "__debug_unit",
        "./pkg/..."
      ]
    }
  }
]
```

### Attaching to an existing instance of Delve

You might find yourself needing to connect to an existing instance of Delve that's not necessarily running on your machine; in such case, you can use `tcp_arguments` to instrument Zed's connection to Delve.

```json
[
  {
    "adapter": "Delve",
    "label": "Connect to a running Delve instance",
    "program": "/Users/zed/Projects/language_repositories/golang/hello/hello",
    "cwd": "/Users/zed/Projects/language_repositories/golang/hello",
    "args": [],
    "env": {},
    "request": "launch",
    "mode": "exec",
    "stopOnEntry": false,
    "tcp_connection": { "host": "123.456.789.012", "port": 53412 }
  }
]
```

In such case Zed won't spawn a new instance of Delve, as it opts to use an existing one. The consequence of this is that _there will be no terminal_ in Zed; you have to interact with the Delve instance directly, as it handles stdin/stdout of the debuggee.

## Go Mod

- Tree-sitter: [camdencheek/tree-sitter-go-mod](https://github.com/camdencheek/tree-sitter-go-mod)
- Language Server: N/A

## Go Sum

- Tree-sitter: [amaanq/tree-sitter-go-sum](https://github.com/amaanq/tree-sitter-go-sum)
- Language Server: N/A

## Go Work

- Tree-sitter:
  [tree-sitter-go-work](https://github.com/d1y/tree-sitter-go-work)
- Language Server: N/A

    # Groovy

Groovy language support in Zed is provided by the community-maintained [Groovy extension](https://github.com/valentinegb/zed-groovy).
Report issues to: [https://github.com/valentinegb/zed-groovy/issues](https://github.com/valentinegb/zed-groovy/issues)

- Tree-sitter: [murtaza64/tree-sitter-groovy](https://github.com/murtaza64/tree-sitter-groovy)
- Language Server: [GroovyLanguageServer/groovy-language-server](https://github.com/GroovyLanguageServer/groovy-language-server)

    # Haskell

Haskell support is available through the [Haskell extension](https://github.com/zed-extensions/haskell).

- Tree-sitter: [tree-sitter-haskell](https://github.com/tree-sitter/tree-sitter-haskell)
- Language Server: [haskell-language-server](https://github.com/haskell/haskell-language-server)

## Installing HLS

Recommended method to [install haskell-language-server](https://haskell-language-server.readthedocs.io/en/latest/installation.html) (HLS) is via [ghcup](https://www.haskell.org/ghcup/install/) (`curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
`):

```sh
ghcup install hls
which haskell-language-server-wrapper
```

## Configuring HLS

If you need to configure haskell-language-server (hls) you can add configuration options to your Zed settings.json:

```json
{
  "lsp": {
    "hls": {
      "initialization_options": {
        "haskell": {
          "formattingProvider": "fourmolu"
        }
      }
    }
  }
}
```

See the official [configuring haskell-language-server](https://haskell-language-server.readthedocs.io/en/latest/configuration.html) docs for more options.

If you would like to use a specific hls binary, or perhaps use [static-ls](https://github.com/josephsumabat/static-ls) as a drop-in replacement instead, you can specify the binary path and arguments:

```json
{
  "lsp": {
    "hls": {
      "binary": {
        "path": "static-ls",
        "arguments": ["--experimentalFeatures"]
      }
    }
  }
}
```

    # Helm

Support for Helm in Zed is provided by the community-maintained [Helm extension](https://github.com/cabrinha/helm.zed).

- Tree-sitter: [tree-sitter-go-template](https://github.com/ngalaiko/tree-sitter-go-template/tree/master)
- Language Server: [mrjosh/helm-ls](https://github.com/mrjosh/helm-ls)

## Setup

Enable Helm language for Helm files by editing your `.zed/settings.json` and adding:

```json
  "file_types": {
    "Helm": [
      "**/templates/**/*.tpl",
      "**/templates/**/*.yaml",
      "**/templates/**/*.yml",
      "**/helmfile.d/**/*.yaml",
      "**/helmfile.d/**/*.yml",
      "**/values*.yaml"
    ]
  }
```

This will also mark values.yaml files as the type helm, since helm-ls supports this.

    # HTML

HTML support is available through the [HTML extension](https://github.com/zed-industries/zed/tree/main/extensions/html).

- Tree-sitter: [tree-sitter/tree-sitter-html](https://github.com/tree-sitter/tree-sitter-html)
- Language Server: [microsoft/vscode-html-languageservice](https://github.com/microsoft/vscode-html-languageservice)

This extension is automatically installed, but if you do not want to use it, you can add the following to your settings:

```json
{
  "auto_install_extensions": {
    "html": false
  }
}
```

## Formatting

By default Zed uses [Prettier](https://prettier.io/) for formatting HTML.

You can disable `format_on_save` by adding the following to your Zed `settings.json`:

```json
  "languages": {
    "HTML": {
      "format_on_save": "off",
    }
  }
```

You can still trigger formatting manually with {#kb editor::Format} or by opening [the Command Palette](..//getting-started.md#command-palette) ({#kb command_palette::Toggle}) and selecting "Format Document".

### LSP Formatting

To use the `vscode-html-language-server` language server auto-formatting instead of Prettier, add the following to your Zed settings:

```json
  "languages": {
    "HTML": {
      "formatter": "language_server",
    }
  }
```

You can customize various [formatting options](https://code.visualstudio.com/docs/languages/html#_formatting) for `vscode-html-language-server` via your Zed `settings.json`:

```json
  "lsp": {
    "vscode-html-language-server": {
      "settings": {
        "html": {
          "format": {
            // Indent under <html> and <head> (default: false)
            "indentInnerHtml": true,
            // Disable formatting inside <svg> or <script>
            "contentUnformatted": "svg,script",
            // Add an extra newline before <div> and <p>
            "extraLiners": "div,p"
          }
        }
      }
    }
  }
```

## See also

- [CSS](./css.md)
- [JavaScript](./javascript.md)
- [TypeScript](./typescript.md)

    # Java

Java language support in Zed is provided by:

- Zed Java: [zed-extensions/java](https://github.com/zed-extensions/java)
- Tree-sitter: [tree-sitter/tree-sitter-java](https://github.com/tree-sitter/tree-sitter-java)
- Language Server: [eclipse-jdtls/eclipse.jdt.ls](https://github.com/eclipse-jdtls/eclipse.jdt.ls)

## Install OpenJDK

You will need to install a Java runtime (OpenJDK).

- macOS: `brew install openjdk`
- Ubuntu: `sudo add-apt-repository ppa:openjdk-23 && sudo apt-get install openjdk-23`
- Windows: `choco install openjdk`
- Arch Linux: `sudo pacman -S jre-openjdk-headless`

Or manually download and install [OpenJDK 23](https://jdk.java.net/23/).

## Extension Install

You can install either by opening {#action zed::Extensions}({#kb zed::Extensions}) and searching for `java`.

## Settings / Initialization Options

The extension will automatically download the language server, see: [Manual JDTLS Install](#manual-jdts-install) below if you'd prefer to manage that yourself.

For available `initialization_options` please see the [Initialize Request section of the Eclipse.jdt.ls Wiki](https://github.com/eclipse-jdtls/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request).

You can add these customizations to your Zed Settings by launching {#action zed::OpenSettings}({#kb zed::OpenSettings}) or by using a `.zed/setting.json` inside your project.

### Zed Java Settings

```json
{
  "lsp": {
    "jdtls": {
      "initialization_options": {}
    }
  }
}
```

## Example Configs

### JDTLS Binary

By default, zed will look in your `PATH` for a `jdtls` binary, if you wish to specify an explicit binary you can do so via settings:

```json
  "lsp": {
    "jdtls": {
      "binary": {
        "path": "/path/to/java/bin/jdtls",
        // "arguments": [],
        // "env": {},
        "ignore_system_version": true
      }
    }
  }
```

### Zed Java Initialization Options

There are also many more options you can pass directly to the language server, for example:

```json
{
  "lsp": {
    "jdtls": {
      "initialization_options": {
        "bundles": [],
        "workspaceFolders": ["file:///home/snjeza/Project"],
        "settings": {
          "java": {
            "home": "/usr/local/jdk-9.0.1",
            "errors": {
              "incompleteClasspath": {
                "severity": "warning"
              }
            },
            "configuration": {
              "updateBuildConfiguration": "interactive",
              "maven": {
                "userSettings": null
              }
            },
            "trace": {
              "server": "verbose"
            },
            "import": {
              "gradle": {
                "enabled": true
              },
              "maven": {
                "enabled": true
              },
              "exclusions": [
                "**/node_modules/**",
                "**/.metadata/**",
                "**/archetype-resources/**",
                "**/META-INF/maven/**",
                "/**/test/**"
              ]
            },
            "jdt": {
              "ls": {
                "lombokSupport": {
                  "enabled": false // Set this to true to enable lombok support
                }
              }
            },
            "referencesCodeLens": {
              "enabled": false
            },
            "signatureHelp": {
              "enabled": false
            },
            "implementationsCodeLens": {
              "enabled": false
            },
            "format": {
              "enabled": true
            },
            "saveActions": {
              "organizeImports": false
            },
            "contentProvider": {
              "preferred": null
            },
            "autobuild": {
              "enabled": false
            },
            "completion": {
              "favoriteStaticMembers": [
                "org.junit.Assert.*",
                "org.junit.Assume.*",
                "org.junit.jupiter.api.Assertions.*",
                "org.junit.jupiter.api.Assumptions.*",
                "org.junit.jupiter.api.DynamicContainer.*",
                "org.junit.jupiter.api.DynamicTest.*"
              ],
              "importOrder": ["java", "javax", "com", "org"]
            }
          }
        }
      }
    }
  }
}
```

## Manual JDTLS Install

If you prefer, you can install JDTLS yourself and the extension can be configured to use that instead.

- macOS: `brew install jdtls`
- Arch: [`jdtls` from AUR](https://aur.archlinux.org/packages/jdtls)

Or manually download install:

- [JDTLS Milestone Builds](http://download.eclipse.org/jdtls/milestones/) (updated every two weeks)
- [JDTLS Snapshot Builds](https://download.eclipse.org/jdtls/snapshots/) (frequent updates)

## See also

- [Zed Java Repo](https://github.com/zed-extensions/java)
- [Zed Java Issues](https://github.com/zed-extensions/java/issues)

    # JavaScript

JavaScript support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-javascript](https://github.com/tree-sitter/tree-sitter-javascript)
- Language Server: [typescript-language-server/typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
- Debug Adapter: [vscode-js-debug](https://github.com/microsoft/vscode-js-debug)

## Code formatting

Formatting on save is enabled by default for JavaScript, using TypeScript's built-in code formatting.
But many JavaScript projects use other command-line code-formatting tools, such as [Prettier](https://prettier.io/).
You can use one of these tools by specifying an _external_ code formatter for JavaScript in your settings.
See [the configuration docs](../configuring-zed.md) for more information.

For example, if you have Prettier installed and on your `PATH`, you can use it to format JavaScript files by adding the following to your `settings.json`:

```json
{
  "languages": {
    "JavaScript": {
      "formatter": {
        "external": {
          "command": "prettier",
          "arguments": ["--stdin-filepath", "{buffer_path}"]
        }
      }
    }
  }
}
```

## JSX

Zed supports JSX syntax highlighting out of the box.

In JSX strings, the [`tailwindcss-language-server`](./tailwindcss.md) is used provide autocompletion for Tailwind CSS classes.

## JSDoc

Zed supports JSDoc syntax in JavaScript and TypeScript comments that match the JSDoc syntax.
Zed uses [tree-sitter/tree-sitter-jsdoc](https://github.com/tree-sitter/tree-sitter-jsdoc) for parsing and highlighting JSDoc.

## ESLint

You can configure Zed to format code using `eslint --fix` by running the ESLint code action when formatting:

```json
{
  "languages": {
    "JavaScript": {
      "code_actions_on_format": {
        "source.fixAll.eslint": true
      }
    }
  }
}
```

You can also only execute a single ESLint rule when using `fixAll`:

```json
{
  "languages": {
    "JavaScript": {
      "code_actions_on_format": {
        "source.fixAll.eslint": true
      }
    }
  },
  "lsp": {
    "eslint": {
      "settings": {
        "codeActionOnSave": {
          "rules": ["import/order"]
        }
      }
    }
  }
}
```

> **Note:** the other formatter you have configured will still run, after ESLint.
> So if your language server or Prettier configuration don't format according to
> ESLint's rules, then they will overwrite what ESLint fixed and you end up with
> errors.

If you **only** want to run ESLint on save, you can configure code actions as
the formatter:

```json
{
  "languages": {
    "JavaScript": {
      "formatter": {
        "code_actions": {
          "source.fixAll.eslint": true
        }
      }
    }
  }
}
```

### Configure ESLint's `nodePath`:

You can configure ESLint's `nodePath` setting:

```json
{
  "lsp": {
    "eslint": {
      "settings": {
        "nodePath": ".yarn/sdks"
      }
    }
  }
}
```

### Configure ESLint's `problems`:

You can configure ESLint's `problems` setting.

For example, here's how to set `problems.shortenToSingleLine`:

```json
{
  "lsp": {
    "eslint": {
      "settings": {
        "problems": {
          "shortenToSingleLine": true
        }
      }
    }
  }
}
```

### Configure ESLint's `rulesCustomizations`:

You can configure ESLint's `rulesCustomizations` setting:

```json
{
  "lsp": {
    "eslint": {
      "settings": {
        "rulesCustomizations": [
          // set all eslint errors/warnings to show as warnings
          { "rule": "*", "severity": "warn" }
        ]
      }
    }
  }
}
```

### Configure ESLint's `workingDirectory`:

You can configure ESLint's `workingDirectory` setting:

```json
{
  "lsp": {
    "eslint": {
      "settings": {
        "workingDirectory": {
          "mode": "auto"
        }
      }
    }
  }
}
```

## Debugging

Zed supports debugging JavaScript code out of the box.
The following can be debugged without writing additional configuration:

- Tasks from `package.json`
- Tests written using several popular frameworks (Jest, Mocha, Vitest, Jasmine)

Run {#action debugger::Start} ({#kb debugger::Start}) to see a contextual list of these predefined debug tasks.

As for all languages, configurations from `.vscode/launch.json` are also available for debugging in Zed.

If your use-case isn't covered by any of these, you can take full control by adding debug configurations to `.zed/debug.json`. See below for example configurations.

### Debug the current file

```json
[
  {
    "adapter": "JavaScript",
    "label": "Debug JS file",
    "type": "node",
    "request": "launch",
    "program": "$ZED_FILE",
    "skipFiles": ["<node_internals>/**"]
  }
]
```

This implicitly runs the current file using `node`.

### Launch a web app in Chrome

```json
[
  {
    "adapter": "JavaScript",
    "label": "Debug app in Chrome",
    "type": "chrome",
    "request": "launch",
    "file": "$ZED_WORKTREE_ROOT/index.html",
    "webRoot": "$ZED_WORKTREE_ROOT",
    "console": "integratedTerminal",
    "skipFiles": ["<node_internals>/**"]
  }
]
```

## See also

- [Yarn documentation](./yarn.md) for a walkthrough of configuring your project to use Yarn.
- [TypeScript documentation](./typescript.md)

    # JSON

JSON support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json)
- Language Server: [zed-industries/json-language-server](https://github.com/zed-industries/json-language-server)

## JSONC

Zed also supports a super-set of JSON called JSONC, which allows single line comments (`//`) in JSON files.
While editing these files you can use `cmd-/` (macOS) or `ctrl-/` (Linux) to toggle comments on the current line or selection.

## JSONC Prettier Formatting

If you use files with the `*.jsonc` extension when using `Format Document` or have `format_on_save` enabled, Zed invokes Prettier as the formatter. Prettier has an [outstanding issue](https://github.com/prettier/prettier/issues/15956) where it will add trailing commas to files with a `jsonc` extension. JSONC files which have a `.json` extension are unaffected.

To workaround this behavior you can add the following to your `.prettierrc` configuration file:

```json
{
  "overrides": [
    {
      "files": ["*.jsonc"],
      "options": {
        "parser": "json",
        "trailingComma": "none"
      }
    }
  ]
}
```

## JSON Language Server

Zed automatically out of the box supports JSON Schema validation of `package.json` and `tsconfig.json` files, but `json-language-server` can use JSON Schema definitions in project files, from the [JSON Schema Store](https://www.schemastore.org) or other publicly available URLs for JSON validation.

### Inline Schema Specification

To specify a schema inline with your JSON files, add a `$schema` top level key linking to your json schema file.

For example to for a `.luarc.json` for use with [lua-language-server](https://github.com/LuaLS/lua-language-server/):

```json
{
  "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
  "runtime.version": "Lua 5.4"
}
```

### Schema Specification via Settings

You can alternatively associate JSON Schemas with file paths by via Zed LSP settings.

To

```json
"lsp": {
  "json-language-server": {
    "settings": {
      "json": {
        "schemas": [
          {
            "fileMatch": ["*/*.luarc.json"],
            "url": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json"
          }
        ]
      }
    }
  }
}
```

You can also pass any of the [supported settings](https://github.com/Microsoft/vscode/blob/main/extensions/json-language-features/server/README.md#settings) to json-language-server by specifying them in your Zed settings.json:

<!--
TBD: Add formatter (prettier) settings (autoformat, tab_size, etc)
-->

    # Jsonnet

Jsonnet language support in Zed is provided by the community-maintained [Jsonnet extension](https://github.com/narqo/zed-jsonnet).

- Tree-sitter: [sourcegraph/tree-sitter-jsonnet](https://github.com/sourcegraph/tree-sitter-jsonnet)
- Language Server: [grafana/jsonnet-language-server](https://github.com/grafana/jsonnet-language-server)

## Configuration

Workspace configuration options can be passed to the language server via the `lsp` settings of the `settings.json`.

The following example enables support for resolving [tanka](https://tanka.dev) import paths in `jsonnet-language-server`:

```json
{
  "lsp": {
    "jsonnet-language-server": {
      "settings": {
        "resolve_paths_with_tanka": true
      }
    }
  }
}
```

    # Julia

Julia language support in Zed is provided by the community-maintained [Julia extension](https://github.com/JuliaEditorSupport/zed-julia).
Report issues to: [https://github.com/JuliaEditorSupport/zed-julia/issues](https://github.com/JuliaEditorSupport/zed-julia/issues)

- Tree-sitter: [tree-sitter/tree-sitter-julia](https://github.com/tree-sitter/tree-sitter-julia)
- Language Server: [julia-vscode/LanguageServer.jl](https://github.com/julia-vscode/LanguageServer.jl)

<!--
TBD: Document Julia Installation
TBD: Julia REPL Setup instructions
-->

    # Kotlin

Kotlin language support in Zed is provided by the community-maintained [Kotlin extension](https://github.com/zed-extensions/kotlin).
Report issues to: [https://github.com/zed-extensions/kotlin/issues](https://github.com/zed-extensions/kotlin/issues)

- Tree-sitter: [fwcd/tree-sitter-kotlin](https://github.com/fwcd/tree-sitter-kotlin)
- Language Server: [fwcd/kotlin-language-server](https://github.com/fwcd/kotlin-language-server)

## Configuration

Workspace configuration options can be passed to the language server via lsp
settings in `settings.json`.

The full list of lsp `settings` can be found
[here](https://github.com/fwcd/kotlin-language-server/blob/main/server/src/main/kotlin/org/javacs/kt/Configuration.kt)
under `class Configuration` and initialization_options under `class InitializationOptions`.

### JVM Target

The following example changes the JVM target from `default` (which is 1.8) to
`17`:

```json
{
  "lsp": {
    "kotlin-language-server": {
      "settings": {
        "compiler": {
          "jvm": {
            "target": "17"
          }
        }
      }
    }
  }
}
```

### JAVA_HOME

To use a specific java installation, just specify the `JAVA_HOME` environment variable with:

```json
{
  "lsp": {
    "kotlin-language-server": {
      "binary": {
        "env": {
          "JAVA_HOME": "/Users/whatever/Applications/Work/Android Studio.app/Contents/jbr/Contents/Home"
        }
      }
    }
  }
}
```

    # Lua

Lua support is available through the [Lua extension](https://github.com/zed-extensions/lua).

- Tree-sitter: [tree-sitter-grammars/tree-sitter-lua](https://github.com/tree-sitter-grammars/tree-sitter-lua)
- Language server: [LuaLS/lua-language-server](https://github.com/LuaLS/lua-language-server)

## luarc.json

To configure LuaLS you can create a `.luarc.json` file in the root of your workspace.

```json
{
  "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
  "runtime.version": "Lua 5.4",
  "format.enable": true,
  "workspace.library": ["../somedir/library"]
}
```

See [LuaLS Settings Documentation](https://luals.github.io/wiki/settings/) for all available configuration options, or when editing this file in Zed available settings options will autocomplete, (e.g `runtime.version` will show `"Lua 5.1"`, `"Lua 5.2"`, `"Lua 5.3"`, `"Lua 5.4"` and `"LuaJIT"` as allowed values). Note when importing settings options from VS Code, remove the `Lua.` prefix. (e.g. `runtime.version` instead of `Lua.runtime.version`).

### LuaCATS Definitions

LuaLS can provide enhanced LSP autocompletion suggestions and type validation with the help of LuaCATS (Lua Comment and Type System) definitions. These definitions are available for many common Lua libraries, and local paths containing them can be specified via `workspace.library` in `luarc.json`. You can do this via relative paths if you checkout your definitions into the same partent directory of your project (`../playdate-luacats`, `../love2d`, etc). Alternatively you can create submodule(s) inside your project for each LuaCATS definition repo.

### LÖVE (Love2D) {#love2d}

To use [LÖVE (Love2D)](https://love2d.org/) in Zed, checkout [LuaCATS/love2d](https://github.com/LuaCATS/love2d) into a folder called `love2d-luacats` into the parent folder of your project:

```sh
cd .. && git clone https://github.com/LuaCATS/love2d love2d-luacats
```

Then in your `.luarc.json`:

```
{
  "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
  "runtime.version": "Lua 5.4",
  "workspace.library": ["../love2d-luacats"],
  "runtime.special": {
    "love.filesystem.load": "loadfile"
  }
}
```

### PlaydateSDK

To use [Playdate Lua SDK](https://play.date/dev/) in Zed, checkout [playdate-luacats](https://github.com/notpeter/playdate-luacats) into the parent folder of your project:

```sh
cd .. && git clone https://github.com/notpeter/playdate-luacats
```

Then in your `.luarc.json`:

```json
{
  "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
  "runtime.version": "Lua 5.4",
  "runtime.nonstandardSymbol": [
    "+=",
    "-=",
    "*=",
    "/=",
    "//=",
    "%=",
    "<<=",
    ">>=",
    "&=",
    "|=",
    "^="
  ],
  "diagnostics.severity": { "duplicate-set-field": "Hint" },
  "diagnostics.globals": ["import"],
  "workspace.library": ["../playdate-luacats"],
  "format.defaultConfig": {
    "indent_style": "space",
    "indent_size": "4"
  },
  "format.enable": true,
  "runtime.builtin": { "io": "disable", "os": "disable", "package": "disable" }
}
```

### Inlay Hints

To enable [Inlay Hints](../configuring-languages.md#inlay-hints) for LuaLS in Zed

1. Add the following to your Zed settings.json:

```json
  "languages": {
    "Lua": {
      "inlay_hints": {
        "enabled": true,
        "show_type_hints": true,
        "show_parameter_hints": true,
        "show_other_hints": true
      }
    }
  }
```

2. Add `"hint.enable": true` to your `.luarc.json`.

## Formatting

### LuaLS Formatting

To enable auto-formatting with your LuaLS (provided by [CppCXY/EmmyLuaCodeStyle](https://github.com/CppCXY/EmmyLuaCodeStyle)) make sure you have `"format.enable": true,` in your .luarc.json:

```json
{
  "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
  "format.enable": true
}
```

Then add the following to your Zed `settings.json`:

```json
{
  "languages": {
    "Lua": {
      "format_on_save": "on",
      "formatter": "language_server"
    }
  }
}
```

You can customize various EmmyLuaCodeStyle style options via `.editorconfig`, see [lua.template.editorconfig](https://github.com/CppCXY/EmmyLuaCodeStyle/blob/master/lua.template.editorconfig) for all available options.

### StyLua Formatting

Alternatively to use [StyLua](https://github.com/JohnnyMorganz/StyLua) for auto-formatting:

1. Install [StyLua](https://github.com/JohnnyMorganz/StyLua): `brew install stylua` or `cargo install stylua --features lua52,lua53,lua54,luau,luajit` (feel free to remove any Lua versions you don't need).
2. Add the following to your `settings.json`:

```json
{
  "languages": {
    "Lua": {
      "format_on_save": "on",
      "formatter": {
        "external": {
          "command": "stylua",
          "arguments": [
            "--syntax=Lua54",
            "--respect-ignores",
            "--stdin-filepath",
            "{buffer_path}",
            "-"
          ]
        }
      }
    }
  }
}
```

You can specify various options to StyLua either on the command line above (like `--syntax=Lua54`) or in a `stylua.toml` in your workspace:

```toml
syntax = "Lua54"
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
collapse_simple_statement = "All"

[sort_requires]
enabled = true
```

For a complete list of available options, see: [StyLua Options](https://github.com/JohnnyMorganz/StyLua?tab=readme-ov-file#options).

    # Luau

[Luau](https://luau.org/) is a fast, small, safe, gradually typed, embeddable scripting language derived from Lua. Luau was developed by Roblox and is available under the MIT license.

Luau language support in Zed is provided by the community-maintained [Luau extension](https://github.com/4teapo/zed-luau).
Report issues to: [https://github.com/4teapo/zed-luau/issues](https://github.com/4teapo/zed-luau/issues)

- Tree-sitter: [4teapo/tree-sitter-luau](https://github.com/4teapo/tree-sitter-luau)
- Language Server: [JohnnyMorganz/luau-lsp](https://github.com/JohnnyMorganz/luau-lsp)

## Configuration

Configuration instructions are available in the [Luau Zed Extension README](https://github.com/4teapo/zed-luau).

## Formatting

To support automatically formatting your code, you can use [JohnnyMorganz/StyLua](https://github.com/JohnnyMorganz/StyLua), a Lua code formatter.

Install with:

```sh
# macOS via Homebrew
brew install stylua
# Or via Cargo
cargo install stylua --features lua52,lua53,lua54,luau
```

Then add the following to your Zed `settings.json`:

```json
  "languages": {
    "Luau": {
      "formatter": {
        "external": {
          "command": "stylua",
          "arguments": ["-"]
        }
      }
    }
  }
```

    # Makefile

Makefile language support in Zed is provided by the community-maintained [Make extension](https://github.com/caius/zed-make).
Report issues to: [https://github.com/caius/zed-make/issues](https://github.com/caius/zed-make/issues).

- Tree-sitter: [caius/tree-sitter-make](https://github.com/caius/tree-sitter-make)

    # Markdown

Markdown support is available natively in Zed.

- Tree-sitter: [tree-sitter-markdown](https://github.com/tree-sitter-grammars/tree-sitter-markdown)
- Language Server: N/A

## Syntax Highlighting Code Blocks

Zed supports language-specific syntax highlighting of markdown code blocks by leveraging [tree-sitter language grammars](../extensions/languages.md#grammar). All [Zed supported languages](../languages.md), including those provided by official or community extensions, are available for use in markdown code blocks. All you need to do is provide a language name after the opening <kbd>```</kbd> code fence like so:

````python
```python
import functools as ft

@ft.lru_cache(maxsize=500)
def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)
```
````

## Configuration

### Format

Zed supports using Prettier to automatically re-format Markdown documents. You can trigger this manually via the {#action editor::Format} action or via the {#kb editor::Format} keyboard shortcut. Alternately, you can automatically format by enabling [`format_on_save`](../configuring-zed.md#format-on-save) in your settings.json:

```json
  "languages": {
    "Markdown": {
      "format_on_save": "on"
    }
  },
```

### Trailing Whitespace

By default Zed will remove trailing whitespace on save. If you rely on invisible trailing whitespace being converted to `<br />` in Markdown files you can disable this behavior with:

```json
  "languages": {
    "Markdown": {
      "remove_trailing_whitespace_on_save": false
    }
  },
```

    # Nim

Nim language support in Zed is provided by the community-maintained [Nim extension](https://github.com/foxoman/zed-nim).
Report issues to: [https://github.com/foxoman/zed-nim/issues](https://github.com/foxoman/zed-nim/issues)

- Tree-sitter: [alaviss/tree-sitter-nim](https://github.com/alaviss/tree-sitter-nim)
- Language Server: [nim-lang/langserver](https://github.com/nim-lang/langserver)

## Formatting

To use [arnetheduck/nph](https://github.com/arnetheduck/nph) as a formatter, follow the [nph installation instructions](https://github.com/arnetheduck/nph?tab=readme-ov-file#installation) and add this to your Zed `settings.json`:

```json
  "languages": {
    "Nim": {
      "formatter": {
        "external": {
          "command": "nph",
          "arguments": ["-"]
        }
      }
    }
  }
```

    # OCaml

OCaml support is available through the [OCaml extension](https://github.com/zed-extensions/ocaml).

- Tree-sitter: [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml)
- Language Server: [ocaml/ocaml-lsp](https://github.com/ocaml/ocaml-lsp)

## Setup Instructions

If you have the development environment already setup, you can skip to [Launching Zed](#launching-zed)

### Using Opam

Opam is the official package manager for OCaml and is highly recommended for getting started with OCaml. To get started using Opam, please follow the instructions provided [here](https://ocaml.org/install).

Once you install opam and setup a switch with your development environment as per the instructions, you can proceed.

### Launching Zed

By now you should have `ocamllsp` installed, you can verify so by running

```sh
ocamllsp --help
```

in your terminal. If you get a help message, you're good to go. If not, please revisit the installation instructions for `ocamllsp` and ensure it's properly installed.

With that aside, we can now launch Zed. Given how the OCaml package manager works, we require you to run Zed from the terminal, so please make sure you install the [Zed cli](https://zed.dev/features#cli) if you haven't already.

Once you have the cli, simply from a terminal, navigate to your project and run

```sh
zed .
```

Voila! You should have Zed running with OCaml support, no additional setup required.

    # PHP

PHP support is available through the [PHP extension](https://github.com/zed-extensions/php).

- Tree-sitter: https://github.com/tree-sitter/tree-sitter-php
- Language Servers:
  - [phpactor](https://github.com/phpactor/phpactor)
  - [intelephense](https://github.com/bmewburn/vscode-intelephense/)

## Choosing a language server

The PHP extension offers both `phpactor` and `intelephense` language server support.

`phpactor` is enabled by default.

## Phpactor

The Zed PHP Extension can install `phpactor` automatically but requires `php` to be installed and available in your path:

```sh
# brew install php            # macOS
# sudo apt-get install php    # Debian/Ubuntu
# yum install php             # CentOS/RHEL
# pacman -S php               # Arch Linux
which php
```

## Intelephense

[Intelephense](https://intelephense.com/) is a [proprietary](https://github.com/bmewburn/vscode-intelephense/blob/master/LICENSE.txt#L29) language server for PHP operating under a freemium model. Certain features require purchase of a [premium license](https://intelephense.com/).

To switch to `intelephense`, add the following to your `settings.json`:

```json
{
  "languages": {
    "PHP": {
      "language_servers": ["intelephense", "!phpactor", "..."]
    }
  }
}
```

To use the premium features, you can place your [licence.txt file](https://intelephense.com/faq.html) at `~/intelephense/licence.txt` inside your home directory. Alternatively, you can pass the licence key or a path to a file containing the licence key as an initialization option for the `intelephense` language server. To do this, add the following to your `settings.json`:

```json
{
  "lsp": {
    "intelephense": {
      "initialization_options": {
        "licenceKey": "/path/to/licence.txt"
      }
    }
  }
}
```

## PHPDoc

Zed supports syntax highlighting for PHPDoc comments.

- Tree-sitter: [claytonrcarter/tree-sitter-phpdoc](https://github.com/claytonrcarter/tree-sitter-phpdoc)

    # PowerShell

PowerShell language support in Zed is provided by the community-maintained [Zed PowerShell extension](https://github.com/wingyplus/zed-powershell). Please report issues to: [github.com/wingyplus/zed-powershell/issues](https://github.com/wingyplus/zed-powershell/issues)

- Tree-sitter: [airbus-cert/tree-sitter-powershell](https://github.com/airbus-cert/tree-sitter-powershell)
- Language Server: [PowerShell/PowerShellEditorServices](https://github.com/PowerShell/PowerShellEditorServices)

## Setup

### Install PowerShell 7+ {#powershell-install}

- macOS: `brew install powershell/tap/powershell`
- Alpine: [Installing PowerShell on Alpine Linux](https://learn.microsoft.com/en-us/powershell/scripting/install/install-alpine)
- Debian: [Install PowerShell on Debian Linux](https://learn.microsoft.com/en-us/powershell/scripting/install/install-debian)
- RedHat: [Install PowerShell on RHEL](https://learn.microsoft.com/en-us/powershell/scripting/install/install-rhel)
- Ubuntu: [Install PowerShell on RHEL](https://learn.microsoft.com/en-us/powershell/scripting/install/install-ubuntu)
- Windows: [Install PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows)

The Zed PowerShell extension will default to the `pwsh` executable found in your path.

### Install PowerShell Editor Services (Optional) {#powershell-editor-services}

The Zed PowerShell extensions will attempt to download [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) automatically.

If want to use a specific binary, you can specify in your that in your Zed settings.json:

```json
  "lsp": {
    "powershell-es": {
      "binary": {
        "path": "/path/to/PowerShellEditorServices"
      }
    }
  }
```

    # Prisma

Prisma support is available through the [Prisma extension](https://github.com/zed-extensions/prisma).

- Tree-sitter: [victorhqc/tree-sitter-prisma](https://github.com/victorhqc/tree-sitter-prisma)
- Language-Server: [prisma/language-tools](https://github.com/prisma/language-tools)

<!--
TBD: Prisma usage and configuration documentation
-->

    # Proto

Proto/proto3 (Protocol Buffers definition language) support is available through the [Proto extension](https://github.com/zed-industries/zed/tree/main/extensions/proto).

- Tree-sitter: [coder3101/tree-sitter-proto](https://github.com/coder3101/tree-sitter-proto)
- Language Servers: [protobuf-language-server](https://github.com/lasorda/protobuf-language-server)

<!--
TBD: Clarify which language server(s) to use / Feature support.

## Setup

### Install protobuf-language-server

Install protobuf-language-server and make sure it's in your PATH:

```
go install github.com/lasorda/protobuf-language-server@latest
which protobuf-language-server
```

### Install ProtoLS

Install protols and make sure it's in your PATH:

```
cargo install protols
which protols
```

## Configuration

```json
"lsp": {
  "protobuf-language-server": {
    "binary": {
      "path": "protols"
    }
  }
}
```

## Formatting

ProtoLS supports formatting if you have `clang-format` installed.

```sh
# MacOS:
brew install clang-format
# Ubuntu
sudo apt-get install clang-format
# Fedora
sudo dnf install clang-tools-extra
```

To customize your formatting preferences, create a `.clang-format` file, e.g.:

```clang-format
IndentWidth: 4
ColumnLimit: 120
```

Or you can have zed directly invoke `clang-format` by specifying it as a [formatter](https://zed.dev/docs/configuring-zed#formatter) in your settings:

```json
  "languages": {
    "Proto": {
      "format_on_save": "on",
      "tab_size": 4,
      "formatter": {
        "external": {
          "command": "clang-format",
          "arguments": ["-style={IndentWidth: 4, ColumnLimit: 0}"]
        }
      }
    },
  }
```
-->

    # PureScript

PureScript support is available through the [PureScript extension](https://github.com/zed-extensions/purescript).

- Tree-sitter: [postsolar/tree-sitter-purescript](https://github.com/postsolar/tree-sitter-purescript)
- Language-Server: [nwolverson/purescript-language-server](https://github.com/nwolverson/purescript-language-server)

    # How to Set Up Python in Zed

Python support is available natively in Zed.

- Tree-sitter: [tree-sitter-python](https://github.com/zed-industries/tree-sitter-python)
- Language Servers:
  - [DetachHead/basedpyright](https://github.com/DetachHead/basedpyright)
  - [astral-sh/ruff](https://github.com/astral-sh/ruff)
  - [astral-sh/ty](https://github.com/astral-sh/ty)
  - [microsoft/pyright](https://github.com/microsoft/pyright)
  - [python-lsp/python-lsp-server](https://github.com/python-lsp/python-lsp-server) (PyLSP)
- Debug Adapter: [debugpy](https://github.com/microsoft/debugpy)

## Install Python

You'll need both Zed and Python installed before you can begin.

### Step 1: Install Python

Zed does not bundle a Python runtime, so you’ll need to install one yourself.
Choose one of the following options:

- uv (recommended)

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

To learn more, visit [Astral’s installation guide](https://docs.astral.sh/uv/getting-started/installation/).

- Homebrew:

```bash
brew install python
```

- Python.org installer: Download the latest version from [python.org/downloads](https://python.org/downloads).

### Step 2: Verify Python Installation

Confirm Python is installed and available in your shell:

```bash
python3 --version
```

You should see an output like `Python 3.x.x`.

## Open Your First Python Project in Zed

Once Zed and Python are installed, open a folder containing Python code to start working.

### Step 1: Launch Zed with a Python Project

Open Zed.
From the menu bar, choose File > Open Folder, or launch from the terminal:

```bash
zed path/to/your/project
```

Zed will recognize `.py` files automatically using its native tree-sitter-python parser, with no plugins or manual setup required.

### Step 2: Use the Integrated Terminal (Optional)

Zed includes an integrated terminal, accessible from the bottom panel. If Zed detects that your project is using a [virtual environment](#virtual-environments), it will be activated automatically in newly-created terminals. You can configure this behavior with the [`detect_venv`](../configuring-zed.md#terminal-detect_venv) setting.

## Configure Python Language Servers in Zed

Zed provides several Python language servers out of the box. By default, [basedpyright](https://github.com/DetachHead/basedpyright) is the primary language server, and [Ruff](https://github.com/astral-sh/ruff) is used for formatting and linting.

Other built-in language servers are:

- [Ty](https://docs.astral.sh/ty/)&mdash;Up-and-coming language server from Astral, built for speed.
- [Pyright](https://github.com/microsoft/pyright)&mdash;The basis for basedpyright.
- [PyLSP](https://github.com/python-lsp/python-lsp-server)&mdash;A plugin-based language server that integrates with tools like `pycodestyle`, `autopep8`, and `yapf`.

These are disabled by default, but can be enabled in your settings. For example:

```json
{
  "languages": {
    "Python": {
      "language_servers": [
        // Disable basedpyright and enable Ty, and otherwise
        // use the default configuration.
        "ty",
        "!basedpyright",
        "..."
      ]
    }
  }
}
```

See: [Working with Language Servers](https://zed.dev/docs/configuring-languages#working-with-language-servers) for more information about how to enable and disable language servers.

### Basedpyright

[basedpyright](https://docs.basedpyright.com/latest/) is the primary Python language server in Zed beginning with Zed v0.204.0. It provides core language server functionality like navigation (go to definition/find all references) and type checking. Compared to Pyright, it adds support for additional language server features (like inlay hints) and checking rules.

Note that while basedpyright in isolation defaults to the `recommended` [type-checking mode](https://docs.basedpyright.com/latest/benefits-over-pyright/better-defaults/#typecheckingmode), Zed configures it to use the less-strict `standard` mode by default, which matches the behavior of Pyright. You can set the type-checking mode for your project using the `typeCheckingMode` setting in `pyrightconfig.json` or `pyproject.toml`, which will override Zed's default. Read on more for more details about how to configure basedpyright.

#### Basedpyright Configuration

basedpyright reads configuration options from two different kinds of sources:

- Language server settings ("workspace configuration"), which must be configured per-editor (using `settings.json` in Zed's case) but apply to all projects opened in that editor
- Configuration files (`pyrightconfig.json`, `pyproject.toml`), which are editor-independent but specific to the project where they are placed

As a rule of thumb, options that are only relevant when using basedpyright from an editor must be set in language server settings, and options that are relevant even if you're running it [as a command-line tool](https://docs.basedpyright.com/latest/configuration/command-line/) must be set in configuration files. Settings related to inlay hints are examples of the first category, and the [diagnostic category](https://docs.basedpyright.com/latest/configuration/config-files/#diagnostic-categories) settings are examples of the second category.

Examples of both kinds of configuration are provided below. Refer to the basedpyright documentation on [language server settings](https://docs.basedpyright.com/latest/configuration/language-server-settings/) and [configuration files](https://docs.basedpyright.com/latest/configuration/config-files/) for comprehensive lists of available options.

##### Language server settings

Language server settings for basedpyright in Zed can be set in the `lsp` section of your `settings.json`.

For example, in order to:

- diagnose all files in the workspace instead of the only open files default
- disable inlay hints on function arguments

You can use the following configuration:

```json
{
  "lsp": {
    "basedpyright": {
      "settings": {
        "basedpyright.analysis": {
          "diagnosticMode": "workspace",
          "inlayHints.callArgumentNames": false
        }
      }
    }
  }
}
```

##### Configuration files

basedpyright reads project-specific configuration from the `pyrightconfig.json` configuration file and from the `[tool.basedpyright]` and `[tool.pyright]` sections of `pyproject.toml` manifests. `pyrightconfig.json` overrides `pyproject.toml` if configuration is present in both places.

Here's an example `pyrightconfig.json` file that configures basedpyright to use the `strict` type-checking mode and not to issue diagnostics for any files in `__pycache__` directories:

```json
{
  "typeCheckingMode": "strict",
  "ignore": ["**/__pycache__"]
}
```

### PyLSP

[python-lsp-server](https://github.com/python-lsp/python-lsp-server/), more commonly known as PyLSP, by default integrates with a number of external tools (autopep8, mccabe, pycodestyle, yapf) while others are optional and must be explicitly enabled and configured (flake8, pylint).

See [Python Language Server Configuration](https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md) for more.

## Virtual Environments

[Virtual environments](https://docs.python.org/3/library/venv.html) are a useful tool for fixing a Python version and set of dependencies for a specific project, in a way that's isolated from other projects on the same machine. Zed has built-in support for discovering, configuring, and activating virtual environments, based on the language-agnostic concept of a [toolchain](../toolchains.md).

Note that if you have a global Python installation, it is also counted as a toolchain for Zed's purposes.

### Create a Virtual Environment

If your project doesn't have a virtual environment set up already, you can create one as follows:

```bash
python3 -m venv .venv
```

Alternatively, if you're using `uv`, running `uv sync` will create a virtual environment the first time you run it.

### How Zed Uses Python Toolchains

Zed uses the selected Python toolchain for your project in the following ways:

- Built-in language servers will be automatically configured with the path to the toolchain's Python interpreter and, if applicable, virtual environment. This is important so that they can resolve dependencies. (Note that language servers provided by extensions can't be automatically configured like this currently.)
- Python tasks (such as pytest tests) will be run using the toolchain's Python interpreter.
- If the toolchain is a virtual environment, the environment's activation script will be run automatically when you launch a new shell in Zed's integrated terminal, giving you convenient access to the selected Python interpreter and dependency set.
- If a built-in language server is installed in the active virtual environment, that binary will be used instead of Zed's private automatically-installed binary. This also applies to debugpy.

### Selecting a Toolchain

For most projects, Zed will automatically select the right Python toolchain. In complex projects with multiple virtual environments, it might be necessary to override this selection. You can use the [toolchain selector](../toolchains.md#selecting-toolchains) to pick a toolchain from the list discovered by Zed, or [specify the path to a toolchain manually](../toolchains.md#adding-toolchains-manually) if it's not on the list.

## Code Formatting & Linting

Zed provides the [Ruff](https://docs.astral.sh/ruff/) formatter and linter for Python code. (Specifically, Zed runs Ruff as an LSP server using the `ruff server` subcommand.) Both formatting and linting are enabled by default, including format-on-save.

### Configuring formatting

You can disable format-on-save for Python files in your `settings.json`:

```json
{
  "languages": {
    "Python": {
      "format_on_save": "off"
    }
  }
}
```

Alternatively, you can use the `black` command-line tool for Python formatting, while keeping Ruff enabled for linting:

```json
{
  "languages": {
    "Python": {
      "formatter": {
        "external": {
          "command": "black",
          "arguments": ["--stdin-filename", "{buffer_path}", "-"]
        }
      }
      // Or use `"formatter": null` to disable formatting entirely.
    }
  }
}
```

### Configuring Ruff

Like basedpyright, Ruff reads options from both Zed's language server settings and configuration files (`ruff.toml`) when used in Zed. Unlike basedpyright, _all_ options can be configured in either of these locations, so the choice of where to put your Ruff configuration comes down to whether you want it to be shared between projects but specific to Zed (in which case you should use language server settings), or specific to one project but common to all Ruff invocations (in which case you should use `ruff.toml`).

Here's an example of using language server settings in Zed's `settings.json` to disable all Ruff lints in Zed (while still using Ruff as a formatter):

```json
{
  "lsp": {
    "ruff": {
      "initialization_options": {
        "settings": {
          "exclude": ["*"]
        }
      }
    }
  }
}
```

And here's an example `ruff.toml` with linting and formatting options, adapted from the Ruff documentation:

```toml
[lint]
# Avoid enforcing line-length violations (`E501`)
ignore = ["E501"]

[format]
# Use single quotes when formatting.
quote-style = "single"
```

For more details, refer to the Ruff documentation about [configuration files](https://docs.astral.sh/ruff/configuration/) and [language server settings](https://docs.astral.sh/ruff/editors/settings/), and the [list of options](https://docs.astral.sh/ruff/settings/).

## Debugging

Zed supports Python debugging through the `debugpy` adapter. You can start with no configuration or define custom launch profiles in `.zed/debug.json`.

### Start Debugging with No Setup

Zed can automatically detect debuggable Python entry points. Press F4 (or run debugger: start from the Command Palette) to see available options for your current project.
This works for:

- Python scripts
- Modules
- pytest tests

Zed uses `debugpy` under the hood, but no manual adapter configuration is required.

### Define Custom Debug Configurations

For reusable setups, create a `.zed/debug.json` file in your project root. This gives you more control over how Zed runs and debugs your code.

#### Debug Active File

```json
[
  {
    "label": "Python Active File",
    "adapter": "Debugpy",
    "program": "$ZED_FILE",
    "request": "launch"
  }
]
```

This runs the file currently open in the editor.

#### Debug a Flask App

For projects using Flask, you can define a full launch configuration:

```
.venv/
app/
  init.py
  main.py
  routes.py
templates/
  index.html
static/
  style.css
requirements.txt
```

…the following configuration can be used:

```json
[
  {
    "label": "Python: Flask",
    "adapter": "Debugpy",
    "request": "launch",
    "module": "app",
    "cwd": "$ZED_WORKTREE_ROOT",
    "env": {
      "FLASK_APP": "app",
      "FLASK_DEBUG": "1"
    },
    "args": [
      "run",
      "--reload", // Enables Flask reloader that watches for file changes
      "--debugger" // Enables Flask debugger
    ],
    "autoReload": {
      "enable": true
    },
    "jinja": true,
    "justMyCode": true
  }
]
```

These can be combined to tailor the experience for web servers, test runners, or custom scripts.

## Troubleshoot and Maintain a Productive Python Setup

Zed is designed to minimize configuration overhead, but occasional issues can still arise—especially around environments, language servers, or tooling. Here's how to keep your Python setup working smoothly.

### Resolve Language Server Startup Issues

If a language server isn't responding or features like diagnostics or autocomplete aren't available:

- Check your Zed log (using the {#action zed::OpenLog} action) for errors related to the language server you're trying to use. This is where you're likely to find useful information if the language server failed to start up at all.
- Use the language server logs view to understand the lifecycle of the affected language server. You can access this view using the {#action dev::OpenLanguageServerLogs} action, or by clicking the lightning bolt icon in the status bar and selecting your language server. The most useful pieces of data in this view are:
  - "Server Logs", which shows any errors printed by the language server
  - "Server Info", which shows details about how the language server was started
- Verify your `settings.json` or `pyrightconfig.json` is syntactically correct.
- Restart Zed to reinitialize language server connections, or try restarting the language server using the {#action editor::RestartLanguageServer}

If the language server is failing to resolve imports, and you're using a virtual environment, make sure that the right environment is chosen in the selector. You can use "Server Info" view to confirm which virtual environment Zed is sending to the language server&mdash;look for the `* Configuration` section at the end.

    # R

R support is available via multiple R Zed extensions:

- [ocsmit/zed-r](https://github.com/ocsmit/zed-r)

  - Tree-sitter: [r-lib/tree-sitter-r](https://github.com/r-lib/tree-sitter-r)
  - Language-Server: [REditorSupport/languageserver](https://github.com/REditorSupport/languageserver)

- [posit-dev/air](https://github.com/posit-dev/air/tree/main/editors/zed)
  - Language-Server: [posit-dev/air](https://github.com/posit-dev/air)

## Installation

1. [Download and Install R](https://cloud.r-project.org/).
2. Install the R packages `languageserver` and `lintr`:

```R
install.packages("languageserver")
install.packages("lintr")
```

3. Install the [ocsmit/zed-r](https://github.com/ocsmit/zed-r) through Zed's extensions manager.

For example on macOS:

```sh
brew install --cask r
Rscript --version
Rscript -e 'options(repos = "https://cran.rstudio.com/"); install.packages("languageserver")'
Rscript -e 'options(repos = "https://cran.rstudio.com/"); install.packages("lintr")'
Rscript -e 'packageVersion("languageserver")'
Rscript -e 'packageVersion("lintr")'
```

## Configuration

### Linting

`REditorSupport/languageserver` bundles support for [r-lib/lintr](https://github.com/r-lib/lintr) as a linter. This can be configured via the use of a `.lintr` inside your project (or in your home directory for global defaults).

```r
linters: linters_with_defaults(
    line_length_linter(120),
    commented_code_linter = NULL
  )
exclusions: list(
    "inst/doc/creating_linters.R" = 1,
    "inst/example/bad.R",
    "tests/testthat/exclusions-test"
  )
```

Or exclude it from linting anything,

```r
exclusions: list(".")
```

See [Using lintr](https://lintr.r-lib.org/articles/lintr.html) for a complete list of options,

### Formatting

`REditorSupport/languageserver` bundles support for [r-lib/styler](https://github.com/r-lib/styler) as a formatter. See [Customizing Styler](https://cran.r-project.org/web/packages/styler/vignettes/customizing_styler.html) for more information on how to customize its behavior.

<!--
TBD: Get this working

### REditorSupport/languageserver Configuration

You can configure the [R languageserver settings](https://github.com/REditorSupport/languageserver#settings) via Zed Project Settings `.zed/settings.json` or Zed User Settings `~/.config/zed/settings.json`:

For example to disable Lintr linting and suppress code snippet suggestions (both enabled by default):

```json
{
  "lsp": {
    "r_language_server": {
      "settings": {
        "r": {
          "lsp": {
            "diagnostics": false,
            "snippet_support": false
          }
        }
      }
    }
  }
}
```

-->

<!--
TBD: R REPL Docs

## REPL

### Ark Installation

To use the Zed REPL with R you need to install [Ark](https://github.com/posit-dev/ark), an R Kernel for Jupyter applications.
You can down the latest version from the [Ark GitHub Releases](https://github.com/posit-dev/ark/releases) and then extract the `ark` binary to a directory in your `PATH`.

For example to install the latest non-debug build:

```sh
# macOS
cd /tmp
curl -L -o ark-latest-darwin.zip \
    $(curl -s "https://api.github.com/repos/posit-dev/ark/releases/latest" | \
    jq -r '.assets[] | select(.name | contains("darwin-universal") and (contains("debug") | not)) | .browser_download_url')
unzip ark-latest-darwin.zip ark
sudo mv /tmp/ark /usr/local/bin/
```

```sh
# Linux X86_64
cd /tmp
curl -L -o ark-latest-linux.zip \
    $(curl -s "https://api.github.com/repos/posit-dev/ark/releases/latest" \
        | jq -r '.assets[] | select(.name | contains("linux-x64") and (contains("debug") | not)) | .browser_download_url'
    )
unzip ark-latest-linux.zip ark
sudo mv /tmp/ark /usr/local/bin/
```

-->

    # Racket

Racket support is available through the [Racket extension](https://github.com/zed-extensions/racket).

- Tree-sitter: [zed-industries/tree-sitter-racket](https://github.com/zed-industries/tree-sitter-racket)

The [racket-language-server](https://docs.racket-lang.org/racket-language-server/index.html) is not yet supported in Zed, please see [Issue #15789](https://github.com/zed-industries/zed/issues/15789) for more information.

    # Rego

Rego language support in Zed is provided by the community-maintained [Rego extension](https://github.com/StyraInc/zed-rego).

- Tree-sitter: [FallenAngel97/tree-sitter-rego](https://github.com/FallenAngel97/tree-sitter-rego)
- Language Server: [StyraInc/regal](https://github.com/StyraInc/regal)

## Installation

The extensions is largely based on the [Regal](https://docs.styra.com/regal/language-server) language server which should be installed to make use of the extension. Read the [getting started](https://docs.styra.com/regal#getting-started) instructions for more information.

## Configuration

The extension's behavior is configured in the `.regal/config.yaml` file. The following is an example configuration which disables the `todo-comment` rule, customizes the `line-length` rule, and ignores test files for the `opa-fmt` rule:

```yaml
rules:
  style:
    todo-comment:
      # don't report on todo comments
      level: ignore
    line-length:
      # custom rule configuration
      max-line-length: 100
      # warn on too long lines, but don't fail
      level: warning
    opa-fmt:
      # not needed as error is the default, but
      # being explicit won't hurt
      level: error
      # files can be ignored for any individual rule
      # in this example, test files are ignored
      ignore:
        files:
          - "*_test.rego"
```

Read Regal's [configuration documentation](https://docs.styra.com/regal#configuration) for more information.

    # Roc

[Roc](https://www.roc-lang.org/) is a fast, friendly, functional language.

Roc language support in Zed is provided by the community-maintained [Roc extension](https://github.com/h2000/zed-roc).
Report issues to: [https://github.com/h2000/zed-roc/issues](https://github.com/h2000/zed-roc/issues)

- Tree-sitter: [faldor20/tree-sitter-roc](https://github.com/faldor20/tree-sitter-roc)
- Language Server: [roc-lang/roc/tree/main/crates/language_server](https://github.com/roc-lang/roc/tree/main/crates/language_server)

## Setup

1. Follow instructions to [Install Roc](https://www.roc-lang.org/install) from the Roc-Lang website.
2. Ensure `roc` and `roc_language_server` are in your PATH.

    # ReStructuredText (rst)

ReStructuredText language support in Zed is provided by the community-maintained [reST extension](https://github.com/elmarco/zed-rst).
Report issues to: [https://github.com/elmarco/zed-rst/issues](https://github.com/elmarco/zed-rst/issues)

- Tree-sitter: [stsewd/tree-sitter-rst.git](https://github.com/stsewd/tree-sitter-rst.git)
- Language Server: [swyddfa/esbonio](https://github.com/swyddfa/esbonio)

    # Ruby

Ruby support is available through the [Ruby extension](https://github.com/zed-extensions/ruby).

- Tree-sitters:
  - [tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby)
  - [tree-sitter-embedded-template](https://github.com/tree-sitter/tree-sitter-embedded-template)
- Language Servers:
  - [ruby-lsp](https://github.com/Shopify/ruby-lsp)
  - [solargraph](https://github.com/castwide/solargraph)
  - [rubocop](https://github.com/rubocop/rubocop)
  - [Herb](https://herb-tools.dev)
- Debug Adapter: [`rdbg`](https://github.com/ruby/debug)

The Ruby extension also provides support for ERB files.

## Language Servers

There are multiple language servers available for Ruby. Zed supports the two following:

- [solargraph](https://github.com/castwide/solargraph)
- [ruby-lsp](https://github.com/Shopify/ruby-lsp)

They both have an overlapping feature set of autocomplete, diagnostics, code actions, etc. and it's up to you to decide which one you want to use. Note that you can't use both at the same time.

In addition to these two language servers, Zed also supports:

- [rubocop](https://github.com/rubocop/rubocop) which is a static code analyzer and linter for Ruby. Under the hood, it's also used by Zed as a language server, but its functionality is complimentary to that of solargraph and ruby-lsp.
- [sorbet](https://sorbet.org/) which is a static type checker for Ruby with a custom gradual type system.
- [steep](https://github.com/soutaro/steep) which is a static type checker for Ruby that leverages Ruby Signature (RBS).
- [Herb](https://herb-tools.dev) which is a language server for ERB files.

When configuring a language server, it helps to open the LSP Logs window using the 'dev: Open Language Server Logs' command. You can then choose the corresponding language instance to see any logged information.

## Configuring a language server

The [Ruby extension](https://github.com/zed-extensions/ruby) offers both `solargraph` and `ruby-lsp` language server support.

### Language Server Activation

For all supported Ruby language servers (`solargraph`, `ruby-lsp`, `rubocop`, `sorbet`, and `steep`), the Ruby extension follows this activation sequence:

1. If the language server is found in your project's `Gemfile`, it will be used through `bundle exec`.
2. If not found in the `Gemfile`, the Ruby extension will look for the executable in your system `PATH`.
3. If the language server is not found in either location, the Ruby extension will automatically install it as a global gem (note: this will not install to your current Ruby gemset).

You can skip step 1 and force using the system executable by setting `use_bundler` to `false` in your settings:

```json
{
  "lsp": {
    "<SERVER_NAME>": {
      "settings": {
        "use_bundler": false
      }
    }
  }
}
```

### Using `solargraph`

`solargraph` is enabled by default in the Ruby extension.

### Using `ruby-lsp`

To switch to `ruby-lsp`, add the following to your `settings.json`:

```json
{
  "languages": {
    "Ruby": {
      "language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."]
    }
  }
}
```

That disables `solargraph` and `rubocop` and enables `ruby-lsp`.

### Using `rubocop`

The Ruby extension also provides support for `rubocop` language server for offense detection and autocorrection.

To enable it, add the following to your `settings.json`:

```json
{
  "languages": {
    "Ruby": {
      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
    }
  }
}
```

Or, conversely, you can disable `ruby-lsp` and enable `solargraph` and `rubocop` by adding the following to your `settings.json`:

```json
{
  "languages": {
    "Ruby": {
      "language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
    }
  }
}
```

## Setting up `solargraph`

Solargraph has formatting and diagnostics disabled by default. We can tell Zed to enable them by adding the following to your `settings.json`:

```json
{
  "lsp": {
    "solargraph": {
      "initialization_options": {
        "diagnostics": true,
        "formatting": true
      }
    }
  }
}
```

### Configuration

Solargraph reads its configuration from a file called `.solargraph.yml` in the root of your project. For more information about this file, see the [Solargraph configuration documentation](https://solargraph.org/guides/configuration).

## Setting up `ruby-lsp`

You can pass Ruby LSP configuration to `initialization_options`, e.g.

```json
{
  "languages": {
    "Ruby": {
      "language_servers": ["ruby-lsp", "!solargraph", "..."]
    }
  },
  "lsp": {
    "ruby-lsp": {
      "initialization_options": {
        "enabledFeatures": {
          // "someFeature": false
        }
      }
    }
  }
}
```

LSP `settings` and `initialization_options` can also be project-specific. For example to use [standardrb/standard](https://github.com/standardrb/standard) as a formatter and linter for a particular project, add this to a `.zed/settings.json` inside your project repo:

```json
{
  "lsp": {
    "ruby-lsp": {
      "initialization_options": {
        "formatter": "standard",
        "linters": ["standard"]
      }
    }
  }
}
```

## Setting up `rubocop` LSP

Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your `settings.json`:

```json
{
  "languages": {
    "Ruby": {
      // Use ruby-lsp as the primary language server and rubocop as the secondary.
      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
    }
  },
  "lsp": {
    "rubocop": {
      "initialization_options": {
        "safeAutocorrect": false
      }
    },
    "ruby-lsp": {
      "initialization_options": {
        "enabledFeatures": {
          "diagnostics": false
        }
      }
    }
  }
}
```

## Setting up Sorbet

[Sorbet](https://sorbet.org/) is a popular static type checker for Ruby that includes a language server.

To enable Sorbet, add `\"sorbet\"` to the `language_servers` list for Ruby in your `settings.json`. You may want to disable other language servers if Sorbet is intended to be your primary LSP, or if you plan to use it alongside another LSP for specific features like type checking.

```json
{
  "languages": {
    "Ruby": {
      "language_servers": [
        "ruby-lsp",
        "sorbet",
        "!rubocop",
        "!solargraph",
        "..."
      ]
    }
  }
}
```

For all aspects of installing Sorbet, setting it up in your project, and configuring its behavior, please refer to the [official Sorbet documentation](https://sorbet.org/docs/overview).

## Setting up Steep

[Steep](https://github.com/soutaro/steep) is a static type checker for Ruby that uses RBS files to define types.

To enable Steep, add `\"steep\"` to the `language_servers` list for Ruby in your `settings.json`. You may need to adjust the order or disable other LSPs depending on your desired setup.

```json
{
  "languages": {
    "Ruby": {
      "language_servers": [
        "ruby-lsp",
        "steep",
        "!solargraph",
        "!rubocop",
        "..."
      ]
    }
  }
}
```

## Setting up Herb

`Herb` is enabled by default for the `HTML/ERB` language.

## Using the Tailwind CSS Language Server with Ruby

It's possible to use the [Tailwind CSS Language Server](https://github.com/tailwindlabs/tailwindcss-intellisense/tree/HEAD/packages/tailwindcss-language-server#readme) in Ruby and ERB files.

In order to do that, you need to configure the language server so that it knows about where to look for CSS classes in Ruby/ERB files by adding the following to your `settings.json`:

```json
{
  "languages": {
    "Ruby": {
      "language_servers": ["tailwindcss-language-server", "..."]
    }
  },
  "lsp": {
    "tailwindcss-language-server": {
      "settings": {
        "includeLanguages": {
          "html/erb": "html",
          "ruby": "html"
        },
        "experimental": {
          "classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
        }
      }
    }
  }
}
```

With these settings you will get completions for Tailwind CSS classes in HTML attributes inside ERB files and inside Ruby/ERB strings that are coming after a `class:` key. Examples:

```rb
# Ruby file:
def method
  div(class: "pl-2 <completion here>") do
    p(class: "mt-2 <completion here>") { "Hello World" }
  end
end

# ERB file:
<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
<a href="/hello" class="pl-2 <completion here>">Hello</a>
```

## Running tests

To run tests in your Ruby project, you can set up custom tasks in your local `.zed/tasks.json` configuration file. These tasks can be defined to work with different test frameworks like Minitest, RSpec, quickdraw, and tldr. Below are some examples of how to set up these tasks to run your tests from within your editor.

### Minitest with Rails

```json
[
  {
    "label": "test $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
    "command": "bin/rails",
    "args": [
      "test",
      "$ZED_RELATIVE_FILE",
      "-n",
      "\"$ZED_CUSTOM_RUBY_TEST_NAME\""
    ],
    "cwd": "$ZED_WORKTREE_ROOT",
    "tags": ["ruby-test"]
  }
]
```

### Minitest

Plain minitest does not support running tests by line number, only by name, so we need to use `$ZED_CUSTOM_RUBY_TEST_NAME` instead:

```json
[
  {
    "label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
    "command": "bundle",
    "args": [
      "exec",
      "ruby",
      "-Itest",
      "$ZED_RELATIVE_FILE",
      "-n",
      "\"$ZED_CUSTOM_RUBY_TEST_NAME\""
    ],
    "cwd": "$ZED_WORKTREE_ROOT",
    "tags": ["ruby-test"]
  }
]
```

### RSpec

```json
[
  {
    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
    "command": "bundle",
    "args": ["exec", "rspec", "\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
    "cwd": "$ZED_WORKTREE_ROOT",
    "tags": ["ruby-test"]
  }
]
```

Similar task syntax can be used for other test frameworks such as `quickdraw` or `tldr`.

## Debugging

The Ruby extension provides a debug adapter for debugging Ruby code. Zed's name for the adapter (in the UI and `debug.json`) is `rdbg`, and under the hood, it uses the [`debug`](https://github.com/ruby/debug) gem. The extension uses the [same activation logic](#language-server-activation) as the language servers.

### Examples

#### Debug a Ruby script

```json
[
  {
    "label": "Debug current file",
    "adapter": "rdbg",
    "request": "launch",
    "script": "$ZED_FILE",
    "cwd": "$ZED_WORKTREE_ROOT"
  }
]
```

#### Debug Rails server

```json
[
  {
    "label": "Debug Rails server",
    "adapter": "rdbg",
    "request": "launch",
    "command": "./bin/rails",
    "args": ["server"],
    "cwd": "$ZED_WORKTREE_ROOT",
    "env": {
      "RUBY_DEBUG_OPEN": "true"
    }
  }
]
```

## Formatters

### `erb-formatter`

To format ERB templates, you can use the `erb-formatter` formatter. This formatter uses the [`erb-formatter`](https://rubygems.org/gems/erb-formatter) gem to format ERB templates.

```jsonc
{
  "HTML/ERB": {
    "formatter": {
      "external": {
        "command": "erb-formatter",
        "arguments": ["--stdin-filename", "{buffer_path}"],
      },
    },
  },
}
```

    # Rust

Rust support is available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-rust](https://github.com/tree-sitter/tree-sitter-rust)
- Language Server: [rust-lang/rust-analyzer](https://github.com/rust-lang/rust-analyzer)
- Debug Adapter: [CodeLLDB](https://github.com/vadimcn/codelldb) (primary), [GDB](https://sourceware.org/gdb/) (secondary, not available on Apple silicon)

<!--
TBD: Polish Rust Docs. Zed is a good rust editor, good Rust docs make it look like we care about Rust (we do!)
TBD: Users may not know what inlayHints, don't start there.
TBD: Provide explicit examples not just `....`
-->

## Inlay Hints

The following configuration can be used to change the inlay hint settings for `rust-analyzer` in Rust:

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "inlayHints": {
          "maxLength": null,
          "lifetimeElisionHints": {
            "enable": "skip_trivial",
            "useParameterNames": true
          },
          "closureReturnTypeHints": {
            "enable": "always"
          }
        }
      }
    }
  }
}
```

See [Inlay Hints](https://rust-analyzer.github.io/book/features.html#inlay-hints) in the Rust Analyzer Manual for more information.

## Target directory

The `rust-analyzer` target directory can be set in `initialization_options`:

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "rust": {
          "analyzerTargetDir": true
        }
      }
    }
  }
}
```

A `true` setting will set the target directory to `target/rust-analyzer`. You can set a custom directory with a string like `"target/analyzer"` instead of `true`.

## Binary

You can configure which `rust-analyzer` binary Zed should use.

By default, Zed will try to find a `rust-analyzer` in your `$PATH` and try to use that. If that binary successfully executes `rust-analyzer --help`, it's used. Otherwise, Zed will fall back to installing its own stable `rust-analyzer` version and use that.

If you want to install pre-release `rust-analyzer` version instead you can instruct Zed to do so by setting `pre_release` to `true` in your `settings.json`:

```json
{
  "lsp": {
    "rust-analyzer": {
      "fetch": {
        "pre_release": true
      }
    }
  }
}
```

If you want to disable Zed looking for a `rust-analyzer` binary, you can set `ignore_system_version` to `true` in your `settings.json`:

```json
{
  "lsp": {
    "rust-analyzer": {
      "binary": {
        "ignore_system_version": true
      }
    }
  }
}
```

If you want to use a binary in a custom location, you can specify a `path` and optional `arguments`:

```json
{
  "lsp": {
    "rust-analyzer": {
      "binary": {
        "path": "/Users/example/bin/rust-analyzer",
        "arguments": []
      }
    }
  }
}
```

This `"path"` has to be an absolute path.

## Alternate Targets

If you want rust-analyzer to provide diagnostics for a target other than your current platform (e.g. for windows when running on macOS) you can use the following Zed lsp settings:

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "cargo": {
          "target": "x86_64-pc-windows-msvc"
        }
      }
    }
  }
}
```

If you are using `rustup`, you can find a list of available target triples (`aarch64-apple-darwin`, `x86_64-unknown-linux-gnu`, etc) by running:

```sh
rustup target list --installed
```

## LSP tasks

Zed provides tasks using tree-sitter, but rust-analyzer has an LSP extension method for querying file-related tasks via LSP.
This is enabled by default and can be configured as

```json
"lsp": {
  "rust-analyzer": {
    "enable_lsp_tasks": true,
  }
}
```

## Manual Cargo Diagnostics fetch

By default, rust-analyzer has `checkOnSave: true` enabled, which causes every buffer save to trigger a `cargo check --workspace --all-targets` command.
If disabled with `checkOnSave: false` (see the example of the server configuration json above), it's still possible to fetch the diagnostics manually, with the `editor: run/clear/cancel flycheck` commands in Rust files to refresh cargo diagnostics; the project diagnostics editor will also refresh cargo diagnostics with `editor: run flycheck` command when the setting is enabled.

## More server configuration

<!--
TBD: Is it possible to specify RUSTFLAGS? https://github.com/zed-industries/zed/issues/14334
-->

Rust-analyzer [manual](https://rust-analyzer.github.io/book/) describes various features and configuration options for rust-analyzer language server.
Rust-analyzer in Zed runs with the default parameters.

### Large projects and performance

One of the main caveats that might cause extensive resource usage on large projects, is the combination of the following features:

```
rust-analyzer.checkOnSave (default: true)
    Run the check command for diagnostics on save.
```

```
rust-analyzer.check.workspace (default: true)
    Whether --workspace should be passed to cargo check. If false, -p <package> will be passed instead.
```

```
rust-analyzer.cargo.allTargets (default: true)
    Pass --all-targets to cargo invocation
```

Which would mean that every time Zed saves, a `cargo check --workspace --all-targets` command is run, checking the entire project (workspace), lib, doc, test, bin, bench and [other targets](https://doc.rust-lang.org/cargo/reference/cargo-targets.html).

While that works fine on small projects, it does not scale well.

The alternatives would be to use [tasks](../tasks.md), as Zed already provides a `cargo check --workspace --all-targets` task and the ability to cmd/ctrl-click on the terminal output to navigate to the error, and limit or turn off the check on save feature entirely.

Check on save feature is responsible for returning part of the diagnostics based on cargo check output, so turning it off will limit rust-analyzer with its own [diagnostics](https://rust-analyzer.github.io/book/diagnostics.html).

Consider more `rust-analyzer.cargo.` and `rust-analyzer.check.` and `rust-analyzer.diagnostics.` settings from the manual for more fine-grained configuration.
Here's a snippet for Zed settings.json (the language server will restart automatically after the `lsp.rust-analyzer` section is edited and saved):

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        // get more cargo-less diagnostics from rust-analyzer,
        // which might include false-positives (those can be turned off by their names)
        "diagnostics": {
          "experimental": {
            "enable": true
          }
        },
        // To disable the checking entirely
        // (ignores all cargo and check settings below)
        "checkOnSave": false,
        // To check the `lib` target only.
        "cargo": {
          "allTargets": false
        },
        // Use `-p` instead of `--workspace` for cargo check
        "check": {
          "workspace": false
        }
      }
    }
  }
}
```

### Multi-project workspaces

If you want rust-analyzer to analyze multiple Rust projects in the same folder that are not listed in `[members]` in the Cargo workspace,
you can list them in `linkedProjects` in the local project settings:

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "linkedProjects": ["./path/to/a/Cargo.toml", "./path/to/b/Cargo.toml"]
      }
    }
  }
}
```

### Snippets

There's a way to get custom completion items from rust-analyzer, that will transform the code according to the snippet body:

```json
{
  "lsp": {
    "rust-analyzer": {
      "initialization_options": {
        "completion": {
          "snippets": {
            "custom": {
              "Arc::new": {
                "postfix": "arc",
                "body": ["Arc::new(${receiver})"],
                "requires": "std::sync::Arc",
                "scope": "expr"
              },
              "Some": {
                "postfix": "some",
                "body": ["Some(${receiver})"],
                "scope": "expr"
              },
              "Ok": {
                "postfix": "ok",
                "body": ["Ok(${receiver})"],
                "scope": "expr"
              },
              "Rc::new": {
                "postfix": "rc",
                "body": ["Rc::new(${receiver})"],
                "requires": "std::rc::Rc",
                "scope": "expr"
              },
              "Box::pin": {
                "postfix": "boxpin",
                "body": ["Box::pin(${receiver})"],
                "requires": "std::boxed::Box",
                "scope": "expr"
              },
              "vec!": {
                "postfix": "vec",
                "body": ["vec![${receiver}]"],
                "description": "vec![]",
                "scope": "expr"
              }
            }
          }
        }
      }
    }
  }
}
```

## Debugging

Zed supports debugging Rust binaries and tests out of the box. Run {#action debugger::Start} ({#kb debugger::Start}) to launch one of these preconfigured debug tasks.

For more control, you can add debug configurations to `.zed/debug.json`. See the examples below.

### Build binary then debug

```json
[
  {
    "label": "Build & Debug native binary",
    "build": {
      "command": "cargo",
      "args": ["build"]
    },
    "program": "$ZED_WORKTREE_ROOT/target/debug/binary",
    // sourceLanguages is required for CodeLLDB (not GDB) when using Rust
    "sourceLanguages": ["rust"],
    "request": "launch",
    "adapter": "CodeLLDB"
  }
]
```

### Automatically locate a debug target based on build command

When you use `cargo build` or `cargo test` as the build command, Zed can infer the path to the output binary.

```json
[
  {
    "label": "Build & Debug native binary",
    "adapter": "CodeLLDB",
    "build": {
      "command": "cargo",
      "args": ["build"]
    },
    // sourceLanguages is required for CodeLLDB (not GDB) when using Rust
    "sourceLanguages": ["rust"]
  }
]
```

    # Scala

Scala language support in Zed is provided by the community-maintained [Scala extension](https://github.com/scalameta/metals-zed).
Report issues to: [https://github.com/scalameta/metals-zed/issues](https://github.com/scalameta/metals-zed/issues)

- Tree-sitter: [tree-sitter/tree-sitter-scala](https://github.com/tree-sitter/tree-sitter-scala)
- Language Server: [scalameta/metals](https://github.com/scalameta/metals)

## Setup

- Install Scala with `cs setup` (Coursier): https://www.scala-lang.org/download/
  - `brew install coursier/formulas/coursier && cs setup`
- REPL (Almond) Setup Instructions https://almond.sh/docs/quick-start-install
  - `brew install --cask temurin` (Eclipse foundation official OpenJDK binaries)
  - `brew install coursier/formulas/coursier && cs setup`
  - `coursier launch --use-bootstrap almond -- --install`

## Configuration

Behavior of the Metals language server can be controlled with:

- `.scalafix.conf` file - See [Scalafix Configuration](https://scalacenter.github.io/scalafix/docs/users/configuration.html)
- `.scalafmt.conf` file - See [Scalafmt Configuration](https://scalameta.org/scalafmt/docs/configuration.html)

You can place these files in the root of your project or specifying their location in the Metals configuration. See [Metals User Configuration](https://scalameta.org/metals/docs/editors/user-configuration) for more.

<!--
TBD: Provide LSP configuration example for metals in Zed settings.json. metals.{javaHome,excludedPackages,customProjectRoot} etc.
-->

    # Scheme

Scheme support is available through the [Scheme extension](https://github.com/zed-extensions/scheme).

- Tree-sitter: [6cdh/tree-sitter-scheme](https://github.com/6cdh/tree-sitter-scheme)

    # Shell Scripts

Shell Scripts (bash, zsh, dash, sh) are supported natively by Zed.

- Tree-sitter: [tree-sitter/tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash)

## Settings

You can configure various settings for Shell Scripts in your Zed User Settings (`~/.config/zed/settings.json`) or Zed Project Settings (`.zed/settings.json`):

```json
  "languages": {
    "Shell Script": {
      "tab_size": 2,
      "hard_tabs": false
    }
  }
```

### Formatting

Zed supports auto-formatting Shell Scripts using external tools like [`shfmt`](https://github.com/mvdan/sh).

1. Install `shfmt`:

```sh
brew install shfmt            # macos (homebrew)
sudo apt-get install shfmt    # debian/ubuntu
dnf install shfmt             # fedora
yum install shfmt             # redhat
pacman -Sy shfmt              # archlinux
choco install shfmt           # windows (chocolatey)
```

2. Ensure `shfmt` is available in your path and check the version:

```sh
which shfmt
shfmt --version
```

3. Configure Zed to automatically format Shell Scripts with `shfmt` on save:

```json
  "languages": {
    "Shell Script": {
      "format_on_save": "on",
      "formatter": {
        "external": {
          "command": "shfmt",
          // Change `--indent 2` to match your preferred tab_size
          "arguments": ["--filename", "{buffer_path}", "--indent", "2"]
        }
      }
    }
  }
```

## See also:

- [Zed Docs: Language Support: Bash](./bash.md)
- [Zed Docs: Language Support: Fish](./fish.md)

    # SQL

SQL files are handled by the [SQL Extension](https://github.com/zed-extensions/sql).

- Tree-sitter: [nervenes/tree-sitter-sql](https://github.com/nervenes/tree-sitter-sql)

### Formatting

Zed supports auto-formatting SQL using external tools like [`sql-formatter`](https://github.com/sql-formatter-org/sql-formatter).

1. Install `sql-formatter`:

```sh
npm install -g sql-formatter
```

2. Ensure `sql-formatter` is available in your path and check the version:

```sh
which sql-formatter
sql-formatter --version
```

3. Configure Zed to automatically format SQL with `sql-formatter`:

```json
  "languages": {
    "SQL": {
      "formatter": {
        "external": {
          "command": "sql-formatter",
          "arguments": ["--language", "mysql"]
        }
      }
    }
  },
```

Substitute your preferred [SQL Dialect] for `mysql` above (`duckdb`, `hive`, `mariadb`, `postgresql`, `redshift`, `snowflake`, `sqlite`, `spark`, etc).

You can add this to Zed project settings (`.zed/settings.json`) or via your Zed user settings (`~/.config/zed/settings.json`).

### Advanced Formatting

Sql-formatter also allows more precise control by providing [sql-formatter configuration options](https://github.com/sql-formatter-org/sql-formatter#configuration-options). To provide these, create a `.sql-formatter.json` file in your project:

```json
{
  "language": "postgresql",
  "tabWidth": 2,
  "keywordCase": "upper",
  "linesBetweenQueries": 2
}
```

When using a `.sql-formatter.json` file you can use a more simplified set of Zed settings since the language need not be specified inline:

```json
  "languages": {
    "SQL": {
      "formatter": {
        "external": {
          "command": "sql-formatter"
        }
      }
    }
  },
```

    # Svelte

Svelte support is available through the [Svelte extension](https://github.com/zed-extensions/svelte).

- Tree-sitter: [tree-sitter-grammars/tree-sitter-svelte](https://github.com/tree-sitter-grammars/tree-sitter-svelte)
- Language Server: [sveltejs/language-tools](https://github.com/sveltejs/language-tools)

## Extra theme styling configuration

You can modify how certain styles, such as directives and modifiers, appear in attributes:

```json
"syntax": {
  // Styling for directives (e.g., `class:foo` or `on:click`) (the `on` or `class` part of the attribute).
  "attribute.function": {
    "color": "#ff0000"
  },
  // Styling for modifiers at the end of attributes, e.g. `on:<click|preventDefault|stopPropagation>`
  "attribute.special": {
    "color": "#00ff00"
  }
}
```

## Inlay Hints

When inlay hints is enabled in Zed, to make the language server send them back, Zed sets the following initialization options:

```json
"inlayHints": {
  "parameterNames": {
    "enabled": "all",
    "suppressWhenArgumentMatchesName": false
  },
  "parameterTypes": {
    "enabled": true
  },
  "variableTypes": {
    "enabled": true,
    "suppressWhenTypeMatchesName": false
  },
  "propertyDeclarationTypes": {
    "enabled": true
  },
  "functionLikeReturnTypes": {
    "enabled": true
  },
  "enumMemberValues": {
    "enabled": true
  }
}
```

To override these settings, use the following:

```json
"lsp": {
  "svelte-language-server": {
    "initialization_options": {
      "configuration": {
        "typescript": {
          ......
        },
        "javascript": {
          ......
        }
      }
    }
  }
}
```

See [the TypeScript language server `package.json`](https://github.com/microsoft/vscode/blob/main/extensions/typescript-language-features/package.json) for more information.

    # Swift

Swift language support in Zed is provided by the community-maintained [Swift extension](https://github.com/zed-extensions/swift).
Report issues to: [https://github.com/zed-extensions/swift/issues](https://github.com/zed-extensions/swift/issues)

- Tree-sitter: [alex-pinkus/tree-sitter-swift](https://github.com/alex-pinkus/tree-sitter-swift)
- Language Server: [swiftlang/sourcekit-lsp](https://github.com/swiftlang/sourcekit-lsp)
- Debug Adapter: [`lldb-dap`](https://github.com/swiftlang/llvm-project/blob/next/lldb/tools/lldb-dap/README.md)

## Language Server Configuration

You can modify the behavior of SourceKit LSP by creating a `.sourcekit-lsp/config.json` under your home directory or in your project root. See [SourceKit-LSP configuration file](https://github.com/swiftlang/sourcekit-lsp/blob/main/Documentation/Configuration%20File.md) for complete documentation.

## Debugging

The Swift extension provides a debug adapter for debugging Swift code.
Zed's name for the adapter (in the UI and `debug.json`) is `Swift`, and under the hood it uses [`lldb-dap`](https://github.com/swiftlang/llvm-project/blob/next/lldb/tools/lldb-dap/README.md), as provided by the Swift toolchain.
The extension tries to find an `lldb-dap` binary using `swiftly`, using `xcrun`, and by searching `$PATH`, in that order of preference.
The extension doesn't attempt to download `lldb-dap` if it's not found.

### Examples

#### Build and debug a Swift binary

```json
[
  {
    "label": "Debug Swift",
    "build": {
      "command": "swift",
      "args": ["build"]
    },
    "program": "$ZED_WORKTREE_ROOT/swift-app/.build/arm64-apple-macosx/debug/swift-app",
    "request": "launch",
    "adapter": "Swift"
  }
]
```

    # Tailwind CSS

Zed has built-in support for Tailwind CSS autocomplete, linting, and hover previews.

- Language Server: [tailwindlabs/tailwindcss-intellisense](https://github.com/tailwindlabs/tailwindcss-intellisense)

## Configuration

To configure the Tailwind CSS language server, refer [to the extension settings](https://github.com/tailwindlabs/tailwindcss-intellisense?tab=readme-ov-file#extension-settings) and add them to the `lsp` section of your `settings.json`:

```jsonc
{
  "lsp": {
    "tailwindcss-language-server": {
      "settings": {
        "classFunctions": ["cva", "cx"],
        "experimental": {
          "classRegex": ["[cls|className]\\s\\:\\=\\s\"([^\"]*)"],
        },
      },
    },
  },
}
```

Languages which can be used with Tailwind CSS in Zed:

- [Astro](./astro.md)
- [CSS](./css.md)
- [ERB](./ruby.md)
- [HEEx](./elixir.md#heex)
- [HTML](./html.md)
- [TypeScript](./typescript.md)
- [JavaScript](./javascript.md)
- [PHP](./php.md)
- [Svelte](./svelte.md)
- [Vue](./vue.md)

### Prettier Plugin

Zed supports Prettier out of the box, which means that if you have the [Tailwind CSS Prettier plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) installed, adding it to your Prettier configuration will make it work automatically:

```json
// .prettierrc
{
  "plugins": ["prettier-plugin-tailwindcss"]
}
```

    # Terraform

Terraform support is available through the [Terraform extension](https://github.com/zed-extensions/terraform).

- Tree-sitter: [MichaHoffmann/tree-sitter-hcl](https://github.com/MichaHoffmann/tree-sitter-hcl)
- Language Server: [hashicorp/terraform-ls](https://github.com/hashicorp/terraform-ls)

## Configuration

<!--
TBD: Add example using `rootModulePaths` to match upstream example https://github.com/hashicorp/terraform-ls/blob/main/docs/SETTINGS.md#vs-code
-->

The Terraform language server can be configured in your `settings.json`, e.g.:

```json
{
  "lsp": {
    "terraform-ls": {
      "initialization_options": {
        "experimentalFeatures": {
          "prefillRequiredFields": true
        }
      }
    }
  }
}
```

See the [full list of server settings here](https://github.com/hashicorp/terraform-ls/blob/main/docs/SETTINGS.md).

    # TOML

TOML support is available through the [TOML extension](https://zed.dev/extensions/toml).

- Tree-sitter: [tree-sitter/tree-sitter-toml](https://github.com/tree-sitter/tree-sitter-toml)

A TOML language server is available in the [Tombi extension](https://zed.dev/extensions/tombi).

    # TypeScript

TypeScript and TSX support are available natively in Zed.

- Tree-sitter: [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript)
- Language Server: [yioneko/vtsls](https://github.com/yioneko/vtsls)
- Alternate Language Server: [typescript-language-server/typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
- Debug Adapter: [vscode-js-debug](https://github.com/microsoft/vscode-js-debug)

<!--
TBD: Document the difference between Language servers
-->

## Language servers

By default Zed uses [vtsls](https://github.com/yioneko/vtsls) for TypeScript, TSX, and JavaScript files.
You can configure the use of [typescript-language-server](https://github.com/typescript-language-server/typescript-language-server) per language in your settings file:

```json
{
  "languages": {
    "TypeScript": {
      "language_servers": ["typescript-language-server", "!vtsls", "..."]
    },
    "TSX": {
      "language_servers": ["typescript-language-server", "!vtsls", "..."]
    },
    "JavaScript": {
      "language_servers": ["typescript-language-server", "!vtsls", "..."]
    }
  }
}
```

Prettier will also be used for TypeScript files by default. To disable this:

```json
{
  "languages": {
    "TypeScript": {
      "prettier": { "allowed": false }
    }
    //...
  }
}
```

## Large projects

`vtsls` may run out of memory on very large projects. We default the limit to 8092 (8 GiB) vs. the default of 3072 but this may not be sufficient for you:

```json
{
  "lsp": {
    "vtsls": {
      "settings": {
        // For TypeScript:
        "typescript": { "tsserver": { "maxTsServerMemory": 16184 } },
        // For JavaScript:
        "javascript": { "tsserver": { "maxTsServerMemory": 16184 } }
      }
    }
  }
}
```

## Inlay Hints

Zed sets the following initialization options to make the language server send back inlay hints (that is, when Zed has inlay hints enabled in the settings).

You can override these settings in your Zed `settings.json` when using `typescript-language-server`:

```json
{
  "lsp": {
    "typescript-language-server": {
      "initialization_options": {
        "preferences": {
          "includeInlayParameterNameHints": "all",
          "includeInlayParameterNameHintsWhenArgumentMatchesName": true,
          "includeInlayFunctionParameterTypeHints": true,
          "includeInlayVariableTypeHints": true,
          "includeInlayVariableTypeHintsWhenTypeMatchesName": true,
          "includeInlayPropertyDeclarationTypeHints": true,
          "includeInlayFunctionLikeReturnTypeHints": true,
          "includeInlayEnumMemberValueHints": true
        }
      }
    }
  }
}
```

See [typescript-language-server inlayhints documentation](https://github.com/typescript-language-server/typescript-language-server?tab=readme-ov-file#inlay-hints-textdocumentinlayhint) for more information.

When using `vtsls`:

```json
{
  "lsp": {
    "vtsls": {
      "settings": {
        // For JavaScript:
        "javascript": {
          "inlayHints": {
            "parameterNames": {
              "enabled": "all",
              "suppressWhenArgumentMatchesName": false
            },
            "parameterTypes": {
              "enabled": true
            },
            "variableTypes": {
              "enabled": true,
              "suppressWhenTypeMatchesName": true
            },
            "propertyDeclarationTypes": {
              "enabled": true
            },
            "functionLikeReturnTypes": {
              "enabled": true
            },
            "enumMemberValues": {
              "enabled": true
            }
          }
        },
        // For TypeScript:
        "typescript": {
          "inlayHints": {
            "parameterNames": {
              "enabled": "all",
              "suppressWhenArgumentMatchesName": false
            },
            "parameterTypes": {
              "enabled": true
            },
            "variableTypes": {
              "enabled": true,
              "suppressWhenTypeMatchesName": true
            },
            "propertyDeclarationTypes": {
              "enabled": true
            },
            "functionLikeReturnTypes": {
              "enabled": true
            },
            "enumMemberValues": {
              "enabled": true
            }
          }
        }
      }
    }
  }
}
```

## Debugging

Zed supports debugging TypeScript code out of the box.
The following can be debugged without writing additional configuration:

- Tasks from `package.json`
- Tests written using several popular frameworks (Jest, Mocha, Vitest, Jasmine)

Run {#action debugger::Start} ({#kb debugger::Start}) to see a contextual list of these predefined debug tasks.

As for all languages, configurations from `.vscode/launch.json` are also available for debugging in Zed.

If your use-case isn't covered by any of these, you can take full control by adding debug configurations to `.zed/debug.json`. See below for example configurations.

### Attach debugger to a server running in web browser (`npx serve`)

Given an externally-ran web server (e.g., with `npx serve` or `npx live-server`) one can attach to it and open it with a browser.

```json
[
  {
    "label": "Launch Chrome (TypeScript)",
    "adapter": "JavaScript",
    "type": "chrome",
    "request": "launch",
    "url": "http://localhost:5500",
    "program": "$ZED_FILE",
    "webRoot": "${ZED_WORKTREE_ROOT}",
    "build": {
      "command": "npx",
      "args": ["tsc"]
    },
    "skipFiles": ["<node_internals>/**"]
  }
]
```

## See also

- [Zed Yarn documentation](./yarn.md) for a walkthrough of configuring your project to use Yarn.
- [Zed Deno documentation](./deno.md)

    # Uiua

[Uiua](https://www.uiua.org/) is a general purpose, stack-based, array-oriented programming language with a focus on simplicity, beauty, and tacit code.

Uiua support is available through the [Uiua extension](https://github.com/zed-extensions/uiua).

- Tree-sitter: [shnarazk/tree-sitter-uiua](https://github.com/shnarazk/tree-sitter-uiua)
- Language Server: [uiua-lang/uiua](https://github.com/uiua-lang/uiua/)

    # Vue

Vue support is available through the [Vue extension](https://github.com/zed-extensions/vue).

- Tree-sitter: [tree-sitter-grammars/tree-sitter-vue](https://github.com/tree-sitter-grammars/tree-sitter-vue)
- Language Server: [vuejs/language-tools/](https://github.com/vuejs/language-tools/)

    # XML

XML support is available through the [XML extension](https://github.com/sweetppro/zed-xml/).

- Tree-sitter: [tree-sitter-grammars/tree-sitter-xml](https://github.com/tree-sitter-grammars/tree-sitter-xml)

## Configuration

If you have additional file extensions that are not being automatically recognized as XML just add them to [file_types](../configuring-zed.md#file-types) in your Zed settings:

```json
  "file_types": {
    "XML": ["rdf", "gpx", "kml"]
  }
```

    # YAML

YAML support is available natively in Zed.

- Tree-sitter: [zed-industries/tree-sitter-yaml](https://github.com/zed-industries/tree-sitter-yaml)
- Language Server: [redhat-developer/yaml-language-server](https://github.com/redhat-developer/yaml-language-server)

## Configuration

You can configure various [yaml-language-server settings](https://github.com/redhat-developer/yaml-language-server?tab=readme-ov-file#language-server-settings) by adding them to your Zed settings.json in a `yaml-language-server` block under the `lsp` key. For example:

```json
  "lsp": {
    "yaml-language-server": {
      "settings": {
        "yaml": {
          "keyOrdering": true,
          "format": {
            "singleQuote": true
          },
          "schemas": {
              "http://json.schemastore.org/composer": ["/*"],
              "../relative/path/schema.json": ["/config*.yaml"]
          }
        }
      }
    }
  }
```

Note, settings keys must be nested, so `yaml.keyOrdering` becomes `{"yaml": { "keyOrdering": true }}`.

## Formatting

By default, Zed uses Prettier for formatting YAML files.

### Prettier Formatting

You can customize the formatting behavior of Prettier. For example to use single-quotes in yaml files add the following to your `.prettierrc` configuration file:

```json
{
  "overrides": [
    {
      "files": ["*.yaml", "*.yml"],
      "options": {
        "singleQuote": false
      }
    }
  ]
}
```

### yaml-language-server Formatting

To use `yaml-language-server` instead of Prettier for YAML formatting, add the following to your Zed `settings.json`:

```json
  "languages": {
    "YAML": {
      "formatter": "language_server"
    }
  }
```

## Schemas

By default yaml-language-server will attempt to determine the correct schema for a given yaml file and retrieve the appropriate JSON Schema from [Json Schema Store](https://schemastore.org/).

You can override any auto-detected schema via the `schemas` settings key (demonstrated above) or by providing an [inlined schema](https://github.com/redhat-developer/yaml-language-server#using-inlined-schema) reference via a modeline comment at the top of your yaml file:

```yaml
# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
name: Issue Assignment
on:
  issues:
    types: [oppened]
```

You can disable the automatic detection and retrieval of schemas from the JSON Schema if desired:

```json
  "lsp": {
    "yaml-language-server": {
      "settings": {
        "yaml": {
          "schemaStore": {
            "enable": false
          }
        }
      }
    }
  }
```

## Custom Tags

Yaml-language-server supports [custom tags](https://github.com/redhat-developer/yaml-language-server#adding-custom-tags) which can be used to inject custom application functionality at runtime into your yaml files.

For example Amazon CloudFormation YAML uses a number of custom tags, to support these you can add the following to your settings.json:

```json
  "lsp": {
    "yaml-language-server": {
      "settings": {
        "yaml": {
          "customTags": [
            "!And scalar",
            "!And mapping",
            "!And sequence",
            "!If scalar",
            "!If mapping",
            "!If sequence",
            "!Not scalar",
            "!Not mapping",
            "!Not sequence",
            "!Equals scalar",
            "!Equals mapping",
            "!Equals sequence",
            "!Or scalar",
            "!Or mapping",
            "!Or sequence",
            "!FindInMap scalar",
            "!FindInMap mapping",
            "!FindInMap sequence",
            "!Base64 scalar",
            "!Base64 mapping",
            "!Base64 sequence",
            "!Cidr scalar",
            "!Cidr mapping",
            "!Cidr sequence",
            "!Ref scalar",
            "!Ref mapping",
            "!Ref sequence",
            "!Sub scalar",
            "!Sub mapping",
            "!Sub sequence",
            "!GetAtt scalar",
            "!GetAtt mapping",
            "!GetAtt sequence",
            "!GetAZs scalar",
            "!GetAZs mapping",
            "!GetAZs sequence",
            "!ImportValue scalar",
            "!ImportValue mapping",
            "!ImportValue sequence",
            "!Select scalar",
            "!Select mapping",
            "!Select sequence",
            "!Split scalar",
            "!Split mapping",
            "!Split sequence",
            "!Join scalar",
            "!Join mapping",
            "!Join sequence",
            "!Condition scalar",
            "!Condition mapping",
            "!Condition sequence"
          ]
        }
      }
    }
  }
```

    # Yara

`Yara` language support in Zed is provided by the [Yara](https://github.com/egibs/yara.zed) extension. Please report issues to [https://github.com/egibs/yara.zed/issues](https://github.com/egibs/yara.zed).

- Tree-sitter: [egibs/tree-sitter-yara](https://github.com/egibs/tree-sitter-yara)
- Language Server: [avast/yls](https://github.com/avast/yls)

    # Yarn

[Yarn](https://yarnpkg.com/) is a versatile package manager that improves dependency management and workflow efficiency for JavaScript and other languages. It ensures a deterministic dependency tree, offers offline support, and enhances security for reliable builds.

## Setup

1. Run `yarn dlx @yarnpkg/sdks base` to generate a `.yarn/sdks` directory.
2. Set your language server (e.g. VTSLS) to use TypeScript SDK from `.yarn/sdks/typescript/lib` directory in [LSP initialization options](../configuring-zed.md#lsp). The actual setting for that depends on language server; for example, for VTSLS you should set [`typescript.tsdk`](https://github.com/yioneko/vtsls/blob/6adfb5d3889ad4b82c5e238446b27ae3ee1e3767/packages/service/configuration.schema.json#L5).
3. Voilla! Language server functionalities such as Go to Definition, Code Completions and On Hover documentation should work.

    # Zig

Zig support is available through the [Zig extension](https://github.com/zed-extensions/zig).

- Tree-sitter: [tree-sitter-zig](https://github.com/tree-sitter-grammars/tree-sitter-zig)
- Language Server: [zls](https://github.com/zigtools/zls)

    # Zed on Linux

## Standard Installation

For most people we recommend using the script on the [download](https://zed.dev/download) page to install Zed:

```sh
curl -f https://zed.dev/install.sh | sh
```

We also offer a preview build of Zed which receives updates about a week ahead of stable. You can install it with:

```sh
curl -f https://zed.dev/install.sh | ZED_CHANNEL=preview sh
```

The Zed installed by the script works best on systems that:

- have a Vulkan compatible GPU available (for example Linux on an M-series macBook)
- have a system-wide glibc (NixOS and Alpine do not by default)
  - x86_64 (Intel/AMD): glibc version >= 2.31 (Ubuntu 20 and newer)
  - aarch64 (ARM): glibc version >= 2.35 (Ubuntu 22 and newer)

Both Nix and Alpine have third-party Zed packages available (though they are currently a few weeks out of date). If you'd like to use our builds they do work if you install a glibc compatibility layer. On NixOS you can try [nix-ld](https://github.com/Mic92/nix-ld), and on Alpine [gcompat](https://wiki.alpinelinux.org/wiki/Running_glibc_programs).

You will need to build from source for:

- architectures other than 64-bit Intel or 64-bit ARM (for example a 32-bit or RISC-V machine)
- Redhat Enterprise Linux 8.x, Rocky Linux 8, AlmaLinux 8, Amazon Linux 2 on all architectures
- Redhat Enterprise Linux 9.x, Rocky Linux 9.3, AlmaLinux 8, Amazon Linux 2023 on aarch64 (x86_x64 OK)

## Other ways to install Zed on Linux

Zed is open source, and [you can install from source](./development/linux.md).

### Installing via a package manager

There are several third-party Zed packages for various Linux distributions and package managers, sometimes under `zed-editor`. You may be able to install Zed using these packages:

- Flathub: [`dev.zed.Zed`](https://flathub.org/apps/dev.zed.Zed)
- Arch: [`zed`](https://archlinux.org/packages/extra/x86_64/zed/)
- Arch (AUR): [`zed-git`](https://aur.archlinux.org/packages/zed-git), [`zed-preview`](https://aur.archlinux.org/packages/zed-preview), [`zed-preview-bin`](https://aur.archlinux.org/packages/zed-preview-bin)
- Alpine: `zed` ([aarch64](https://pkgs.alpinelinux.org/package/edge/testing/aarch64/zed)) ([x86_64](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/zed))
- Nix: `zed-editor` ([unstable](https://search.nixos.org/packages?channel=unstable&show=zed-editor))
- Fedora/Ultramarine (Terra): [`zed`](https://github.com/terrapkg/packages/tree/frawhide/anda/devs/zed/stable), [`zed-preview`](https://github.com/terrapkg/packages/tree/frawhide/anda/devs/zed/preview), [`zed-nightly`](https://github.com/terrapkg/packages/tree/frawhide/anda/devs/zed/nightly)
- Solus: [`zed`](https://github.com/getsolus/packages/tree/main/packages/z/zed)
- Parabola: [`zed`](https://www.parabola.nu/packages/extra/x86_64/zed/)
- Manjaro: [`zed`](https://packages.manjaro.org/?query=zed)
- ALT Linux (Sisyphus): [`zed`](https://packages.altlinux.org/en/sisyphus/srpms/zed/)
- AOSC OS: [`zed`](https://packages.aosc.io/packages/zed)

See [Repology](https://repology.org/project/zed-editor/versions) for a list of Zed packages in various repositories.

When installing a third-party package please be aware that it may not be completely up to date and may be slightly different from the Zed we package (a common change is to rename the binary to `zedit` or `zeditor` to avoid conflicting with other packages).

We'd love your help making Zed available for everyone. If Zed is not yet available for your package manager, and you would like to fix that, we have some notes on [how to do it](./development/linux.md#notes-for-packaging-zed).

### Downloading manually

If you'd prefer, you can install Zed by downloading our pre-built .tar.gz. This is the same artifact that our install script uses, but you can customize the location of your installation by modifying the instructions below:

Download the `.tar.gz` file:

- [zed-linux-x86_64.tar.gz](https://zed.dev/api/releases/stable/latest/zed-linux-x86_64.tar.gz) ([preview](https://zed.dev/api/releases/preview/latest/zed-linux-x86_64.tar.gz))
- [zed-linux-aarch64.tar.gz](https://zed.dev/api/releases/stable/latest/zed-linux-aarch64.tar.gz)
  ([preview](https://zed.dev/api/releases/preview/latest/zed-linux-aarch64.tar.gz))

Then ensure that the `zed` binary in the tarball is on your path. The easiest way is to unpack the tarball and create a symlink:

```sh
mkdir -p ~/.local
# extract zed to ~/.local/zed.app/
tar -xvf <path/to/download>.tar.gz -C ~/.local
# link the zed binary to ~/.local/bin (or another directory in your $PATH)
ln -sf ~/.local/zed.app/bin/zed ~/.local/bin/zed
```

If you'd like integration with an XDG-compatible desktop environment, you will also need to install the `.desktop` file:

```sh
cp ~/.local/zed.app/share/applications/zed.desktop ~/.local/share/applications/dev.zed.Zed.desktop
sed -i "s|Icon=zed|Icon=$HOME/.local/zed.app/share/icons/hicolor/512x512/apps/zed.png|g" ~/.local/share/applications/dev.zed.Zed.desktop
sed -i "s|Exec=zed|Exec=$HOME/.local/zed.app/libexec/zed-editor|g" ~/.local/share/applications/dev.zed.Zed.desktop
```

## Uninstalling Zed

### Standard Uninstall

If Zed was installed using the default installation script, it can be uninstalled by supplying the `--uninstall` flag to the `zed` shell command

```sh
zed --uninstall
```

If there are no errors, the shell will then prompt you whether you'd like to keep your preferences or delete them. After making a choice, you should see a message that Zed was successfully uninstalled.

In the case that the `zed` shell command was not found in your PATH, you can try one of the following commands

```sh
$HOME/.local/bin/zed --uninstall
```

or

```sh
$HOME/.local/zed.app/bin.zed --uninstall
```

The first case might fail if a symlink was not properly established between `$HOME/.local/bin/zed` and `$HOME/.local/zed.app/bin.zed`. But the second case should work as long as Zed was installed to its default location.

If Zed was installed to a different location, you must invoke the `zed` binary stored in that installation directory and pass the `--uninstall` flag to it in the same format as the previous commands.

### Package Manager

If Zed was installed using a package manager, please consult the documentation for that package manager on how to uninstall a package.

## Troubleshooting

Linux works on a large variety of systems configured in many different ways. We primarily test Zed on a vanilla Ubuntu setup, as it is the most common distribution our users use, that said we do expect it to work on a wide variety of machines.

### Zed fails to start

If you see an error like "/lib64/libc.so.6: version 'GLIBC_2.29' not found" it means that your distribution's version of glibc is too old. You can either upgrade your system, or [install Zed from source](./development/linux.md).

### Graphics issues

#### Zed fails to open windows

Zed requires a GPU to run effectively. Under the hood, we use [Vulkan](https://www.vulkan.org/) to communicate with your GPU. If you are seeing problems with performance, or Zed fails to load, it is possible that Vulkan is the culprit.

If you see a notification saying `Zed failed to open a window: NoSupportedDeviceFound` this means that Vulkan cannot find a compatible GPU. you can try running [vkcube](https://github.com/krh/vkcube) (usually available as part of the `vulkaninfo` or `vulkan-tools` package on various distributions) to try to troubleshoot where the issue is coming from like so:

```
vkcube
```

> **_Note_**: Try running in both X11 and wayland modes by running `vkcube -m [x11|wayland]`. Some versions of `vkcube` use `vkcube` to run in X11 and `vkcube-wayland` to run in wayland.

This should output a line describing your current graphics setup and show a rotating cube. If this does not work, you should be able to fix it by installing Vulkan compatible GPU drivers, however in some cases (for example running Linux on an Arm-based MacBook) there is no Vulkan support yet.

You can find out which graphics card Zed is using by looking in the Zed log (`~/.local/share/zed/logs/Zed.log`) for `Using GPU: ...`.

If you see errors like `ERROR_INITIALIZATION_FAILED` or `GPU Crashed` or `ERROR_SURFACE_LOST_KHR` then you may be able to work around this by installing different drivers for your GPU, or by selecting a different GPU to run on. (See [#14225](https://github.com/zed-industries/zed/issues/14225))

On some systems the file `/etc/prime-discrete` can be used to enforce the use of a discrete GPU using [PRIME](https://wiki.archlinux.org/title/PRIME). Depending on the details of your setup, you may need to change the contents of this file to "on" (to force discrete graphics) or "off" (to force integrated graphics).

On others, you may be able to the environment variable `DRI_PRIME=1` when running Zed to force the use of the discrete GPU.

If you're using an AMD GPU and Zed crashes when selecting long lines, try setting the `ZED_PATH_SAMPLE_COUNT=0` environment variable. (See [#26143](https://github.com/zed-industries/zed/issues/26143))

If you're using an AMD GPU, you might get a 'Broken Pipe' error. Try using the RADV or Mesa drivers. (See [#13880](https://github.com/zed-industries/zed/issues/13880))

If you are using `amdvlk`, the default open-source AMD graphics driver, you may find that Zed consistently fails to launch. This is a known issue for some users, for example on Omarchy (see issue [#28851](https://github.com/zed-industries/zed/issues/28851)). To fix this, you will need to use a different driver. We recommend removing the `amdvlk` and `lib32-amdvlk` packages and installing `vulkan-radeon` instead (see issue [#14141](https://github.com/zed-industries/zed/issues/14141)).

For more information, the [Arch guide to Vulkan](https://wiki.archlinux.org/title/Vulkan) has some good steps that translate well to most distributions.

#### Forcing Zed to use a specific GPU

There are a few different ways to force Zed to use a specific GPU:

##### Option A

You can use the `ZED_DEVICE_ID={device_id}` environment variable to specify the device ID of the GPU you wish to have Zed use.

You can obtain the device ID of your GPU by running `lspci -nn | grep VGA` which will output each GPU on one line like:

```
08:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104 [GeForce RTX 3070] [10de:2484] (rev a1)
```

where the device ID here is `2484`. This value is in hexadecimal, so to force Zed to use this specific GPU you would set the environment variable like so:

```
ZED_DEVICE_ID=0x2484 zed
```

Make sure to export the variable if you choose to define it globally in a `.bashrc` or similar.

##### Option B

If you are using Mesa, you can run `MESA_VK_DEVICE_SELECT=list zed --foreground` to get a list of available GPUs and then export `MESA_VK_DEVICE_SELECT=xxxx:yyyy` to choose a specific device.

##### Option C

Using [vkdevicechooser](https://github.com/jiriks74/vkdevicechooser).

#### Reporting graphics issues

If Vulkan is configured correctly, and Zed is still not working for you, please [file an issue](https://github.com/zed-industries/zed) with as much information as possible.

When reporting issues where Zed fails to start due to graphics initialization errors on GitHub, it can be impossible to run the `zed: copy system specs into clipboard` command like we instruct you to in our issue template. We provide an alternative way to collect the system specs specifically for this situation.

Passing the `--system-specs` flag to Zed like

```sh
zed --system-specs
```

will print the system specs to the terminal like so. It is strongly recommended to copy the output verbatim into the issue on GitHub, as it uses markdown formatting to ensure the output is readable.

Additionally, it is extremely beneficial to provide the contents of your Zed log when reporting such issues. The log is usually located at `~/.local/share/zed/logs/Zed.log`. The recommended process for producing a helpful log file is as follows:

```sh
truncate -s 0 ~/.local/share/zed/logs/Zed.log # Clear the log file
ZED_LOG=blade_graphics=info zed .
cat ~/.local/share/zed/logs/Zed.log
# copy the output
```

Or, if you have the Zed cli setup, you can do

```sh
ZED_LOG=blade_graphics=info /path/to/zed/cli --foreground .
# copy the output
```

It is also highly recommended when pasting the log into a github issue, to do so with the following template:

> **_Note_**: The whitespace in the template is important, and will cause incorrect formatting if not preserved.

````
<details><summary>Zed Log</summary>

```
{zed log contents}
```

</details>
````

This will cause the logs to be collapsed by default, making it easier to read the issue.

### I can't open any files

### Clicking links isn't working

These features are provided by XDG desktop portals, specifically:

- `org.freedesktop.portal.FileChooser`
- `org.freedesktop.portal.OpenURI`

Some window managers, such as `Hyprland`, don't provide a file picker by default. See [this list](https://wiki.archlinux.org/title/XDG_Desktop_Portal#List_of_backends_and_interfaces) as a starting point for alternatives.

### Zed isn't remembering my API keys

### Zed isn't remembering my login

These feature also requires XDG desktop portals, specifically:

- `org.freedesktop.portal.Secret` or
- `org.freedesktop.Secrets`

Zed needs a place to securely store secrets such as your Zed login cookie or your OpenAI API Keys and we use a system provided keychain to do this. Examples of packages that provide this are `gnome-keyring`, `KWallet` and `keepassxc` among others.

### Could not start inotify

Zed relies on inotify to watch your filesystem for changes. If you cannot start inotify then Zed will not work reliably.

If you are seeing "too many open files" then first try `sysctl fs.inotify`.

- You should see that max_user_instances is 128 or higher (you can change the limit with `sudo sysctl fs.inotify.max_user_instances=1024`). Zed needs only 1 inotify instance.
- You should see that `max_user_watches` is 8000 or higher (you can change the limit with `sudo sysctl fs.inotify.max_user_watches=64000`). Zed needs one watch per directory in all your open projects + one per git repository + a handful more for settings, themes, keymaps, extensions.

It is also possible that you are running out of file descriptors. You can check the limits with `ulimit` and update them by editing `/etc/security/limits.conf`.

### No sound or wrong output device

If you're not hearing any sound in Zed or the audio is routed to the wrong device, it could be due to a mismatch between audio systems. Zed relies on ALSA, while your system may be using PipeWire or PulseAudio. To resolve this, you need to configure ALSA to route audio through PipeWire/PulseAudio.

If your system uses PipeWire:

1. **Install the PipeWire ALSA plugin**

   On Debian-based systems, run:

   ```bash
   sudo apt install pipewire-alsa
   ```

2. **Configure ALSA to use PipeWire**

   Add the following configuration to your ALSA settings file. You can use either `~/.asoundrc` (user-level) or `/etc/asound.conf` (system-wide):

   ```bash
   pcm.!default {
       type pipewire
   }

   ctl.!default {
       type pipewire
   }
   ```

3. **Restart your system**

### Forcing X11 scale factor

On X11 systems, Zed automatically detects the appropriate scale factor for high-DPI displays. The scale factor is determined using the following priority order:

1. `GPUI_X11_SCALE_FACTOR` environment variable (if set)
2. `Xft.dpi` from X resources database (xrdb)
3. Automatic detection via RandR based on monitor resolution and physical size

If you want to customize the scale factor beyond what Zed detects automatically, you have several options:

#### Check your current scale factor

You can verify if you have `Xft.dpi` set:

```sh
xrdb -query | grep Xft.dpi
```

If this command returns no output, Zed is using RandR (X11's monitor management extension) to automatically calculate the scale factor based on your monitor's reported resolution and physical dimensions.

#### Option 1: Set Xft.dpi (X Resources Database)

`Xft.dpi` is a standard X11 setting that many applications use for consistent font and UI scaling. Setting this ensures Zed scales the same way as other X11 applications that respect this setting.

Edit or create the `~/.Xresources` file:

```sh
vim ~/.Xresources
```

Add this line with your desired DPI:

```sh
Xft.dpi: 96
```

Common DPI values:

- `96` for standard 1x scaling
- `144` for 1.5x scaling
- `192` for 2x scaling
- `288` for 3x scaling

Load the configuration:

```sh
xrdb -merge ~/.Xresources
```

Restart Zed for the changes to take effect.

#### Option 2: Use the GPUI_X11_SCALE_FACTOR environment variable

This Zed-specific environment variable directly sets the scale factor, bypassing all automatic detection.

```sh
GPUI_X11_SCALE_FACTOR=1.5 zed
```

You can use decimal values (e.g., `1.25`, `1.5`, `2.0`) or set `GPUI_X11_SCALE_FACTOR=randr` to force RandR-based detection even when `Xft.dpi` is set.

To make this permanent, add it to your shell profile or desktop entry.

#### Option 3: Adjust system-wide RandR DPI

This changes the reported DPI for your entire X11 session, affecting how RandR calculates scaling for all applications that use it.

Add this to your `.xprofile` or `.xinitrc`:

```sh
xrandr --dpi 192
```

Replace `192` with your desired DPI value. This affects the system globally and will be used by Zed's automatic RandR detection when `Xft.dpi` is not set.

    # Multibuffers

One of the superpowers Zed gives you is the ability to edit multiple files simultaneously. When combined with multiple cursors, this makes wide-ranging refactors significantly faster.

## Editing in a multibuffer

<div class="video" style="position: relative; padding-top: 71.71314741035857%;">
  <iframe
    src="https://customer-snccc0j9v3kfzkif.cloudflarestream.com/bda0a6584c19f4b39e58a263c0ae4358/iframe?muted=true&preload=true&loop=true&autoplay=true&poster=https%3A%2F%2Fcustomer-snccc0j9v3kfzkif.cloudflarestream.com%2Fbda0a6584c19f4b39e58a263c0ae4358%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600&controls=false"
    style="border: none; position: absolute; top: 0; left: 0; height: 100%; width: 100%;"
    allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
    allowfullscreen="true"
  ></iframe>
</div>

Editing a multibuffer is the same as editing a normal file. Changes you make will be reflected in the open copies of that file in the rest of the editor, and you can save all files with `editor: Save` (bound to `cmd-s` on macOS, `ctrl-s` on Windows/Linux, or `:w` in Vim mode).

When in a multibuffer, it is often useful to use multiple cursors to edit every file simultaneously. If you want to edit a few instances, you can select them with the mouse (`option-click` on macOS, `alt-click` on Window/Linux) or the keyboard. `cmd-d` on macOS, `ctrl-d` on Windows/Linux, or `gl` in Vim mode will select the next match of the word under the cursor.

When you want to edit all matches you can select them by running the `editor: Select All Matches` command (`cmd-shift-l` on macOS, `ctrl-shift-l` on Windows/Linux, or `g a` in Vim mode).

## Navigating to the Source File

While you can easily edit files in a multibuffer, navigating directly to the source file is often beneficial. You can accomplish this by clicking on any of the divider lines between excerpts or by placing your cursor in an excerpt and executing the `editor: open excerpts` command. It’s key to note that if multiple cursors are being used, the command will open the source file positioned under each cursor within the multibuffer.

Additionally, if you prefer to use the mouse and would like to double-click on an excerpt to open it, you can enable this functionality with the setting: `"double_click_in_multibuffer": "open"`.

## Project search

To start a search run the `pane: Toggle Search` command (`cmd-shift-f` on macOS, `ctrl-shift-f` on Windows/Linux, or `g/` in Vim mode). After the search has completed, the results will be shown in a new multibuffer. There will be one excerpt for each matching line across the whole project.

## Diagnostics

If you have a language server installed, the diagnostics pane can show you all errors across your project. You can open it by clicking on the icon in the status bar, or running the `diagnostics: Deploy` command` ('cmd-shift-m` on macOS, `ctrl-shift-m` on Windows/Linux, or `:clist` in Vim mode).

## Find References

If you have a language server installed, you can find all references to the symbol under the cursor with the `editor: Find References` command (`cmd-click` on macOS, `ctrl-click` on Windows/Linux, or `g A` in Vim mode.

Depending on your language server, commands like `editor: Go To Definition` and `editor: Go To Type Definition` will also open a multibuffer if there are multiple possible definitions.

    # Outline Panel

In addition to the modal outline (`cmd-shift-o`), Zed offers an outline panel. The outline panel can be deployed via `cmd-shift-b` (`outline panel: toggle focus` via the command palette), or by clicking the `Outline Panel` button in the status bar.

When viewing a "singleton" buffer (i.e., a single file on a tab), the outline panel works similarly to that of the outline modal－it displays the outline of the current buffer's symbols, as reported by tree-sitter. Clicking on an entry allows you to jump to the associated section in the file. The outline view will also automatically scroll to the section associated with the current cursor position within the file.

![Using the outline panel in a singleton buffer](https://zed.dev/img/outline-panel/singleton.png)

## Usage with multibuffers

The outline panel truly excels when used with multi-buffers. Here are some examples of its versatility:

### Project Search Results

Get an overview of search results across your project.

![Using the outline panel in a project search multi-buffer](https://zed.dev/img/outline-panel/project-search.png)

### Project Diagnostics

View a summary of all errors and warnings reported by the language server.

![Using the outline panel while viewing project diagnostics multi-buffer](https://zed.dev/img/outline-panel/project-diagnostics.png)

### Find All References

Quickly navigate through all references when using the `editor: find all references` action.

![Using the outline panel while viewing `find all references` multi-buffer](https://zed.dev/img/outline-panel/find-all-references.png)

The outline view provides a great way to quickly navigate to specific parts of your code and helps you maintain context when working with large result sets in multi-buffers.

    # Remote Development

Remote Development allows you to code at the speed of thought, even when your codebase is not on your local machine. You use Zed locally so the UI is immediately responsive, but offload heavy computation to the development server so that you can work effectively.

## Overview

Remote development requires two computers, your local machine that runs the Zed UI and the remote server which runs a Zed headless server. The two communicate over SSH, so you will need to be able to SSH from your local machine into the remote server to use this feature.

![Architectural overview of Zed Remote Development](https://zed.dev/img/remote-development/diagram.png)

On your local machine, Zed runs its UI, talks to language models, uses Tree-sitter to parse and syntax-highlight code, and store unsaved changes and recent projects. The source code, language servers, tasks, and the terminal all run on the remote server.

> **Note:** The original version of remote development sent traffic via Zed's servers. As of Zed v0.157 you can no-longer use that mode.

## Setup

1. Download and install the latest [Zed](https://zed.dev/releases). You need at least Zed v0.159.
1. Use {#kb projects::OpenRemote} to open the "Remote Projects" dialog.
1. Click "Connect New Server" and enter the command you use to SSH into the server. See [Supported SSH options](#supported-ssh-options) for options you can pass.
1. Your local machine will attempt to connect to the remote server using the `ssh` binary on your path. Assuming the connection is successful, Zed will download the server on the remote host and start it.
1. Once the Zed server is running, you will be prompted to choose a path to open on the remote server.
   > **Note:** Zed does not currently handle opening very large directories (for example, `/` or `~` that may have >100,000 files) very well. We are working on improving this, but suggest in the meantime opening only specific projects, or subfolders of very large mono-repos.

For simple cases where you don't need any SSH arguments, you can run `zed ssh://[<user>@]<host>[:<port>]/<path>` to open a remote folder/file directly. If you'd like to hotlink into an SSH project, use a link of the format: `zed://ssh/[<user>@]<host>[:<port>]/<path>`.

## Supported platforms

The remote machine must be able to run Zed's server. The following platforms should work, though note that we have not exhaustively tested every Linux distribution:

- macOS Catalina or later (Intel or Apple Silicon)
- Linux (x86_64 or arm64, we do not yet support 32-bit platforms)
- Windows is not yet supported.

## Configuration

The list of remote servers is stored in your settings file {#kb zed::OpenSettings}. You can edit this list using the Remote Projects dialog {#kb projects::OpenRemote}, which provides some robustness - for example it checks that the connection can be established before writing it to the settings file.

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "projects": [{ "paths": ["~/code/zed/zed"] }]
    }
  ]
}
```

Zed shells out to the `ssh` on your path, and so it will inherit any configuration you have in `~/.ssh/config` for the given host. That said, if you need to override anything you can configure the following additional options on each connection:

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "projects": [{ "paths": ["~/code/zed/zed"] }],
      // any argument to pass to the ssh master process
      "args": ["-i", "~/.ssh/work_id_file"],
      "port": 22, // defaults to 22
      // defaults to your username on your local machine
      "username": "me"
    }
  ]
}
```

There are two additional Zed-specific options per connection, `upload_binary_over_ssh` and `nickname`:

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "projects": [{ "paths": ["~/code/zed/zed"] }],
      // by default Zed will download the server binary from the internet on the remote.
      // When this is true, it'll be downloaded to your laptop and uploaded over SSH.
      // This is useful when your remote server has restricted internet access.
      "upload_binary_over_ssh": true,
      // Shown in the Zed UI to help distinguish multiple hosts.
      "nickname": "lil-linux"
    }
  ]
}
```

If you use the command line to open a connection to a host by doing `zed ssh://192.168.1.10/~/.vimrc`, then extra options are read from your settings file by finding the first connection that matches the host/username/port of the URL on the command line.

Additionally it's worth noting that while you can pass a password on the command line `zed ssh://user:password@host/~`, we do not support writing a password to your settings file. If you're connecting repeatedly to the same host, you should configure key-based authentication.

## Port forwarding

If you'd like to be able to connect to ports on your remote server from your local machine, you can configure port forwarding in your settings file. This is particularly useful for developing websites so you can load the site in your browser while working.

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "port_forwards": [{ "local_port": 8080, "remote_port": 80 }]
    }
  ]
}
```

This will cause requests from your local machine to `localhost:8080` to be forwarded to the remote machine's port 80. Under the hood this uses the `-L` argument to ssh.

By default these ports are bound to localhost, so other computers in the same network as your development machine cannot access them. You can set the local_host to bind to a different interface, for example, 0.0.0.0 will bind to all local interfaces.

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "port_forwards": [
        {
          "local_port": 8080,
          "remote_port": 80,
          "local_host": "0.0.0.0"
        }
      ]
    }
  ]
}
```

These ports also default to the `localhost` interface on the remote host. If you need to change this, you can also set the remote host:

```json
{
  "ssh_connections": [
    {
      "host": "192.168.1.10",
      "port_forwards": [
        {
          "local_port": 8080,
          "remote_port": 80,
          "remote_host": "docker-host"
        }
      ]
    }
  ]
}
```

## Zed settings

When opening a remote project there are three relevant settings locations:

- The local Zed settings (in `~/.zed/settings.json` on macOS or `~/.config/zed/settings.json` on Linux) on your local machine.
- The server Zed settings (in the same place) on the remote server.
- The project settings (in `.zed/settings.json` or `.editorconfig` of your project)

Both the local Zed and the server Zed read the project settings, but they are not aware of the other's main `settings.json`.

Depending on the kind of setting you want to make, which settings file you should use:

- Project settings should be used for things that affect the project: indentation settings, which formatter / language server to use, etc.
- Server settings should be used for things that affect the server: paths to language servers, etc.
- Local settings should be used for things that affect the UI: font size, etc.

In addition any extensions you have installed locally will be propagated to the remote server. This means that language servers, etc. will run correctly.

## Initializing the remote server

Once you provide the SSH options, Zed shells out to `ssh` on your local machine to create a ControlMaster connection with the options you provide.

Any prompts that SSH needs will be shown in the UI, so you can verify host keys, type key passwords, etc.

Once the master connection is established, Zed will check to see if the remote server binary is present in `~/.zed_server` on the remote, and that its version matches the current version of Zed that you're using.

If it is not there or the version mismatches, Zed will try to download the latest version. By default, it will download from `https://zed.dev` directly, but if you set: `{"upload_binary_over_ssh":true}` in your settings for that server, it will download the binary to your local machine and then upload it to the remote server.

If you'd like to maintain the server binary yourself you can. You can either download our prebuilt versions from [GitHub](https://github.com/zed-industries/zed/releases), or [build your own](https://zed.dev/docs/development) with `cargo build -p remote_server --release`. If you do this, you must upload it to `~/.zed_server/zed-remote-server-{RELEASE_CHANNEL}-{VERSION}` on the server, for example `~/.zed_server/zed-remote-server-stable-0.181.6`. The version must exactly match the version of Zed itself you are using.

## Maintaining the SSH connection

Once the server is initialized. Zed will create new SSH connections (reusing the existing ControlMaster) to run the remote development server.

Each connection tries to run the development server in proxy mode. This mode will start the daemon if it is not running, and reconnect to it if it is. This way when your connection drops and is restarted, you can continue to work without interruption.

In the case that reconnecting fails, the daemon will not be re-used. That said, unsaved changes are by default persisted locally, so that you do not lose work. You can always reconnect to the project at a later date and Zed will restore unsaved changes.

If you are struggling with connection issues, you should be able to see more information in the Zed log `cmd-shift-p Open Log`. If you are seeing things that are unexpected, please file a [GitHub issue](https://github.com/zed-industries/zed/issues/new) or reach out in the #remoting-feedback channel in the [Zed Discord](https://zed.dev/community-links).

## Supported SSH Options

Under the hood, Zed shells out to the `ssh` binary to connect to the remote server. We create one SSH control master per project, and use then use that to multiplex SSH connections for the Zed protocol itself, any terminals you open and tasks you run. We read settings from your SSH config file, but if you want to specify additional options to the SSH control master you can configure Zed to set them.

When typing in the "Connect New Server" dialog, you can use bash-style quoting to pass options containing a space. Once you have created a server it will be added to the `"ssh_connections": []` array in your settings file. You can edit the settings file directly to make changes to SSH connections.

Supported options:

- `-p` / `-l` - these are equivalent to passing the port and the username in the host string.
- `-L` / `-R` for port forwarding
- `-i` - to use a specific key file
- `-o` - to set custom options
- `-J` / `-w` - to proxy the SSH connection
- `-F` for specifying an `ssh_config`
- And also... `-4`, `-6`, `-A`, `-B`, `-C`, `-D`, `-I`, `-K`, `-P`, `-X`, `-Y`, `-a`, `-b`, `-c`, `-i`, `-k`, `-l`, `-m`, `-o`, `-p`, `-w`, `-x`, `-y`

Note that we deliberately disallow some options (for example `-t` or `-T`) that Zed will set for you.

## Known Limitations

- You can't open files from the remote Terminal by typing the `zed` command.

## Feedback

Please join the #remoting-feedback channel in the [Zed Discord](https://zed.dev/community-links).

    # REPL

## Getting started

Bring the power of [Jupyter kernels](https://docs.jupyter.org/en/latest/projects/kernels.html) to your editor! The built-in REPL for Zed allows you to run code interactively in your editor similarly to a notebook with your own text files.

<figure style="width: 100%; margin: 0; overflow: hidden; border-top-left-radius: 2px; border-top-right-radius: 2px;">
    <video loop controls playsinline>
        <source
            src="https://customer-snccc0j9v3kfzkif.cloudflarestream.com/aec66e79f23d6d1a0bee5e388a3f17cc/downloads/default.mp4"
            type='video/webm; codecs="vp8.0, vorbis"'
        />
        <source
            src="https://customer-snccc0j9v3kfzkif.cloudflarestream.com/aec66e79f23d6d1a0bee5e388a3f17cc/downloads/default.mp4"
            type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'
        />
        <source
          src="https://zed.dev/img/post/repl/typescript-deno-kernel-markdown.png"
          type="image/png"
        />
    </video>
</figure>

## Installation

Zed supports running code in multiple languages. To get started, you need to install a kernel for the language you want to use.

**Currently supported languages:**

- [Python (ipykernel)](#python)
- [TypeScript (Deno)](#typescript-deno)
- [R (Ark)](#r-ark)
- [R (Xeus)](#r-xeus)
- [Julia](#julia)
- [Scala (Almond)](#scala)

Once installed, you can start using the REPL in the respective language files, or other places those languages are supported, such as Markdown. If you recently added the kernels, run the `repl: refresh kernelspecs` command to make them available in the editor.

## Using the REPL

To start the REPL, open a file with the language you want to use and use the `repl: run` command (defaults to `ctrl-shift-enter` on macOS) to run a block, selection, or line. You can also click on the REPL icon in the toolbar.

The `repl: run` command will be executed on your selection(s), and the result will be displayed below the selection.

Outputs can be cleared with the `repl: clear outputs` command, or from the REPL menu in the toolbar.

### Cell mode

Zed supports [notebooks as scripts](https://jupytext.readthedocs.io/en/latest/formats-scripts.html) using the `# %%` cell separator in Python and `// %%` in TypeScript. This allows you to write code in a single file and run it as if it were a notebook, cell by cell.

The `repl: run` command will run each block of code between the `# %%` markers as a separate cell.

```python
# %% Cell 1
import time
import numpy as np

# %% Cell 2
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')
```

## Language specific instructions

### Python {#python}

#### Global environment

<div class="warning">

On macOS, your system Python will _not_ work. Either set up [pyenv](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation) or use a virtual environment.

</div>

To setup your current Python to have an available kernel, run:

```sh
pip install ipykernel
python -m ipykernel install --user
```

#### Conda Environment

```sh
source activate myenv
conda install ipykernel
python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
```

#### Virtualenv with pip

```sh
source activate myenv
pip install ipykernel
python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
```

### R (Ark Kernel) {#r-ark}

Install [Ark](https://github.com/posit-dev/ark/releases) by downloading the release for your operating system. For example, for macOS just unpack `ark` binary and put it into `/usr/local/bin`. Then run:

```sh
ark --install
```

### R (Xeus Kernel) {#r-xeus}

- Install [Xeus-R](https://github.com/jupyter-xeus/xeus-r)
- Install the R Extension for Zed (search for `R` in Zed Extensions)

<!--
TBD: Improve R REPL (Ark Kernel) instructions
-->

### TypeScript: Deno {#typescript-deno}

- [Install Deno](https://docs.deno.com/runtime/manual/getting_started/installation/) and then install the Deno jupyter kernel:

```sh
deno jupyter --install
```

<!--
TBD: Improve R REPL (Ark Kernel) instructions
-->

### Julia

- Download and install Julia from the [official website](https://julialang.org/downloads/).
- Install the Julia Extension for Zed (search for `Julia` in Zed Extensions)

<!--
TBD: Improve Julia REPL instructions
-->

### Scala

- [Install Scala](https://www.scala-lang.org/download/) with `cs setup` (Coursier):
  - `brew install coursier/formulas/coursier && cs setup`
- REPL (Almond) [setup instructions](https://almond.sh/docs/quick-start-install):
  - `brew install --cask temurin` (Eclipse foundation official OpenJDK binaries)
  - `brew install coursier/formulas/coursier && cs setup`
  - `coursier launch --use-bootstrap almond -- --install`

## Changing which kernel is used per language {#changing-kernels}

Zed automatically detects the available kernels on your system. If you need to configure a different default kernel for a
language, you can assign a kernel for any supported language in your `settings.json`.

```json
{
  "jupyter": {
    "kernel_selections": {
      "python": "conda-env",
      "typescript": "deno",
      "javascript": "deno",
      "r": "ark"
    }
  }
}
```

## Debugging Kernelspecs

Available kernels are shown via the `repl: sessions` command. To refresh the kernels you can run, use the `repl: refresh kernelspecs` command.

If you have `jupyter` installed, you can run `jupyter kernelspec list` to see the available kernels.

```sh
$ jupyter kernelspec list
Available kernels:
  ark                   /Users/z/Library/Jupyter/kernels/ark
  conda-base            /Users/z/Library/Jupyter/kernels/conda-base
  deno                  /Users/z/Library/Jupyter/kernels/deno
  python-chatlab-dev    /Users/z/Library/Jupyter/kernels/python-chatlab-dev
  python3               /Users/z/Library/Jupyter/kernels/python3
  ruby                  /Users/z/Library/Jupyter/kernels/ruby
  rust                  /Users/z/Library/Jupyter/kernels/rust
```

> Note: Zed makes best effort usage of `sys.prefix` and `CONDA_PREFIX` to find kernels in Python environments. If you want explicitly control run `python -m ipykernel install --user --name myenv --display-name "Python (myenv)"` to install the kernel directly while in the environment.

    # Snippets

Use the {#action snippets::ConfigureSnippets} action to create a new snippets file or edit a existing snippets file for a specified [scope](#scopes).

The snippets are located in `~/.config/zed/snippets` directory to which you can navigate to with the {#action snippets::OpenFolder} action.

## Example configuration

```json
{
  // Each snippet must have a name and body, but the prefix and description are optional.
  // The prefix is used to trigger the snippet, but when omitted then the name is used.
  // Use placeholders like $1, $2 or ${1:defaultValue} to define tab stops.
  // The $0 determines the final cursor position.
  // Placeholders with the same value are linked.
  "Log to console": {
    "prefix": "log",
    "body": ["console.info(\"Hello, ${1:World}!\")", "$0"],
    "description": "Logs to console"
  }
}
```

## Scopes

The scope is determined by the language name in lowercase e.g. `python.json` for Python, `shell script.json` for Shell Script, but there are some exceptions to this rule:

| Scope      | Filename        |
| ---------- | --------------- |
| Global     | snippets.json   |
| JSX        | javascript.json |
| Plain Text | plaintext.json  |

To create JSX snippets you have to use `javascript.json` snippets file, instead of `jsx.json`, but this does not apply to TSX and TypeScript which follow the above rule.

## Known Limitations

- Only the first prefix is used when an list of prefixes is passed in.
- Currently only the `json` snippet file format is supported, even though the `simple-completion-language-server` supports both `json` and `toml` file formats.

## See also

The `feature_paths` option in `simple-completion-language-server` is disabled by default.

If you want to enable it you can add the following to your `settings.json`:

```json
{
  "lsp": {
    "snippet-completion-server": {
      "settings": {
        "feature_paths": true
      }
    }
  }
}
```

For more configuration information, see the [`simple-completion-language-server` instructions](https://github.com/zed-industries/simple-completion-language-server/tree/main).

    # System Requirements

## Apple

### macOS

Zed supports the follow macOS releases:

| Version       | Codename | Apple Status   | Zed Status          |
| ------------- | -------- | -------------- | ------------------- |
| macOS 15.x    | Sequoia  | Supported      | Supported           |
| macOS 14.x    | Sonoma   | Supported      | Supported           |
| macOS 13.x    | Ventura  | Supported      | Supported           |
| macOS 12.x    | Monterey | EOL 2024-09-16 | Supported           |
| macOS 11.x    | Big Sur  | EOL 2023-09-26 | Partially Supported |
| macOS 10.15.x | Catalina | EOL 2022-09-12 | Partially Supported |
| macOS 10.14.x | Mojave   | EOL 2021-10-25 | Unsupported         |

The macOS releases labelled "Partially Supported" (Big Sur and Catalina) do not support screen sharing via Zed Collaboration. These features use the [LiveKit SDK](https://livekit.io) which relies upon [ScreenCaptureKit.framework](https://developer.apple.com/documentation/screencapturekit/) only available on macOS 12 (Monterey) and newer.

### Mac Hardware

Zed supports machines with Intel (x86_64) or Apple (aarch64) processors that meet the above macOS requirements:

- MacBook Pro (Early 2015 and newer)
- MacBook Air (Early 2015 and newer)
- MacBook (Early 2016 and newer)
- Mac Mini (Late 2014 and newer)
- Mac Pro (Late 2013 or newer)
- iMac (Late 2015 and newer)
- iMac Pro (all models)
- Mac Studio (all models)

## Linux

Zed supports 64bit Intel/AMD (x86_64) and 64Bit ARM (aarch64) processors.

Zed requires a Vulkan 1.3 driver, and the following desktop portals:

- `org.freedesktop.portal.FileChooser`
- `org.freedesktop.portal.OpenURI`
- `org.freedesktop.portal.Secret`, or `org.freedesktop.Secrets`

## Windows

Not yet available as an official download. Can be built [from source](./development/windows.md).

## FreeBSD

Not yet available as an official download. Can be built [from source](./development/freebsd.md).

## Web

Not supported at this time. See our [Platform Support issue](https://github.com/zed-industries/zed/issues/5391).

    # Tasks

Zed supports ways to spawn (and rerun) commands using its integrated terminal to output the results. These commands can read a limited subset of Zed state (such as a path to the file currently being edited or selected text).

```json
[
  {
    "label": "Example task",
    "command": "for i in {1..5}; do echo \"Hello $i/5\"; sleep 1; done",
    //"args": [],
    // Env overrides for the command, will be appended to the terminal's environment from the settings.
    "env": { "foo": "bar" },
    // Current working directory to spawn the command into, defaults to current project root.
    //"cwd": "/path/to/working/directory",
    // Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
    "use_new_terminal": false,
    // Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
    "allow_concurrent_runs": false,
    // What to do with the terminal pane and tab, after the command was started:
    // * `always` — always show the task's pane, and focus the corresponding tab in it (default)
    // * `no_focus` — always show the task's pane, add the task's tab in it, but don't focus it
    // * `never` — do not alter focus, but still add/reuse the task's tab in its pane
    "reveal": "always",
    // What to do with the terminal pane and tab, after the command has finished:
    // * `never` — Do nothing when the command finishes (default)
    // * `always` — always hide the terminal tab, hide the pane also if it was the last tab in it
    // * `on_success` — hide the terminal tab on task success only, otherwise behaves similar to `always`
    "hide": "never",
    // Which shell to use when running a task inside the terminal.
    // May take 3 values:
    // 1. (default) Use the system's default terminal configuration in /etc/passwd
    //      "shell": "system"
    // 2. A program:
    //      "shell": {
    //        "program": "sh"
    //      }
    // 3. A program with arguments:
    //     "shell": {
    //         "with_arguments": {
    //           "program": "/bin/bash",
    //           "args": ["--login"]
    //         }
    //     }
    "shell": "system",
    // Whether to show the task line in the output of the spawned task, defaults to `true`.
    "show_summary": true,
    // Whether to show the command line in the output of the spawned task, defaults to `true`.
    "show_command": true
    // Represents the tags for inline runnable indicators, or spawning multiple tasks at once.
    // "tags": []
  }
]
```

There are two actions that drive the workflow of using tasks: `task: spawn` and `task: rerun`.
`task: spawn` opens a modal with all available tasks in the current file.
`task: rerun` reruns the most recently spawned task. You can also rerun tasks from the task modal.

By default, rerunning tasks reuses the same terminal (due to the `"use_new_terminal": false` default) but waits for the previous task to finish before starting (due to the `"allow_concurrent_runs": false` default).

Keep `"use_new_terminal": false` and set `"allow_concurrent_runs": true` to allow cancelling previous tasks on rerun.

## Task templates

Tasks can be defined:

- in the global `tasks.json` file; such tasks are available in all Zed projects you work on. This file is usually located in `~/.config/zed/tasks.json`. You can edit them by using the `zed: open tasks` action.
- in the worktree-specific (local) `.zed/tasks.json` file; such tasks are available only when working on a project with that worktree included. You can edit worktree-specific tasks by using the `zed: open project tasks` action.
- on the fly with [oneshot tasks](#oneshot-tasks). These tasks are project-specific and do not persist across sessions.
- by language extension.

## Variables

Zed tasks act just like your shell; that also means that you can reference environmental variables via sh-esque `$VAR_NAME` syntax. A couple of additional environmental variables are set for your convenience.
These variables allow you to pull information from the current editor and use it in your tasks. The following variables are available:

- `ZED_COLUMN`: current line column
- `ZED_ROW`: current line row
- `ZED_FILE`: absolute path of the currently opened file (e.g. `/Users/my-user/path/to/project/src/main.rs`)
- `ZED_FILENAME`: filename of the currently opened file (e.g. `main.rs`)
- `ZED_DIRNAME`: absolute path of the currently opened file with file name stripped (e.g. `/Users/my-user/path/to/project/src`)
- `ZED_RELATIVE_FILE`: path of the currently opened file, relative to `ZED_WORKTREE_ROOT` (e.g. `src/main.rs`)
- `ZED_RELATIVE_DIR`: path of the currently opened file's directory, relative to `ZED_WORKTREE_ROOT` (e.g. `src`)
- `ZED_STEM`: stem (filename without extension) of the currently opened file (e.g. `main`)
- `ZED_SYMBOL`: currently selected symbol; should match the last symbol shown in a symbol breadcrumb (e.g. `mod tests > fn test_task_contexts`)
- `ZED_SELECTED_TEXT`: currently selected text
- `ZED_WORKTREE_ROOT`: absolute path to the root of the current worktree. (e.g. `/Users/my-user/path/to/project`)
- `ZED_CUSTOM_RUST_PACKAGE`: (Rust-specific) name of the parent package of $ZED_FILE source file.

To use a variable in a task, prefix it with a dollar sign (`$`):

```json
{
  "label": "echo current file's path",
  "command": "echo $ZED_FILE"
}
```

You can also use verbose syntax that allows specifying a default if a given variable is not available: `${ZED_FILE:default_value}`

These environmental variables can also be used in tasks' `cwd`, `args`, and `label` fields.

### Variable Quoting

When working with paths containing spaces or other special characters, please ensure variables are properly escaped.

For example, instead of this (which will fail if the path has a space):

```json
{
  "label": "stat current file",
  "command": "stat $ZED_FILE"
}
```

Provide the following:

```json
{
  "label": "stat current file",
  "command": "stat",
  "args": ["$ZED_FILE"]
}
```

Or explicitly include escaped quotes like so:

```json
{
  "label": "stat current file",
  "command": "stat \"$ZED_FILE\""
}
```

## Oneshot tasks

The same task modal opened via `task: spawn` supports arbitrary bash-like command execution: type a command inside the modal text field, and use `opt-enter` to spawn it.

The task modal persists these ad-hoc commands for the duration of the session, `task: rerun` will also rerun such tasks if they were the last ones spawned.

You can also adjust the currently selected task in a modal (`tab` is the default key binding). Doing so will put its command into a prompt that can then be edited & spawned as a oneshot task.

### Ephemeral tasks

You can use the `cmd` modifier when spawning a task via a modal; tasks spawned this way will not have their usage count increased (thus, they will not be respawned with `task: rerun` and they won't have a high rank in the task modal).
The intended use of ephemeral tasks is to stay in the flow with continuous `task: rerun` usage.

### More task rerun control

By default, tasks capture their variables into a context once, and this "resolved task" is being rerun always.

This can be controlled with the `"reevaluate_context"` argument to the task: setting it to `true` will force the task to be reevaluated before each run.

```json
{
  "context": "Workspace",
  "bindings": {
    "alt-t": ["task::Rerun", { "reevaluate_context": true }]
  }
}
```

## Custom keybindings for tasks

You can define your own keybindings for your tasks via an additional argument to `task::Spawn`. If you wanted to bind the aforementioned `echo current file's path` task to `alt-g`, you would add the following snippet in your [`keymap.json`](./key-bindings.md) file:

```json
{
  "context": "Workspace",
  "bindings": {
    "alt-g": ["task::Spawn", { "task_name": "echo current file's path" }]
  }
}
```

Note that these tasks can also have a 'target' specified to control where the spawned task should show up.
This could be useful for launching a terminal application that you want to use in the center area:

```json
// In tasks.json
{
  "label": "start lazygit",
  "command": "lazygit -p $ZED_WORKTREE_ROOT"
}
```

```json
// In keymap.json
{
  "context": "Workspace",
  "bindings": {
    "alt-g": [
      "task::Spawn",
      { "task_name": "start lazygit", "reveal_target": "center" }
    ]
  }
}
```

## Binding runnable tags to task templates

Zed supports overriding the default action for inline runnable indicators via workspace-local and global `tasks.json` file with the following precedence hierarchy:

1. Workspace `tasks.json`
2. Global `tasks.json`
3. Language-provided tag bindings (default).

To tag a task, add the runnable tag name to the `tags` field on the task template:

```json
{
  "label": "echo current file's path",
  "command": "echo $ZED_FILE",
  "tags": ["rust-test"]
}
```

In doing so, you can change which task is shown in the runnables indicator.

## Keybindings to run tasks bound to runnables

When you have a task definition that is bound to the runnable, you can quickly run it using [Code Actions](https://zed.dev/docs/configuring-languages?#code-actions) that you can trigger either via `editor: Toggle Code Actions` command or by the `cmd-.`/`ctrl-.` shortcut. Your task will be the first in the dropdown. The task will run immediately if there are no additional Code Actions for this line.

    # Telemetry in Zed

Zed collects anonymous telemetry data to help the team understand how people are using the application and to see what sort of issues they are experiencing.

## Configuring Telemetry Settings

You have full control over what data is sent out by Zed.
To enable or disable some or all telemetry types, open your `settings.json` file via {#action zed::OpenSettings}({#kb zed::OpenSettings}) from the command palette.

Insert and tweak the following:

```json
"telemetry": {
    "diagnostics": false,
    "metrics": false
},
```

## Dataflow

Telemetry is sent from the application to our servers. Data is proxied through our servers to enable us to easily switch analytics services. We currently use:

- [Sentry](https://sentry.io): Crash-monitoring service - stores diagnostic events
- [Snowflake](https://snowflake.com): Data warehouse - stores both diagnostic and metric events
- [Hex](https://www.hex.tech): Dashboards and data exploration - accesses data stored in Snowflake
- [Amplitude](https://www.amplitude.com): Dashboards and data exploration - accesses data stored in Snowflake

## Types of Telemetry

### Diagnostics

Crash reports consist of a [minidump](https://learn.microsoft.com/en-us/windows/win32/debug/minidump-files) and some extra debug information. Reports are sent on the first application launch after the crash occurred. We've built dashboards that allow us to visualize the frequency and severity of issues experienced by users. Having these reports sent automatically allows us to begin implementing fixes without the user needing to file a report in our issue tracker. The plots in the dashboards also give us an informal measurement of the stability of Zed.

You can see what extra data is sent alongside the minidump in the `Panic` struct in [crates/telemetry_events/src/telemetry_events.rs](https://github.com/zed-industries/zed/blob/main/crates/telemetry_events/src/telemetry_events.rs) in the Zed repo. You can find additional information in the [Debugging Crashes](./development/debugging-crashes.md) documentation.

### Client-Side Usage Data {#client-metrics}

To improve Zed and understand how it is being used in the wild, Zed optionally collects usage data like the following:

- (a) file extensions of opened files;
- (b) features and tools You use within the Editor;
- (c) project statistics (e.g., number of files); and
- (d) frameworks detected in Your projects

Usage Data does not include any of Your software code or sensitive project details. Metric events are reported over HTTPS, and requests are rate-limited to avoid using significant network bandwidth.

Usage Data is associated with a secure random telemetry ID which may be linked to Your email address. This linkage currently serves two purposes: (1) it allows Zed to analyze usage patterns over time while maintaining Your privacy; and (2) it enables Zed to reach out to specific user groups for feedback and improvement suggestions.

You can audit the metrics data that Zed has reported by running the command {#action zed::OpenTelemetryLog} from the command palette, or clicking `Help > View Telemetry Log` in the application menu.

You can see the full list of the event types and exactly the data sent for each by inspecting the `Event` enum and the associated structs in [crates/telemetry_events/src/telemetry_events.rs](https://github.com/zed-industries/zed/blob/main/crates/telemetry_events/src/telemetry_events.rs) in the Zed repository.

### Server-Side Usage Data {#metrics}

When using Zed's hosted services, we may collect, generate, and Process data to allow us to support users and improve our hosted offering. Examples include metadata around rate limiting and billing metrics/token usage. Zed does not persistently store user content or use user content to evaluate and/or improve our AI features, unless it is explicitly shared with Zed, and we have a zero-data retention agreement with Anthropic.

You can see more about our stance on data collection (and that any prompt data shared with Zed is explicitly opt-in) at [AI Improvement](./ai/ai-improvement.md).

## Concerns and Questions

If you have concerns about telemetry, please feel free to [open an issue](https://github.com/zed-industries/zed/issues/new/choose).

    # Themes

Zed comes with a number of built-in themes, with more themes available as extensions.

## Selecting a Theme

See what themes are installed and preview them via the Theme Selector, which you can open from the command palette with "theme selector: Toggle" (bound to `cmd-k cmd-t` on macOS and `ctrl-k ctrl-t` on Linux).

Navigating through the theme list by moving up and down will change the theme in real time and hitting enter will save it to your settings file.

## Installing more Themes

More themes are available from the Extensions page, which you can access via the command palette with "zed: Extensions" or the [Zed website](https://zed.dev/extensions).

Many popular themes have been ported to Zed, and if you're struggling to choose one, visit [zed-themes.com](https://zed-themes.com), a third-party gallery with visible previews for many of them.

## Configuring a Theme

Your selected theme is stored in your settings file. You can open your settings file from the command palette with "zed: Open Settings" (bound to `cmd-,` on macOS and `ctrl-,` on Linux).

By default, Zed maintains two themes: one for light mode and one for dark mode. You can set the mode to `"dark"` or `"light"` to ignore the current system mode.

```json
{
  "theme": {
    "mode": "system",
    "light": "One Light",
    "dark": "One Dark"
  }
}
```

## Theme Overrides

To override specific attributes of a theme, use the `experimental.theme_overrides` setting.

For example, add the following to your `settings.json` if you wish to override the background color of the editor and display comments and doc comments as italics:

```json
{
  "experimental.theme_overrides": {
    "editor.background": "#333",
    "syntax": {
      "comment": {
        "font_style": "italic"
      },
      "comment.doc": {
        "font_style": "italic"
      }
    }
  }
}
```

To see a comprehensive list of list of captures (like `comment` and `comment.doc`) see: [Language Extensions: Syntax highlighting](./extensions/languages.md#syntax-highlighting).

To see a list of available theme attributes look at the JSON file for your theme. For example, [assets/themes/one/one.json](https://github.com/zed-industries/zed/blob/main/assets/themes/one/one.json) for the default One Dark and One Light themes.

## Local Themes

Store new themes locally by placing them in the `~/.config/zed/themes` directory.

For example, to create a new theme called `my-cool-theme`, create a file called `my-cool-theme.json` in that directory. It will be available in the theme selector the next time Zed loads.

Find more themes at [zed-themes.com](https://zed-themes.com).

## Theme Development

See: [Developing Zed Themes](./extensions/themes.md)

    # Toolchains

Zed projects offer a dedicated UI for toolchain selection, which lets you pick a set of tools for working with a given language in a current project.

Imagine you're working with Python project, which has virtual environments that encapsulate a set of dependencies of your project along with a suitable interpreter to run it with. The language server has to know which virtual environment you're working with, as it uses it to understand your project's code.
With toolchain selector, you don't need to spend time configuring your language server to point it at the right virtual environment directory—you can just select the right virtual environment (toolchain) from a dropdown.

You can even select different toolchains for different subprojects within your Zed project. A definition of a subproject is language-specific.
In collaborative scenarios, only the project owner can see and modify an active toolchain.

In [remote projects](./remote-development.md), you can use the toolchain selector to control the active toolchain on the SSH host. When [sharing your project](./collaboration.md), the toolchain selector is not available to guests.

## Why do we need toolchains?

The active toolchain is relevant for launching language servers, which may need it to function properly—it may not be able to resolve dependencies, which in turn may make functionalities like "Go to definition" or "Code completions" unavailable.

The active toolchain is also relevant when launching a shell in the terminal panel: some toolchains provide "activation scripts" for shells, which make those toolchains available in the shell environment for your convenience. Zed will run these activation scripts automatically when you create a new terminal.

This also applies to [tasks](./tasks.md)—Zed tasks behave "as if" you opened a new terminal tab and ran a given task invocation yourself, which in turn means that Zed task execution is affected by the active toolchain and its activation script.

## Selecting toolchains

The active toolchain (if there is one) is displayed in the status bar (on the right hand side). Click on it to access the toolchain selector—you can also use an action from a command palette ({#action toolchain::Select}).

Zed will automatically infer a set of toolchains to choose from based on the project you're working with. A default will also be selected on your behalf on a best-effort basis when you open a project for the first time.

The toolchain selection applies to a current subproject, which—depending on the structure of your Zed project—might be your whole project or just a subset of it. For example, if you have a monorepo with multiple subprojects, you might want to select a different toolchain for each subproject.

## Adding toolchains manually

If automatic detection does not suffice for you, you can add toolchains manually. To do that, click on the "Add toolchain" button in the toolchain selector. From there you can provide a path to a toolchain and set a name of your liking for it.

    # Vim Mode

Zed includes a Vim emulation layer known as "vim mode". On this page, you will learn how to turn Zed's vim mode on or off, what tools and commands Zed provides to help you navigate and edit your code, and generally how to make the most of vim mode in Zed.

You'll learn how to:

- Understand the core differences between Zed's vim mode and traditional Vim
- Enable or disable vim mode
- Make the most of Zed-specific features within vim mode
- Customize vim mode key bindings
- Configure vim mode settings

Whether you're new to vim mode or an experienced Vim user looking to optimize your Zed experience, this guide will help you harness the full power of modal editing in Zed.

## Zed's vim mode design

Vim mode tries to offer a familiar experience to Vim users: it replicates the behavior of motions and commands precisely when it makes sense and uses Zed-specific functionality to provide an editing experience that "just works" without requiring configuration on your part.

This includes support for semantic navigation, multiple cursors, or other features usually provided by plugins like surrounding text.

So, Zed's vim mode does not replicate Vim one-to-one, but it meshes Vim's modal design with Zed's modern features to provide a more fluid experience. It's also configurable, so you can add your own key bindings or override the defaults.

### Core differences

There are four types of features in vim mode that use Zed's core functionality, leading to some differences in behavior:

1. **Motions**: vim mode uses Zed's semantic parsing to tune the behavior of motions per language. For example, in Rust, jumping to matching bracket with `%` works with the pipe character `|`. In JavaScript, `w` considers `$` to be a word character.
2. **Visual block selections**: vim mode uses Zed's multiple cursor to emulate visual block selections, making block selections a lot more flexible. For example, anything you insert after a block selection updates on every line in real-time, and you can add or remove cursors anytime.
3. **Macros**: vim mode uses Zed's recording system for vim macros. So, you can capture and replay more complex actions, like autocompletion.
4. **Search and replace**: vim mode uses Zed's search system, so, the syntax for regular expressions is slightly different compared to Vim. [Head to the Regex differences section](#regex-differences) for details.

> **Note:** The foundations of Zed's vim mode should already cover many use cases, and we're always looking to improve it. If you find missing features that you rely on in your workflow, please [file an issue on GitHub](https://github.com/zed-industries/zed/issues).

## Enabling and disabling vim mode

When you first open Zed, you'll see a checkbox on the welcome screen that allows you to enable vim mode.

If you missed this, you can toggle vim mode on or off anytime by opening the command palette and using the workspace command `toggle vim mode`.

> **Note**: This command toggles the following property in your user settings:
>
> ```json
> {
>   "vim_mode": true
> }
> ```

## Zed-specific features

Zed is built on a modern foundation that (among other things) uses tree-sitter and language servers to understand the content of the file you're editing and supports multiple cursors out of the box.

Vim mode has several "core Zed" key bindings that will help you make the most of Zed's specific feature set.

### Language server

The following commands use the language server to help you navigate and refactor your code.

| Command                                  | Default Shortcut |
| ---------------------------------------- | ---------------- |
| Go to definition                         | `g d`            |
| Go to declaration                        | `g D`            |
| Go to type definition                    | `g y`            |
| Go to implementation                     | `g I`            |
| Rename (change definition)               | `c d`            |
| Go to All references to the current word | `g A`            |
| Find symbol in current file              | `g s`            |
| Find symbol in entire project            | `g S`            |
| Go to next diagnostic                    | `g ]` or `] d`   |
| Go to previous diagnostic                | `g [` or `[ d`   |
| Show inline error (hover)                | `g h`            |
| Open the code actions menu               | `g .`            |

### Git

| Command                         | Default Shortcut |
| ------------------------------- | ---------------- |
| Go to next git change           | `] c`            |
| Go to previous git change       | `[ c`            |
| Expand diff hunk                | `d o`            |
| Toggle staged                   | `d O`            |
| Stage and next (in diff view)   | `d u`            |
| Unstage and next (in diff view) | `d U`            |
| Restore change                  | `d p`            |

### Treesitter

Treesitter is a powerful tool that Zed uses to understand the structure of your code. Zed provides motions that change the current cursor position, and text objects that can be used as the target of actions.

| Command                         | Default Shortcut            |
| ------------------------------- | --------------------------- |
| Go to next/previous method      | `] m` / `[ m`               |
| Go to next/previous method end  | `] M` / `[ M`               |
| Go to next/previous section     | `] ]` / `[ [`               |
| Go to next/previous section end | `] [` / `[ ]`               |
| Go to next/previous comment     | `] /`, `] *` / `[ /`, `[ *` |
| Select a larger syntax node     | `[ x`                       |
| Select a smaller syntax node    | `] x`                       |

| Text Objects                                               | Default Shortcut |
| ---------------------------------------------------------- | ---------------- |
| Around a class, definition, etc.                           | `a c`            |
| Inside a class, definition, etc.                           | `i c`            |
| Around a function, method etc.                             | `a f`            |
| Inside a function, method, etc.                            | `i f`            |
| A comment                                                  | `g c`            |
| An argument, or list item, etc.                            | `i a`            |
| An argument, or list item, etc. (including trailing comma) | `a a`            |
| Around an HTML-like tag                                    | `a t`            |
| Inside an HTML-like tag                                    | `i t`            |
| The current indent level, and one line before and after    | `a I`            |
| The current indent level, and one line before              | `a i`            |
| The current indent level                                   | `i i`            |

Note that the definitions for the targets of the `[m` family of motions are the same as the
boundaries defined by `af`. The targets of the `[[` are the same as those defined by `ac`, though
if there are no classes, then functions are also used. Similarly `gc` is used to find `[ /`. `g c`

The definition of functions, classes and comments is language dependent, and support can be added
to extensions by adding a [`textobjects.scm`]. The definition of arguments and tags operates at
the tree-sitter level, but looks for certain patterns in the parse tree and is not currently configurable
per language.

### Multi cursor

These commands help you manage multiple cursors in Zed.

| Command                                                      | Default Shortcut |
| ------------------------------------------------------------ | ---------------- |
| Add a cursor selecting the next copy of the current word     | `g l`            |
| Add a cursor selecting the previous copy of the current word | `g L`            |
| Skip latest word selection, and add next                     | `g >`            |
| Skip latest word selection, and add previous                 | `g <`            |
| Add a visual selection for every copy of the current word    | `g a`            |

### Pane management

These commands open new panes or jump to specific panes.

| Command                                    | Default Shortcut   |
| ------------------------------------------ | ------------------ |
| Open a project-wide search                 | `g /`              |
| Open the current search excerpt            | `g <space>`        |
| Open the current search excerpt in a split | `<ctrl-w> <space>` |
| Go to definition in a split                | `<ctrl-w> g d`     |
| Go to type definition in a split           | `<ctrl-w> g D`     |

### In insert mode

The following commands help you bring up Zed's completion menu, request a suggestion from GitHub Copilot, or open the inline AI assistant without leaving insert mode.

| Command                                                                      | Default Shortcut |
| ---------------------------------------------------------------------------- | ---------------- |
| Open the completion menu                                                     | `ctrl-x ctrl-o`  |
| Request GitHub Copilot suggestion (requires GitHub Copilot to be configured) | `ctrl-x ctrl-c`  |
| Open the inline AI assistant (requires a configured assistant)               | `ctrl-x ctrl-a`  |
| Open the code actions menu                                                   | `ctrl-x ctrl-l`  |
| Hides all suggestions                                                        | `ctrl-x ctrl-z`  |

### Supported plugins

Zed's vim mode includes some features that are usually provided by very popular plugins in the Vim ecosystem:

- You can surround text objects with `ys` (yank surround), change surrounding with `cs`, and delete surrounding with `ds`.
- You can comment and uncomment selections with `gc` in visual mode and `gcc` in normal mode.
- The project panel supports many shortcuts modeled after the Vim plugin `netrw`: navigation with `hjkl`, open file with `o`, open file in a new tab with `t`, etc.
- You can add key bindings to your keymap to navigate "camelCase" names. [Head down to the Optional key bindings](#optional-key-bindings) section to learn how.
- You can use `gR` to do [ReplaceWithRegister](https://github.com/vim-scripts/ReplaceWithRegister).
- You can use `cx` for [vim-exchange](https://github.com/tommcdo/vim-exchange) functionality. Note that it does not have a default binding in visual mode, but you can add one to your keymap (refer to the [optional key bindings](#optional-key-bindings) section).
- You can navigate to indent depths relative to your cursor with the [indent wise](https://github.com/jeetsukumaran/vim-indentwise) plugin `[-`, `]-`, `[+`, `]+`, `[=`, `]=`.
- You can select quoted text with AnyQuotes and bracketed text with AnyBrackets text objects. Zed also provides MiniQuotes and MiniBrackets which offer alternative selection behavior based on the [mini.ai](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-ai.md) Neovim plugin. See the [Quote and Bracket text objects](#quote-and-bracket-text-objects) section below for details.
- You can configure AnyQuotes, AnyBrackets, MiniQuotes, and MiniBrackets text objects for selecting quoted and bracketed text using different selection strategies. See the [Any Bracket Functionality](#any-bracket-functionality) section below for details.

### Any Bracket Functionality

Zed offers two different strategies for selecting text surrounded by any quote, or any bracket. These text objects are **not enabled by default** and must be configured in your keymap to be used.

#### Included Characters

Each text object type works with specific characters:

| Text Object              | Characters                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------- |
| AnyQuotes/MiniQuotes     | Single quote (`'`), Double quote (`"`), Backtick (`` ` ``)                             |
| AnyBrackets/MiniBrackets | Parentheses (`()`), Square brackets (`[]`), Curly braces (`{}`), Angle brackets (`<>`) |

Both "Any" and "Mini" variants work with the same character sets, but differ in their selection strategy.

#### AnyQuotes and AnyBrackets (Traditional Vim behavior)

These text objects implement traditional Vim behavior:

- **Selection priority**: Finds the innermost (closest) quotes or brackets first
- **Fallback mechanism**: If none are found, falls back to the current line
- **Character-based matching**: Focuses solely on open and close characters without considering syntax
- **Vanilla Vim similarity**: AnyBrackets matches the behavior of commands like `ci<`, `ci(`, etc., in vanilla Vim, including potential edge cases (like considering `>` in `=>` as a closing delimiter)

#### MiniQuotes and MiniBrackets (mini.ai behavior)

These text objects implement the behavior of the [mini.ai](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-ai.md) Neovim plugin:

- **Selection priority**: Searches the current line first before expanding outward
- **Tree-sitter integration**: Uses Tree-sitter queries for more context-aware selections
- **Syntax-aware matching**: Can distinguish between actual brackets and similar characters in other contexts (like `>` in `=>`)

#### Choosing Between Approaches

- Use **AnyQuotes/AnyBrackets** if you:

  - Prefer traditional Vim behavior
  - Want consistent character-based selection prioritizing innermost delimiters
  - Need behavior that closely matches vanilla Vim's text objects

- Use **MiniQuotes/MiniBrackets** if you:
  - Prefer the mini.ai plugin behavior
  - Want more context-aware selections using Tree-sitter
  - Prefer current-line priority when searching

#### Example Configuration

To use these text objects, you need to add bindings to your keymap. Here's an example configuration that makes them available when using text object operators (`i` and `a`) or change-surrounds (`cs`):

```json
{
  "context": "vim_operator == a || vim_operator == i || vim_operator == cs",
  "bindings": {
    // Traditional Vim behavior
    "q": "vim::AnyQuotes",
    "b": "vim::AnyBrackets",

    // mini.ai plugin behavior
    "Q": "vim::MiniQuotes",
    "B": "vim::MiniBrackets"
  }
}
```

With this configuration, you can use commands like:

- `cib` - Change inside brackets using AnyBrackets behavior
- `cim` - Change inside brackets using MiniBrackets behavior
- `ciq` - Change inside quotes using AnyQuotes behavior
- `ciM` - Change inside quotes using MiniQuotes behavior

## Command palette

Vim mode allows you to open Zed's command palette with `:`. You can then type to access any usual Zed command. Additionally, vim mode adds aliases for popular Vim commands to ensure your muscle memory transfers to Zed. For example, you can write `:w` or `:write` to save the file.

Below, you'll find tables listing the commands you can use in the command palette. We put optional characters in square brackets to indicate that you can omit them.

> **Note**: We don't emulate the full power of Vim's command line yet. In particular, commands currently do not support arguments. Please [file issues on GitHub](https://github.com/zed-industries/zed) as you find things that are missing from the command palette.

### File and window management

This table shows commands for managing windows, tabs, and panes. As commands don't support arguments currently, you cannot specify a filename when saving or creating a new file.

| Command        | Description                                          |
| -------------- | ---------------------------------------------------- |
| `:w[rite][!]`  | Save the current file                                |
| `:wq[!]`       | Save the file and close the buffer                   |
| `:q[uit][!]`   | Close the buffer                                     |
| `:wa[ll][!]`   | Save all open files                                  |
| `:wqa[ll][!]`  | Save all open files and close all buffers            |
| `:qa[ll][!]`   | Close all buffers                                    |
| `:[e]x[it][!]` | Close the buffer                                     |
| `:up[date]`    | Save the current file                                |
| `:cq`          | Quit completely (close all running instances of Zed) |
| `:vs[plit]`    | Split the pane vertically                            |
| `:sp[lit]`     | Split the pane horizontally                          |
| `:new`         | Create a new file in a horizontal split              |
| `:vne[w]`      | Create a new file in a vertical split                |
| `:tabedit`     | Create a new file in a new tab                       |
| `:tabnew`      | Create a new file in a new tab                       |
| `:tabn[ext]`   | Go to the next tab                                   |
| `:tabp[rev]`   | Go to previous tab                                   |
| `:tabc[lose]`  | Close the current tab                                |
| `:ls`          | Show all buffers                                     |

> **Note:** The `!` character is used to force the command to execute without saving changes or prompting before overwriting a file.

### Ex commands

These ex commands open Zed's various panels and windows.

| Command                      | Default Shortcut |
| ---------------------------- | ---------------- |
| Open the project panel       | `:E[xplore]`     |
| Open the collaboration panel | `:C[ollab]`      |
| Open the chat panel          | `:Ch[at]`        |
| Open the AI panel            | `:A[I]`          |
| Open the git panel           | `:G[it]`         |
| Open the debug panel         | `:D[ebug]`       |
| Open the notifications panel | `:No[tif]`       |
| Open the feedback window     | `:fe[edback]`    |
| Open the diagnostics window  | `:cl[ist]`       |
| Open the terminal            | `:te[rm]`        |
| Open the extensions window   | `:Ext[ensions]`  |

### Navigating diagnostics

These commands navigate diagnostics.

| Command                  | Description                    |
| ------------------------ | ------------------------------ |
| `:cn[ext]` or `:ln[ext]` | Go to the next diagnostic      |
| `:cp[rev]` or `:lp[rev]` | Go to the previous diagnostics |
| `:cc` or `:ll`           | Open the errors page           |

### Git

These commands interact with the version control system git.

| Command         | Description                                             |
| --------------- | ------------------------------------------------------- |
| `:dif[fupdate]` | View the diff under the cursor (`d o` in normal mode)   |
| `:rev[ert]`     | Revert the diff under the cursor (`d p` in normal mode) |

### Jump

These commands jump to specific positions in the file.

| Command             | Description                         |
| ------------------- | ----------------------------------- |
| `:<number>`         | Jump to a line number               |
| `:$`                | Jump to the end of the file         |
| `:/foo` and `:?foo` | Jump to next/prev line matching foo |

### Replacement

This command replaces text. It emulates the substitute command in vim. The substitute command uses regular expressions, and Zed uses a slightly different syntax than vim. You can learn more about Zed's syntax below, [in the regex differences section](#regex-differences). Zed will replace only the first occurrence of the search pattern in the current line. To replace all matches append the `g` flag.

| Command                 | Description                       |
| ----------------------- | --------------------------------- |
| `:[range]s/foo/bar/[g]` | Replace instances of foo with bar |

### Editing

These commands help you edit text.

| Command           | Description                                             |
| ----------------- | ------------------------------------------------------- |
| `:j[oin]`         | Join the current line                                   |
| `:d[elete][l][p]` | Delete the current line                                 |
| `:s[ort] [i]`     | Sort the current selection (with i, case-insensitively) |
| `:y[ank]`         | Yank (copy) the current selection or line               |

### Set

These commands modify editor options locally for the current buffer.

| Command                         | Description                                                                                   |
| ------------------------------- | --------------------------------------------------------------------------------------------- |
| `:se[t] [no]wrap`               | Lines longer than the width of the window will wrap and displaying continues on the next line |
| `:se[t] [no]nu[mber]`           | Print the line number in front of each line                                                   |
| `:se[t] [no]r[elative]nu[mber]` | Changes the displayed number to be relative to the cursor                                     |

### Command mnemonics

As any Zed command is available, you may find that it's helpful to remember mnemonics that run the correct command. For example:

- `:diffs` for "toggle all hunk diffs"
- `:cpp` for "copy path to file"
- `:crp` for "copy relative path"
- `:reveal` for "reveal in finder"
- `:zlog` for "open zed log"
- `:clank` for "cancel language server work"

## Customizing key bindings

In this section, we'll learn how to customize the key bindings of Zed's vim mode. You'll learn:

- How to select the correct context for your new key bindings.
- Useful contexts for vim mode key bindings.
- Common key bindings to customize for extra productivity.

### Selecting the correct context

Zed's key bindings are evaluated only when the `"context"` property matches your location in the editor. For example, if you add key bindings to the `"Editor"` context, they will only work when you're editing a file. If you add key bindings to the `"Workspace"` context, they will work everywhere in Zed. Here's an example of a key binding that saves when you're editing a file:

```json
{
  "context": "Editor",
  "bindings": {
    "ctrl-s": "file::Save"
  }
}
```

Contexts are nested, so when you're editing a file, the context is the `"Editor"` context, which is inside the `"Pane"` context, which is inside the `"Workspace"` context. That's why any key bindings you add to the `"Workspace"` context will work when you're editing a file. Here's an example:

```json
// This key binding will work when you're editing a file. It comes built into Zed by default as the workspace: save command.
{
  "context": "Workspace",
  "bindings": {
    "ctrl-s": "file::Save"
  }
}
```

Contexts are expressions. They support boolean operators like `&&` (and) and `||` (or). For example, you can use the context `"Editor && vim_mode == normal"` to create key bindings that only work when you're editing a file _and_ you're in vim's normal mode.

Vim mode adds several contexts to the `"Editor"` context:

| Operator             | Description                                                                                                                                                                        |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| VimControl           | Indicates that vim keybindings should work. Currently an alias for `vim_mode == normal \|\| vim_mode == visual \|\| vim_mode == operator`, but the definition may change over time |
| vim_mode == normal   | Normal mode                                                                                                                                                                        |
| vim_mode == visual   | Visual mode                                                                                                                                                                        |
| vim_mode == insert   | Insert mode                                                                                                                                                                        |
| vim_mode == replace  | Replace mode                                                                                                                                                                       |
| vim_mode == waiting  | Waiting for an arbitrary key (e.g., after typing `f` or `t`)                                                                                                                       |
| vim_mode == operator | Waiting for another binding to trigger (e.g., after typing `c` or `d`)                                                                                                             |
| vim_operator         | Set to `none` unless `vim_mode == operator`, in which case it is set to the current operator's default keybinding (e.g., after typing `d`, `vim_operator == d`)                    |

> **Note**: Contexts are matched only on one level at a time. So it is possible to use the expression `"Editor && vim_mode == normal"`, but `"Workspace && vim_mode == normal"` will never match because we set the vim context at the `"Editor"` level.

### Useful contexts for vim mode key bindings

Here's a template with useful vim mode contexts to help you customize your vim mode key bindings. You can copy it and integrate it into your user keymap.

```json
[
  {
    "context": "VimControl && !menu",
    "bindings": {
      // Put key bindings here if you want them to work in normal & visual mode.
    }
  },
  {
    "context": "vim_mode == normal && !menu",
    "bindings": {
      // "shift-y": ["workspace::SendKeystrokes", "y $"] // Use neovim's yank behavior: yank to end of line.
    }
  },
  {
    "context": "vim_mode == insert",
    "bindings": {
      // "j k": "vim::NormalBefore" // In insert mode, make jk escape to normal mode.
    }
  },
  {
    "context": "EmptyPane || SharedScreen",
    "bindings": {
      // Put key bindings here (in addition to the context above) if you want them to
      // work when no editor exists.
      // "space f": "file_finder::Toggle"
    }
  }
]
```

> **Note**: If you would like to emulate Vim's `map` commands (`nmap`, etc.), you can use the action `workspace::SendKeystrokes` in the correct context.

### Optional key bindings

By default, you can navigate between the different files open in the editor with shortcuts like `ctrl+w` followed by one of `hjkl` to move to the left, down, up, or right, respectively.

But you cannot use the same shortcuts to move between all the editor docks (the terminal, project panel, assistant panel, ...). If you want to use the same shortcuts to navigate to the docks, you can add the following key bindings to your user keymap.

```json
{
  "context": "Dock",
  "bindings": {
    "ctrl-w h": "workspace::ActivatePaneLeft",
    "ctrl-w l": "workspace::ActivatePaneRight",
    "ctrl-w k": "workspace::ActivatePaneUp",
    "ctrl-w j": "workspace::ActivatePaneDown"
    // ... or other keybindings
  }
}
```

Subword motion, which allows you to navigate and select individual words in camelCase or snake_case, is not enabled by default. To enable it, add these bindings to your keymap.

```json
{
  "context": "VimControl && !menu && vim_mode != operator",
  "bindings": {
    "w": "vim::NextSubwordStart",
    "b": "vim::PreviousSubwordStart",
    "e": "vim::NextSubwordEnd",
    "g e": "vim::PreviousSubwordEnd"
  }
}
```

Vim mode comes with shortcuts to surround the selection in normal mode (`ys`), but it doesn't have a shortcut to add surrounds in visual mode. By default, `shift-s` substitutes the selection (erases the text and enters insert mode). To use `shift-s` to add surrounds in visual mode, you can add the following object to your keymap.

```json
{
  "context": "vim_mode == visual",
  "bindings": {
    "shift-s": "vim::PushAddSurrounds"
  }
}
```

In non-modal text editors, cursor navigation typically wraps when moving past line ends. Zed, however, handles this behavior exactly like Vim by default: the cursor stops at line boundaries. If you prefer your cursor to wrap between lines, override these keybindings:

```json
// In VimScript, this would look like this:
// set whichwrap+=<,>,[,],h,l
{
  "context": "VimControl && !menu",
  "bindings": {
    "left": "vim::WrappingLeft",
    "right": "vim::WrappingRight",
    "h": "vim::WrappingLeft",
    "l": "vim::WrappingRight"
  }
}
```

The [Sneak motion](https://github.com/justinmk/vim-sneak) feature allows for quick navigation to any two-character sequence in your text. You can enable it by adding the following keybindings to your keymap. By default, the `s` key is mapped to `vim::Substitute`. Adding these bindings will override that behavior, so ensure this change aligns with your workflow preferences.

```json
{
  "context": "vim_mode == normal || vim_mode == visual",
  "bindings": {
    "s": "vim::PushSneak",
    "shift-s": "vim::PushSneakBackward"
  }
}
```

The [vim-exchange](https://github.com/tommcdo/vim-exchange) feature does not have a default binding for visual mode, as the `shift-x` binding conflicts with the default `shift-x` binding for visual mode (`vim::VisualDeleteLine`). To assign the default vim-exchange binding, add the following keybinding to your keymap:

```json
{
  "context": "vim_mode == visual",
  "bindings": {
    "shift-x": "vim::Exchange"
  }
}
```

### Restoring common text editing keybindings

If you're using vim mode on Linux or Windows, you may find it overrides keybindings you can't live without: `ctrl+v` to paste, `ctrl+f` to search, etc. You can restore them by copying this data into your keymap:

```json
{
  "context": "Editor && !menu",
  "bindings": {
    "ctrl-c": "editor::Copy",          // vim default: return to normal mode
    "ctrl-x": "editor::Cut",           // vim default: decrement
    "ctrl-v": "editor::Paste",         // vim default: visual block mode
    "ctrl-y": "editor::Undo",          // vim default: line up
    "ctrl-f": "buffer_search::Deploy", // vim default: page down
    "ctrl-o": "workspace::Open",       // vim default: go back
    "ctrl-s": "workspace::Save",       // vim default: show signature
    "ctrl-a": "editor::SelectAll",     // vim default: increment
  }
},
```

## Changing vim mode settings

You can change the following settings to modify vim mode's behavior:

| Property                     | Description                                                                                                                                                                                   | Default Value |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| default_mode                 | The default mode to start in. One of "normal", "insert", "replace", "visual", "visual_line", "visual_block", "helix_normal".                                                                  | "normal"      |
| use_system_clipboard         | Determines how system clipboard is used:<br><ul><li>"always": use for all operations</li><li>"never": only use when explicitly specified</li><li>"on_yank": use for yank operations</li></ul> | "always"      |
| use_multiline_find           | deprecated                                                                                                                                                                                    |
| use_smartcase_find           | If `true`, `f` and `t` motions are case-insensitive when the target letter is lowercase.                                                                                                      | false         |
| toggle_relative_line_numbers | If `true`, line numbers are relative in normal mode and absolute in insert mode, giving you the best of both options.                                                                         | false         |
| custom_digraphs              | An object that allows you to add custom digraphs. Read below for an example.                                                                                                                  | {}            |
| highlight_on_yank_duration   | The duration of the highlight animation(in ms). Set to `0` to disable                                                                                                                         | 200           |

Here's an example of adding a digraph for the zombie emoji. This allows you to type `ctrl-k f z` to insert a zombie emoji. You can add as many digraphs as you like.

```json
{
  "vim": {
    "custom_digraphs": {
      "fz": "🧟‍♀️"
    }
  }
}
```

Here's an example of these settings changed:

```json
{
  "vim": {
    "default_mode": "insert",
    "use_system_clipboard": "never",
    "use_smartcase_find": true,
    "toggle_relative_line_numbers": true,
    "highlight_on_yank_duration": 50,
    "custom_digraphs": {
      "fz": "🧟‍♀️"
    }
  }
}
```

## Useful core Zed settings for vim mode

Here are a few general Zed settings that can help you fine-tune your Vim experience:

| Property                | Description                                                                                                                                                   | Default Value        |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| cursor_blink            | If `true`, the cursor blinks.                                                                                                                                 | `true`               |
| relative_line_numbers   | If `true`, line numbers in the left gutter are relative to the cursor.                                                                                        | `false`              |
| scrollbar               | Object that controls the scrollbar display. Set to `{ "show": "never" }` to hide the scroll bar.                                                              | `{ "show": "auto" }` |
| scroll_beyond_last_line | If set to `"one_page"`, allows scrolling up to one page beyond the last line. Set to `"off"` to prevent this behavior.                                        | `"one_page"`         |
| vertical_scroll_margin  | The number of lines to keep above or below the cursor when scrolling. Set to `0` to allow the cursor to go up to the edges of the screen vertically.          | `3`                  |
| gutter.line_numbers     | Controls the display of line numbers in the gutter. Set the `"line_numbers"` property to `false` to hide line numbers.                                        | `true`               |
| command_aliases         | Object that defines aliases for commands in the command palette. You can use it to define shortcut names for commands you use often. Read below for examples. | `{}`                 |

Here's an example of these settings changed:

```json
{
  // Disable cursor blink
  "cursor_blink": false,
  // Use relative line numbers
  "relative_line_numbers": true,
  // Hide the scroll bar
  "scrollbar": { "show": "never" },
  // Prevent the buffer from scrolling beyond the last line
  "scroll_beyond_last_line": "off",
  // Allow the cursor to reach the edges of the screen
  "vertical_scroll_margin": 0,
  "gutter": {
    // Disable line numbers completely:
    "line_numbers": false
  },
  "command_aliases": {
    "W": "w",
    "Wq": "wq",
    "Q": "q"
  }
}
```

The `command_aliases` property is a single object that maps keys or key sequences to vim mode commands. The example above defines multiple aliases: `W` for `w`, `Wq` for `wq`, and `Q` for `q`.

## Regex differences

Zed uses a different regular expression engine from Vim. This means that you will have to use a different syntax in some cases. Here are the most common differences:

- **Capture groups**: Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`. On the flip side, in Vim, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`.
- **Matches**: When replacing, Vim uses the backslash character followed by a number to represent a matched capture group. For example, `\1`. Zed uses the dollar sign instead. So, when in Vim you use `\0` to represent the entire match, in Zed the syntax is `$0` instead. Same for numbered capture groups: `\1` in Vim is `$1` in Zed.
- **Global option**: By default, in Vim, regex searches only match the first occurrence on a line, and you append `/g` at the end of your query to find all matches. In Zed, regex searches are global by default.
- **Case sensitivity**: Vim uses `/i` to indicate a case-insensitive search. In Zed you can either write `(?i)` at the start of the pattern or toggle case-sensitivity with the shortcut {#kb search::ToggleCaseSensitive}.

> **Note**: To help with the transition, the command palette will fix parentheses and replace groups for you when you write a Vim-style substitute command, `:%s//`. So, Zed will convert `%s:/\(a\)(b)/\1/` into a search for "(a)\(b\)" and a replacement of "$1".

For the full syntax supported by Zed's regex engine [see the regex crate documentation](https://docs.rs/regex/latest/regex/#syntax).

    # Visual Customization

Various aspects of Zed's visual layout can be configured via Zed settings.json which you can access via {#action zed::OpenSettings} ({#kb zed::OpenSettings}).

See [Configuring Zed](./configuring-zed.md) for additional information and other non-visual settings.

## Themes

Use may install zed extensions providing [Themes](./themes.md) and [Icon Themes](./icon-themes.md) via {#action zed::Extensions} from the command palette or menu.

You can preview/choose amongst your installed themes and icon themes with {#action theme_selector::Toggle} ({#kb theme_selector::Toggle}) and ({#action icon_theme_selector::Toggle}) which will modify the following settings:

```json
{
  "theme": "One Dark",
  "icon_theme": "Zed (Default)"
}
```

If you would like to use distinct themes for light mode/dark mode that can be set with:

```json
{
  "theme": {
    "dark": "One Dark"
    "light": "One Light",
    // Mode to use (dark, light) or "system" to follow the OS's light/dark mode (default)
    "mode": "system",
  },
  "icon_theme": {
    "dark": "Zed (Default)"
    "light": "Zed (Default)",
    // Mode to use (dark, light) or "system" to follow the OS's light/dark mode (default)
    "mode": "system",
  }
}
```

## Fonts

```json
  // UI Font. Use ".SystemUIFont" to use the default system font (SF Pro on macOS),
  // or ".ZedSans" for the bundled default (currently IBM Plex)
  "ui_font_family": ".SystemUIFont",
  "ui_font_weight": 400, // Font weight in standard CSS units from 100 to 900.
  "ui_font_size": 16,

  // Buffer Font - Used by editor buffers
  // use ".ZedMono" for the bundled default monospace (currently Lilex)
  "buffer_font_family": "Berkeley Mono", // Font name for editor buffers
  "buffer_font_size": 15,                 // Font size for editor buffers
  "buffer_font_weight": 400,              // Font weight in CSS units [100-900]
  // Line height "comfortable" (1.618), "standard" (1.3) or custom: `{ "custom": 2 }`
  "buffer_line_height": "comfortable",

  // Terminal Font Settings
  "terminal": {
    "font_family": "",
    "font_size": 15,
    // Terminal line height: comfortable (1.618), standard(1.3) or `{ "custom": 2 }`
    "line_height": "comfortable",
  },

  // Agent Panel Font Settings
  "agent_font_size": 15
```

### Font ligatures

By default Zed enable font ligatures which will visually combines certain adjacent characters.

For example `=>` will be displayed as `→` and `!=` will be `≠`. This is purely cosmetic and the individual characters remain unchanged.

To disable this behavior use:

```json
{
  "buffer_font_features": {
    "calt": false // Disable ligatures
  }
}
```

### Status Bar

```json
{
  // Whether to show full labels in line indicator or short ones
  //   - `short`: "2 s, 15 l, 32 c"
  //   - `long`: "2 selections, 15 lines, 32 characters"
  "line_indicator_format": "long"

  // Individual status bar icons can be hidden:
  // "project_panel": {"button": false },
  // "outline_panel": {"button": false },
  // "collaboration_panel": {"button": false },
  // "git_panel": {"button": false },
  // "notification_panel": {"button": false },
  // "agent": {"button": false },
  // "debugger": {"button": false },
  // "diagnostics": {"button": false },
  // "search": {"button": false },
}
```

### Titlebar

```json
  // Control which items are shown/hidden in the title bar
  "title_bar": {
    "show": "always",               // When to show: always | never | hide_in_full_screen
    "show_branch_icon": false,      // Show/hide branch icon beside branch switcher
    "show_branch_name": true,       // Show/hide branch name
    "show_project_items": true,     // Show/hide project host and name
    "show_onboarding_banner": true, // Show/hide onboarding banners
    "show_user_picture": true,      // Show/hide user avatar
    "show_sign_in": true,           // Show/hide sign-in button
    "show_menus": false             // Show/hide menus
  },
```

## Workspace

```json
{
  // Force usage of Zed build in path prompts (file and directory pickers)
  // instead of OS native pickers (false).
  "use_system_path_prompts": true,
  // Force usage of Zed built in confirmation prompts ("Do you want to save?")
  // instead of OS native prompts (false). On linux this is ignored (always false).
  "use_system_prompts": true,

  // Whether to use the system provided dialogs for Open and Save As (true) or
  // Zed's built-in keyboard-first pickers (false)
  "use_system_path_prompts": true,

  // Active pane styling settings.
  "active_pane_modifiers": {
    // Inset border size of the active pane, in pixels.
    "border_size": 0.0,
    // Opacity of the inactive panes. 0 means transparent, 1 means opaque.
    "inactive_opacity": 1.0
  },

  // Layout mode of the bottom dock: contained, full, left_aligned, right_aligned
  "bottom_dock_layout": "contained",

  // Whether to resize all the panels in a dock when resizing the dock.
  // Can be a combination of "left", "right" and "bottom".
  "resize_all_panels_in_dock": ["left"]
}
```

<!--
TBD: Centered layout related settings
```json
    "centered_layout": {
    // The relative width of the left padding of the central pane from the
    // workspace when the centered layout is used.
    "left_padding": 0.2,
    // The relative width of the right padding of the central pane from the
    // workspace when the centered layout is used.
    "right_padding": 0.2
    },
```
-->

## Editor

```json
  // Whether the cursor blinks in the editor.
  "cursor_blink": true,

  // Cursor shape for the default editor: bar, block, underline, hollow
  "cursor_shape": null,

  // Highlight the current line in the editor: none, gutter, line, all
  "current_line_highlight": "all",

  // When does the mouse cursor hide: never, on_typing, on_typing_and_movement
  "hide_mouse": "on_typing_and_movement",

  // Whether to highlight all occurrences of the selected text in an editor.
  "selection_highlight": true,

  // Visually show tabs and spaces  (none, all, selection, boundary, trailing)
  "show_whitespaces": "selection",
  "whitespace_map": { // Which characters to show when `show_whitespaces` enabled
    "space": "•",
    "tab": "→"
  },

  "unnecessary_code_fade": 0.3, // How much to fade out unused code.

  // Hide the values of in variables from visual display in private files
  "redact_private_values": false,

  // Soft-wrap and rulers
  "soft_wrap": "none",          // none, editor_width, preferred_line_length, bounded
  "preferred_line_length": 80,  // Column to soft-wrap
  "show_wrap_guides": true,     // Show/hide wrap guides (vertical rulers)
  "wrap_guides": [],            // Where to position wrap_guides (character counts)

  // Gutter Settings
  "gutter": {
    "line_numbers": true,         // Show/hide line numbers in the gutter.
    "runnables": true,            // Show/hide runnables buttons in the gutter.
    "breakpoints": true,          // Show/hide show breakpoints in the gutter.
    "folds": true,                // Show/hide show fold buttons in the gutter.
    "min_line_number_digits": 4   // Reserve space for N digit line numbers
  },
  "relative_line_numbers": false, // Show relative line numbers in gutter

  // Indent guides
  "indent_guides": {
    "enabled": true,
    "line_width": 1,                  // Width of guides in pixels [1-10]
    "active_line_width": 1,           // Width of active guide in pixels [1-10]
    "coloring": "fixed",              // disabled, fixed, indent_aware
    "background_coloring": "disabled" // disabled, indent_aware
  }
```

### Git Blame {#editor-blame}

```json
  "git": {
    "inline_blame": {
      "enabled": true,             // Show/hide inline blame
      "delay_ms": 0,                  // Show after delay (ms)
      "min_column": 0,             // Minimum column to inline display blame
      "padding": 7,                // Padding between code and inline blame (em)
      "show_commit_summary": false // Show/hide commit summary
    },
    "hunk_style": "staged_hollow"  // staged_hollow, unstaged_hollow
  }
```

### Editor Toolbar

```json
  // Editor toolbar related settings
  "toolbar": {
    "breadcrumbs": true, // Whether to show breadcrumbs.
    "quick_actions": true, // Whether to show quick action buttons.
    "selections_menu": true, // Whether to show the Selections menu
    "agent_review": true, // Whether to show agent review buttons
    "code_actions": false // Whether to show code action buttons
  }
```

### Editor Scrollbar and Minimap {#editor-scrollbar}

```json
  // Scrollbar related settings
  "scrollbar": {
    // When to show the scrollbar in the editor (auto, system, always, never)
    "show": "auto",
    "cursors": true,          // Show cursor positions in the scrollbar.
    "git_diff": true,         // Show git diff indicators in the scrollbar.
    "search_results": true,   // Show buffer search results in the scrollbar.
    "selected_text": true,    // Show selected text occurrences in the scrollbar.
    "selected_symbol": true,  // Show selected symbol occurrences in the scrollbar.
    "diagnostics": "all",     // Show diagnostics (none, error, warning, information, all)
    "axes": {
      "horizontal": true,     // Show/hide the horizontal scrollbar
      "vertical": true        // Show/hide the vertical scrollbar
    }
  },

  // Minimap related settings
  "minimap": {
    "show": "never",                // When to show (auto, always, never)
    "display_in": "active_editor",  // Where to show (active_editor, all_editor)
    "thumb": "always",              // When to show thumb (always, hover)
    "thumb_border": "left_open",    // Thumb border (left_open, right_open, full, none)
    "max_width_columns": 80,        // Maximum width of minimap
    "current_line_highlight": null  // Highlight current line (null, line, gutter)
  },

  // Control Editor scroll beyond the last line: off, one_page, vertical_scroll_margin
  "scroll_beyond_last_line": "one_page",
  // Lines to keep above/below the cursor when scrolling with the keyboard
  "vertical_scroll_margin": 3,
  // The number of characters to keep on either side when scrolling with the mouse
  "horizontal_scroll_margin": 5,
  // Scroll sensitivity multiplier
  "scroll_sensitivity": 1.0,
  // Scroll sensitivity multiplier for fast scrolling (hold alt while scrolling)
  "fast_scroll_sensitivity": 4.0,
```

### Editor Tabs

```json
  // Maximum number of tabs per pane. Unset for unlimited.
  "max_tabs": null,

  // Customize the tab bar appearance
  "tab_bar": {
    "show": true,                     // Show/hide the tab bar
    "show_nav_history_buttons": true, // Show/hide history buttons on tab bar
    "show_tab_bar_buttons": true      // Show hide buttons (new, split, zoom)
  },
  "tabs": {
    "git_status": false,              // Color to show git status
    "close_position": "right",        // Close button position (left, right, hidden)
    "show_close_button": "hover",     // Close button shown (hover, always, hidden)
    "file_icons": false,              // Icon showing file type
    // Show diagnostics in file icon (off, errors, all). Requires file_icons=true
    "show_diagnostics": "off"
  }
```

### Status Bar

```json
  "status_bar": {
    // Show/hide a button that displays the active buffer's language.
    // Clicking the button brings up the language selector.
    // Defaults to true.
    "active_language_button": true,
    // Show/hide a button that displays the cursor's position.
    // Clicking the button brings up an input for jumping to a line and column.
    // Defaults to true.
    "cursor_position_button": true,
  },
  "global_lsp_settings": {
    // Show/hide the LSP button in the status bar.
    // Activity from the LSP is still shown.
    // Button is not shown if "enable_language_server" if false.
    "button": true
  },
```

### Multibuffer

```json
{
  // The default number of lines to expand excerpts in the multibuffer by.
  "expand_excerpt_lines": 5,
  // The default number of lines of context provided for excerpts in the multibuffer by.
  "excerpt_context_lines": 2
}
```

### Editor Completions, Snippets, Actions, Diagnostics {#editor-lsp}

```json
  "snippet_sort_order": "inline",        // Snippets completions: top, inline, bottom, none
  "show_completions_on_input": true,     // Show completions while typing
  "show_completion_documentation": true, // Show documentation in completions
  "auto_signature_help": false,          // Show method signatures inside parentheses

  // Whether to show the signature help after completion or a bracket pair inserted.
  // If `auto_signature_help` is enabled, this setting will be treated as enabled also.
  "show_signature_help_after_edits": false,

  // Whether to show code action button at start of buffer line.
  "inline_code_actions": true,

  // Which level to use to filter out diagnostics displayed in the editor:
  "diagnostics_max_severity": null,      // off, error, warning, info, hint, null (all)

  // How to render LSP `textDocument/documentColor` colors in the editor.
  "lsp_document_colors": "inlay",        // none, inlay, border, background
```

### Edit Predictions {#editor-ai}

```json
  "edit_predictions": {
    "mode": "eager",                // Automatically show (eager) or hold-alt (subtle)
    "enabled_in_text_threads": true // Show/hide predictions in agent text threads
  },
  "show_edit_predictions": true     // Show/hide predictions in editor
```

### Editor Inlay Hints

```json
{
  "inlay_hints": {
    "enabled": false,
    // Toggle certain types of hints on and off, all switched on by default.
    "show_type_hints": true,
    "show_parameter_hints": true,
    "show_other_hints": true,

    // Whether to show a background for inlay hints (theme `hint.background`)
    "show_background": false, //

    // Time to wait after editing before requesting hints (0 to disable debounce)
    "edit_debounce_ms": 700,
    // Time to wait after scrolling before requesting hints (0 to disable debounce)
    "scroll_debounce_ms": 50,

    // A set of modifiers which, when pressed, will toggle the visibility of inlay hints.
    "toggle_on_modifiers_press": {
      "control": false,
      "shift": false,
      "alt": false,
      "platform": false,
      "function": false
    }
  }
}
```

## File Finder

```json
  // File Finder Settings
  "file_finder": {
    "file_icons": true,         // Show/hide file icons
    "modal_max_width": "small", // Horizontal size: small, medium, large, xlarge, full
    "git_status": true,         // Show the git status for each entry
    "include_ignored": null     // gitignored files in results: true, false, null
  },
```

## Project Panel

Project panel can be shown/hidden with {#action project_panel::ToggleFocus} ({#kb project_panel::ToggleFocus}) or with {#action pane::RevealInProjectPanel} ({#kb pane::RevealInProjectPanel}).

```json
  // Project Panel Settings
  "project_panel": {
    "button": true,                 // Show/hide button in the status bar
    "default_width": 240,           // Default panel width
    "dock": "left",                 // Position of the dock (left, right)
    "entry_spacing": "comfortable", // Vertical spacing (comfortable, standard)
    "file_icons": true,             // Show/hide file icons
    "folder_icons": true,           // Show/hide folder icons
    "git_status": true,             // Indicate new/updated files
    "indent_size": 20,              // Pixels for each successive indent
    "auto_reveal_entries": true,    // Show file in panel when activating its buffer
    "auto_fold_dirs": true,         // Fold dirs with single subdir
    "sticky_scroll": true,          // Stick parent directories at top of the project panel.
    "drag_and_drop": true,          // Whether drag and drop is enabled
    "scrollbar": {                  // Project panel scrollbar settings
      "show": null                  // Show/hide: (auto, system, always, never)
    },
    "show_diagnostics": "all",      //
    // Settings related to indent guides in the project panel.
    "indent_guides": {
      // When to show indent guides in the project panel. (always, never)
      "show": "always"
    },
    // Whether to hide the root entry when only one folder is open in the window.
    "hide_root": false
  }.
```

## Agent Panel

```json
  "agent": {
    "version": "2",
    "enabled": true,        // Enable/disable the agent
    "button": true,         // Show/hide the icon in the status bar
    "dock": "right",        // Where to dock: left, right, bottom
    "default_width": 640,   // Default width (left/right docked)
    "default_height": 320,  // Default height (bottom docked)
  },
  "agent_font_size": 16
```

See [Zed AI Documentation](./ai/overview.md) for additional non-visual AI settings.

## Terminal Panel

```json
  // Terminal Panel Settings
  "terminal": {
    "dock": "bottom",                   // Where to dock: left, right, bottom
    "button": true,                     // Show/hide status bar icon
    "default_width": 640,               // Default width (left/right docked)
    "default_height": 320,              // Default height (bottom docked)

    // Set the cursor blinking behavior in the terminal (on, off, terminal_controlled)
    "blinking": "terminal_controlled",
    // Default cursor shape for the terminal cursor (block, bar, underline, hollow)
    "cursor_shape": "block",

    // Environment variables to add to terminal's process environment
    "env": {
      // "KEY": "value"
    },

    // Terminal scrollbar
    "scrollbar": {
      "show": null                       // Show/hide: (auto, system, always, never)
    },
    // Terminal Font Settings
    "font_family": "Fira Code",
    "font_size": 15,
    "font_weight": 400,
    // Terminal line height: comfortable (1.618), standard(1.3) or `{ "custom": 2 }`
    "line_height": "comfortable",

    "max_scroll_history_lines": 10000,   // Scrollback history (0=disable, max=100000)
  }
```

See [Terminal settings](./configuring-zed.md#terminal) for additional non-visual customization options.

### Other Panels

```json
  // Git Panel
  "git_panel": {
    "button": true,               // Show/hide status bar icon
    "dock": "left",               // Where to dock: left, right
    "default_width": 360,         // Default width of the git panel.
    "status_style": "icon",       // label_color, icon
    "sort_by_path": false,        // Sort by path (false) or status (true)
    "scrollbar": {
      "show": null                // Show/hide: (auto, system, always, never)
    }
  },

  // Debugger Panel
  "debugger": {
    "dock": "bottom",             // Where to dock: left, right, bottom
    "button": true                // Show/hide status bar icon
  },

  // Outline Panel
  "outline_panel": {
    "button": true,               // Show/hide status bar icon
    "default_width": 300,         // Default width of the git panel
    "dock": "left",               // Where to dock: left, right
    "file_icons": true,           // Show/hide file_icons
    "folder_icons": true,         // Show file_icons (true), chevrons (false) for dirs
    "git_status": true,           // Show git status
    "indent_size": 20,            // Indentation for nested items (pixels)
    "indent_guides": {
      "show": "always"            // Show indent guides (always, never)
    },
    "auto_reveal_entries": true,  // Show file in panel when activating its buffer
    "auto_fold_dirs": true,       // Fold dirs with single subdir
    "scrollbar": {                // Project panel scrollbar settings
      "show": null                // Show/hide: (auto, system, always, never)
    }
  }
```

## Collaboration Panels

```json
{
  // Collaboration Panel
  "collaboration_panel": {
    "button": true,               // Show/hide status bar icon
    "dock": "left",               // Where to dock: left, right
    "default_width": 240          // Default width of the collaboration panel.
  },
  "show_call_status_icon": true,  // Shown call status in the OS status bar.

  // Notification Panel
  "notification_panel": {
    // Whether to show the notification panel button in the status bar.
    "button": true,
    // Where to dock the notification panel. Can be 'left' or 'right'.
    "dock": "right",
    // Default width of the notification panel.
    "default_width": 380
  }
```

    # Zed on Windows

Zed is not supported on Windows (yet). We have limited developer bandwidth, and a
new platform is a large undertaking. However, the community has developed
a build of Zed on Windows, and you can compile it yourself with these instructions:

- [Building for Windows](./development/windows.md)

For now, we welcome contributions from the community to improve Windows support.

- [GitHub Issues with 'Windows' label](https://github.com/zed-industries/zed/issues?q=is%3Aissue+is%3Aopen+label%3Awindows)
- [Zed Community Discord](https://zed.dev/community-links) -> `#windows`

    # Workspace Persistence

Zed creates local SQLite databases to persist data relating to its workspace and your projects. These databases store, for instance, the tabs and panes you have open in a project, the scroll position of each open file, the list of all projects you've opened (for the recent projects modal picker), etc. You can find and explore these databases in the following locations:

- macOS: `~/Library/Application Support/Zed`
- Linux and FreeBSD: `~/.local/share/zed` (or within `XDG_DATA_HOME` or `FLATPAK_XDG_DATA_HOME`)
- Windows: `%LOCALAPPDATA%\Zed`

The naming convention of these databases takes on the form of `0-<zed_channel>`:

- Stable: `0-stable`
- Preview: `0-preview`

**If you encounter workspace persistence issues in Zed, deleting the database and restarting Zed often resolves the problem, as the database may have been corrupted at some point.** If your issue continues after restarting Zed and regenerating a new database, please [file an issue](https://github.com/zed-industries/zed/issues/new?template=10_bug_report.yml).

## Settings

You can customize workspace restoration behavior with the following settings:

```json
{
  // Workspace restoration behavior.
  //   All workspaces ("last_session"), last workspace ("last_workspace") or "none"
  "restore_on_startup": "last_session",
  // Whether to attempt to restore previous file's state when opening it again.
  // E.g. for editors, selections, folds and scroll positions are restored
  "restore_on_file_reopen": true,
  // Whether to automatically close files that have been deleted on disk.
  "close_on_file_delete": false
}
```

    # Extracting an extension to dedicated repo

These are some notes of how to extract an extension from the main zed repository and generate a new repository which preserves the history as best as possible. In the this example we will be extracting the `ruby` extension, substitute as appropriate.

## Pre-requisites

Install [git-filter-repo](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md):

```
brew install git-filter-repo
```

## Process

We are going to use a `$LANGNAME` variable for all these steps. Make sure it is set correctly.

> **Note**
> If you get `zsh: command not found: #` errors, run:
> `setopt interactive_comments && echo "setopt interactive_comments" >> ~/.zshrc`

1. Create a clean clone the zed repository, delete tags and delete branches.

```sh
LANGNAME=your_language_name_here

rm -rf $LANGNAME
git clone --single-branch --no-tags git@github.com:zed-industries/zed.git $LANGNAME
cd $LANGNAME
```

2. Create an expressions.txt file somewhere (e.g. `~/projects/$LANGNAME.txt`)

This file takes the form of `patern==>replacement`, where the replacement is optional.
Note whitespace matters so `ruby: ==>` is removing the `ruby:` prefix from a commit messages and adding a space after `==> ` means the replacement begins with a space. Regex capture groups are numbered `\1`, `\2`, etc.

See: [Git Filter Repo Docs](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html) for more.

```sh
# Create regex mapping for rewriting commit messages (edit as appropriate)
mkdir -p ~/projects
echo "${LANGNAME}: ==>
extension: ==>
chore: ==>
zed_extension_api: ==>
"'regex:(?<![\[a-zA-Z0-9])(#[0-9]{3,5})==>zed-industries/zed\1' \
  > ~/projects/${LANGNAME}.txt

# This removes the LICENSE symlink
git filter-repo --invert-paths --path extensions/$LANGNAME/LICENSE-APACHE

# This does the work
git filter-repo \
    --use-mailmap \
    --subdirectory-filter extensions/$LANGNAME/ \
    --path LICENSE-APACHE \
    --replace-message ~/projects/${LANGNAME}.txt
```

3. Review the commits.

This is your last chance to make any modifications.
If you don't fix it now, it'll be wrong forever.

For example, a previous commit message was `php/ruby: bump version to 0.0.5`
which was replaced with `php/bump version to 0.0.5`
so I added a new line to expressions.txt with `php/==>`
and next run it became `bump version to 0.0.5`.

4. [Optional] Generate tags

You can always add tags later, but it's a nice touch.

Show you all commits that mention a version number:

```sh
git log --grep="(\d+\.\d+\.\d+)" --perl-regexp --oneline --reverse
```

Then just:

```
git tag v0.0.2 abcd1234
git tag v0.0.3 deadbeef
```

Usually the initial extraction didn't mention a version number so you can just do that one manually.

4. [Optional] Add a README.md and commit.

5. Push to the new repo

Create a new empty repo on github under the [zed-extensions](https://github.com/organizations/zed-extensions/repositories/new) organization.

```
git remote add origin git@github.com:zed-extensions/$LANGNAME
git push origin main --tags
git branch --set-upstream-to=origin/main main
```

6. Setup the new repository:

- Go to the repository settings:
  - Disable Wikis
  - Uncheck "Allow Merge Commits"
  - Check "Allow Squash Merging"
    - Default commit message: "Pull request title and description"

7. Publish a new version of the extension.

```sh
OLD_VERSION=$(grep '^version = ' extension.toml | cut -d'"' -f2)
NEW_VERSION=$(echo "$OLD_VERSION" | awk -F. '{$NF = $NF + 1;} 1' OFS=.)
echo $OLD_VERSION $NEW_VERSION
perl -i -pe "s/$OLD_VERSION/$NEW_VERSION/" extension.toml
perl -i -pe "s#https://github.com/zed-industries/zed#https://github.com/zed-extensions/${LANGNAME}#g" extension.toml

# if there's rust code, update this too.
test -f Cargo.toml && perl -i -pe "s/$OLD_VERSION/$NEW_VERSION/" Cargo.toml
# remove workspace Cargo.toml lines
test -f Cargo.toml && perl -ni -e 'print unless /^.*(workspace\s*=\s*true|\[lints\])\s*$/' Cargo.toml
test -f Cargo.toml && cargo check

# add a .gitignore
echo "target/
grammars/
*.wasm" > .gitignore

# commit and push
git add -u
git checkout -b "bump_${NEW_VERSION}"
git commit -m "Bump to v${NEW_VERSION}"
git push
gh pr create --title "Bump to v${NEW_VERSION}" --web

# merge PR in web interface
git checkout main
git pull
git tag v${NEW_VERSION}
git push origin v${NEW_VERSION}
```

7. In zed repository, remove the old extension and push a PR.

```sh
rm -rf extensions/$LANGNAME
sed -i '' "/extensions\/$LANGNAME/d" Cargo.toml
cargo check
git checkout -b remove_$LANGNAME
git add extensions/$LANGNAME
git add Cargo.toml Cargo.lock extensions/$LANGNAME
git commit -m "Migrate to $LANGNAME extension to zed-extensions/$LANGNAME"
git push
gh pr create --web
```

8. Update extensions repository:

```sh
cd ../extensions
git checkout main
git pull
git submodule init
git submodule update
git status

git checkout -b ${LANGNAME}_v${NEW_VERSION}
git submodule add https://github.com/zed-extensions/${LANGNAME}.git extensions/${LANGNAME}
pnpm sort-extensions

# edit extensions.toml:
# - bump version
# - change `submodule` from `extensions/zed` to new path
# - remove `path` line all together

git add extensions.toml .gitmodules extensions/${LANGNAME}
git diff --cached
git commit -m "Bump ${LANGNAME} to v${NEW_VERSION}"
git push
```

Create PR and reference the Zed PR with removal from tree.

    # Zed Extensions

This directory contains extensions for Zed that are largely maintained by the Zed team. They currently live in the Zed repository for ease of maintenance.

If you are looking for the Zed extension registry, see the [`zed-industries/extensions`](https://github.com/zed-industries/extensions) repo.

## Structure

Currently, Zed includes support for a number of languages without requiring installing an extension. Those languages can be found under [`crates/languages/src`](https://github.com/zed-industries/zed/tree/main/crates/languages/src).

Support for all other languages is done via extensions. This directory ([extensions/](https://github.com/zed-industries/zed/tree/main/extensions/)) contains a number of officially maintained extensions. These extensions use the same [zed_extension_api](https://docs.rs/zed_extension_api/latest/zed_extension_api/) available to all [Zed Extensions](https://zed.dev/extensions) for providing [language servers](https://zed.dev/docs/extensions/languages#language-servers), [tree-sitter grammars](https://zed.dev/docs/extensions/languages#grammar) and [tree-sitter queries](https://zed.dev/docs/extensions/languages#tree-sitter-queries).

## Dev Extensions

See the docs for [Developing an Extension Locally](https://zed.dev/docs/extensions/developing-extensions#developing-an-extension-locally) for how to work with one of these extensions.

## Updating

> [!NOTE]
> This update process is usually handled by Zed staff.
> Community contributors should just submit a PR (step 1) and we'll take it from there.

The process for updating an extension in this directory has three parts.

1. Create a PR with your changes. (Merge it)
2. Bump the extension version in:

   - extensions/{language_name}/extension.toml
   - extensions/{language_name}/Cargo.toml
   - Cargo.lock

   You can do this manually, or with a script:

   ```sh
   # Output the current version for a given language
   ./script/language-extension-version <langname>

   # Update the version in `extension.toml` and `Cargo.toml` and trigger a `cargo check`
   ./script/language-extension-version <langname> <new_version>
   ```

   Commit your changes to a branch, push a PR and merge it.

3. Open a PR to [`zed-industries/extensions`](https://github.com/zed-industries/extensions) repo that updates the extension in question

Edit [`extensions.toml`](https://github.com/zed-industries/extensions/blob/main/extensions.toml) in the extensions repo to reflect the new version you set above and update the submodule latest Zed commit.

```sh
# Go into your clone of the extensions repo
cd ../extensions

# Update
git checkout main
git pull
just init-submodule extensions/zed

# Update the Zed submodule
cd extensions/zed
git checkout main
git pull
cd -
git add extensions.toml extensions/zed
```

    # ruff

Documentation for configuring Zed to use the Ruff extension can be found [here](https://docs.astral.sh/ruff/editors/setup/#zed).

    # Slash Commands Example Extension

This is an example extension showcasing how to write slash commands.

See: [Extensions: Slash Commands](https://zed.dev/docs/extensions/slash-commands) in the Zed Docs.

## Pre-requisites

[Install Rust Toolchain](https://www.rust-lang.org/tools/install):

```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

## Setup

```sh
git clone https://github.com/zed-industries/zed.git
cp -RL zed/extensions/slash-commands-example .

cd slash-commands-example/

# Update Cargo.toml to make it standalone
cat > Cargo.toml << EOF
[package]
name = "slash_commands_example"
version = "0.1.0"
edition = "2021"
license = "Apache-2.0"

[lib]
path = "src/slash_commands_example.rs"
crate-type = ["cdylib"]

[dependencies]
zed_extension_api = "0.1.0"
EOF

curl -O https://raw.githubusercontent.com/rust-lang/rust/master/LICENSE-APACHE
echo "# Zed Slash Commands Example Extension" > README.md
echo "Cargo.lock" > .gitignore
echo "target/" >> .gitignore
echo "*.wasm" >> .gitignore

git init
git add .
git commit -m "Initial commit"

cd ..
mv slash-commands-example MY-SUPER-COOL-ZED-EXTENSION
zed $_
```

## Installation

1. Open the command palette (`cmd-shift-p` or `ctrl-shift-p`).
2. Launch `zed: install dev extension`
3. Select the extension folder created above

## Test

Open the assistant and type `/echo` and `/pick-one` at the beginning of a line.

## Customization

Open the `extensions.toml` file and set the `id`, `name`, `description`, `authors` and `repository` fields.

Rename `slash-commands-example.rs` you'll also have to update `Cargo.toml`

## Rebuild

Rebuild to see these changes reflected:

1. Open Zed Extensions (`cmd-shift-x` or `ctrl-shift-x`).
2. Click `Rebuild` next to your Dev Extension (formerly "Slash Command Example")

## Troubleshooting / Logs

- MacOS: `tail -f ~/Library/Logs/Zed/Zed.log`
- Linux: `tail -f ~/.local/share/zed/logs/Zed.log`

## Documentation

- [zed.dev docs: Extensions: Developing Extensions](https://zed.dev/docs/extensions/developing-extensions)
- [zed.dev docs: Extensions: Slash Commands](https://zed.dev/docs/extensions/slash-commands)

    # Test Extension

This is a test extension that we use in the tests for the `extension` crate.

Originally based off the Gleam extension.

    ---
title: Privacy Policy
slug: privacy-policy
---

At Zed Industries, Inc. ("Zed", "Company" or "we"), we take privacy and the security of data seriously. This Privacy Policy is established to help advise you about how we treat your personal data. By using or accessing our website located at zed.dev, or the Solution or services available pursuant the Zed End User Terms located at [https://zed.dev/terms](https://zed.dev/terms) (collectively, the "Services"), you acknowledge awareness of the practices and policies outlined below, and hereby consent that we will collect, use, and share your personal data as described in this Privacy Policy.

As we grow and expand our Services, we may modify this Privacy Policy from time to time. When material modifications are made, we will alert you to any such changes by placing a notice on the Company website, by sending you an email and/or by some other means. Please note that if you've opted not to receive legal notice emails from us (or haven't provided us with a valid email address), those legal notices will still govern your use of the Services. If you use the Services after any changes to the Privacy Policy have been published on our website, you consent and agree to all of the changes.

## What this Privacy Policy Covers

Our Privacy Policy covers how we treat Personal Data that we gather when you access or use our Services. "Personal Data" means information that identifies or relates to a particular individual and includes information referred to as "personally identifiable information" or "personal information" under applicable data privacy laws, rules or regulations. Our Privacy Policy does not cover the practices of companies we don't own or control or people we don't manage.

## Personal Data

### Categories of Personal Data We Collect

This chart details the categories of Personal Data that we collect and have collected over the past 12 months:

| Category of personal data     | Examples of data we collect                                   | Categories of third parties with whom we share this data |
| ----------------------------- | ------------------------------------------------------------- | -------------------------------------------------------- |
| Profile or contact data       | First and last name<br/>Email address<br/>GitHub username     | Cloud infrastructure providers <br/>Analytics providers  |
| IP data                       | IP address & derived geolocation data                         | Cloud infrastructure providers <br/>Analytics providers  |
| Web analytics                 | Interactions<br/>Referrer<br/>Request IDs<br/>Statistics      | Cloud infrastructure providers <br/>Analytics providers  |
| Photos, videos and recordings | Screenshots<br/>Videos and video recordings you share with us | Cloud infrastructure providers                           |
| Audio, screenshare data       | Audio and screen sharing during collaboration calls           | Cloud infrastructure providers                           |

Note that "collection" does not necessarily imply long-term storage.

### Categories of Sources of Personal Data

We collect Personal Data about you from the following categories of sources:

#### You

- When you provide such information directly to us. Examples include:
  - When you create an account
  - When you voluntarily provide information through our Services or through responses to surveys or questionnaires.
  - When you send us an email or otherwise contact us.
  - When you sign up to our mailing list.
- When you use our hosted Services and such information is collected automatically. Examples include:
  - Cookies (defined in the "Tracking Tools and Opt-Out" section below).
- When you use the client software we provide on your machine. Examples include:
  - Authentication information when you sign in.
  - Version and system metadata when the software checks for updates.
  - Usage data, unless you opt out.
  - Crash reports, unless you opt out.
  - When you make requests to language models we host for you.
    - Zed does not store or train on your requests without consent.
  - Other relevant data necessary to provide you with our Services.

#### Third Parties

- When you login to the service using a third-party service like GitHub.
- Information collected by content delivery networks or similar service providers
- We may use analytics providers to analyze how you interact and engage with the Services, or third parties may help us provide you with customer support.

## Our Business Purposes for Collecting or Disclosing Personal Data

- Providing, Customizing and Improving the Services
  - Creating and managing your account or other user profiles.
  - Processing orders or other fee-based transactions; billing.
  - Providing you with the products, services or information you request.
  - Meeting or fulfilling the reason you provided the information to us.
  - Providing support and assistance for the Services.
  - Improving the Services, including testing, research, internal analytics and product development.
  - Doing fraud protection, security and debugging.
  - Carrying out other business purposes stated when collecting your Personal Data or as otherwise set forth in applicable data privacy laws.
- Marketing the Services
  - Marketing and selling the Services.
- Corresponding with You
  - Responding to correspondence that we receive from you, contacting you when necessary or requested, and sending you information about Zed or our Services.
  - Sending emails and other communications according to your preferences or that display content that we think will interest you.
- Meeting Legal Requirements and Enforcing Legal Terms
  - Fulfilling our legal obligations under applicable law, regulation, court order or other legal process, such as preventing, detecting and investigating security incidents and potentially illegal or prohibited activities.
  - Protecting the rights, property or safety of you, Zed or another party.
  - Enforcing any agreements with you.
  - Responding to claims that any posting or other content violates third-party rights.
  - Resolving disputes.

We will not collect additional categories of Personal Data or use the Personal Data we collected for materially different, unrelated or incompatible purposes without providing you notice as is described above.

## How We Disclose Your Personal Data

We disclose your Personal Data to categories of service providers and other parties listed in this section. Some of these disclosures may constitute a "sale" of your Personal Data as defined under applicable laws. For more information, please refer to the state-specific sections below.

- Service Providers. These parties help us provide the Services or perform business functions on our behalf. They include:
  - Hosting, technology and communication providers.
  - Providers of artificial intelligence or machine learning models
  - Payment processors.
    - If you are using our Services on a fee-basis, our payment processing partner Stripe, Inc. ("Stripe") collects your voluntarily-provided payment card information necessary to process your payment.
    - Please see Stripe Terms of Service and Stripe Privacy Policy for information on its use and storage of your Personal Data.
- Analytics Partners. These parties provide analytics on web traffic or usage of the Services. They include:
  - Companies that track how users found or were referred to the Services.
  - Companies that track how users interact with the Services.
- Authorized authentication providers (e.g. GitHub OAuth)

### Fulfilling Legal Obligations

We may share any Personal Data that we collect with third parties in relation to the activities set forth under "Meeting Legal Requirements and Enforcing Legal Terms" in the "Our Business Purposes for Collecting Personal Data" section above.

### Business Transfers

Personal Data collected may be transferred to a third party if we undergo a merger, acquisition, bankruptcy or other transaction in which such third party assumes control of our business (in whole or in part). In such an event, we will make reasonable efforts to notify you before your information becomes subject to different privacy and security policies and practices as authorized or mandated by applicable law.

## Data that is Not Personal Data

We may create aggregated, de-identified or anonymized data from the Personal Data we collect, including by removing information that makes the data personally identifiable to a particular user. We may use such aggregated, de-identified or anonymized data and share it with third parties for our lawful business purposes, including to analyze, build and improve the Services and promote our business, provided that we will not share such data in a manner that could identify you.

## Tracking Tools and Opt-Out

The Services use cookies and similar technologies such as pixel tags, web beacons, clear GIFs and JavaScript (collectively, "Cookies") to enable our servers to recognize your web browser, tell us how and when you visit and use our Services, analyze trends, learn about our user base and operate and improve our Services. Cookies are small pieces of data– usually text files – placed on your computer, tablet, phone or similar device when you use that device to access our Services. We may also supplement the information we collect from you with information received from third parties, including third parties that have placed their own Cookies on your device(s).

### We use the following types of Cookies:

- Essential Cookies. Essential Cookies are required for providing you with features or services that you have requested. For example, certain Cookies enable you to log into secure areas of our Services. Disabling these Cookies may make certain features and services unavailable.
- Functional Cookies. Functional Cookies are used to record your choices and settings regarding our Services, maintain your preferences over time and recognize you when you return to our Services. These Cookies help us to personalize our content for you, greet you by name and remember your preferences (for example, your choice of language or region).
- Performance/Analytical Cookies. Performance/Analytical Cookies allow us to understand how visitors use our Services. They do this by collecting information about the number of visitors to the Services, what pages visitors view on our Services and how long visitors are viewing pages on the Services. Performance/Analytical Cookies also help us measure the performance of our advertising campaigns to help us improve our campaigns and Services' content for those who engage with our advertising.

You can decide whether or not to accept Cookies through your internet browser's settings. Most browsers have an option for turning off the Cookie feature, which will prevent your browser from accepting new Cookies, as well as (depending on the sophistication of your browser software) allow you to decide on acceptance of each new Cookie in a variety of ways. You can also delete all Cookies that are already on your device. If you do this, however, you may have to manually adjust some preferences every time you visit our website and some of the Services and functionalities may not work.

To find out more information about Cookies generally, including information about how to manage and delete Cookies, please visit [https://allaboutcookies.org/](https://allaboutcookies.org/) or [https://ico.org.uk/for-the-public/online/cookies/](https://ico.org.uk/for-the-public/online/cookies/) if you are located in the European Union.

## Data Security

We endeavor to protect your Personal Data from unauthorized access, use and disclosure using appropriate physical, technical, organizational and administrative security measures based on our Services,the type of Personal Data being collected and how we are processing that data. You should also help protect your data by selecting and protecting your password and/or other sign-on mechanism(s) with care; limiting access to your computer or device and browser; and signing off after you have finished accessing your account. Although we work to protect the security of your account and other data that we hold in our records, be aware that no method of transmitting data over the internet or storing data is completely secure.

## Data Retention

We retain Personal Data about you for as long as reasonably necessary to provide you with our Services or otherwise in support of our business or commercial purposes for utilization of your Personal Data, as expressed. When establishing a retention period for particular categories of data, we consider who we collected the data from, our need for the Personal Data, why we collected the Personal Data, and the sensitivity of the Personal Data. In some cases we retain Personal Data for a longer period, if doing so is necessary to comply with our legal obligations, resolve disputes or collect fees owed, or as is otherwise permitted or required by applicable law, rule or regulation. We may further retain information in an anonymous or aggregated form where such information would not identify you personally.

For example:

- We retain your profile information and credentials for as long as you have an account with us.
- We retain your payment data for as long as we need to process your purchase or subscription.
- We retain your device/IP data for as long as we need it to ensure that our systems are working appropriately, effectively and efficiently.

It's worth noting that we avoid retaining data unless necessary to provide our Service. For example:

- We do not currently store source code that we proxy during collaboration sessions.
- We do not currently store audio or video recordings of Collaboration calls handled by LiveKit.

## Personal Data of Children

We do not knowingly collect or solicit Personal Data from children under 13 years of age; if you are a child under the age of 13, please do not attempt to register for or otherwise use the Services or send us any Personal Data. If we learn we have collected Personal Data from a child under 13 years of age, we will delete that information as quickly as possible. If you believe that a child under 13 years of age may have provided Personal Data to us, please contact us at hi@zed.dev.

## California Resident Rights

If you are a California resident, you have the rights set forth in this section. Please see the "Exercising Your Rights" section below for instructions regarding how to exercise these rights. Please note that we may process Personal Data of our customers' end users or employees in connection with our provision of certain services to our customers. If we are processing your Personal Data as a service provider, you may contact the entity that collected your Personal Data in the first instance to address your rights with respect to such data as desired.

If there are any conflicts between this section and any other provision of this Privacy Policy and you are a California resident, the portion that is more protective of Personal Data shall control to the extent of such conflict. If you have any questions about this section or whether any of the following rights apply to you, please contact us at hi@zed.dev.

### Access

You have the right to request certain information about our collection and use of your Personal Data over the past 12 months. In response, we will provide you with the following information:

- The categories of Personal Data that we have collected about you.
- The categories of sources from which that Personal Data was collected.
- The business or commercial purpose for collecting or selling your Personal Data.
- The categories of third parties with whom we have shared your Personal Data.
- The specific pieces of Personal Data that we have collected about you.
- If we have disclosed your Personal Data to any third parties for a business purpose over the past 12 months, we will identify the categories of Personal Data shared with each category of third party recipient. If we have sold your Personal Data over the past 12 months, we will identify the categories of Personal Data sold to each category of third party recipient.

### Deletion

You have the right to request that we delete the Personal Data that we have collected about you. Under the CCPA, this right is subject to certain exceptions: for e.g., we may need to retain your Personal Data to provide you with the Services or complete a transaction or other action you may have requested, or if deletion of your Personal Data involves disproportionate effort to achieve. If your deletion request is subject to one of these exceptions, we may deny your deletion request to such data.

### Correction

You have the right to request that we correct any inaccurate Personal Data we have collected about you. Under the CCPA, this right is subject to certain exceptions: for example, if we reasonably decide, based on the totality of circumstances related to your Personal Data, that such data is correct. If your correction request is subject to one of these CCPA exceptions, we may deny your request to correct such data.

### Processing of Sensitive Personal Information Opt-Out

Consumers have certain rights over the processing of their sensitive information. However, we do not intentionally collect sensitive categories of personal information, but it is possible to share sensitive information with us through your use of the Services. It is your responsibility not to share any such sensitive information when you use the Services.

### Personal Data Sales Opt-Out and Opt-In

We will not sell your Personal Data, and have not done so over the last 12 months. To our knowledge, we do not sell the Personal Data of minors under 16 years of age. Under the CCPA, California residents have certain rights when a business "shares" Personal Data with third parties for purposes of cross-contextual behavioral advertising. We have shared the foregoing categories of Personal Data for the purposes of cross-contextual behavioral advertising, as applicable.

Under California Civil Code Sections 1798.83-1798.84, California residents are entitled to contact us to prevent disclosure of Personal Data to third parties for such third parties' direct marketing purposes; in order to submit such a request, please contact us at hi@zed.dev.

Your browser may offer you a "Do Not Track" option, which allows you to signal to operators of websites and web applications and services that you do not wish such operators to track certain of your online activities over time and across different websites. Our Services do not support Do Not Track requests at this time. To find out more about "Do Not Track," you can visit [www.allaboutdnt.com](https://www.allaboutdnt.com).

### Exercising Your Rights under CCPA

To exercise the rights described in this Privacy Policy, you or, if you are a California resident, your Authorized Agent (as defined below) can send us a request that (1) provides sufficient information to allow us to adequately verify that you are the person about whom we have collected Personal Data, and (2) describes your request in sufficient detail to allow us to understand, evaluate and respond ( a "Valid Request"). We are not obligated to respond to requests that do not meet these criteria. We will only use Personal Data provided in a Valid Request to verify your identity and complete your request.

We are committed to respond to Valid Requests within the time frame required by applicable law. We will not charge you a fee for making a Valid Request unless your Valid Request(s) is excessive, repetitive or manifestly unfounded. If we determine that your Valid Request warrants a fee, we will notify you of the fee and explain that decision before completing your request.

You may submit a Valid Request using the following methods:

- Email us at: hi@zed.dev

If you are a California resident, you may also authorize an agent (an "Authorized Agent") to exercise your rights on your behalf.

### We Will Not Discriminate Against You for Exercising Your Rights

We will not discriminate against you for exercising your rights under applicable data protection laws. We will not deny you our goods or services, charge you different prices or rates, or provide you a lower quality of goods and services if you exercise your rights under applicable law. However, we may offer different tiers of our Services, as allowed by applicable law, with varying prices, rates or levels of quality of the goods or services you receive related to the value of Personal Data that we receive from you.

# European Union and United Kingdom Data Subject Rights

## EU and UK Residents

If you are a resident of the European Union ("EU"), United Kingdom ("UK"), Lichtenstein, Norway or Iceland, you may have additional rights under the EU or UK General Data Protection Regulation (the "GDPR") with respect to your Personal Data, as outlined below.
We use the terms "Personal Data" and "processing" as they are defined in the GDPR in this section, but "Personal Data" generally means information that can be used to individually identify a person, and "processing" generally covers actions that can be performed in connection with data such as collection, use, storage and disclosure. Company will be the controller of your Personal Data processed in connection with the Services.
If there are any conflicts between this section and any other provision of this Privacy Policy, the policy or portion that is more protective of Personal Data shall control to the extent of such conflict. If you have any questions about this section or whether any of the following applies to you, please contact us at hi@zed.dev. Note that we may also process Personal Data of our customers' end users or employees in connection with our provision of certain services to you, in which case we are the processor of Personal Data. If we are the processor of your Personal Data, please contact the controller party in the first instance to address your rights with respect to such data.

## Personal Data We Collect

The "Categories of Personal Data We Collect" section above details the Personal Data that we collect from you.

## Personal Data Use and Processing Grounds

The "Our Commercial or Business Purposes for Collecting Personal Data" section above explains how we use your Personal Data.

We will only process your Personal Data if we have a lawful basis for doing so. Lawful bases for processing include consent, contractual necessity and our "legitimate interests" or the legitimate interest of others, as further described below.

- Contractual Necessity: We process the following categories of Personal Data as a matter of "contractual necessity", meaning that we need to process the data to perform under our End User Terms with you, which enables us to provide you with the Services. When we process data due to contractual necessity, failure to provide such Personal Data will result in your inability to use some or all portions of the Services that require such data.
  - Profile or Contact Data
  - Payment Data
- Legitimate Interest: We process the following categories of Personal Data when we believe it furthers the legitimate interest of us or third parties:
  - Device/IP Data
  - Web Analytics
  - We may also de-identify or anonymize Personal Data to further our legitimate interests.
- Examples of these legitimate interests include (as described in more detail above):
  - Providing, customizing and improving the Services.
  - Marketing the Services.
  - Corresponding with you.
  - Meeting legal requirements and enforcing legal terms.
  - Completing corporate transactions.
- Consent: In some cases, we process Personal Data based on the consent you expressly grant to us at the time we collect such data.
  - Other Processing Grounds: From time to time we may also need to process Personal Data to comply with a legal obligation, if it is necessary to protect the interests of you or other data subjects, or if it is necessary in the public interest.

## Sharing Personal Data

The "How We Share Your Personal Data" section above details how we share your Personal Data with third parties.

## EU Data Subject Rights

For more information about these EU or UK personal data terms and your rights related thereto, or to submit a request for information, please email us at hi@zed.dev. Please note that in some circumstances, we may not be able to fully comply with your request, such as if it is frivolous or impractical, if it jeopardizes the rights of others, or if it is not required by law, but, in those circumstances, we are committed to respond to notify you of such a decision regardless. In some cases, we may also need you to provide us with additional information, which may include Personal Data, if necessary to verify your identity and the nature of your request.

- Access: You can request more information about the Personal Data we hold about you and request a copy of such Personal Data. You can also access certain of your Personal Data by logging on to your account.
- Rectification: If you believe that any Personal Data we are holding about you is incorrect or incomplete, you can request that we correct or supplement such data. You can also correct some of this information directly by logging on to your account.
- Erasure: You can request that we erase some or all of your Personal Data from our systems.
- Withdrawal of Consent: If we are processing your Personal Data based on your consent, you have the right to withdraw your consent at any time. Please note, however, that if you exercise this right, you may have to then provide express consent on a case-by-case basis for the use or disclosure of certain of your Personal Data, if such use or disclosure is necessary to enable you to utilize some or all of our Services.
- Portability: You can ask for a copy of your Personal Data in a machine-readable format. You can also request that we transmit the data to another controller where technically feasible.
- Objection: You can contact us to let us know that you object to the further use or disclosure of your Personal Data for certain purposes, such as for direct marketing purposes.
- Restriction of Processing: You can ask us to restrict further processing of your Personal Data.
- Right to File Complaint: You have the right to lodge a complaint about Company's practices with respect to your Personal Data with the supervisory authority of your country or EU Member State. A list of Supervisory Authorities is available here: [https://edpb.europa.eu/about-edpb/board/members_en](https://edpb.europa.eu/about-edpb/board/members_en)

## Transfers of Personal Data

The Services are hosted and operated in the United States ("U.S.") through Company and its service providers. By using the Services, you acknowledge that any Personal Data about you is being provided to Company in the U.S. and will be hosted on U.S. servers, and you authorize Company to transfer, store and process your information to and in the U.S., and possibly other countries. In some circumstances, your Personal Data may be transferred to the U.S. pursuant to a data processing agreement incorporating legally required data protection clauses.

# Contact Information:

If you have additional questions about this Privacy Policy, the methods in which we collect and use your Personal Data or your choices and rights regarding such collection and use, please do not hesitate to contact us at:

- Website: zed.dev
- Email Address: hi@zed.dev
- Corporate Address:
  Zed Industries, Inc.
  2590 Welton St
  Suite 200
  PO Box 1916
  Denver CO 80205

**DATE: May 6, 2025**

    ---
title: Subprocessor List
slug: subprocessors
---

This page provides information about the Subprocessors Zed has engaged to provide processing activities on Customer Data as defined in the [Zed End User Terms](https://zed.dev/terms).

| Subprocessor        | Purpose                  | Location      |
| ------------------- | ------------------------ | ------------- |
| Cloudflare          | Cloud Infrastructure     | Worldwide     |
| Amazon Web Services | Cloud Infrastructure     | United States |
| DigitalOcean        | Cloud Infrastructure     | United States |
| Vercel              | Cloud Infrastructure     | United States |
| ConvertKit          | Email Marketing          | United States |
| Axiom               | Analytics                | United States |
| Hex Technologies    | Analytics                | United States |
| Snowflake           | Analytics                | United States |
| LiveKit             | Audio/Video Conferencing | United States |
| GitHub              | Authentication           | United States |
| Anthropic           | AI Services              | United States |
| BaseTen             | AI Services              | United States |
| Exa Labs            | AI Services              | United States |
| Google              | AI Services              | United States |
| OpenAI              | AI Services              | United States |

**DATE: May 6th, 2025**

    ---
title: Zed End User Terms
slug: terms
---

PLEASE READ THESE TERMS AND CONDITIONS CAREFULLY BEFORE USING THE SERVICE OR SOFTWARE OFFERED BY ZED INDUSTRIES, INC. ("ZED", OR "WE"). BY ACCESSING OR USING THE SOLUTION (AS DEFINED BELOW) IN ANY MANNER, YOU ("YOU" OR "CUSTOMER") AGREE TO BE BOUND BY THESE TERMS (THE "AGREEMENT") TO THE EXCLUSION OF ALL OTHER TERMS. YOU REPRESENT AND WARRANT THAT YOU HAVE THE AUTHORITY TO ENTER INTO THIS AGREEMENT; IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF AN ORGANIZATION OR ENTITY, REFERENCES TO "CUSTOMER" AND "YOU" IN THIS AGREEMENT, REFER TO THAT ORGANIZATION OR ENTITY. IF YOU DO NOT AGREE TO ALL OF THE FOLLOWING, YOU MAY NOT USE OR ACCESS THE SOLUTION IN ANY MANNER. IF THE TERMS OF THIS AGREEMENT ARE CONSIDERED AN OFFER, ACCEPTANCE IS EXPRESSLY LIMITED TO SUCH TERMS.

## 1. ACCESS TO AND USE OF THE SOLUTION

Subject to the terms and conditions of this Agreement, Zed hereby grants to You, and You hereby accept from Zed, a term-limited, non-exclusive, non-transferable, non-assignable and non-sublicensable license to make use of the Editor for Your internal use only, and subject to the use limitations in Section 2.2.

## 2. TERMS APPLICABLE TO THE EDITOR

### 2.1. License Grant

Subject to the terms and conditions of this Agreement, Zed hereby grants to You, and You hereby accept from Zed, a term-limited, non-exclusive, non-transferable, non-assignable and non-sublicensable license to make use of the Editor for Your internal use only, and subject to the use limitations in Section 2.2.

### 2.2. License Limitations

You agree that You shall not: (a) exceed the scope of the licenses granted in Section 2.1; (b) make copies of the Editor; (c) distribute, sublicense, assign, delegate, rent, lease, sell, time-share or otherwise transfer the benefits of, use under, or rights to, the license granted in Section 2.1; (d) reverse engineer, decompile, disassemble or otherwise attempt to learn the source code, structure or algorithms underlying the Editor, except to the extent required to be permitted under applicable law; (e) modify, translate or create derivative works of the Editor; or (f) remove any copyright, trademark, patent or other proprietary notice that appears on the Editor or copies thereof.

### 2.3. Open Source Software

Zed makes certain versions of the Editor and related software available at the Zed GitHub Repository: [https://github.com/zed-industries/zed](https://github.com/zed-industries/zed) (the "Repo"). Your use of such software is subject to the open source software licenses declared in the Repo.

## 3. TERMS APPLICABLE TO THE ZED SERVICE

### 3.1. Access to and Scope of Zed Service

If you have elected to use the Zed Service by enabling or activating the Zed Service, Zed will use commercially reasonable efforts to make the Zed Service available to You as set forth in this Agreement. Once you elected to use the Zed Service, You may access and use the Zed Service during the Term, subject to Your compliance with the terms and conditions of the Agreement.

### 3.2. Restrictions

You will use the Zed Service only in accordance with all applicable laws, including, but not limited to, laws related to data (whether applicable within the United States, the European Union, or otherwise). You agree not to (and will not allow any third party to): (i) remove or otherwise alter any proprietary notices or labels from the Zed Service or any portion thereof; (ii) reverse engineer, decompile, disassemble, or otherwise attempt to discover the underlying structure, ideas, or algorithms of the Zed Service or any software used to provide or make the Zed Service available; or (iii) rent, resell or otherwise allow any third party access to or use of the Zed Service. Zed may suspend Your access to or use of the Zed Service as follows: (a) immediately if Zed reasonably believes Your use of the Zed Service may pose a security risk to or may adversely impact the Zed Service; or (b) if You are in breach of this Agreement.

### 3.3. Customer Data

You are solely responsible for Customer Data including, but not limited to: (a) compliance with all applicable laws and this Agreement; (b) any claims relating to Customer Data; and (c) any claims that Customer Data infringes, misappropriates, or otherwise violates the rights of any third party. You agree and acknowledge that Customer Data may be irretrievably deleted if Your account is terminated. For purposes of this Agreement, "Customer Data" shall mean any data, information or other material provided, uploaded, or submitted by You to the Zed Service in the course of using the Zed Service. Notwithstanding anything to the contrary, You represent and warrant that You will not transfer or make available to Zed any personally identifiable information or related information subject to applicable data privacy laws or regulations, unless otherwise agreed to in writing by Zed.

#### 3.3.1. Customer Data Made Available to Zed

To the extent You elect to make Customer Data available to Zed, the same may only be used by Zed according to the Customer Data type and the use rights regarding the same as described herein:

#### 3.3.2. Usage Data

To improve the Editor and understand how You use it, Zed optionally collects the following usage data:

- (a) file extensions of opened files;
- (b) features and tools You use within the Editor;
- (c) project statistics (e.g., number of files); and
- (d) frameworks detected in Your projects

(a-d collectively, "Usage Data"). Usage Data does not include any of Your software code or sensitive project details. You may change Your preferences disabling the collection of Usage Data and You can audit Usage Data collected by the Editor at any time. See [https://zed.dev/docs/telemetry](https://zed.dev/docs/telemetry) for more.

Usage Data is associated with a secure random telemetry ID which may be linked to Your email address. This linkage currently serves two purposes: (1) it allows Zed to analyze usage patterns over time while maintaining Your privacy; and (2) it enables Zed to reach out to specific user groups for feedback and improvement suggestions. Zed may contact You based on Your usage patterns to better understand your needs and improve the Solution. If You delete Your account, the link between Your telemetry ID and Your email address will be permanently removed. By continuing to use Editor or Solution with this feature enabled You agree to this Usage Data collection.

#### 3.3.3. Crash Reports

Customer Data consisting of data related to the behavior of the Solution prior to a crash or failure, such as stack traces are collected and classified as "Crash Reports". Zed will use commercially reasonable efforts to exclude any personally identifiable information from Crash Reports, but due to the nature of a crash, Zed does not ensure that information such as paths will be excluded from Crash Reports. Crash Reports will be used solely for Zed's internal purposes in connection with diagnosing defects in the Solution that led to the crash. You may grant us permission to capture Crash Reports when installing or activating the Solution, and You may change Your preferences at any time in the settings feature of the Solution. Once You grant us this permission, Zed will retain the Crash Reports indefinitely.

#### 3.3.4. User Content

• You may access, modify or create certain data or information in connection with your access or use of the Zed Editor or the Solution. Such data and information may include, but is not limited to any of the following:

- (a) file contents and associated metadata (e.g., filename, paths, size, timestamps);
- (b) source control history, comments and metadata (e.g., git history, commit messages);
- (c) configuration data (e.g., settings, keymaps);
- (d) anything typed, pasted and/or displayed on screen while using the Editor;
- (e) derivative works of the above generated by the Editor (e.g., format conversions, summaries, indexes, caches);
- (f) metadata, code and other derivative works of the above returned by language servers and other local tooling; and
- (g) metadata, code and other derivative works of the above returned by services integrated with the Zed Editor

(a-g collectively, "User Content").

#### 3.3.5. Handling of User Content

Zed will make use of or transfer User Content only as specified in this Agreement, or as necessary to comply with applicable law.

#### 3.3.5.1. Zed Collaboration Services

When using Zed Collaboration Services, User Content is transmitted from Your environment only if You collaborate with other Zed users by electing to share a project in the Editor. Once You share a project, Zed may transmit User Content consisting of file paths, file contents, and metadata regarding the code returned by language servers. Currently, Zed does not persist any User Content beyond the Your collaboration session. If You unshare a project or disconnect from the Solution, all information associated with such project will be deleted from Zed servers. In the future, Zed may save User Content regarding projects beyond the scope of a single collaboration session. We may share such User Content with those users You elected to grant access to. Zed's access to such User Content is limited to debugging and making improvements to the Solution.

#### 3.3.5.2. Other Services

The Zed Editor supports integration with API-based services maintained and not operated by Zed (the "Other Services"). By way of example, Other Services includes those made available by GitHub, Anthropic, OpenAI, and similar providers, or those You host or manage directly. You may configure the Zed Editor to interoperate, communicate with, and exchange data (including User Content) directly with the Other Services. Zed is not responsible or otherwise liable with respect to Your use of any Other Service, including but not limited to the exchange of data between the Other Service and the Zed Editor. The terms and conditions, including the applicable privacy policy, with respect to the Other Service are those made available by the applicable Other Service, not these Terms.

#### 3.3.5.3. Zed AI Services

The Zed Editor supports integration with API-based services maintained and operated by Zed (the "Zed AI Services"). You may elect to use Zed AI Services as the provider for various Zed Editor features (e.g., Agent Panel, Inline Assistant, Edit Predictions, and similar features). In connection with Your use of these features, the Zed Editor and Zed AI Services may make use of User Content to generate contextually relevant responses (the “Output”). Other than as specified in Section 3.3.5.4 of these Terms, Zed will not use User Content for training of its models, or disclose User Content.

Output is provided "as is" without any warranties or guarantees of functionality, security, or fitness for a particular purpose. While efforts are made to ensure the accuracy and reliability, Output may include errors, vulnerabilities, and defects. You are responsible for reviewing, testing, and validating Output before use in any production or critical environment. Zed assumes no liability for any damages, losses, or liability arising from the use, modification, reliance on, or deployment of Output. Any such use is at Your own risk.

#### 3.3.5.4. Improvement Feedback

When using Zed AI Services to provide Edit Predictions in connection with certain open source software projects, You may elect to share requests, responses and feedback comments (collectively "Model Improvement Feedback") with Zed, and Zed may use the same to improve Zed Edit Predictions models. You may opt-out of sharing Model Improvement Feedback at any time.

For more information on Zed Edit Predictions please see: [https://zed.dev/docs/ai/ai-improvement](https://zed.dev/docs/ai/ai-improvement)

When using Zed AI Services in connection with the Agent Panel, You may elect to share with Zed requests, responses and feedback regarding the Agent Panel and related Output (the “Agent Improvement Feedback”) with Zed, and Zed may use the same to improve the Agent Panel and related Output. Zed will only collect Agent Improvement Feedback when You elect to share the same.

For more information regarding the Agent Panel please see: [https://zed.dev/docs/ai/ai-improvement](https://zed.dev/docs/ai/ai-improvement)

#### 3.4. Privacy Policy

You and Zed are bound by the terms and conditions contained in the Zed Privacy Policy which is incorporated by reference hereto. The Zed Privacy Policy is available at the following URL: [https://zed.dev/privacy-policy](https://zed.dev/privacy-policy).

## 4. FEE BASED SERVICES, FEES AND PAYMENT TERMS

### 4.1. Fee Based Services

The Zed AI Services is made available with additional usage benefits (the “Enhanced Use ”) as described in the table published at [zed.dev/pricing](https://zed.dev/pricing) (the “Pricing Table”), subject to the requirements and limitations set forth in the Pricing Table and these Terms. In order to make use of the Enhanced Use, Customer must access the Zed AI Services through a Zed registered account.

### 4.2. Fees

Customer shall pay to Zed the applicable fees set forth in Pricing Table, together with any applicable taxes and shipping and handling (collectively, the “Fees”). Customer shall have no right of return, and all Fees shall be non-refundable.

### 4.3. Payment Terms

All amounts payable to Zed under this Agreement shall be paid in United States dollars and paid Zed according to the method of payment, frequency and calculated as set forth in the Pricing Table.

### 4.4. Taxes; Set-offs

Any and all payments made by Customer in accordance with this Agreement are exclusive of any taxes that might be assessed by any jurisdiction. Customer shall pay or reimburse Zed for all sales, use, property and similar taxes; all customs duties, import fees, stamp duties, license fees and similar charges; and all other mandatory payments to government agencies of whatever kind, except taxes imposed on the net or gross income of Zed. All amounts payable to Zed under this Agreement shall be without set-off and without deduction of any taxes, levies, imposts, charges, withholdings and/or duties of any nature which may be levied or imposed, including without limitation, value added tax, customs duty and withholding tax.

## 5. TERM AND TERMINATION

### 5.1. Term

The term of this Agreement shall commence on the date You first download the Editor or use the Zed Service (the "Effective Date"), and unless terminated earlier according to this Section 3, will end pursuant to this Section 5 (the "Term").

### 5.2. Termination

This Agreement may be terminated: (a) by either party if the other has materially breached this Agreement; or (b) by Zed at any time and for any reason upon notice to Customer. You acknowledge that Zed is under no obligation to continue to operate the Zed Service or make the Editor available, and We may end any programs in connection with the same at any time.

### 5.3. Effect of Termination and Survival

Upon any expiration or termination of this Agreement, Customer shall (i) immediately cease use of the Zed Service, and (ii) return all Zed Confidential Information and other materials provided by Zed. The following provisions will survive termination of this Agreement: Sections 3.3 (Customer Data), Section 3.4 (Privacy Policy), Section 5.3 (Effect of Termination and Survival), Section 6 (Ownership), Section 7 (Indemnification), Section 9 (Limitation of Liability), Section 10 (Third Party Services), and Section 11 (Miscellaneous).

## 6. OWNERSHIP

Zed retains all right, title, and interest in and to the Zed Service, Editor, and any software, products, works or other intellectual property created, used, provided, or made available by Zed under or in connection with the Zed Service or Editor. Customer may from time to time provide suggestions, comments, or other feedback to Zed with respect to the Zed Service or Editor ("Feedback"). Customer shall, and hereby does, grant to Zed a nonexclusive, worldwide, perpetual, irrevocable, transferable, sublicensable, royalty-free, fully paid-up license to use and exploit the Feedback for any purpose. You retain all right, title and interest in and to the Customer Data, including all intellectual property rights therein. No intellectual property rights with respect to any software code you develop or modify with the Editor or Zed Service (collectively, the “Output”) are transferred or assigned to Zed hereunder.

## 7. INDEMNIFICATION

Customer will defend, indemnify, and hold Zed, its affiliates, suppliers and licensors harmless and each of their respective officers, directors, employees and representatives from and against any claims, damages, losses, liabilities, costs, and expenses (including reasonable attorneys' fees) arising out of or relating to any third party claim with respect to: (a) Customer Data; (b) breach of this Agreement or violation of applicable law by Customer; or (c) alleged infringement or misappropriation of third-party's intellectual property rights resulting from Customer Data.

## 8. WARRANTY

Zed does not represent or warrant that the operation of the Zed Service or Editor (or any portion thereof) will be uninterrupted or error free, or that the Zed Service or Editor (or any portion thereof) will operate in combination with other hardware, software, systems or data not provided by Zed. CUSTOMER ACKNOWLEDGES THAT, ZED MAKES NO EXPRESS OR IMPLIED REPRESENTATIONS OR WARRANTIES OF ANY KIND WITH RESPECT TO THE SERVICE OR SOFTWARE, OR THEIR CONDITION. ZED HEREBY EXPRESSLY EXCLUDES, ANY AND ALL OTHER EXPRESS OR IMPLIED REPRESENTATIONS OR WARRANTIES, WHETHER UNDER COMMON LAW, STATUTE OR OTHERWISE, INCLUDING WITHOUT LIMITATION ANY AND ALL WARRANTIES AS TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, SATISFACTORY QUALITY OR NON-INFRINGEMENT OF THIRD-PARTY RIGHTS.

## 9. LIMITATIONS OF LIABILITY

IN NO EVENT SHALL ZED BE LIABLE FOR ANY LOST DATA, LOST PROFITS, BUSINESS INTERRUPTION, REPLACEMENT SERVICE OR OTHER SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR INDIRECT DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THEORY OF LIABILITY. ZED'S LIABILITY FOR ALL CLAIMS ARISING UNDER THIS AGREEMENT, WHETHER IN CONTRACT, TORT OR OTHERWISE, SHALL NOT EXCEED THE GREATER OF: THE FEES PAID TO ZED BY CUSTOMER DURING THE TWELVE (12) MONTH PERIOD PRECEDING THE DATE OF THE CLAIM, OR ONE THOUSAND US DOLLARS ($1,000).

## 10. Third Party Services

Zed may make certain third party services available to You within the Editor or the Zed Service (each a "Third Party Service"). You acknowledge and agree that (a) use of each Third Party Service is subject to the corresponding terms and conditions available at the following URL: [https://zed.dev/third-party-terms](https://zed.dev/third-party-terms) and/or presented in connection with Your use of such Third Party Service; (b) the terms and conditions of this Agreement do not apply with respect to Your use of any Third Party Service; and (c) Zed is not liable in any way regarding Your use of any Third Party Service.

## 11. MISCELLANEOUS

### 11.1. Export Control

You hereby certify that You will comply with all current US Export Control laws. You agree to defend, indemnify and hold Zed harmless from any liability for Your violation of U.S. Export Control laws.

### 11.2. Compliance with Laws

You shall comply with all applicable laws and regulations in its use of the Solution, including without limitation the unlawful gathering or collecting, or assisting in the gathering or collecting of information in violation of any privacy laws or regulations. You shall, at its own expense, defend, indemnify and hold harmless Zed from and against any and all claims, losses, liabilities, damages, judgments, government or federal sanctions, costs and expenses (including attorneys' fees) incurred by Zed arising from any claim or assertion by any third party of violation of privacy laws or regulations by You or any of its agents, officers, directors or employees.

### 11.3. Assignment

Neither party may transfer and assign its rights and obligations under this Agreement without the prior written consent of the other party. Notwithstanding the foregoing, Zed may transfer and assign its rights under this Agreement without consent from the other party in connection with a change in control, acquisition or sale of all or substantially all of its assets.

### 11.4. Force Majeure

Neither party shall be responsible for failure or delay in performance by events out of their reasonable control, including but not limited to, acts of God, Internet outage, terrorism, war, fires, earthquakes and other disasters (each a "Force Majeure"). Notwithstanding the foregoing: if a Force Majeure continues for more than thirty (30) days, either party may to terminate this agreement by written notice to the other party.

### 11.5. Notice

All notices between the parties shall be in writing and shall be deemed to have been given if personally delivered or sent by registered or certified mail (return receipt), or by recognized courier service.

### 11.6. No Agency

Both parties agree that no agency, partnership, joint venture, or employment is created as a result of this Agreement. You do not have any authority of any kind to bind Zed.

### 11.7. Governing Law

This Agreement shall be governed exclusively by, and construed exclusively in accordance with, the laws of the United States and the State of California, without regard to its conflict of laws provisions. The federal courts of the United States in the Northern District of California and the state courts of the State of California shall have exclusive jurisdiction to adjudicate any dispute arising out of or relating to this Agreement. Each party hereby consents to the jurisdiction of such courts and waives any right it may otherwise have to challenge the appropriateness of such forums, whether on the basis of the doctrine of forum non conveniens or otherwise. The United Nations Convention on Contracts for the International Sale of Goods shall not apply to this Agreement or any Purchase Order issued under this Agreement.

### 11.8. Updated Agreement

Zed reserves the right to update this Agreement at any time. The terms and conditions of the updated version of the Agreement shall apply to the Zed Service and Editor downloaded, or accessed following the date of publication of the updated version. If You do not agree with any terms of the updated Agreement, You may not use or access the Zed Service or Editor in any manner. Zed may from time-to-time provide release notes applicable to the Editor or Zed Service, and such release notes may contain additional use restrictions or terms applicable to Customer Data. Your use of the Editor or Zed Service after the applicable release notes are made available shall be subject to the additional use restrictions or terms applicable to Customer Data.

### 11.9. Entire Agreement

This Agreement is the complete and exclusive statement of the mutual understanding of the parties and supersedes and cancels all previous written and oral agreements, communications, and other understandings relating to the subject matter of this Agreement, and all waivers and modifications must be in a writing signed by both parties, except as otherwise provided herein. Any term or provision of this Agreement held to be illegal or unenforceable shall be, to the fullest extent possible, interpreted so as to be construed as valid, but in any event the validity or enforceability of the remainder hereof shall not be affected.

**DATE: May 6, 2025**

    ---
title: 3rd Party Terms
slug: third-party-terms
---

In addition to the [Zed End User Terms](/terms) and [Zed Privacy Policy](/privacy-policy) usage of certain Zed features may also subject you to additional 3rd party terms and conditions. These terms and conditions may include, but are not limited to, the following:

## Anthropic

- [Anthropic Usage Policy](https://www.anthropic.com/legal/aup)
- [Anthropic Privacy Policy](https://www.anthropic.com/legal/privacy)
- [Anthropic Commercial Terms of Service](https://www.anthropic.com/legal/commercial-terms)

## Baseten

- [BaseTen Terms and Conditions](https://www.baseten.co/terms-and-conditions/)

### Exa.ai

- [Exa Labs Terms and Conditions](https://exa.ai/assets/Exa_Labs_Terms_of_Service.pdf)
- [Exa Labs Privacy Policy](https://exa.ai/privacy-policy)

## GitHub

- [GitHub Terms of Service](https://docs.github.com/en/site-policy/github-terms/github-terms-of-service)
- [GitHub Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement)
- [GitHub Acceptable Use Policies](https://docs.github.com/en/site-policy/acceptable-use-policies/github-acceptable-use-policies)
- [GitHub Copilot Product Specific Terms](https://github.com/customer-terms/github-copilot-product-specific-terms)

## Google

- [Google APIs Terms of Service](https://developers.google.com/terms)
- [Google Gemini API Additional Terms of Service](https://ai.google.dev/gemini-api/terms)
- [Google Generative AI Prohibited Use Policy](https://policies.google.com/terms/generative-ai/use-policy)

## LiveKit

- [LiveKit Terms of Service](https://livekit.io/legal/terms-of-service)
- [LiveKit Privacy Policy](https://livekit.io/legal/privacy-policy)

## OpenAI

- [OpenAI Terms of Use](https://openai.com/policies/terms-of-use/)
- [OpenAI Privacy Policy](https://openai.com/policies/privacy-policy/)
- [OpenAI Business terms](https://openai.com/policies/business-terms/)
- [OpenAI Service terms](https://openai.com/policies/service-terms/)

## SuperMaven

- [SuperMaven Terms of Service](https://supermaven.com/terms-of-service)
- [SuperMaven Privacy Policy](https://supermaven.com/privacy-policy)

**DATE: May 6, 2025**