developing-extensions.md

  1---
  2title: Developing Extensions
  3description: "Create Zed extensions: languages, themes, debuggers, slash commands, and more."
  4---
  5
  6# Developing Extensions {#developing-extensions}
  7
  8Zed extensions are Git repositories containing an `extension.toml` manifest. They can provide languages, themes, debuggers, snippets, slash commands, and MCP servers.
  9
 10## Extension Features {#extension-features}
 11
 12Extensions can provide:
 13
 14- [Languages](./languages.md)
 15- [Debuggers](./debugger-extensions.md)
 16- [Themes](./themes.md)
 17- [Icon Themes](./icon-themes.md)
 18- [Snippets](./snippets.md)
 19- [Slash Commands](./slash-commands.md)
 20- [MCP Servers](./mcp-extensions.md)
 21
 22## Developing an Extension Locally
 23
 24Before starting to develop an extension for Zed, be sure to [install Rust via rustup](https://www.rust-lang.org/tools/install).
 25
 26> Rust must be installed via rustup. If you have Rust installed via homebrew or otherwise, installing dev extensions will not work.
 27
 28When developing an extension, you can use it in Zed without needing to publish it by installing it as a _dev extension_.
 29
 30From the extensions page, click the `Install Dev Extension` button (or the {#action zed::InstallDevExtension} action) and select the directory containing your extension.
 31
 32If you need to troubleshoot, check Zed.log ({#action zed::OpenLog}) for additional output. For debug output, close and relaunch Zed from the command line with `zed --foreground`, which shows more verbose INFO-level logs.
 33
 34If you already have the published version of the extension installed, the published version will be uninstalled prior to the installation of the dev extension. After successful installation, the `Extensions` page will indicate that the upstream extension is "Overridden by dev extension".
 35
 36## Directory Structure of a Zed Extension
 37
 38A Zed extension is a Git repository that contains an `extension.toml`. This file must contain some
 39basic information about the extension:
 40
 41```toml
 42id = "my-extension"
 43name = "My extension"
 44version = "0.0.1"
 45schema_version = 1
 46authors = ["Your Name <you@example.com>"]
 47description = "Example extension"
 48repository = "https://github.com/your-name/my-zed-extension"
 49```
 50
 51> **Note:** If you are working on a theme extension with the intent to publish it later, suffix your theme extension ID with `-theme`. Otherwise, this may be raised during [extension publishing](#publishing-your-extension).
 52
 53In 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:
 54
 55```
 56my-extension/
 57  extension.toml
 58  Cargo.toml
 59  src/
 60    lib.rs
 61  languages/
 62    my-language/
 63      config.toml
 64      highlights.scm
 65  themes/
 66    my-theme.json
 67  snippets/
 68    snippets.json
 69    rust.json
 70```
 71
 72## WebAssembly
 73
 74Procedural 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:
 75
 76```toml
 77[package]
 78name = "my-extension"
 79version = "0.0.1"
 80edition = "2021"
 81
 82[lib]
 83crate-type = ["cdylib"]
 84
 85[dependencies]
 86zed_extension_api = "0.1.0"
 87```
 88
 89Use 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.
 90
 91In 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:
 92
 93```rs
 94use zed_extension_api as zed;
 95
 96struct MyExtension {
 97    // ... state
 98}
 99
100impl zed::Extension for MyExtension {
101    // ...
102}
103
104zed::register_extension!(MyExtension);
105```
106
107> `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.
108
109## Forking and cloning the repo
110
1111. Fork the repo
112
113> **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.
114
1152. Clone the repo to your local machine
116
117```sh
118# Substitute the url of your fork here:
119# git clone https://github.com/zed-industries/extensions
120cd extensions
121git submodule init
122git submodule update
123```
124
125## Extension License Requirements
126
127As of October 1st, 2025, extension repositories must include a license.
128The following licenses are accepted:
129
130- [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)
131- [BSD 2-Clause](https://opensource.org/license/bsd-2-clause)
132- [BSD 3-Clause](https://opensource.org/license/bsd-3-clause)
133- [CC BY 4.0](https://creativecommons.org/licenses/by/4.0)
134- [GNU GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)
135- [GNU LGPLv3](https://www.gnu.org/licenses/lgpl-3.0.en.html)
136- [MIT](https://opensource.org/license/mit)
137- [Unlicense](https://unlicense.org)
138- [zlib](https://opensource.org/license/zlib)
139
140This allows us to distribute the resulting binary produced from your extension code to our users.
141Without a valid license, the pull request to add or update your extension in the following steps will fail CI.
142
143Your license file should be at the root of your extension repository. Any filename that has `LICENCE` or `LICENSE` as a prefix (case insensitive) will be inspected to ensure it matches one of the accepted licenses. See the [license validation source code](https://github.com/zed-industries/extensions/blob/main/src/lib/license.js).
144
145> This license requirement applies only to your extension code itself (the code that gets compiled into the extension binary).
146> It does not apply to any tools your extension may download or interact with, such as language servers or other external dependencies.
147> If your repository contains both extension code and other projects (like a language server), you are not required to relicense those other projects—only the extension code needs to be one of the aforementioned accepted licenses.
148
149## Publishing your extension
150
151To publish an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).
152
153In your PR, do the following:
154
1551. Add your extension as a Git submodule within the `extensions/` directory
156
157```sh
158git submodule add https://github.com/your-username/foobar-zed.git extensions/foobar
159git add extensions/foobar
160```
161
162> All extension submodules must use HTTPS URLs and not SSH URLS (`git@github.com`).
163
1642. Add a new entry to the top-level `extensions.toml` file containing your extension:
165
166```toml
167[my-extension]
168submodule = "extensions/my-extension"
169version = "0.0.1"
170```
171
172> If your extension is in a subdirectory within the submodule you can use the `path` field to point to where the extension resides.
173
1743. Run `pnpm sort-extensions` to ensure `extensions.toml` and `.gitmodules` are sorted
175
176Once your PR is merged, the extension will be packaged and published to the Zed extension registry.
177
178> Extension IDs and names should not contain `zed` or `Zed`, since they are all Zed extensions.
179
180## Updating an extension
181
182To update an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).
183
184In your PR do the following:
185
1861. Update the extension's submodule to the commit of the new version. For this, you can run
187
188```sh
189# From the root of the repository:
190git submodule update --remote extensions/your-extension-name
191```
192
193to update your extension to the latest commit available in your remote repository.
194
1952. Update the `version` field for the extension in `extensions.toml`
196   - Make sure the `version` matches the one set in `extension.toml` at the particular commit.
197
198If you'd like to automate this process, there is a [community GitHub Action](https://github.com/huacnlee/zed-extension-action) you can use.
199
200> **Note:** If your extension repository has a different license, you'll need to update it to be one of the [accepted extension licenses](#extension-license-requirements) before publishing your update.