前言
最近在不同的 AI Coding 工具之间切换得比较多:Claude Code、Codex、Qoder,还有一些项目里用到的 Gemini CLI、Copilot 等。
Skill 的格式现在已经逐步收敛了。基本都是一个目录,入口叫 SKILL.md,里面放 name、description 和具体的工作流说明;需要时还可以带脚本、模板和参考资料。
问题不在 Skill 怎么写,而在它们放在哪里。
同一个 release-note Skill,如果希望 Claude Code、Qoder、Cline、Kiro 都能发现,最直接的做法往往是复制四份:
.claude/skills/release-note/
.qoder/skills/release-note/
.cline/skills/release-note/
.kiro/skills/release-note/
刚开始只有一个 Skill 的时候没有感觉。后面一旦改了脚本、补了参考资料,或者调整触发描述,就很容易漏改其中一份。更麻烦的是,用户级 Skill 和项目级 Skill 又是两套目录,久而久之根本不知道哪一份才是“最新的”。
所以我写了一个很小的脚本原型:不发明新的 Skill 格式,也不检查 SKILL.md 内容,只做一件事——把自己的 Skills 集中放好,再让不同工具能找到它们。
GitHub:仓库准备中,后续会补在这里。

问题:目录不统一,不等于格式不统一
现在主流工具对 SKILL.md 的理解已经比较接近,不过发现目录各有一套。
| 工具 | 用户级目录 | 项目级目录 | 是否直接扫描 .agents/skills |
|---|---|---|---|
| Claude Code | ~/.claude/skills/ | .claude/skills/ | 官方文档未声明 |
| Codex | ~/.codex/skills/ | .agents/skills/ | 当前项目环境已验证 |
| Gemini CLI | ~/.gemini/skills/ | .gemini/skills/ | 是 |
| GitHub Copilot | ~/.copilot/skills/ | .github/skills/ | 是 |
| Qoder | ~/.qoder/skills/ | .qoder/skills/ | 官方文档未声明 |
| Cline | ~/.cline/skills/ | .cline/skills/ | 官方文档未声明 |
| Kiro | ~/.kiro/skills/ | .kiro/skills/ | 官方文档未声明 |
| Windsurf / Amp / OpenCode / Roo / OpenClaw | 各有原生目录 | 各有原生目录 | 是 |
这里不再把每个产品的差异全部展开。关键是:.agents/skills/ 已经成了一个很有价值的跨工具约定,但还不能替代所有原生路径。
比如 Gemini CLI 明确把 .agents/skills/ 作为 .gemini/skills/ 的兼容别名;Copilot 同时接受 .github/skills/、.claude/skills/ 和 .agents/skills/;Windsurf、Amp、OpenCode、Roo Code、OpenClaw 也都支持这个共享入口。反过来,Claude Code、Qoder、Cline、Kiro 仍然应该保留原生目录适配。 Gemini CLI GitHub Copilot Windsurf Amp OpenCode Roo Code OpenClaw
先确定边界:这个脚本不管理 Skill 内容
一开始很容易把这个工具做成“Skill 管理平台”:解析 frontmatter、校验规范、扫描脚本安全性、做一个注册表、记录遥测数据……
这些事情当然都有人在做,但不是我这次要解决的问题。
这里的前提很简单:进入管理目录的 Skill 默认已经符合规范,也由使用者自己负责内容。 脚本不读取和修改 SKILL.md,自然也不对“写得好不好”“会不会触发”做判断。
它只管理四类关系:
统一来源 .agents/skills/
目录迁移 原生目录 -> 统一目录
目录发现 原生目录 -> 软链接 -> 统一目录
来源同步 Git checkout -> git pull --ff-only
状态检查 已链接 / 未配置 / 冲突 / 本地有修改
这也是它保持轻量的关键。
和现有 Skill 工具有什么不同
其实业界并不缺 Skill 安装工具。
- skills.sh 提供了发现、安装、榜单和 Skill Packs,更像一个公共目录与分发入口。
- GitHub CLI 的
gh skill可以搜索、预览、安装、更新和发布,并记录来源仓库、ref、tree SHA,支持指定 agent host 和版本固定。 GitHub Docs - OpenSkill 则是面向多个 coding agent 的 Git 型 Skill 包管理器,覆盖发现、安装、更新和发布。
这些方案并不是“太重所以不能用”。如果团队要分发公共 Skill、维护版本、管理第三方来源,它们解决的问题更完整。
我这里的场景更靠前一步:本机已经有一批自己写的、或者团队仓库里已有的 Skills,只希望它们不再复制多份,并且能在多个 AI 工具里被立即发现。为这件事情引入一个市场、中心服务或新的包格式,有点绕了。
简单来说:
| 需求 | 更合适的方案 |
|---|---|
| 发现和安装第三方 Skill | skills.sh、gh skill、OpenSkill |
| 发布团队公共 Skill 包 | Git 仓库、gh skill publish、平台能力 |
| 管理自己电脑和当前项目已有的目录 | 本文的软链接脚本 |
统一目录:用户态和项目态各一份
脚本选择下面两个目录作为唯一真实来源:
~/.agents/skills/ # 用户态:自己的通用工作流
<project>/.agents/skills/ # 项目态:随仓库提交的团队工作流
项目态和用户态不要混在一起。比如发布博客、生成 changelog 这一类个人习惯,放用户态比较合适;某个仓库的发布流程、测试约定、代码审查模板,则应该放进项目态,和代码一起演进。
多数支持 .agents/skills/ 的工具不需要额外工作,直接能扫描到。只有不扫描这个路径的宿主才创建适配链接:
<project>/.agents/skills/ # 唯一真实目录
<project>/.claude/skills -> ../.agents/skills
<project>/.qoder/skills -> ../.agents/skills
<project>/.cline/skills -> ../.agents/skills
<project>/.kiro/skills -> ../.agents/skills
用户态也是同样的逻辑:
~/.agents/skills/ # 唯一真实目录
~/.claude/skills -> ../.agents/skills
~/.codex/skills -> ../.agents/skills
~/.qoder/skills -> ../.agents/skills
~/.cline/skills -> ../.agents/skills
~/.kiro/skills -> ../.agents/skills
注意相对路径的写法。链接文件在 .claude/ 内,所以项目级应该是:
mkdir -p .claude
ln -s ../.agents/skills .claude/skills
而不是 ln -s .agents/skills .claude/skills。后者会被解析为 .claude/.agents/skills,路径就错了。
另外也不要给所有工具无脑创建原生链接。比如 Copilot、OpenCode、Amp 同时会扫描多个兼容目录;把同一目录再链接过去,可能造成同名 Skill 被重复发现。脚本只给“没有 .agents/skills 兼容入口”的工具建链接。
脚本流程
脚本是一个单文件 Bash 工具,迁移和链接不依赖额外运行时;如果要同步 Git 来源,则需要本机有 Git。macOS/Linux 可以直接运行:
chmod +x agent-skills-manager.sh
./agent-skills-manager.sh
默认在当前 Git 项目根目录工作;没有 Git 仓库时就使用当前目录。也可以用 --root 明确指定项目目录。加 --global 则管理 ~/.agents/skills/:
./agent-skills-manager.sh --project
./agent-skills-manager.sh --root ~/Code/my-project
./agent-skills-manager.sh --global
交互菜单目前是这样:
Agent Skills Manager (project)
1) Migrate existing Skills to .agents/skills
2) Check tool and directory compatibility
3) Configure or repair native Skill links
4) Sync Git-backed shared Skill sources
5) Show status
q) Exit
各菜单的责任刻意分得比较开:
1. 迁移
迁移时只看目录,不校验里面的 SKILL.md。
例如项目里原来有:
.claude/skills/release-note/
.qoder/skills/api-review/
脚本会逐个询问,确认后移动为:
.agents/skills/release-note/
.agents/skills/api-review/
对应原生 skills/ 目录在确认已经空了以后,才会被替换为软链接。
如果统一目录已经存在同名 Skill,脚本不会猜哪一份应该保留,也不会覆盖,而是报告冲突并把原目录留在原地。这个地方宁愿麻烦一点,也不能把别人本地改过的 Skill 静默丢掉。
2. 检查
检查只做两件事:统一目录是否存在;各工具的原生目录是缺失、正确链接、错误链接,还是普通目录。
它也会尝试在 PATH 里查找 claude、codex、gemini、qoder、cline、kiro-cli、opencode、openclaw。这只是一个提示,不把“命令不存在”当作兼容性结论——很多 IDE 工具并不一定提供命令行入口。
3. 链接
链接阶段不会覆盖目标目录:
- 目标不存在,创建链接;
- 已经是正确链接,跳过;
- 是普通目录,提示先迁移;
- 是指向别处的链接,原样保留。
这样脚本可以重复执行。反复运行不会不断修改用户环境,也不会吞掉手工配置。
核心实现其实没有多少东西:
# 原生目录都位于 <scope>/.工具名/skills,统一回到 <scope>/.agents/skills
link_value='../.agents/skills'
mkdir -p "$(dirname "$target")"
ln -s "$link_value" "$target"
真正需要多写一点的是状态判断和冲突保护,而不是 ln -s 本身。
4. 更新
“统一目录”解决的是一处修改、到处生效;它并不等于自动知道所有 Skill 的上游版本。
这个原型没有再设计一个 Manifest。当前约定很简单:如果 .agents/skills/ 本身是一个 Git checkout,或者它下面某个 Skill 目录本身是 Git checkout,菜单 4 会在工作区干净时执行:
git pull --ff-only
本地有未提交修改时直接跳过,不使用 reset、不覆盖。不是 Git 目录则提示“无需同步”。
这已经能覆盖一个很常见的长期维护方式:把个人 Skills 或团队 Skills 放在一个 Git 仓库里,然后链接到各个工具。以后如果确实需要锁定版本、多来源依赖、安装第三方 Skill,再接入 gh skill 或其他包管理工具也不晚。
代码结构
目前脚本内部按下面的层次拆分:
agent-skills-manager.sh
├── 参数解析
│ ├── --project
│ ├── --global
│ ├── --root DIRECTORY
│ └── --action migrate|diagnose|link|update
├── Provider 路径表
│ ├── 原生发现 .agents/skills 的工具
│ └── 需要创建原生目录链接的工具
├── 状态判断
│ ├── missing
│ ├── linked
│ ├── other-link
│ ├── directory
│ └── file
├── 迁移与链接
├── Git 同步
└── 交互菜单
脚本不把所有已知工具都硬编码成“必须创建目录”。Provider 表最重要的字段其实只有两个:原生路径,以及它是否已经扫描 .agents/skills。以后增加新工具,只要补一条路径映射和兼容判断即可。
一点限制
软链接最适合本机环境。用户态目录基本没有问题,改一处立即生效。
项目态则要注意 Git checkout、Windows 和云端 sandbox 对 symlink 的支持差异。如果团队环境不稳定,推荐把 <project>/.agents/skills/ 作为真实目录提交;在每个开发者机器上运行脚本生成原生适配链接。这样仓库本身仍然是普通文件结构,链接只属于本地运行环境。
还有一点:Cursor、Aider、Continue 等工具目前主要使用 Rules、AGENTS.md 或自定义命令体系,不能因为它们也能写 Markdown 就强行创建 .cursor/skills/。脚本应该明确显示“不在 Skill provider 表中”,而不是创建一个看起来合理、实际上不会被发现的目录。
总结
这套方案没有试图统一所有 AI 工具,也没有试图成为新的 Skill 平台。
它只做一件很实际的事:
一份 Skill 内容
↓
.agents/skills 作为唯一来源
↓
按需生成各个工具的原生目录链接
↓
一次修改,多个 AI 工具立即看到
对个人开发者来说,先把目录关系理顺,比先选择一个复杂的注册表更有用。等 Skills 多起来、需要分发给团队或维护第三方来源时,再把它交给 Git、gh skill、skills.sh 之类的工具即可。
至此,这个小脚本最核心的实现点就是这些。后面准备把脚本单独整理到 GitHub 仓库,再持续补 Provider 映射和实际使用中的兼容问题。~~~