Appearance
构建高质量 Gemini CLI 扩展的核心是:只申请必要权限、严格验证 MCP 工具输入、用 sensitive 字段保护密钥、TypeScript + link 命令做本地迭代,以及 SemVer 让用户平滑升级。本页是扩展开发者在发布前必须过一遍的清单。
扩展开发最佳实践
本页汇总了开发、安全加固和维护 Gemini CLI 扩展的最佳实践,配合 扩展开发入门 和 扩展完整参考 一起阅读效果最佳。
开发
推荐目录结构
简单扩展只需几个文件,复杂项目建议使用分层结构:
text
my-extension/
├── package.json
├── tsconfig.json
├── gemini-extension.json
├── src/
│ ├── index.ts
│ └── tools/
└── dist/推荐 TypeScript:强烈建议用 TypeScript 开发 MCP 服务器,类型安全能帮助你捕获运行时错误,尤其是工具参数验证逻辑。
分离源码和构建产物:源码放 src/,构建产物输出到 dist/,避免两者混杂。
打包依赖:若扩展依赖较多,使用 esbuild 等工具打包,减少安装时间并避免依赖冲突。
用 link 迭代开发
本地开发时,每次改代码都重新安装扩展非常低效。使用 link 命令:
bash
cd my-extension
gemini extensions link .link 创建符号链接,代码改动后只需:
- 重新构建(如
npm run build) - 重启 CLI 会话
变更即时生效,无需 uninstall + install。
有效使用 GEMINI.md
GEMINI.md 是扩展向模型传递上下文的主要途径:
- 聚焦目标:说明扩展的核心用途和如何与工具交互,而不是写完整的 API 文档
- 保持简洁:避免把大量文档堆进去,清晰直接的语言比面面俱到更有效
- 提供示例:包含简短示例,告诉模型该何时调用哪些工具或命令
安全
最小权限原则
只申请 MCP 服务器实际需要的权限。如果受限工具足够完成任务,不要开放全 Shell 访问。
如果扩展需要 run_shell_command,在 manifest 中明确限制危险命令:
json
{
"name": "my-safe-extension",
"excludeTools": ["run_shell_command(rm -rf *)"]
}这样即使模型尝试执行危险命令,CLI 也会在策略层拦截。
验证工具输入
MCP 服务器运行在用户机器上,不受沙箱保护。必须对所有工具输入进行验证,防止路径遍历、任意代码执行等安全问题:
typescript
// 路径访问控制示例
import path from 'node:path';
function validatePath(inputPath: string, allowedDir: string): string {
const resolved = path.resolve(inputPath);
const allowed = path.resolve(allowedDir);
if (!resolved.startsWith(allowed + path.sep)) {
throw new Error('Access denied: path is outside the allowed directory');
}
return resolved;
}安全存储敏感配置
如果扩展需要 API Key 等敏感信息,在 settings 中使用 sensitive: true:
json
"settings": [
{
"name": "API Key",
"envVar": "MY_API_KEY",
"sensitive": true
}
]sensitive: true 效果:
- 值存入操作系统 Keychain(macOS Keychain、Windows Credential Manager)
- CLI 界面中脱敏显示(显示为
***) - 通过 MCP 服务器启动参数的环境变量安全注入,不会明文写到磁盘
发布
语义化版本(SemVer)
遵循 Semantic Versioning 规范,让用户清楚了解每次更新的影响范围:
| 版本号变化 | 含义 | 示例 |
|---|---|---|
| Major(主版本) | 破坏性变更 | 重命名工具、修改参数签名 |
| Minor(次版本) | 新功能,向后兼容 | 添加新工具、新命令 |
| Patch(补丁版本) | Bug 修复、性能优化 | 修正工具行为、改进错误消息 |
发布渠道管理
用 Git 分支管理发布渠道,让用户自由选择稳定版或最新功能:
bash
# 安装稳定版(默认分支)
gemini extensions install github.com/user/repo
# 安装开发版
gemini extensions install github.com/user/repo --ref dev推荐策略:
- 默认分支(
main/master)作为稳定发布渠道 dev或preview分支用于日常开发- 功能稳定后合并到默认分支发布
GitHub Release 打包
发布 GitHub Release 时,只打包必要文件(dist/、gemini-extension.json、package.json),排除 node_modules/ 和 src/,减少用户下载体积。
详细发布流程参见 发布 Gemini CLI 扩展。
测试与验证
手动验证
- 用
gemini extensions link在真实 CLI 会话中测试扩展 - 检查工具是否出现在 F12 调试控制台
- 验证自定义命令是否正确解析参数
自动化测试
如果扩展包含 MCP 服务器,为工具逻辑编写单元测试(推荐使用 Vitest 或 Jest)。测试时可通过 mock transport 层来隔离 MCP 工具,无需运行完整服务器。
故障排查
扩展不加载
如果 /extensions list 中没有出现你的扩展:
- 检查 manifest:确认
gemini-extension.json在根目录且 JSON 格式合法 - 确认名称匹配:manifest 中的
name字段必须与扩展目录名完全一致 - 重启 CLI:扩展在会话启动时加载,修改后必须重启
MCP 服务器工具不工作
- 查看日志:检查 CLI 日志确认 MCP 服务器是否启动失败
- 直接测试命令:在终端直接运行
command和args确认服务器能独立启动 - F12 调试控制台:在交互模式中按 F12 查看工具调用和响应详情
自定义命令不响应
- 检查优先级:用户命令和项目命令优先级高于扩展命令。若有冲突,扩展命令会加前缀(
/extension.command) - 验证命令名:运行
/help查看所有已注册命令及其来源
常见问题
Q: 什么时候应该用 MCP 服务器,什么时候用自定义命令?
A: MCP 服务器适合需要模型主动调用的动态能力(查 API、执行逻辑);自定义命令适合用户手动触发的固定 Prompt 模板或 Shell 脚本快捷方式。两者可以同时存在于一个扩展中。
Q: 扩展的 GEMINI.md 和项目的 GEMINI.md 会冲突吗?
A: 不会冲突,两者都会被加载。项目级 .gemini/GEMINI.md 优先级高于扩展提供的 GEMINI.md,但两者内容通常是互补关系。
Q: 可以在扩展中引用另一个扩展的工具吗?
A: 扩展相互独立,不直接引用彼此的工具。但如果两个扩展都已安装,它们的工具都会注册到同一个会话中,模型可以同时使用。