尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

改一条 Skill 规则要改四处?一条 ln -s 让多个 AI 编码工具共享同一份配置

改一条 Skill 规则要改四处?一条 ln -s 让多个 AI 编码工具共享同一份配置 摘要Claude Code、Codex、QoderCN 国际版和国内版Skill 格式一样但目录各不同改一条规则要改四处。本文用软链做到「一份维护、处处生效」真相源只存一份 SKILL.md各工具 skills 目录ln -s指过去。重点是三个反直觉的坑Codex 项目级读的是中立目录.agents/skills而非.codex/skillsQoderCN 项目级只认项目根skills/~/.agents/skills项目层一条顶一片、全局层只覆盖一小组工具。写在前面如果你跟我一样同时跑着四个 AI 编码工具——Claude Code、Codex、QoderCN 国际版、QoderCN 国内版——那你大概率遇到过这个场景你写了一条新的 Skill 规则“Java 内部方法调用必须加this.前缀”。然后你发现Claude Code 读~/.claude/skills/Codex 读~/.codex/skills/QoderCN 国际版读~/.qoder/skills/QoderCN 国内版读~/.qoder-cn/skills/四个目录四份文件。你建了四份。过了两周你想改一下这条规则的触发描述。你得打开四个文件改四遍。又过了一周你同事问你这条规则到底在哪定义的你指了指.claude/skills/。同事说但 Codex 好像不认这个路径啊你沉默了三秒默默又建了一条软链。这就是配置漂移——同一个意图散落在多个物理位置改一处漏两处时间一长谁也不知道哪份是最新的。折腾一圈之后我想通了一件事这四个工具的 Skill 格式完全相同都是SKILL.md frontmatter只是配置目录不一样。既然内容一样为什么不只维护一份然后用软链把四个目录串起来✅ 一条 ln -s改一条规则只改 1 处ln -sln -sln -sln -sln -s规则改动真相源SKILL.md~/.claude/skills~/.codex/skills~/.agents/skills~/.qoder/skills~/.qoder-cn/skills❌ 复制四份改一条规则要改 4 处规则改动.claude/skills.codex/skills.qoder/skills.qoder-cn/skills 如果你对 Skill 的概念还不太熟悉建议先看一下 《CLAUDE.md 写到 500 行还管不住 AISkills 分层食用指南》这篇把 Skill 和 CLAUDE.md 的区别讲得很清楚。本文聚焦在多工具共享这个环节。一、问题本质格式一样目录不同先把四个工具的 Skill 目录摆出来注意是 Skill 目录不是配置目录下面会说这个区别有多坑工具全局 Skill 目录项目级 Skill 目录Claude Code~/.claude/skills/.claude/skills/Codex~/.codex/skills/.agents/skills/QoderCN 国际版~/.qoder/skills/项目根skills/⚠️ 见下QoderCN 国内版~/.qoder-cn/skills/项目根skills/⚠️ 见下两个反直觉的点都是踩过才知道的① 全局和项目不是「加个~」那么简单。最典型的是 Codex全局在~/.codex/skills/项目级却不是.codex/skills/而是.agents/skills/——一个跟工具名毫无关系的目录。你按「全局路径去掉~」的直觉去建项目级软链建完不生效还查不出为什么。② 「配置目录」和「Skill 目录」是两回事而且文档不一定对得上实现。QoderCN 的settings之类确实读.qoder/。公开的规范映射表里它项目级 Skill 目录也写的是.qoder/skills/——但我实测放那儿不生效只有项目根的skills/才被加载详见 3.2。⚠️ 这条值得单独记一笔这类映射表是社区维护的未必跟得上每个工具的每个版本。真按表建完不生效别怀疑人生直接换个位置试——判据很简单建完开一个新会话问它「你现在加载了哪些 skill」比读任何文档都快。 顺带说那个.agents/不是 Codex 自创的——它是 Agent Skills 规范 定义的厂商中立目录一批工具正在往上收敛。这件事对本文方案影响很大单独放在第四节讲。好在 Skill 文件的格式完全一样——一个SKILL.mdfrontmatter 里写name和description正文写规则内容。各工具加载的逻辑也一样扫描自己那个skills/目录每个子目录就是一个 Skill。唯一的区别就是目录名。这就给软链创造了条件只要把内容放在一个物理目录里然后让四个工具的skills/都指向它问题就解决了。二、核心思路一份物理文件 多条软链~/docs/team-docs/skills/ ← 真相源单一事实源唯一维护点 ├── common/ ← 全局通用那份 └── order-svc/ ← 项目专属那份 全局层软链所有项目生效 ├ ~/.claude/skills/ ← Claude Code ├ ~/.codex/skills/ ← Codex ├ ~/.agents/skills/ ← 中立目录Cline / Warp / Zed / Kimi Code CLI ├ ~/.qoder/skills/ ← QoderCN 国际版 └ ~/.qoder-cn/skills/ ← QoderCN 国内版 项目层软链仅本仓库生效 ├ project/.claude/skills/ ← Claude Code ├ project/.agents/skills/ ← 中立目录Codex / Cursor / Gemini CLI / Copilot / OpenCode… └ project/skills/ ← QoderCN项目根两版本共用一句话总结SKILL.md 共享一份各工具的 README / settings 各自维护。为什么不全量软链把整个.claude/链过去因为每个工具还有自己的配置文件——Claude Code 有CLAUDE.mdQoderCN 有settings.json这些东西不该共享。只软链skills/这一层粒度刚好。三、实操两层软链全局 项目Skill 分两层——全局层所有项目生效和项目层仅当前项目生效。软链也要分两层建。3.1 全局层全局层放在用户主目录下所有项目都会加载# 真相源只有一份公共层放在~/docs/team-docs/skills/common/# Claude Codemkdir-p~/.claudeln-s~/docs/team-docs/skills/common ~/.claude/skills# Codexmkdir-p~/.codexln-s~/docs/team-docs/skills/common ~/.codex/skills# QoderCN 国际版mkdir-p~/.qoderln-s~/docs/team-docs/skills/common ~/.qoder/skills# QoderCN 国内版mkdir-p~/.qoder-cnln-s~/docs/team-docs/skills/common ~/.qoder-cn/skills# 中立目录Cline / Warp / Zed / Kimi Code CLI 这一组全局读它mkdir-p~/.agentsln-s~/docs/team-docs/skills/common ~/.agents/skills建完之后这几个路径都指向同一个物理目录。你在里面新增一个 Skill对应的工具同时生效。⚠️全局层没有「一条通吃」的写法。~/.agents/skills听着像万能钥匙但它在全局层只覆盖 Cline、Warp、Zed、Kimi Code CLI 这一组Codex 全局读的是~/.codex/skills/、Cursor 是~/.cursor/skills/、Gemini CLI 是~/.gemini/skills/——各建各的一条都省不了。真正能「一条顶一片」的是项目层见 3.2 和第四节。3.2 项目层项目专属的 Skill 同样收在真相源里——~/docs/team-docs/skills/下的项目子目录如order-svc各项目再软链接入。这里有个和全局层不一样、且实测踩过的坑项目级的 QoderCN不认.qoder/skills、.qoder-cn/skills这种放在 dot 目录里的软链全局层放~/.qoder/skills是认的项目层却不认。项目级 QoderCN 只认项目根目录下的skills/。所以项目层的 QoderCN 只需在项目根建一条skills软链国际版、国内版就都生效了# 真相源~/docs/team-docs/skills/order-svcorder-svc 项目专属那份# Claude Code项目级读 project/.claude/skills指过去ln-s~/docs/team-docs/skills/order-svc ~/repos/order-svc/.claude/skills# Codex 及一大批工具项目级读中立目录 project/.agents/skills不是 .codex/skillsmkdir-p~/repos/order-svc/.agents\ln-s~/docs/team-docs/skills/order-svc ~/repos/order-svc/.agents/skills# QoderCN国际版 国内版共用这一条软链建在项目根名字就叫 skillsln-s~/docs/team-docs/skills/order-svc ~/repos/order-svc/skills 上面第二条是本文更新过的写法。我最早按「全局~/.codex/skills→ 项目级.codex/skills」的对称直觉建建完 Codex 根本不加载。查了规范才知道Codex 项目级读的是中立目录.agents/skills/——而且不只 CodexCursor、Gemini CLI、GitHub Copilot、OpenCode 等一批工具项目级全都读这个路径。这条软链的性价比因此高得离谱一条顶一片。⚠️别在项目里建.qoder/skills/.qoder-cn/skills——实测不生效。项目级 QoderCN 只扫项目根的skills/一条软链两个版本共用比全局层还省一条。全局层没有项目根这一说仍按 3.1 给~/.qoder、~/.qoder-cn各建一条。3.3 一个完整的软链清单以下是我实际在用的完整清单涵盖全局层和多个项目层供参考# 真相源唯一维护点~/docs/team-docs/skills/{common,order-svc,dw-platform,card-keeper}# ── 全局层各工具各挂一条都指向 common这一层省不了──ln-s~/docs/team-docs/skills/common ~/.claude/skills# Claude Codeln-s~/docs/team-docs/skills/common ~/.codex/skills# Codexln-s~/docs/team-docs/skills/common ~/.agents/skills# Cline / Warp / Zed / Kimiln-s~/docs/team-docs/skills/common ~/.qoder/skills# QoderCN 国际版ln-s~/docs/team-docs/skills/common ~/.qoder-cn/skills# QoderCN 国内版# ── 项目层每个项目三条即可 ──# .claude/skills → Claude Code# .agents/skills → Codex / Cursor / Gemini CLI / Copilot / OpenCode… 一条顶一片# skills项目根→ QoderCN 国际版 国内版共用forpinorder-svc dw-platform card-keeper;doSRC~/docs/team-docs/skills/$pmkdir-p~/repos/$p/.claude ~/repos/$p/.agentsln-s$SRC~/repos/$p/.claude/skillsln-s$SRC~/repos/$p/.agents/skillsln-s$SRC~/repos/$p/skillsdone⚠️ln -s前必须确保目标位置不存在。如果目标已经是个目录哪怕是空的ln -s不会替换它而是在它里面建一个同名软链变成skills/skills——而且不报错。建完一律ls -l看一眼箭头别只看命令没报错就以为成了。四、.agents/skills正在收敛的中立标准写这篇的时候我发现一件事值得单独说这个「每家一个目录」的乱局正在被一个中立标准收拾。Agent Skills 规范 定义了一个不属于任何厂商的目录——.agents/skills/。摘一段各工具的实际映射完整表在 vercel-labs/skills工具项目级 Skill 目录全局 Skill 目录Codex.agents/skills/~/.codex/skills/Cursor.agents/skills/~/.cursor/skills/Gemini CLI.agents/skills/~/.gemini/skills/GitHub Copilot.agents/skills/~/.copilot/skills/OpenCode.agents/skills/~/.config/opencode/skills/Cline / Warp / Zed / Kimi Code CLI.agents/skills/~/.agents/skills/Claude Code.claude/skills/~/.claude/skills/QoderCN 国际版 / 国内版.qoder/skills/⚠️ 实测不生效见 3.2~/.qoder/skills/、~/.qoder-cn/skills/盯着这张表看会发现一个很有意思的分裂项目层已经基本统一了Codex、Cursor、Gemini CLI、Copilot、OpenCode、Cline、Warp、Zed……项目级清一色.agents/skills/。全局层还各玩各的同样这批工具全局路径五花八门~/.codex/、~/.cursor/、~/.gemini/、~/.copilot/、~/.config/opencode/只有 Cline、Warp、Zed、Kimi Code CLI 这一组真正落到了中立的~/.agents/skills/。收敛是从项目层开始的——这跟直觉相反你会以为全局配置更容易统一但想想也合理项目目录是团队共享的一个仓库里塞七八个.xxx/skills谁都受不了而全局目录是个人机器上的事各家没动力改。对本文方案的实际影响# 项目层一条 .agents/skills 顶一大片工具优先建这条mkdir-p~/repos/order-svc/.agents\ln-s~/docs/team-docs/skills/order-svc ~/repos/order-svc/.agents/skills# 全局层中立目录只覆盖 Cline / Warp / Zed / Kimi 这一组其余仍需各建各的ln-s~/docs/team-docs/skills/common ~/.agents/skills⚠️别把~/.agents/skills当成全局层的万能钥匙。我一开始就理解错了以为建了它 Codex 全局就通了——实际 Codex 全局读的是~/.codex/skills/那条还得单独建。中立目录在项目层是「一条顶一片」在全局层只是「多一个工具组」。顺带一提既然有了统一规范就有了配套的包管理器skillsCLI 能直接从 GitHub 装社区写好的 Skill装完各工具通用。这也带来一个坑放在第七节讲。五、.gitignore 怎么处理软链软链建好之后有个容易踩的坑Git 会把软链本身当作一个文件来跟踪存储的是链接目标路径字符串而不是跟踪它指向的目录内容。如果你不想把软链提交到仓库比如它是本地开发环境的私有配置需要在.gitignore中排除它。5.1 软链能被 .gitignore 排除吗能。Git 对软链的处理是把它当作一个普通的 blob 文件.gitignore的规则可以正常匹配。# 排除项目级软链项目根的 skills若历史上还留着 .codex/.qoder/.qoder-cn 旧链一并排除 /skills .codex/skills .qoder/skills .qoder-cn/skills5.2 如果软链已经被 Git 跟踪了怎么办需要先从索引中移除再加.gitignore# 从索引中移除不删除物理文件gitrm--cachedskills# 然后加 .gitignoreecho/skills.gitignoregit rm --cached只从 Git 索引中移除不会删除磁盘上的软链。放心用。5.3 另一种思路把软链也提交进去如果你的团队都使用相同的工具组合也可以把软链提交到仓库里。这样其他人git clone下来就自动有了正确的软链结构。不过要注意软链的目标路径必须是相对路径否则换个人机器上就断了或者用脚本在初始化时动态创建见下一节六、新增 Skill 的完整流程有了软链之后新增一条 Skill 的流程变得非常简单判断归属这条 Skill 是全局通用的还是项目专属的在物理目录创建mkdir -p {物理目录}/{skill-name}编写 SKILL.mdfrontmatter 填name和description正文写规则完成——四个工具自动生效不需要额外操作6.1 SKILL.md 的编写注意由于多个工具共享同一份SKILL.mddescription中应使用通用表述不要写死某个工具的名字# 推荐 ✅ description: | TRIGGER when 执行 mvn / gradle / javac 编译时... # 不推荐 ❌ description: | 让 Claude 在执行 mvn 编译时自动...这样无论哪个工具加载这条 Skill描述都是准确的。6.2 软链完整性检查真正容易漏的是全局层——每个工具一条、路径还各不相同漏建一条你只会发现某个工具没加载规则但很难第一时间想到是软链没建。项目层反而省心三条固定写法其中.agents/skills一条覆盖一大批。一个自检脚本全局层逐条查、项目层查三个位置check(){# $1路径if[-L$1];thentgt$(readlink$1)[-e$1]echo✅$1→$tgt||echo 死链:$1→$tgt目标不存在elif[-d$1];thenecho⚠️$1是真实目录不是软链八成是 ln -s 嵌套了查查里面有没有 skills/skillselseecho❌ 缺:$1fi}# 全局层各工具路径不同一条都不能少forlin~/.claude/skills ~/.codex/skills ~/.agents/skills ~/.qoder/skills ~/.qoder-cn/skills;docheck$ldone# 项目层每个项目三条fordirin~/repos/*/;dod${dir%/}check$d/.claude/skills# Claude Codecheck$d/.agents/skills# Codex / Cursor / Gemini CLI / Copilot…check$d/skills# QoderCN项目根done比原来多了两种状态判断死链软链在、目标没了readlink照样有输出容易误判成正常和真实目录多半是ln -s嵌套的后果见 7.1。只判断-L会把这两种都放过去。七、踩坑记录7.1 ln -s 嵌套创建现象软链不生效ls -la发现~/repos/order-svc/skills变成了一个真实目录里面还嵌了一个叫skills的软链。原因建软链时~/repos/order-svc/skills已经存在可能是个空目录ln -s不会覆盖而是在这个目录里面创建了一个名为skills的软链。解决先删掉已有的空目录再建软链rm-rf~/repos/order-svc/skills# 确认是空目录 / 失效软链再删ln-s~/docs/team-docs/skills/order-svc ~/repos/order-svc/skills7.2 软链目标路径用绝对路径 vs 相对路径绝对路径的好处是直观、不容易搞错层级坏处是换台机器或者目录搬家就断了。相对路径的好处是仓库可以整体迁移坏处是层级关系搞错了就 404。我的选择全局层用绝对路径因为~展开后每个人的路径本来就不同全局层本来就是本地配置项目层也用绝对路径配合脚本初始化不依赖相对层级。如果你希望仓库可移植项目层建议用相对路径# 相对路径写法项目根 skillsln-s../../docs/team-docs/skills/order-svc skills7.3 删除物理目录后软链变死链现象某个工具突然不加载 Skill 了ls -la发现软链指向的目标不存在了。原因物理目录被删除或重命名了但软链没有同步更新。排查# 找到所有死链find.-typel!-exectest-e{}\;-print解决重新指向正确的物理目录或者删除死链。7.4 装社区 Skill装进了自己的真相源仓库有了统一规范就有了包管理器skillsCLI 能从 GitHub 拉别人写好的 Skill 装到本地。我顺手装了两个然后git status一看愣住了——它们出现在我的真相源仓库里还被 git 跟踪了。原因~/.agents/skills是一条指向真相源的软链。CLI 往「~/.agents/skills/」写文件写的其实是软链背后那个物理目录——也就是你的仓库。软链是双向透传的你从软链读别人也能从软链写进去。这不是 bug得看你要什么想要三方 Skill 一并版本化、多工具通用、换机器 clone 就有 → 保持现状但在 README 里标出哪些是三方的免得半年后看见没印象的目录顺手删了。不想要那就别把中立目录指向仓库改成物理目录 仓库软链进去反向挂或者干脆.gitignore掉三方那几个目录。还有一条三方 Skill 的安装台账在~/.agents/.skill-lock.json记来源仓库、SKILL.md 路径、内容哈希。要卸载走 CLI别手动rm -rf目录——删了目录但台账还在下次 CLI 检查状态就对不上了。 顺带说这也是「只软链skills/这一层、别整个.agents/链过去」的另一个理由——.skill-lock.json这种工具自己管的状态文件本来就不该进你的仓库。八、方案对比软链 vs 其他方案可能有人会问为什么不直接用其他方案简单对比一下方案优点缺点软链本文方案零依赖、即时生效、改一处全生效需要理解软链机制IDE 偶尔不跟随软链复制文件最简单粗暴改一条改 N 处必然漂移脚本同步可以跨机器需要定时任务或手动触发有延迟统一配置目录最优雅需要工具本身支持自定义配置路径目前不支持软链方案的核心优势是零维护成本——建好之后就不用管了新增/修改/删除 Skill 都是操作物理目录软链自动透传。总结四个 AI 编码工具四份配置目录一份 Skill 内容——用一条ln -s就能把它们串起来告别复制粘贴和配置漂移。核心就四句话物理目录只存一份 SKILL.md这是唯一的维护点全局层每个工具各建一条软链路径互不相同、一条都省不了~/.claude/skills、~/.codex/skills、~/.agents/skills、~/.qoder/skills、~/.qoder-cn/skills项目层只要三条.claude/skills给 Claude Code、.agents/skills一条顶一片Codex / Cursor / Gemini CLI / Copilot / OpenCode…、项目根skills/给 QoderCN 两个版本共用.gitignore可以正常排除软链不想提交就加一行规则如果只让我留一句话是这个「全局路径去掉~就是项目路径」这个直觉是错的。Codex 全局在~/.codex/skills、项目级却在.agents/skillsQoderCN 全局在~/.qoder/skills、项目级却在项目根skills/。这两处不对称是我在这套方案上浪费时间最多的地方——软链本身五秒就建好了难的是知道该往哪儿建。如果你也在多工具之间反复同步配置不妨试试这个方案。毕竟改一条规则只需要改一个地方才是工程师该有的生活。延伸阅读CLAUDE.md 写到 500 行还管不住 AISkills 分层食用指南 AGENTS.md 跨工具吃遍天下 —— 软链共享的这份配置具体怎么写Skills 分层 AGENTS.md 跨工具复用️ 标签AI 编码Claude CodeCodexAgent Skills软链配置管理
返回列表