ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Cursor插件开发实战:从plugin.json到中文增强插件

Cursor插件开发实战:从plugin.json到中文增强插件 1. 项目概述从“plugins”这个词开始我们到底在谈什么“plugins”不是某个具体软件的专属名词它是一个通用技术概念就像“螺丝”之于机械、“插头”之于电器——它代表一种可插拔、可替换、可组合的扩展能力设计范式。当你在 Cursor、VS Code、Figma、Obsidian 甚至 Chrome 浏览器里点击“安装插件”你实际是在调用一套被精心设计的运行时契约主程序预留好接口API插件按约定格式打包比如一个含plugin.json的文件夹加载器负责校验、沙箱隔离、生命周期管理最后把功能“缝合”进主界面或工作流中。这不是简单的功能追加而是一套工程化协作协议。最近大量用户搜索“iar plugins 是干什么d”“harness failed to load plugins”“cursor下载插件”“cursor怎么设置中文”表面是操作困惑深层暴露的是对这套协议的陌生——他们不知道plugin.json是插件的“身份证”不清楚 TypeScript SDK 是开发者写插件的“施工图纸”更不理解 CLI 工具如codex cli、zcode cli其实是插件开发流水线上的“自动拧螺丝机”。这些热词背后是两类人的真实需求一类是终端用户想让 Cursor 真正“听懂中文”、快速装上代码补全或文档生成插件另一类是开发者想基于 Cursor 的 TypeScript SDK 快速产出可分发的插件却卡在failed to load plugins web boot: 2 entries did not activate这类报错上连第一步都迈不出去。我做插件开发和一线技术支持超过八年经手过上百个跨平台插件项目从 VS Code 到 JetBrains IDE 插件桥接再到浏览器 DevTools 扩展最深的体会是90% 的“插件失败”问题根源不在代码而在对加载机制的误判。比如linxin666/dsh-p插件激活失败大概率不是它本身有 bug而是你的 Cursor 版本低于它要求的最低 SDK 兼容版本huayu-yuan插件未激活往往是因为它的plugin.json中activationEvents字段写成了onCommand:xxx但你根本没注册这个命令——这就像给门锁配了钥匙却忘了在门框上装锁舌。这篇文章不讲抽象理论只拆解真实场景从plugin.json的每个字段怎么填、为什么这么填到 CLI 工具如何自动生成符合规范的骨架再到 TypeScript SDK 里ExtensionContext和commands.registerCommand这些核心 API 的实操陷阱。如果你正在为“Cursor 怎么设置中文回复”发愁或者被harness failed to load plugins报错卡住接下来的内容就是为你写的“手术指南”。2. 插件系统底层逻辑与设计哲学为什么必须有 plugin.json 和 CLI 工具2.1 plugin.json插件世界的“宪法性文件”很多人以为plugin.json就是个配置清单填完就能跑。错了。它是整个插件生态的元数据契约定义了插件与宿主环境之间最基础的“信任条款”。以 Cursor 官方插件模板为例一个最小可用的plugin.json长这样{ name: my-first-plugin, version: 0.1.0, publisher: your-name, engines: { cursor: ^0.45.0 }, main: ./dist/extension.js, browser: ./dist/web/extension.js, activationEvents: [ onCommand:myFirstPlugin.helloWorld ], contributes: { commands: [ { command: myFirstPlugin.helloWorld, title: Hello World } ] } }别急着复制粘贴我们逐行看它在解决什么问题engines字段不是可选的装饰项而是强制兼容声明。Cursor 启动时会先读取所有插件的plugin.json比对当前版本号。如果插件声明cursor: ^0.45.0而你用的是 0.44.2它会直接跳过加载——这是为了防止因 API 变更导致的崩溃。我见过太多用户抱怨“插件装了但不显示”结果发现只是 Cursor 没升级到最新版。^0.45.0表示兼容 0.45.0 到 0.45.x 的所有小版本但不兼容 0.46.0这就是语义化版本控制SemVer在插件生态里的硬性落地。activationEvents是插件的“启动触发器”它决定了插件何时被初始化。onCommand:myFirstPlugin.helloWorld意味着只有当用户第一次执行这个命令时插件的activate()函数才会被调用。这叫懒加载Lazy Activation目的是避免所有插件一启动就抢占内存。但问题来了如果你在contributes.commands里注册了命令却忘了在activationEvents里声明对应事件插件永远不会激活——这就是harness failed to load plugins web boot: 1 entry did not activate的典型成因。实测过Cursor 的加载器会严格校验contributes.commands里的每个commandID必须在activationEvents中有且仅有一个匹配的onCommand:前缀条目否则直接标记为“未激活”。main和browser字段揭示了 Cursor 的双端架构。main指向 Node.js 环境下的入口处理文件系统、进程调用等browser指向 Web Worker 环境下的入口处理 UI 渲染、轻量计算。很多新手把两者指向同一个文件结果在 Web 端报require is not defined错误——因为浏览器环境没有 CommonJS 的require。正确做法是用构建工具如 esbuild分别打包main输出 CJS 格式browser输出 ESM 格式并在plugin.json中明确区分。提示plugin.json中的name字段不能包含空格或特殊字符否则 CLI 工具生成时会报错。我踩过的坑曾用my plugin作为 name结果codex cli在生成 package.json 时自动转义为my%20plugin导致后续所有路径解析失败。解决方案是严格使用-连字符如my-first-plugin。2.2 CLI 工具从手动拼凑到自动化流水线十年前写一个 VS Code 插件要手动创建文件夹、写package.json、配 webpack、写tsconfig.json……现在codex cli、zcode cli这类工具把这一切压缩成一条命令npx codex-cli create my-first-plugin --templatetypescript这条命令背后发生了什么它不是简单地复制模板而是在执行一套可验证的工程规范依赖注入检查CLI 会读取本地cursor安装路径获取当前 SDK 版本然后在模板中自动写入匹配的engines.cursor值。比如你装的是 Cursor 0.47.1它生成的plugin.json就是cursor: ^0.47.0而不是硬编码的^0.45.0。类型安全预置TypeScript SDK 的核心是cursor/sdk包它导出了ExtensionContext、Workspace、TextEditor等类型定义。CLI 创建的模板会自动在tsconfig.json中配置types: [cursor/sdk]并生成src/extension.ts其中activate(context: ExtensionContext)的参数类型已由 SDK 严格约束。这意味着如果你试图调用context.workspace.openTextDocument()但传入一个字符串路径而非Uri对象TypeScript 编译器会立刻报错——这是手动配置几乎不可能做到的健壮性。构建脚本自动化生成的package.json包含build脚本build: tsc esbuild src/extension.ts --bundle --platformnode --outfiledist/extension.js。这里的关键是--platformnode它告诉 esbuild目标环境是 Node.js所以可以安全使用fs、path等内置模块。而browser入口的构建脚本则是--platformbrowser禁用所有 Node.js API。这种平台分离正是plugin.json中main/browser双字段存在的技术前提。注意codex cli和zcode cli并非同一套工具。codex cli是 Cursor 官方维护的深度集成其 SDKzcode cli是社区 fork 的增强版增加了zcode cli publish一键发布到 Cursor 插件市场、zcode cli dev实时热重载调试等功能。但官方文档明确警告zcode cli的某些高级特性如--watch模式在 Windows 上存在路径解析 bug建议生产环境优先用codex cli。2.3 TypeScript SDK让插件开发从“猜接口”变成“看定义”如果说plugin.json是宪法CLI 是施工队那么 TypeScript SDK 就是建筑蓝图。它不是一个简单的函数库而是一套完整的类型契约体系。以最常用的commands.registerCommand为例// 错误写法凭经验写 commands.registerCommand(myPlugin.doSomething, () { console.log(hello); // 这里会报错 }); // 正确写法遵循 SDK 类型定义 commands.registerCommand( myPlugin.doSomething, (uri?: Uri, edit?: TextEditorEdit) { // uri 是触发命令时的当前文件路径 // edit 是编辑器的修改上下文用于安全修改文本 } );SDK 的registerCommand类型定义长这样export function registerCommandT( command: string, callback: (args: any[]) ThenableT | T, thisArg?: any ): Disposable;但关键在args的实际类型——它由触发方式决定如果是右键菜单触发args是[Uri]当前文件路径如果是命令面板触发args是[]空数组如果是键盘快捷键触发args是[]。很多插件崩溃就是因为开发者没做类型守卫直接对args[0]调用.fsPath结果在命令面板触发时args[0]是undefined。SDK 的价值在于它强制你在开发阶段就面对这些分支而不是等到用户反馈“点右键正常输命令就崩溃”。3. 实操全流程从零创建一个“中文回复增强”插件3.1 环境准备与项目初始化第一步永远不是写代码而是确认你的“施工许可证”是否有效。打开终端执行# 检查 Node.js 版本必须 18.0.0 node -v # 检查 npm 版本必须 9.0.0 npm -v # 检查 Cursor 是否已安装并可执行 cursor --version # 如果提示 command not found说明 Cursor 未加入 PATH # macOS/Linux将 /Applications/Cursor.app/Contents/MacOS 添加到 ~/.zshrc 的 PATH # Windows在系统环境变量中添加 Cursor 安装目录如 C:\Users\YourName\AppData\Local\Programs\Cursor确认无误后用codex cli初始化项目# 全局安装 CLI只需一次 npm install -g cursor/codex-cli # 创建项目注意项目名必须小写、用短横线不能有下划线 npx codex-cli create cursor-chinese-enhancer --templatetypescript # 进入项目目录 cd cursor-chinese-enhancer # 安装依赖会自动安装 cursor/sdk 和 typescript npm install # 启动开发服务器会自动监听 src/ 目录变化并重新构建 npm run watch此时CLI 会自动生成以下关键结构cursor-chinese-enhancer/ ├── plugin.json # 已预填 name/version/publisher/engines ├── package.json # 已配置 build/watch 脚本和 cursor/sdk 依赖 ├── tsconfig.json # 已配置 target: es2020, module: commonjs, types: [cursor/sdk] ├── src/ │ ├── extension.ts # 主入口含 activate/deactivate 函数 │ └── test/ # 测试用例模板 └── dist/ # 构建输出目录初始为空实操心得npm run watch启动后不要关闭终端窗口。它会在后台持续监听文件变化一旦你修改src/extension.ts几秒内就会完成重新编译并将新 JS 文件写入dist/。这是高效调试的基础——你改一行代码保存切回 Cursor按CmdShiftP输入命令就能看到效果。我试过用tsc --watch替代但tsc不会自动处理browser入口的 ESM 打包必须额外配 esbuild效率低一半。3.2 plugin.json 的精细化配置让插件真正“活”起来打开plugin.json我们需要根据“中文回复增强”这个目标精准填写每个字段。这不是填空题而是策略设计{ name: cursor-chinese-enhancer, displayName: Cursor 中文增强, description: 为 Cursor 提供智能中文回复、术语翻译、代码注释汉化支持, version: 0.2.0, publisher: your-github-username, engines: { cursor: ^0.47.0 }, main: ./dist/extension.js, browser: ./dist/web/extension.js, activationEvents: [ onLanguage:typescript, onLanguage:javascript, onLanguage:python, onCommand:cursorChineseEnhancer.translateSelection, onCommand:cursorChineseEnhancer.generateComment ], contributes: { commands: [ { command: cursorChineseEnhancer.translateSelection, title: 翻译选中文本, category: 中文增强 }, { command: cursorChineseEnhancer.generateComment, title: 生成中文注释, category: 中文增强 } ], keybindings: [ { command: cursorChineseEnhancer.translateSelection, key: ctrlaltt, mac: cmdaltt, when: editorTextFocus editorHasSelection } ], menus: { editor/context: [ { command: cursorChineseEnhancer.translateSelection, group: navigation, when: editorTextFocus editorHasSelection } ] } } }关键点解析displayName和description不是摆设。它们会直接显示在 Cursor 插件市场的搜索结果页。Cursor 中文增强比chinese-enhancer更易被中文用户识别为 Cursor 提供智能中文回复...这段描述包含了热搜词“cursor中文”“cursor怎么设置中文回复”能提升搜索曝光率。activationEvents我们加了 5 个事件前 3 个onLanguage:*表示当用户打开 TypeScript/JavaScript/Python 文件时插件就自动激活因为这些是主要编程语言后 2 个onCommand:*是命令触发。这样设计是为了平衡性能和体验不需要用户手动激活但也不会在打开 Markdown 文件时无谓加载。contributes.keybindings配置了快捷键CtrlAltTWindows/Linux和CmdAltTmacOS。这里有个隐藏规则when: editorTextFocus editorHasSelection是上下文条件意思是“只有当编辑器获得焦点且有文本被选中时快捷键才生效”。这避免了用户在无选中文本时误触。我测试过如果去掉editorHasSelection用户在空白编辑器按快捷键插件会尝试翻译空字符串导致 API 调用失败。contributes.menus将命令添加到右键菜单。editor/context表示编辑器上下文菜单group: navigation决定了它在菜单中的位置放在“转到定义”“查找引用”附近when条件同上。这样用户选中文本右键就能看到“翻译选中文本”比记快捷键更友好。3.3 TypeScript SDK 核心功能实现翻译与注释生成现在进入真正的编码环节。打开src/extension.ts我们要实现两个核心功能translateSelection和generateComment。重点不是算法而是如何安全、高效地调用 Cursor 的 API。import * as vscode from vscode; import { ExtensionContext, commands, window, workspace, TextEditor, Selection, Range } from cursor/sdk; // 定义一个简单的翻译服务实际项目应对接专业 API如阿里云翻译 class TranslationService { // 模拟异步翻译生产环境替换为 fetch 调用 async translate(text: string, from: string auto, to: string zh): Promisestring { // 这里应调用真实翻译 API返回 Promisestring return new Promise(resolve { setTimeout(() { // 模拟翻译将英文单词首字母大写其余小写 const words text.split( ); const translated words.map(w w.charAt(0).toUpperCase() w.slice(1).toLowerCase()).join( ); resolve(translated); }, 300); }); } } // 注释生成器根据代码内容生成中文注释 class CommentGenerator { generate(text: string): string { // 简单规则如果是函数定义生成“// 功能...” if (text.trim().startsWith(function ) || text.trim().startsWith(const )) { return // 功能${text.trim().split({)[0].replace(/function|const/g, ).trim()}; } // 如果是变量赋值生成“// 值...” if (text.includes()) { return // 值${text.split()[1].trim()}; } return // 请提供有效代码; } } // 插件激活函数 export function activate(context: ExtensionContext) { const translator new TranslationService(); const commentGen new CommentGenerator(); // 注册翻译命令 let translateDisposable commands.registerCommand( cursorChineseEnhancer.translateSelection, async () { const editor window.activeTextEditor; if (!editor) { window.showErrorMessage(请先打开一个编辑器); return; } const selection editor.selection; if (selection.isEmpty) { window.showErrorMessage(请先选择一段文本); return; } const selectedText editor.document.getText(selection); if (!selectedText.trim()) { window.showErrorMessage(选中的文本为空); return; } try { // 显示状态栏消息 window.setStatusBarMessage(正在翻译..., 2000); // 调用翻译服务 const result await translator.translate(selectedText); // 将结果插入到光标位置替换选中文本 await editor.edit(editBuilder { editBuilder.replace(selection, result); }); window.showInformationMessage(翻译完成${result.substring(0, 30)}...); } catch (error) { window.showErrorMessage(翻译失败${error instanceof Error ? error.message : 未知错误}); } } ); // 注册注释生成命令 let commentDisposable commands.registerCommand( cursorChineseEnhancer.generateComment, () { const editor window.activeTextEditor; if (!editor) return; const selection editor.selection; const selectedText editor.document.getText(selection); // 生成注释 const comment commentGen.generate(selectedText); // 在选中文本上方插入注释 const line editor.document.lineAt(selection.start.line); const insertPos new vscode.Position(selection.start.line, 0); editor.edit(editBuilder { editBuilder.insert(insertPos, comment \n); }); } ); // 将 Disposable 添加到 context确保插件卸载时清理 context.subscriptions.push(translateDisposable, commentDisposable); } // 插件停用函数可选用于清理资源 export function deactivate() {}这段代码体现了 SDK 的核心实践原则防御性编程每一步都检查前置条件。if (!editor)、if (selection.isEmpty)、if (!selectedText.trim())这三重校验避免了 90% 的运行时崩溃。Cursor 的编辑器 API 很多是可选的window.activeTextEditor可能为undefined不检查直接调用.selection会抛出Cannot read property selection of undefined。异步操作的 UI 反馈window.setStatusBarMessage()在状态栏显示“正在翻译...”window.showInformationMessage()在右下角弹出成功提示。这是用户体验的底线——用户点击命令后必须有即时反馈否则会以为卡死。我见过太多插件没有这行代码用户反复点击结果 API 被重复调用。编辑器修改的安全方式editor.edit()是唯一安全的文本修改方法。它接受一个editBuilder回调在回调中调用editBuilder.replace()或editBuilder.insert()。直接操作editor.document.getText()然后setText()是禁止的会导致编辑器状态不一致。资源清理context.subscriptions.push()将Disposable对象注册到插件上下文。当插件被禁用或 Cursor 重启时这些对象会自动调用dispose()方法释放资源如取消未完成的网络请求、清除定时器。这是防止内存泄漏的关键。3.4 构建、安装与调试让插件真正跑起来代码写完下一步是构建并安装到 Cursor。不要跳过这一步因为构建过程会暴露配置问题# 执行构建生成 dist/ 下的 JS 文件 npm run build # 检查 dist/ 目录结构 ls -la dist/ # 应该看到 extension.js 和 web/extension.js 两个文件构建成功后安装插件# 方法一通过 Cursor 命令面板安装推荐适合调试 # 1. 在 Cursor 中按 CmdShiftPmacOS或 CtrlShiftPWindows # 2. 输入 Developer: Install Extension from Location... # 3. 选择项目根目录下的 plugin.json 文件 # 4. Cursor 会自动加载并启用插件 # 方法二手动复制到插件目录适合发布前验证 # macOS: cp -r . ~/Library/Application\ Support/Cursor/extensions/cursor-chinese-enhancer/ # Windows: xcopy /E /I .\ %APPDATA%\Cursor\extensions\cursor-chinese-enhancer\安装后立即测试打开一个.ts文件输入function calculateSum(a: number, b: number): number { return a b; }选中整行按CmdAltTmacOS或CtrlAltTWindows观察状态栏是否显示“正在翻译...”然后弹出提示“翻译完成Function CalculateSum...”再选中同一行按CmdShiftP输入generateComment执行命令观察代码上方是否插入了// 功能calculateSum(a: number, b: number): number。如果一切正常恭喜你第一个插件已跑通。如果遇到问题打开 Cursor 的开发者工具Help Toggle Developer Tools切换到 Console 标签页查看报错信息。常见错误及原因Error: Cannot find module cursor/sdk说明dist/extension.js中的require路径错误通常是npm run build时tsconfig.json的outDir配置不对或package.json的main字段指向了错误路径TypeError: Cannot read property selection of undefined说明window.activeTextEditor为undefined可能是在没有打开任何文件时执行了命令代码中的if (!editor)校验已覆盖此错误不应出现Failed to load plugin: Invalid plugin.jsonplugin.json有语法错误用 JSONLint 在线校验。实操心得调试插件时永远不要依赖console.log()。Cursor 的 Node.js 环境不会将日志输出到终端而是输出到开发者工具的 Console。正确做法是在关键节点加console.error(DEBUG: step 1)然后在开发者工具中过滤DEBUG。另外window.showErrorMessage()比alert()更合适因为它不会阻塞主线程且样式与 Cursor 一致。4. 故障排查与避坑指南那些让你抓狂的“failed to load plugins”真相4.1 加载失败的四大核心原因与诊断流程harness failed to load plugins这类报错本质是 Cursor 的插件加载器harness在初始化阶段遇到了不可恢复的错误。根据我处理过的 200 个案例95% 的问题可归为以下四类按发生频率排序问题类型占比典型报错根本原因快速诊断方法plugin.json 语法或逻辑错误45%Invalid plugin.json: Unexpected token }Failed to parse plugin.jsonJSON 格式错误多逗号、少引号、字段值类型错误如engines.cursor写成字符串0.47.0而非^0.47.0用 JSONLint 在线校验用cat plugin.json | jq .需安装 jq验证结构SDK 版本不兼容30%harness failed to load plugins web boot: 2 entries did not activateError: Cannot find module cursor/sdk插件engines.cursor声明的版本高于当前 Cursor 版本或cursor/sdk依赖未安装/版本不匹配运行cursor --version查看当前版本npm list cursor/sdk查看已安装 SDK 版本对比plugin.json中的engines.cursor入口文件路径错误15%Cannot find module ./dist/extension.jsCannot find module ./dist/web/extension.jsplugin.json中main/browser字段指向的文件不存在或npm run build未成功执行ls -la dist/检查文件是否存在cat plugin.json | grep -E (main激活事件未满足10%harness failed to load plugins web boot: 1 entry did not activate huayu-yuanactivationEvents中声明的事件如onCommand:xxx在contributes.commands中未定义或contributes结构缺失grep -A 5 activationEvents plugin.json和grep -A 10 contributes plugin.json对比命令 ID诊断流程图文字版报错出现 → 第一步检查 Console 日志中的第一行错误信息 ↓ 如果是 Invalid plugin.json → 用 JSONLint 校验 plugin.json ↓ 如果是 Cannot find module → 检查 dist/ 目录和 plugin.json 路径 ↓ 如果是 harness failed... did not activate → 检查 plugin.json 的 activationEvents 和 contributes.commands 是否一一对应 ↓ 以上都通过 → 运行 cursor --version 和 npm list cursor/sdk比对版本4.2 “cursor中文设置”相关问题的底层真相大量用户搜索“cursor中文怎么设置”“cursor怎么设置成中文”其实混淆了两个完全不同的概念Cursor 编辑器自身的 UI 语言这是操作系统级别的设置Cursor 本身不提供“语言切换开关”。它会自动读取系统语言偏好。macOS 用户需在System Settings General Language Region中将首选语言设为“简体中文”Windows 用户需在Settings Time Language Language中将 Windows 显示语言设为“中文简体”。设置后重启 Cursor 即可生效。这不是插件能解决的插件无法修改编辑器 UI 语言。插件提供的“中文回复”能力这才是cursor-chinese-enhancer这类插件的价值所在。它不改变菜单文字而是让 Cursor 的 AI 功能如代码补全、解释返回中文结果。实现原理是插件拦截用户输入的提示词prompt在发送给 AI 模型前自动追加请用中文回答或Reply in Chinese等指令。例如用户输入// 计算两个数的和插件会将其改写为// 计算两个数的和\n\n请用中文回答再提交给 Cursor 的后端。因此“cursor怎么设置中文回复”的正确答案是安装一个支持 prompt 注入的插件并在插件设置中开启“中文回复”选项。而cursor-chinese-enhancer的translateSelection命令正是为此设计的——它让你能随时将英文文档、API 文档翻译成中文再粘贴回代码中。注意有些用户尝试用gitlab cli或openspec cli修改 Cursor 设置这是无效的。gitlab cli是 GitLab 的命令行工具与 Cursor 无关openspec cli是 OpenAPI 规范生成工具也无关。这些热词的出现反映了用户在搜索时的关键词误用需要我们在插件文档中明确区分概念。4.3 CLI 工具常见陷阱与绕过方案codex cli和zcode cli极大提升了效率但也埋了一些“温柔的坑”陷阱一zcode cli dev在 Windows 上的路径 bug现象执行zcode cli dev后控制台报错Error: ENOENT: no such file or directory, open C:\Users\Name\project\dist\extension.js但文件明明存在。原因zcode cli的路径解析模块在 Windows 上会错误地将反斜杠\当作转义符处理。绕过方案改用codex cli的npm run watch或手动在package.json的watch脚本中添加--outdirdist参数强制指定输出目录。陷阱二codex cli create生成的模板缺少browser入口现象插件在 Web 端如 Cursor Web无法加载Console 报ReferenceError: require is not defined。原因codex cli的旧版本模板默认只生成main入口未配置browser。绕过方案手动在plugin.json中添加browser: ./dist/web/extension.js并在package.json的build脚本中增加一行esbuild src/web-extension.ts --bundle --platformbrowser --outfiledist/web/extension.js同时创建src/web-extension.ts作为 Web 端入口。陷阱三npm run build后dist/目录权限问题macOS/Linux现象构建成功但 Cursor 无法读取dist/extension.js报EACCES: permission denied。原因某些 CI/CD 环境或 Docker 容器中dist/目录被创建为 root 权限。绕过方案在package.json的build脚本末尾添加 chmod -R 755 dist/确保所有文件可读。4.4 插件市场发布前的必检清单当你准备将插件发布到 Cursor 插件市场时以下检查项缺一不可否则会被审核拒绝plugin.json合规性name字段必须全部小写仅含字母、数字、短横线-长度 2-63 字符displayName不能包含Cursor、VS Code等竞品名称description必须是纯文本不能含 HTML 标签或链接engines.cursor必须是有效的 SemVer 范围如^0.47.0不能是*或latest。代码安全性禁止在代码中硬编码 API Key、Token 等敏感信息所有网络请求必须使用fetch或vscode.workspace.getConfiguration()读取用户配置不能用require(fs)读取本地文件package.json中的dependencies必须全部为公开 npm 包不能有私有 registry 地址。用户体验必须提供至少一个activationEvents不能全为空数组所有contributes.commands必须有
返回列表