Cherry Studio Skills 治理实战:.agents/skills 单一事实来源、白名单同步与校验机制
2026/9/12 7:04:13 网站建设 项目流程

Cherry Studio Skills 治理实战:.agents/skills 单一事实来源、白名单同步与校验机制

【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio

本文围绕 Cherry Studio 仓库内.agents/skills目录的治理规范展开:如何新增一个 Skill、命名规则约束、public-skills.txt白名单如何驱动.gitignore生成与 Claude 侧符号链接同步,以及pnpm skills:sync/pnpm skills:check两个脚本的完整校验逻辑。读完本文,你可以独立完成仓库级 Skill 的创建、登记与 CI 合规校验,并理解该机制的源码实现细节。

单一事实来源:.agents/skills 是仓库内 Skill 的唯一维护位置

Skills 管理说明 开篇就确立了核心原则:.agents/skills/是仓库内 skills 的唯一维护来源(single source of truth)。所有需要被仓库跟踪、被 CI 校验、被同步到 Claude 目录的 Skill,其真实文件都必须落在这个目录下;其他位置(如.claude/skills/)只存放指向它的符号链接。

从源码结构看,这一原则在 skills-common.ts 中被显式编码为一组路径常量:

export const AGENTS_SKILLS_DIR = path.join(ROOT_DIR, '.agents', 'skills') export const CLAUDE_SKILLS_DIR = path.join(ROOT_DIR, '.claude', 'skills') export const AGENTS_SKILLS_GITIGNORE = path.join(AGENTS_SKILLS_DIR, '.gitignore') export const CLAUDE_SKILLS_GITIGNORE = path.join(CLAUDE_SKILLS_DIR, '.gitignore') export const PUBLIC_SKILLS_FILE = path.join(AGENTS_SKILLS_DIR, 'public-skills.txt')

即整个治理体系围绕五个对象运转:两个 Skill 根目录、两个自动生成的.gitignore、一份公共白名单文件。当前仓库中.agents/skills/下已经存在 8 个公共 Skill(gh-create-prprepare-releasecreate-skillgh-create-issuegh-pr-reviewvercel-react-best-practicescherry-pr-testcherry-electron-dev),它们的具体内容可通过 public-skills.txt 逐一查看。

新增 Skill 的完整流程

文档给出了四步标准流程,逐条展开如下。

第 1 步:创建技能目录

.agents/skills/<skill-name>/下创建新目录。目录名即 Skill 名,必须满足命名规则(下文详述)。

第 2 步:编写 SKILL.md

每个 Skill 目录必须包含SKILL.md,其结构由两部分组成:

  1. YAML frontmatter:至少包含namedescription两个字段;
  2. 正文:精简的流程说明。

以仓库内的 gh-create-pr/SKILL.md 为例,其 frontmatter 形如:

--- name: gh-create-pr description: Create or update GitHub pull requests using the repository-required workflow and template compliance. Use when asked to create/open/update a PR ... ---

description字段写得非常具体:说明该 Skill 何时应被触发("Use when asked to...")、以及触发后 Agent 必须执行的完整动作序列。这是 Skill 能否被 AI 助手正确路由的关键。

Skill 目录内还可以放补充材料,例如gh-create-pr附带 references/ 参考资料、cherry-electron-dev附带 references/electron-instance.md。这些引用文档不会被单独同步,而是随整个目录通过符号链接整体暴露给 Claude。

第 3 步:(可选)Codex UI 元数据

如需为 Codex UI 提供展示元数据,可在 Skill 目录下添加agents/openai.yaml。以 gh-create-pr/agents/openai.yaml 为例:

interface: display_name: "Create GitHub PR" short_description: "Create PRs with required template compliance" default_prompt: "Create a pull request for my current branch using the repository template workflow."

该文件仅用于界面展示(显示名、短描述、默认提示词),与 Skill 功能本身解耦,属于可选项。

第 4 步:登记到公共白名单

若该 Skill 需要作为仓库公共 Skill 被 Git 跟踪,需将<skill-name>追加到 .agents/skills/public-skills.txt。只有完成这一步,后续的skills:sync才会为它生成.gitignore例外规则和 Claude 侧符号链接。

命名规则及其源码级约束

文档规定:Skill 名称仅使用小写字母、数字和连字符(-,并优先使用简短、动作导向的名称(如gh-create-pr)。

这条规则不只是文档约定,而是被 skills-common.ts 中的正则硬性执行:

const SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/

listSkillNames()在解析public-skills.txt时对每一行执行多重校验,任何一条失败都会直接抛错终止流程:

  • 空行与以#开头的注释行被跳过;
  • 行内注释被显式禁止——若某行在名称之后还出现#,会抛出inline comments are not allowed ... put comments on the previous line,即注释必须单独成行,不能写在行尾;
  • 不符合SKILL_NAME_PATTERN的名称(大写、下划线、前导/尾随连字符等)会被判定为invalid skill name
  • 重复登记同一 Skill 名会报duplicate skill name

解析结果最终按字母序排序(names.sort((a, b) => a.localeCompare(b)))后返回,这保证了后续生成的.gitignore例外规则顺序稳定、diff 可预测。

Claude 兼容:符号链接同步机制

每个新增的公共 Skill,需要执行同步命令:

pnpm skills:sync

对应 package.json 中的脚本定义:

"skills:sync": "tsx scripts/skills-sync.ts", "skills:check": "tsx scripts/skills-check.ts"

同步脚本做了什么

sync 脚本 做两类事情,且都具备幂等性(内容无变化时不写盘):

1. 重新生成两个.gitignore由 buildAgentsSkillsGitignore / buildClaudeSkillsGitignore 按白名单构建:

# AUTO-GENERATED by `pnpm skills:sync`. # Do not edit manually. * !.gitignore !README*.md !public-skills.txt !cherry-electron-dev/ !cherry-electron-dev/** ...(每个白名单 Skill 一组例外)

策略是"默认全部忽略,仅放行白名单":.agents/skills/.gitignore*忽略整个目录,再对.gitignoreREADME*.mdpublic-skills.txt以及每个白名单 Skill 目录(!name/!name/**)逐一放行;.claude/skills/.gitignore同理,但放行的是符号链接条目本身(!name)。当前仓库中的 .agents/skills/.gitignore 与 .claude/skills/.gitignore 就是该机制的生成产物,与 8 个公共 Skill 一一对应。

2. 创建/修正 Claude 侧符号链接。核心函数ensureClaudeSkillSymlink的逻辑是:

  • 确认.agents/skills/<name>源目录存在,缺失则直接抛错;
  • 期望的链接目标是相对路径../../.agents/skills/<name>(相对于.claude/skills/);
  • .claude/skills/<name>已是符号链接且指向正确,则跳过(幂等);
  • 若已存在但指向错误,或是普通目录/文件,先fs.rmSync递归删除,再用fs.symlinkSync重建指向../../.agents/skills/<name>的符号链接。

也就是说,skills:sync会自动创建/更新.claude/skills/<skill-name>为指向../../.agents/skills/<skill-name>的符号链接——Claude 读到的 Skill 内容与.agents/skills源目录永远是同一份文件,不存在内容漂移问题。

脚本结束后按结果输出skills:sync up-to-date (N public skills)或逐项列出更新的文件清单,方便在 CI 日志中确认变更范围。

白名单跟踪规则与 skills:check 校验

公共白名单由 public-skills.txt 定义,当前实际内容为:

# Public skills tracked by skills:sync and skills:check. # One skill name per line. gh-create-pr prepare-release create-skill gh-create-issue gh-pr-review vercel-react-best-practices cherry-pr-test cherry-electron-dev

文档对登记方有三条硬性要求,均与源码行为严格对应:

  • 写入该文件的 Skill 会同步到两个.gitignore——即上一节所述的两组自动放行规则;
  • 私有/仅本地使用的 Skill 不应写入白名单——不登记意味着.agents/skills/.gitignore*规则会将其整体忽略,Git 不会跟踪;同时skills:check会把已跟踪的非白名单文件判为违规(见下文);
  • 每行只写一个 Skill 名,注释行必须以#开头,不能写行尾注释——对应listSkillNames()的解析与报错逻辑。

更新public-skills.txt后依次执行:

pnpm skills:sync # 重新生成 .gitignore 与符号链接 pnpm skills:check # 校验一致性

skills:check 的四层校验

check 脚本 是这套治理机制的"守门员",main()依次执行四类检查,任一失败即打印全部错误并以退出码 1 终止:

  1. Gitignore 时效性:用白名单重新构建期望内容,与磁盘上的 .agents/skills/.gitignore、.claude/skills/.gitignore 逐字节比对;不一致即报is out of date (run pnpm skills:sync)
  2. 源目录存在性:白名单中每个 Skill 都必须有对应的.agents/skills/<name>目录,缺失直接报错。
  3. 符号链接有效性checkClaudeSkillSymlinklstatSync检查.claude/skills/<name>——它必须是符号链接(而非普通目录或文件),且readlinkSync读出的目标必须精确等于../../.agents/skills/<name>
  4. Git 跟踪范围不越界checkTrackedFilesAgainstWhitelist执行git ls-files -- .agents/skills .claude/skills,把 Git 实际跟踪的每个文件与白名单比对。允许跟踪的仅限:两侧的.gitignoreREADME*.md(含README.zh.md这类带语言后缀的变体,由正则^\.agents\/skills\/README(?:\.[a-z0-9-]+)?\.md$匹配)、public-skills.txt,以及白名单 Skill 目录下的文件。出现白名单外的已跟踪文件会报tracked file is outside public skill whitelist

校验通过时输出skills:check passed (8 public skills)

值得注意的是,skills:check已接入 CI 基础检查:package.json 中ci:basic-check脚本串联了 lint、格式、类型检查、i18n 检查以及pnpm skills:checkdocs:check。这意味着 Skill 白名单与仓库实际跟踪状态的一致性是每个 PR 都要过的关卡,而不仅仅是本地约定。

Windows 兼容性:符号链接的前置配置

由于本项目使用符号链接同步 AGENTS.md、skills 等文件,Windows 开发者需要手动启用符号链接支持,文档给出两步路径(任选其一)加两步收尾:

  1. 启用开发者模式(设置 → 更新和安全 → 开发者选项);或
  2. 通过本地安全策略(secpol.msc授予SeCreateSymbolicLinkPrivilege权限

然后:

  1. 配置 Git以创建符号链接:

    git config --global core.symlinks true
  2. 重新克隆仓库(或执行pnpm skills:sync),让 Git 按符号链接物化.claude/skills/下的条目。

从实现角度看这一步的必要性:ensureClaudeSkillSymlinkcheckClaudeSkillSymlink都依赖fs.symlinkSync/fs.lstatSync/fs.readlinkSync,在未开启core.symlinks的 Windows 检出中,符号链接条目可能被还原为普通文件,此时skills:check会明确报出must be a symlink, not a file (run pnpm skills:sync)一类的错误,提示重新同步。

小结

Cherry Studio 的 Skill 治理用一份白名单(public-skills.txt)加两个幂等脚本(skills:sync/skills:check)实现了一套低成本的多人协作约束:真实内容只维护在 .agents/skills/ 一处,Claude 侧通过符号链接零拷贝共享,Git 跟踪范围由自动生成的.gitignore白名单精确控制,而skills:check的 gitignore 比对、符号链接比对、git ls-files越界检查三道防线保证了任何漂移都能在 CI 中被拦截。新增 Skill 时只需记住闭环动作:建目录 → 写SKILL.md(含name/descriptionfrontmatter)→ 登记白名单 →pnpm skills:syncpnpm skills:check通过后提交。

【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询