首页
/ Gemini CLI Agent Skills 完全指南:按需加载的专业能力与渐进式披露机制

Gemini CLI Agent Skills 完全指南:按需加载的专业能力与渐进式披露机制

2026-09-04 13:48:24作者:昌雅子Ethen

本文以 Gemini CLI 官方文档 skills.md 为主体,系统讲解 Agent Skills 的完整生命周期(发现、激活、授权、注入、执行)、发现层级与优先级规则、/skillsgemini skills 两套管理命令,并结合 skillLoader.tsskillManager.tsactivate-skill.ts 等核心源码,剖析其 frontmatter 解析、冲突消解与安全控制的底层实现。

一、什么是 Agent Skills

Agent Skills 让你能够为 Gemini CLI 扩展专业领域知识、流程化工作流和任务专属资源。它基于 Agent Skills 开放标准:一个 "skill" 是一个自包含的目录,把说明文档(instructions)和资源(assets)打包成一个可被发现的能力单元。

与通用上下文文件 GEMINI.md 提供"持久化的、工作区级别的全局背景"不同,Skills 代表的是按需(on-demand)的专业能力。这意味着 Gemini CLI 可以维护一个庞大的专业能力库——例如安全审计、云端部署、代码库迁移——而不会把这些内容全部塞进模型当前的上下文窗口。

一个 skill 的最小目录形态如下:

skill-name/
├── SKILL.md        # 必需:含 YAML frontmatter(name + description)和 Markdown 正文
└── 可选资源
    ├── scripts/    # 可执行脚本(Node.js/Python/Bash 等)
    ├── references/ # 按需加载进上下文的参考文档
    └── assets/     # 用于最终产出的文件(模板、图标、字体等)

二、生命周期:从发现到执行

官方文档将 Agent Skill 的生命周期概括为五个阶段:Discovery(发现)→ Activation(激活)→ Consent(授权)→ Injection(注入)→ Execution(执行)。仓库源码完整印证了这条链路。

1. Discovery:发现

会话开始时,Gemini CLI 扫描各个发现层级(discovery tiers),并把所有已启用 skill 的名称和描述注入系统提示词。对应实现见 snippets.ts 中的系统提示模板:

# Available Agent Skills

You have access to the following specialized skills. To activate a skill and
receive its detailed instructions, call the activate_skill tool with the
skill's name.

<available_skills>
${skillsXml}
</available_skills>

注意:此处注入的只有元数据(name + description),正文不会预载——这正是后文"渐进式披露"省 token 的关键。提示词组装入口在 promptProvider.tscontext.config.getSkillManager().getSkills() 取到的就是所有未禁用的 skill。

2. Activation:激活

当模型判断某个任务与某个 skill 的描述匹配时,它会调用 activate_skill 工具(参数只有一个 name)。工具定义动态注入当前可用的 skill 名单:activate-skill.ts 的构造函数中,getActivateSkillDefinition(skillNames) 把技能名列表写进工具 schema,模型因此只"看得见"真实存在的技能。

3. Consent:用户授权

在交互 UI 中,你看到一个确认提示,展示 skill 的名称、用途以及它将获得访问权限的目录。实现位于 ActivateSkillToolInvocation.getConfirmationDetails

const confirmationDetails: ToolCallConfirmationDetails = {
  type: 'info',
  title: `Activate Skill: ${skillName}`,
  prompt: `You are about to enable the specialized agent skill **${skillName}**.
**Description:**
${skill.description}
**Resources to be shared with the model:**
${folderStructure}`,
  ...
};

有两个值得注意的源码细节:

  • 内置 skill 免确认if (skill.isBuiltin) { return false; }——随 Gemini CLI 分发的内置技能(如 skill-creator)不弹确认框,因为用户已随产品默认接受了它们;
  • 确认时会渲染该 skill 目录的真实文件树(getFolderStructure),让你清楚看到即将暴露给模型的资源范围。

4. Injection:注入

用户批准后,execute() 做三件事:

  1. skillManager.activateSkill(skillName) 把技能标记为会话级激活状态;
  2. this.config.getWorkspaceContext().addDirectory(path.dirname(skill.location))——把 skill 所在目录加入 agent 的允许文件路径,使其有权读取打包资源(文档所说的 "The skill's directory is added to the agent's allowed file paths");
  3. 返回给模型的 llmContent 是如下结构化内容,正文(skill.body)与目录结构被包进 <activated_skill> 标签注入对话历史:
<activated_skill name="${skillName}">
  <instructions>
    ${skill.body}
  </instructions>
  <available_resources>
    ${folderStructure}
  </available_resources>
</activated_skill>

5. Execution:执行

模型带着已激活的专业能力继续工作。系统提示会指示模型"在合理范围内优先遵循该 skill 的流程化指引"。

三、SKILL.md 的解析实现:frontmatter 与容错

skill 的可发现性完全依赖 SKILL.md 顶部的 YAML frontmatter。解析逻辑集中在 skillLoader.ts,包含几个对编写者很实用的实现细节:

(1)扫描模式loadSkillsFromDir 使用 glob 模式 ['SKILL.md', '*/SKILL.md'],即同时支持"目录本身就是 skill"和"目录下每个子目录是一个 skill"两种布局,并忽略 **/node_modules/****/.git/**

const pattern = ['SKILL.md', '*/SKILL.md'];
const skillFiles = await glob(pattern, {
  cwd: absoluteSearchPath,
  absolute: true,
  nodir: true,
  ignore: ['**/node_modules/**', '**/.git/**'],
});

(2)frontmatter 解析的双重保障FRONTMATTER_REGEX 先按 --- ... --- 截取 frontmatter 块,随后 parseFrontmatter 优先用完整 YAML 解析器(js-yaml)解析;一旦 YAML 失败(典型场景是 description 里包含裸冒号),自动回退到 parseSimpleFrontmatter 这个逐行正则解析器,后者还支持"缩进续行"式的多行 description。所以即使你的 description 写法不严格,技能通常也能被发现。

(3)名称净化:frontmatter 中的 name 会被清洗为可用作目录名的形式——frontmatter.name.replace(/[:\\/<>*?"|]/g, '-'),冒号、斜杠等字符替换为连字符。

(4)无效文件的处理:没有 frontmatter、或缺少 name/description 任一字段的文件会被静默跳过(loadSkillFromFile 返回 null);若目录非空却没发现任何 skill,debugLogger 会输出调试提示引导你检查 frontmatter。

数据结构上,每个技能被表示为一个 SkillDefinitionnamedescriptionlocation(磁盘绝对路径)、body(frontmatter 之后的正文)、disabledisBuiltinextensionName(见 skillLoader.ts L17-L32)。

四、发现层级与优先级

Gemini CLI 从多个位置发现技能,按优先级从低到高的顺序依次为:

优先级 层级 位置
最低 内置技能(Built-in) 随 Gemini CLI 分发,见 packages/core/src/skills/builtin/
2 扩展技能(Extension) 安装于 扩展 内的技能
3 用户技能(User) ~/.gemini/skills/~/.agents/skills/ 别名
最高 工作区技能(Workspace) .gemini/skills/.agents/skills/ 别名

这些目录常量由 Storage 类 定义:getUserSkillsDir() 返回 ~/.gemini/skillsgetUserAgentSkillsDir() 返回 ~/.agents/skills;工作区侧的 getProjectSkillsDir() / getProjectAgentSkillsDir()storage.ts L301-L307)则指向项目内对应路径。工作区技能可以随版本控制与团队共享。

SkillManager.discoverSkills 严格按此顺序调用各层级的加载器,并通过 addSkillsWithPrecedence 实现"后者覆盖前者":

// 2. Extension skills
for (const extension of extensions) {
  if (extension.isActive && extension.skills) {
    this.addSkillsWithPrecedence(extension.skills);
  }
}
// 3. User skills
const userSkills = await loadSkillsFromDir(Storage.getUserSkillsDir());
this.addSkillsWithPrecedence(userSkills);
// 3.1 User agent skills alias (.agents/skills)
...
// 4. Workspace skills (highest precedence)

同名冲突与别名规则

  • 跨层级重名:高优先级位置的版本胜出。源码会在覆盖内置技能时打 warning 日志("is overriding the built-in skill"),在覆盖用户/工作区技能时通过 coreEvents.emitFeedback 向前端发出 "Skill conflict detected" 警告(skillManager.ts L124-L147)。
  • 同层别名:在用户层或工作区层内部,.agents/skills/ 别名优先于 .gemini/skills/。从源码看,别名目录的加载发生在同层级 .gemini/skills 之后,因此同名技能以别名目录版本为准。
  • 信任边界discoverSkills 接收一个 isTrusted 参数——如果当前文件夹未被标记为受信任,工作区技能会被整体跳过("Workspace skills disabled because folder is not trusted.")。这是一个重要的安全设计:来自陌生仓库的 .gemini/skills/ 不能未经你信任该目录就进入提示词。
  • .agents/skills/ 别名的存在是为了跨工具互操作:同一份技能目录可以被多个遵循该约定的 AI 工具识别。

五、核心收益:渐进式披露

官方文档列出了 Agent Skills 的四项优势,其中最关键的是 Progressive disclosure(渐进式披露)

  • Shared expertise(共享专业知识):把复杂流程(例如某团队的 PR 评审规范)打包成一个谁都能用的目录;
  • Repeatable workflows(可重复的工作流):通过流程化框架确保多步骤复杂任务执行一致;
  • Resource bundling(资源捆绑):脚本、模板、示例数据与说明同目录存放,agent 所需一应俱全;
  • Progressive disclosure(渐进式披露):初始只加载技能元数据(name + description);详细说明和资源只在模型显式激活技能后才披露,从而节省上下文 token。

这一策略对应三级加载模型:

  1. 元数据(name + description)——始终在系统提示中,体量约百词;
  2. SKILL.md 正文——仅在技能被激活时注入对话历史;
  3. 捆绑资源(scripts/references/assets)——按需读取或直接执行,脚本甚至可以不进入上下文直接运行。

内置的 skill-creator 技能 对这一原则有非常具体的工程化要求,例如"SKILL.md 正文控制在 500 行以内、超过 10k 词的参考文件应附带 grep 模式、引用文件保持一层深度"等,可作为编写高质量技能的权威参考。

注意(原文档 NOTE 块):/skills disable/skills enable 默认作用于 user 作用域,管理工作区级设置需加 --scope workspace。查看当前会话所有可用技能请用 /skills list 命令。

六、管理技能

技能可以通过交互式会话命令或直接使用终端命令来管理。

交互式会话中的 /skills 命令

  • /skills list [all] [nodesc]:列出已发现的技能。all 包含内置技能,nodesc 隐藏描述;
  • /skills link <path> [--scope user|workspace]:链接一个本地目录中的技能;
  • /skills disable <name>:禁用指定技能;
  • /skills enable <name>:重新启用已禁用的技能;
  • /skills reload(或 /skills refresh):从所有层级刷新技能列表。

禁用逻辑由 SkillManager.setDisabledSkills 实现,按不区分大小写的名称匹配标记 disabledgetSkills()(用于提示词与工具)只返回未禁用的技能,而 getDisplayableSkills() 额外排除内置技能、供 UI 展示。

终端中的 gemini skills 命令

# 列出所有已发现的技能。--all 用于包含内置技能。
gemini skills list --all

# 从 Git 仓库或本地目录安装技能。
# --consent 用于跳过安全确认提示。
gemini skills install https://github.com/user/repo.git --consent

# 卸载技能。
gemini skills uninstall my-skill --scope workspace

gemini skills list 为例,list.tsloadCliConfigconfig.initialize() 触发扩展加载与技能发现,然后调用 skillManager.getAllSkills()--all 时)或过滤掉内置技能,按"非内置优先、名字典序"排序后打印名称、[Enabled]/[Disabled] 状态、[Built-in] 标记、描述与磁盘位置。

commands/skills/ 目录下还有对应的 install.tsuninstall.tslink.tsdisable.tsenable.ts,每个命令都配有同名单元测试(如 install.test.ts)。

命令选项

技能管理命令支持以下通用与专属选项:

选项 说明
--scope user(全局,默认)或 workspace(项目本地)
--path Git 仓库内包含技能的子目录
--consent 确认安全风险并跳过安装过程中的交互式确认

CLI 命令的完整参考见 CLI reference

七、内置技能与技能创建工具链

仓库自带的内置技能位于 packages/core/src/skills/builtin/,目前包含两个:

  • skill-creator:技能创建向导,附带三个实用脚本:
    • init_skill.cjs:生成含标准 frontmatter 模板与 scripts/references/assets/ 示例目录的技能骨架;
    • package_skill.cjs:先自动校验(YAML 格式、命名规范、是否残留 TODO)再打包成 .skill 分发文件;
    • validate_skill.cjs:独立校验脚本。
  • antigravity-support:一个展示用途的内置支持类技能。

创建技能的标准流程(摘自 skill-creator/SKILL.md):理解技能场景 → 规划可复用内容 → node init_skill.cjs <skill-name> --path <dir> 初始化 → 编辑 SKILL.md(description 必须单行、包含"何时使用"的触发信息)→ node package_skill.cjs <path/to/skill-folder> 打包 → gemini skills install <file.skill> --scope workspace|user 安装 → 在交互会话中手动执行 /skills reload 生效 → 基于真实使用迭代。

仓库对这条工具链本身也有守护:skill-creator-scripts.test.ts 验证 init/package/validate 三个脚本的端到端行为,skill-creator-vulnerabilities.test.ts 专门检验打包与校验过程中的安全边界。

八、延伸阅读

适用前提小结:上述行为以当前仓库代码为准——工作区技能依赖文件夹受信任;内置技能激活免确认;技能名匹配不区分大小写;.agents/skills/ 别名在同层内优先于 .gemini/skills/。编写技能前建议先运行 /skills list 确认发现结果,避免重名技能被高优先级版本静默覆盖。

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