ByteNoteByteNote

字节笔记本

2026年8月28日

Gemini CLI 扩展:Skills、Hooks 和 MCP 怎么一起用

API中转
¥120

Gemini CLI 的扩展以前主要装 MCP、自定义命令和 GEMINI.md。现在同一个扩展目录还能带上 Agent Skills 和 Hooks:装一次,技能、生命周期脚本、外部工具一起生效。下面按「先装现成的」和「自己组一个」把这三件东西怎么叠在一起说清楚。

一个扩展里能装什么

官方把扩展定义成可安装、可分享的目录,根上必须有 gemini-extension.json。目录里可以同时放下这几类能力:

能力放哪谁触发适合干什么
MCP 服务器gemini-extension.jsonmcpServers模型选工具时给模型新动作:查库、调内部 API、控本地应用
Agent Skillsskills/<name>/SKILL.md模型按 description 激活偶尔才用的专项流程,不常驻上下文
Hookshooks/hooks.jsonCLI 生命周期工具调用前后校验、记账、拦危险操作
上下文GEMINI.md(或 contextFileName会话开始就注入扩展的人设、必知约定
自定义命令commands/*.toml你敲 /命令重复提示词或固定脚本

Skills 和 Hooks 不写进清单文件。CLI 按目录约定自动发现:有 skills/ 就注册技能,有 hooks/hooks.json 就注册钩子。gemini-extension.json 只负责名字、版本、MCP、上下文文件名和 excludeTools 这类清单级配置。

文档在 Extension referenceBuild extensions

先装现成扩展

仓库地址或本地路径都能装:

bash
gemini extensions install https://github.com/gemini-cli-extensions/workspace
gemini extensions list

交互会话里看状态用 /extensions list。装完要重启 CLI,斜杠命令和 MCP 才会进当前会话。

扩展默认全局启用,可以按用户或工作区关掉:

bash
gemini extensions disable workspace --scope workspace
gemini extensions enable workspace --scope workspace

开发自己的扩展时用 gemini extensions link <path>,它在 ~/.gemini/extensions 里做软链,改文件立刻生效,不用反复安装。官方画廊在 geminicli.com/extensions,目前已经有三百多个现成包。

自己组一个:三件套怎么放

最小可跑的目录大概是这样:

text
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},换机器、换安装目录都不用改。

json
{
  "name": "my-dev-kit",
  "version": "1.0.0",
  "description": "把代码评审技能、写后检查和一组内部工具打成一个扩展",
  "contextFileName": "GEMINI.md",
  "mcpServers": {
    "kit-server": {
      "command": "node",
      "args": ["${extensionPath}${/}server.js"],
      "cwd": "${extensionPath}"
    }
  }
}

commandargs 要拆开写,不要把整条命令塞进 command。扩展不会继承你的完整 shell 环境:除了 HOMEPATHTMPDIR 这类安全变量,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 可以这样写:

markdown
---
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}${/}

官方事件名是 BeforeToolAfterToolSessionStart 这类,不要抄成别的产品的 PreToolUse。一个写文件之后跑检查的例子:

json
{
  "hooks": {
    "AfterTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "name": "after-write-lint",
            "type": "command",
            "command": "${extensionPath}/scripts/after-write-lint.sh",
            "timeout": 8000
          }
        ]
      }
    ]
  }
}

matcher 在工具事件上是正则;生命周期事件(比如 SessionStart)是精确字符串。星号或空字符串匹配全部。

钩子脚本有几条硬规矩:

  1. 只往 stdout 打最终那一个 JSON。多打一行普通文本,解析就会失败,CLI 会当成放行,并把整段输出当 systemMessage。
  2. 调试打 stderr,不要污染 stdout。
  3. 退出码 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

落地检查

  1. 根目录有 gemini-extension.json,name 是小写加连字符,并和目录名一致。
  2. MCP 的可执行文件用 ${extensionPath} 引用,command 和 args 已拆开。
  3. 需要的环境变量都写进 settings,敏感项标了 sensitive。
  4. 每个 Skill 都有能触发的 description,路径是 skills//SKILL.md。
  5. hooks/hooks.json 用官方事件名;脚本只输出 JSON,调试走 stderr。
  6. link 之后重启 CLI,extensions list、skills list 和一次真实工具调用都过了。

这三件叠在一个扩展里之后,团队就不用再分头维护技能目录、settings 钩子和 MCP 配置三份东西。clone 下来装一次,会话里该激活的激活,该拦的拦。

分享: