首页
/ Zed 扩展开发实战指南:extension.toml 清单、Rust/WASM 实现与本地 Dev Extension 调试

Zed 扩展开发实战指南:extension.toml 清单、Rust/WASM 实现与本地 Dev Extension 调试

2026-09-06 17:57:30作者:咎竹峻Karen

Zed 的扩展机制允许开发者以 Git 仓库加一份 extension.toml 清单的形式,向编辑器注入语言支持、主题、调试器、代码片段和 MCP 服务器等能力。本文基于官方文档 Developing Extensions 展开,结合本仓库中 extensions/ 目录下的真实扩展样例与 crates/extensioncrates/extension_api 中的实现源码,完整覆盖:扩展清单与目录结构、本地开发安装(Dev Extension)流程、Rust 编译到 WebAssembly 的关键约束,以及调试手段。读完本文,你可以独立搭建一个 Zed 扩展骨架,将其以开发模式装进 Zed 并排查问题。

一、扩展能做什么:能力总览

一个 Zed 扩展是一个包含 extension.toml 清单文件的 Git 仓库,它可以提供以下能力:

从源码结构看,这些能力并非只是文档约定,而是由清单解析代码逐字段驱动的。扩展清单定义 中的 ExtensionManifest 结构体包含 themesicon_themeslanguagesgrammarslanguage_serverscontext_serversslash_commandssnippetscapabilitiesdebug_adaptersdebug_locatorslanguage_model_providers 等字段,每个字段都是可选的(#[serde(default)]),扩展按需声明自己提供哪些能力。provides() 方法会扫描这些字段,汇总出该扩展实际提供的能力集合,供 Zed 在扩展页面展示与索引使用。

二、开发环境准备:Rust 工具链与 wasi-sdk

在动手写扩展之前,必须先完成环境准备,这是本地开发能否跑通的前置条件:

  1. 安装 Rust:通过 rustup 安装。Zed 使用 wasm32-wasip2 Rust 目标来编译扩展;如果 Rust 是通过 rustup 安装的,Zed 会自动安装该目标;如果 Rust 是通过其他方式安装的(如 Homebrew 或 Nix),你需要自行让 wasm32-wasip2 目标可用——例如把它加入 Nix rust-overlay 或 fenix 工具链的 targets 配置中。

  2. 提供 wasi-sdk(仅当扩展包含语法解析器时):提供 grammars 的扩展还需要 wasi-sdk 来编译 Tree-sitter 解析器。Zed 会自动下载,但如果你已有现成的安装,可以将环境变量 WASI_SDK_PATH 指向其根目录(即包含 bin/clang 的那一层)。

WASI_SDK_PATH 的处理逻辑可以在扩展构建源码中得到印证:extension_builder.rs 中,构建器首先读取该环境变量,如果指向的目录下能找到 clang,则以 INFO 级别日志记录并直接使用本地 SDK;否则打印回退日志,转而从网络下载。这意味着配置错误的 WASI_SDK_PATH 不会直接导致构建失败,而是静默回退到下载流程——排查“为何每次都在下载 wasi-sdk”时,应重点检查该路径下是否存在 bin/clang

三、本地开发:以 Dev Extension 方式安装

扩展开发期间不必发布到注册表,可以直接以**开发扩展(dev extension)**的形式在 Zed 中使用:

  • 在扩展页面(Extensions 页面)点击 Install Dev Extension 按钮,或通过命令面板执行 zed::InstallDevExtension 动作,选择包含你扩展的目录即可。

从源码结构看,该动作在 extensions_ui 中注册,并作为 ErrorAction(即出错时会高亮提示的动作)绑定到 InstallDevExtension 动作处理函数;当你安装过同 id 的已发布版本后,再次安装 dev 扩展会先卸载已发布版本,安装成功后扩展卡片上会显示“Overridden by dev extension.”的标注——这段提示文案正是定义在 extension_card.rs

排查问题的两个入口:

  • 查看 Zed.log(通过 zed::OpenLog 动作打开日志),可以看到更多扩展加载相关的输出;
  • 如需调试输出,从命令行以 zed --foreground 关闭并重启 Zed,可以看到更详细的 INFO 级别日志。

四、扩展的清单与目录结构

一个 Zed 扩展是一个包含 extension.toml 的 Git 仓库。该清单必须包含关于扩展的基本信息:

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

其中 schema_version = 1 对应源码中的 SchemaVersion 类型(见 extension_manifest.rs)。仓库内保留的 OldExtensionManifest 结构则说明了历史上扩展清单曾以 extension.json 形式存在,schema_version 正是为了区分这两个格式而保留的。

在此基础之上,还有多个可选的目录和文件用于添加功能。一个提供全部能力的扩展,其示例目录结构如下:

my-extension/
  extension.toml
  Cargo.toml
  src/
    lib.rs
  languages/
    my-language/
      config.toml
      highlights.scm
  themes/
    my-theme.json
  snippets/
    snippets.json
    rust.json

对照仓库内真实存在的 test-extension 清单可以看到清单字段在实践中的用法:

id = "test-extension"
name = "Test Extension"
description = "An extension for use in tests."
version = "0.1.0"
schema_version = 1
authors = ["Marshall Bowers <elliott.codes@gmail.com>"]
repository = "https://github.com/zed-industries/zed"

[language_servers.gleam]
name = "Gleam LSP"
language = "Gleam"

[grammars.gleam]
repository = "https://github.com/gleam-lang/tree-sitter-gleam"
commit = "8432ffe32ccd360534837256747beb5b1c82fca1"

[[capabilities]]
kind = "process:exec"
command = "echo"
args = ["hello from a child process!"]

这个样例展示了三个要点:[language_servers.*] 声明该扩展负责提供某语言的 LSP;[grammars.*] 通过固定 repositorycommit 锁定 Tree-sitter 语法仓库的版本,保证不同用户编译出一致的解析器;[[capabilities]] 声明扩展运行所需的权限(如 process:exec 子进程执行能力),Zed 会据此对扩展行为做沙箱约束。

仓库内还有其他可直接参考的官方维护扩展,包括 glslhtmlproto,其中 proto 扩展 是一个包含多种语言服务器候选实现的完整 Rust 扩展范例。

五、Rust 与 WebAssembly:编写带代码的扩展

先明确一个前提:大多数扩展不需要任何 Rust 代码——只有语言服务器(language server)、上下文服务器(context server)和调试器扩展才需要自定义 Rust 代码才能正常工作。纯语言/主题/片段类扩展只靠 extension.toml 和静态文件即可运行。

需要自定义代码时,在你的扩展中放入如下 Cargo.toml

[package]
name = "my-extension"
version = "0.0.1"
edition = "2021"

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

[dependencies]
zed_extension_api = "0.1.0"

这里 crate-type = ["cdylib"] 是编译到 WebAssembly 的关键配置。依赖版本上,应使用 crates.io 上最新的 zed_extension_api,并确认其与你要支持的 Zed 版本仍然兼容。本仓库 crates/extension_api/README.md 中维护了完整的版本兼容表,例如 Zed 0.192.x 对应 zed_extension_api 0.0.10.6.0,Zed 0.131.x 对应 0.0.10.0.6。从源码目录结构看,crates/extension_api/wit 下按 since_v0.0.1since_v0.8.0 分目录存放了各版本的 WIT 接口定义(如 extension.witlsp.witgithub.witdap.witcontext-server.witslash-command.wit),这些就是扩展宿主与 WASM 扩展之间交互的接口契约——新版本 API 增加的功能(如 DAP 调试适配器支持在 since_v0.6.0 中出现)即通过这些 WIT 文件逐版本扩展。

src/lib.rs 中,你需要为扩展定义一个结构体并实现 Extension trait,同时用 register_extension! 宏注册扩展:

use zed_extension_api as zed;

struct MyExtension {
    // ... state
}

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

zed::register_extension!(MyExtension);

仓库内 test-extension 的 Rust 入口 是这段模式的完整实例:TestExtension 结构体持有 cached_binary_path 状态,new() 中初始化,language_server_command() 中返回 LSP 启动命令(zed::Commandcommandargsenv 三字段),label_for_completion() 中把 LSP 的补全结果转换成带语法高亮 span 的 CodeLabel,最后以 zed::register_extension!(TestExtension); 收尾。它同时还演示了两个实用技巧:

  • zed::current_platform() 获取平台/架构,按平台分支构造命令(Windows 下用 cmd /C echo,Linux/Mac 下用 echo);
  • zed::latest_github_release() + zed::download_file() 下载并缓存语言服务器二进制,配合 zed::set_language_server_installation_status() 更新安装状态(CheckingForUpdateDownloadingNone)。

WASM 环境的限制:由于扩展会被编译到 WebAssembly,部分 Rust 特性不会按预期工作。例如 cfg 指令不生效,std::env::var 也拿不到期望的结果。正确做法是:

  • zed_extension_api::current_platform 获取当前环境信息;
  • Worktree 结构体及其方法读取环境变量、在用户的 PATH 中查找二进制。

六、调试你的 Rust 扩展

扩展的 stdout/stderr 会直接转发到 Zed 进程。因此要在终端看到扩展中 println!/dbg! 的输出,需要:

  1. 在终端中以 --foreground 参数启动 Zed:zed --foreground
  2. 观察终端中的日志输出;遇到加载失败时再配合 Zed.logzed::OpenLog)定位。

仓库中对这套调试方式有直接验证:test_extension.rs 中就是通过 println! 打印子进程输出,供集成测试断言终端日志。此外该测试扩展的 extension.toml 中声明了两个 process:exec 能力(分别对应 echo 与 Windows 下的 cmd /C echo),源码中的 language_server_binary_path 会实际执行这些命令并验证输出——这正是一个“清单声明能力 + Rust 代码使用能力”的端到端示例。

七、关键路径速查

主题 位置
本文对应的官方文档 docs/src/extensions/developing-extensions.md
扩展 API 的 README 与版本兼容表 crates/extension_api/README.md
清单解析(ExtensionManifest crates/extension/src/extension_manifest.rs
wasi-sdk / WASI_SDK_PATH 处理 crates/extension/src/extension_builder.rs
完整 Rust 扩展样例 extensions/test-extension/
官方语言扩展样例(glsl/html/proto) extensions/README.md
各版本 WIT 接口契约 crates/extension_api/wit/

以上路径均可在当前仓库中直接查看,配合官方文档即可开始你的第一个 Zed 扩展开发。

登录后查看全文
热门项目推荐
相关项目推荐