Gemini CLI Agent Skills 完全指南:按需加载的专业能力与渐进式披露机制
本文以 Gemini CLI 官方文档 skills.md 为主体,系统讲解 Agent Skills 的完整生命周期(发现、激活、授权、注入、执行)、发现层级与优先级规则、/skills 与 gemini skills 两套管理命令,并结合 skillLoader.ts、skillManager.ts 与 activate-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.ts:context.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() 做三件事:
skillManager.activateSkill(skillName)把技能标记为会话级激活状态;this.config.getWorkspaceContext().addDirectory(path.dirname(skill.location))——把 skill 所在目录加入 agent 的允许文件路径,使其有权读取打包资源(文档所说的 "The skill's directory is added to the agent's allowed file paths");- 返回给模型的
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。
数据结构上,每个技能被表示为一个 SkillDefinition:name、description、location(磁盘绝对路径)、body(frontmatter 之后的正文)、disabled、isBuiltin、extensionName(见 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/skills,getUserAgentSkillsDir() 返回 ~/.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。
这一策略对应三级加载模型:
- 元数据(name + description)——始终在系统提示中,体量约百词;
- SKILL.md 正文——仅在技能被激活时注入对话历史;
- 捆绑资源(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 实现,按不区分大小写的名称匹配标记 disabled;getSkills()(用于提示词与工具)只返回未禁用的技能,而 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.ts 先 loadCliConfig 并 config.initialize() 触发扩展加载与技能发现,然后调用 skillManager.getAllSkills()(--all 时)或过滤掉内置技能,按"非内置优先、名字典序"排序后打印名称、[Enabled]/[Disabled] 状态、[Built-in] 标记、描述与磁盘位置。
commands/skills/ 目录下还有对应的 install.ts、uninstall.ts、link.ts、disable.ts、enable.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:独立校验脚本。
- init_skill.cjs:生成含标准 frontmatter 模板与
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 专门检验打包与校验过程中的安全边界。
八、延伸阅读
- 快速上手 Agent Skills:触发与使用技能的快速演练;
- 创建 Agent Skills:创建第一个技能并捆绑自定义逻辑;
- 使用 Agent Skills:如何利用内置与自定义技能;
- 最佳实践:构建高效技能的策略。
适用前提小结:上述行为以当前仓库代码为准——工作区技能依赖文件夹受信任;内置技能激活免确认;技能名匹配不区分大小写;.agents/skills/ 别名在同层内优先于 .gemini/skills/。编写技能前建议先运行 /skills list 确认发现结果,避免重名技能被高优先级版本静默覆盖。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00