1# Developing Extensions
2
3## Extension Capabilities
4
5Extensions can add the following capabilities to Zed:
6
7- [Languages](./languages.md)
8- [Debuggers](./debugger-extensions.md)
9- [Themes](./themes.md)
10- [Icon Themes](./icon-themes.md)
11- [Slash Commands](./slash-commands.md)
12- [MCP Servers](./mcp-extensions.md)
13
14## Developing an Extension Locally
15
16Before starting to develop an extension for Zed, be sure to [install Rust via rustup](https://www.rust-lang.org/tools/install).
17
18> Rust must be installed via rustup. If you have Rust installed via homebrew or otherwise, installing dev extensions will not work.
19
20When developing an extension, you can use it in Zed without needing to publish it by installing it as a _dev extension_.
21
22From the extensions page, click the `Install Dev Extension` button and select the directory containing your extension.
23
24If you already have a published extension with the same name installed, your dev extension will override it.
25
26## Directory Structure of a Zed Extension
27
28A Zed extension is a Git repository that contains an `extension.toml`. This file must contain some
29basic information about the extension:
30
31```toml
32id = "my-extension"
33name = "My extension"
34version = "0.0.1"
35schema_version = 1
36authors = ["Your Name <you@example.com>"]
37description = "My cool extension"
38repository = "https://github.com/your-name/my-zed-extension"
39```
40
41In 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:
42
43```
44my-extension/
45 extension.toml
46 Cargo.toml
47 src/
48 lib.rs
49 languages/
50 my-language/
51 config.toml
52 highlights.scm
53 themes/
54 my-theme.json
55```
56
57## WebAssembly
58
59Procedural 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:
60
61```toml
62[package]
63name = "my-extension"
64version = "0.0.1"
65edition = "2021"
66
67[lib]
68crate-type = ["cdylib"]
69
70[dependencies]
71zed_extension_api = "0.1.0"
72```
73
74Use 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.
75
76In 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:
77
78```rs
79use zed_extension_api as zed;
80
81struct MyExtension {
82 // ... state
83}
84
85impl zed::Extension for MyExtension {
86 // ...
87}
88
89zed::register_extension!(MyExtension);
90```
91
92> `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.
93
94## Forking and cloning the repo
95
961. Fork the repo
97
98> 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.
99
1002. Clone the repo to your local machine
101
102```sh
103# Substitute the url of your fork here:
104# git clone https://github.com/zed-industries/extensions
105cd extensions
106git submodule init
107git submodule update
108```
109
110## Publishing your extension
111
112To publish an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).
113
114In your PR, do the following:
115
1161. Add your extension as a Git submodule within the `extensions/` directory
117
118```sh
119git submodule add https://github.com/your-username/foobar-zed.git extensions/foobar
120git add extensions/foobar
121```
122
123> All extension submodules must use HTTPS URLs and not SSH URLS (`git@github.com`).
124
1252. Add a new entry to the top-level `extensions.toml` file containing your extension:
126
127```toml
128[my-extension]
129submodule = "extensions/my-extension"
130version = "0.0.1"
131```
132
133> If your extension is in a subdirectory within the submodule you can use the `path` field to point to where the extension resides.
134
1353. Run `pnpm sort-extensions` to ensure `extensions.toml` and `.gitmodules` are sorted
136
137Once your PR is merged, the extension will be packaged and published to the Zed extension registry.
138
139> Extension IDs and names should not contain `zed` or `Zed`, since they are all Zed extensions.
140
141## Updating an extension
142
143To update an extension, open a PR to [the `zed-industries/extensions` repo](https://github.com/zed-industries/extensions).
144
145In your PR do the following:
146
1471. Update the extension's submodule to the commit of the new version.
1482. Update the `version` field for the extension in `extensions.toml`
149 - Make sure the `version` matches the one set in `extension.toml` at the particular commit.
150
151If you'd like to automate this process, there is a [community GitHub Action](https://github.com/huacnlee/zed-extension-action) you can use.