字节笔记本
2026年8月28日
Gemini CLI 扩展:Skills、Hooks 和 MCP 怎么一起用
Gemini CLI 的扩展以前主要装 MCP、自定义命令和 GEMINI.md。现在同一个扩展目录还能带上 Agent Skills 和 Hooks:装一次,技能、生命周期脚本、外部工具一起生效。下面按「先装现成的」和「自己组一个」把这三件东西怎么叠在一起说清楚。
一个扩展里能装什么
官方把扩展定义成可安装、可分享的目录,根上必须有 gemini-extension.json。目录里可以同时放下这几类能力:
| 能力 | 放哪 | 谁触发 | 适合干什么 |
|---|---|---|---|
| MCP 服务器 | gemini-extension.json 的 mcpServers | 模型选工具时 | 给模型新动作:查库、调内部 API、控本地应用 |
| Agent Skills | skills/<name>/SKILL.md | 模型按 description 激活 | 偶尔才用的专项流程,不常驻上下文 |
| Hooks | hooks/hooks.json | CLI 生命周期 | 工具调用前后校验、记账、拦危险操作 |
| 上下文 | GEMINI.md(或 contextFileName) | 会话开始就注入 | 扩展的人设、必知约定 |
| 自定义命令 | commands/*.toml | 你敲 /命令 | 重复提示词或固定脚本 |
Skills 和 Hooks 不写进清单文件。CLI 按目录约定自动发现:有 skills/ 就注册技能,有 hooks/hooks.json 就注册钩子。gemini-extension.json 只负责名字、版本、MCP、上下文文件名和 excludeTools 这类清单级配置。
文档在 Extension reference 和 Build extensions。
先装现成扩展
仓库地址或本地路径都能装:
gemini extensions install https://github.com/gemini-cli-extensions/workspace
gemini extensions list交互会话里看状态用 /extensions list。装完要重启 CLI,斜杠命令和 MCP 才会进当前会话。
扩展默认全局启用,可以按用户或工作区关掉:
gemini extensions disable workspace --scope workspace
gemini extensions enable workspace --scope workspace开发自己的扩展时用 gemini extensions link <path>,它在 ~/.gemini/extensions 里做软链,改文件立刻生效,不用反复安装。官方画廊在 geminicli.com/extensions,目前已经有三百多个现成包。
自己组一个:三件套怎么放
最小可跑的目录大概是这样:
my-dev-kit/
├── gemini-extension.json
├── GEMINI.md
├── skills/
│ └── pr-review/
│ └── SKILL.md
├── hooks/
│ └── hooks.json
├── scripts/
│ └── after-write-lint.sh
└── server.js先写清单。MCP 路径用 ${extensionPath},换机器、换安装目录都不用改。
{
"name": "my-dev-kit",
"version": "1.0.0",
"description": "把代码评审技能、写后检查和一组内部工具打成一个扩展",
"contextFileName": "GEMINI.md",
"mcpServers": {
"kit-server": {
"command": "node",
"args": ["${extensionPath}${/}server.js"],
"cwd": "${extensionPath}"
}
}
}command 和 args 要拆开写,不要把整条命令塞进 command。扩展不会继承你的完整 shell 环境:除了 HOME、PATH、TMPDIR 这类安全变量,MCP 进程只能看到清单 settings 里用 envVar 声明过的值。API Key 这类敏感项把 sensitive 设成 true,安装时会进系统钥匙串。
本地联调:进入扩展目录,Node 服务先装依赖,然后用 gemini extensions 的 link 子命令把目录链到 ~/.gemini/extensions。重启会话后,问一句能触发 MCP 工具的话,确认服务起来了。
Skills:按需加载,别常驻
Skills 走 Agent Skills 约定,文档见 https://geminicli.com/docs/cli/skills/ 。会话开始时 CLI 只把名称和 description 塞进系统提示;任务对上了,模型才调用 activate_skill,全文和技能目录才会进上下文。适合偶尔做一次的流程,比如开 PR、安全审计、发版检查。天天都要用的规矩放 GEMINI.md。
skills/pr-review/SKILL.md 可以这样写:
---
name: pr-review
description: 用户要评审当前分支、出 PR 意见或对照仓库约定看 diff 时使用。
---
# 步骤
1. 先看当前分支相对主分支的 diff,不要只读最新一次提交。
2. 按仓库测试命令跑一遍相关检查,失败先报检查,再谈风格。
3. 意见按「必须改 / 建议 / 仅供参考」分组,每条指出文件和原因。description 是路由键,写「什么时候该用」,别写成空泛摘要。扩展技能的优先级低于用户技能和工作区技能;同名时,工作区 ./.agents/skills/ 或 ./.gemini/skills/ 会盖住扩展里那份。
会话里查看用 /skills list,终端里也可以 gemini skills list --all。
Hooks:在生命周期里拦一脚
Hooks 是 CLI 自己跑的脚本,不是模型选的工具。扩展里单独放 hooks/hooks.json,格式和用户 settings.json 里的 hooks 段相同。变量替换和清单一样,可以用 ${extensionPath}、${workspacePath}、${/}。
官方事件名是 BeforeTool、AfterTool、SessionStart 这类,不要抄成别的产品的 PreToolUse。一个写文件之后跑检查的例子:
{
"hooks": {
"AfterTool": [
{
"matcher": "write_file|replace",
"hooks": [
{
"name": "after-write-lint",
"type": "command",
"command": "${extensionPath}/scripts/after-write-lint.sh",
"timeout": 8000
}
]
}
]
}
}matcher 在工具事件上是正则;生命周期事件(比如 SessionStart)是精确字符串。星号或空字符串匹配全部。
钩子脚本有几条硬规矩:
- 只往 stdout 打最终那一个 JSON。多打一行普通文本,解析就会失败,CLI 会当成放行,并把整段输出当 systemMessage。
- 调试打 stderr,不要污染 stdout。
- 退出码 0 表示按 JSON 决策走(包括主动拦截)。退出码 2 是系统级中止,动作直接停。其他退出码只警告,流程继续。
扩展钩子的优先级低于项目和工作区的 settings.json。项目钩子会做指纹:仓库更新改了命令,CLI 会当新钩子,执行前再问你一次。
三者叠在一起时怎么分工
同一个扩展里,三件事不要抢活:
- MCP 负责「模型能调用的新工具」。查内部工单、读设计稿、跑你们自己的扫描接口,都走这里。
- Skill 负责「什么时候、按什么步骤用这些工具」。它不启动进程,只在被激活后把流程写进上下文。
- Hook 负责「不管模型想不想,CLI 到这个节点都要跑」。写文件后格式化、拦危险删除、会话开始注入 git 状态,都属于这一层。
一个常见组合:Skill 规定「评审 PR 先跑测试再看 diff」;MCP 提供读 CI 状态的工具;AfterTool 在模型改完测试文件后跑一遍项目已有的 lint。模型漏了步骤,钩子还能补一刀。
GEMINI.md 只写扩展的短约定,比如优先用 kit-server 的工具。长流程放 Skill,避免每个会话都把审计手册塞进上下文。
冲突、安全和别踩的坑
- MCP 重名:扩展和 settings.json 配了同名服务器,以 settings.json 为准。
- 斜杠命令重名:扩展命令优先级最低。跟用户或项目命令撞名时,会变成 /扩展名.命令。
- excludeTools:清单里的 excludeTools 禁的是内置工具,和某个 MCP 服务器自己的 excludeTools 不是同一份配置。
- 扩展策略不能放行:扩展可以带 policies 目录下的 toml,但 CLI 会忽略其中的 allow 和 yolo。扩展不能替你自动批准危险工具。
- 环境变量白名单:没在 settings 的 envVar 里声明的密钥,MCP 和钩子进程都看不到。需要的变量写进清单,安装时让用户填。
本地开发用 link 就够。要分发,把目录推进 Git 仓库,别人用 gemini extensions install 加仓库地址即可。发布到画廊看官方 Extension releasing 文档:https://google-gemini.github.io/gemini-cli/docs/extensions/releasing.html
落地检查
- 根目录有 gemini-extension.json,name 是小写加连字符,并和目录名一致。
- MCP 的可执行文件用 ${extensionPath} 引用,command 和 args 已拆开。
- 需要的环境变量都写进 settings,敏感项标了 sensitive。
- 每个 Skill 都有能触发的 description,路径是 skills//SKILL.md。
- hooks/hooks.json 用官方事件名;脚本只输出 JSON,调试走 stderr。
- link 之后重启 CLI,extensions list、skills list 和一次真实工具调用都过了。
这三件叠在一个扩展里之后,团队就不用再分头维护技能目录、settings 钩子和 MCP 配置三份东西。clone 下来装一次,会话里该激活的激活,该拦的拦。