为什么同时用几个 coding agent,配置会越写越乱?#

单用一家 coding agent 时,指令写在哪其实不是问题——它能读到就行。但从第二家开始,问题就来了:同一条"运行测试用什么命令"要在 CLAUDE.mdAGENTS.md.github/copilot-instructions.md 里各写一份;同一份 “PR review 流程” 要在 .claude/skills/.qwen/skills/.agents/skills/ 里各放一份副本。维护一阵之后,哪份落后了、哪份还没更新,基本靠记忆。

这篇笔记就是围绕这件事展开的:哪些内容应该共享、哪些注定各写各的、共享的那部分怎么组织才不至于每次都手抄

“always-on 指令"和 “skill” 到底不是一回事?#

先把两个经常被混用的词分开。

  • Always-on 指令文件:agent 启动时就加载到系统提示里、每次对话都在的那一段。Claude Code 的 CLAUDE.md、Codex 的 AGENTS.md、GitHub Copilot 的 .github/copilot-instructions.md 都是这一类。
  • Skill:放在 agent 能扫到的目录下的独立指令,主文件叫 SKILL.md、每个 skill 一个子目录。按这些产品目前公开文档的描述,正文通常不默认加载,而是在相关任务出现时再被纳入上下文。

换成提示词工程的类比:always-on 对应"不管你说什么都先念一遍的系统提示”,skill 对应"用户说到特定事情时才从抽屉里拿出来的那份 SOP"。两者能共存,但职责不一样——把它们混在一个大文件里,维护成本会随数量线性上升。

后文讨论的核心只有一条:skill 这一层怎么跨 agent 共享一份源,always-on 那一层为什么我反而劝你各写各的

四家 agent 把这两层分别放在哪?#

到 2026 年,大致是这样(详细路径见后面的落地映射表):

  • Claude Code:always-on 是 CLAUDE.md;skills 在 ~/.claude/skills/.claude/skills/
  • Qwen Code:原生支持 SKILL.md 技能目录,个人级 ~/.qwen/skills/、项目级 .qwen/skills/
  • Codex:always-on 是 AGENTS.md,skills 原生放 .agents/skills
  • GitHub Copilot:三层都有——always-on 的 custom instructions、explicit 入口的 prompt files,还有 Agent Skills。

只要规则数量上来了,再加上"调试流程"“发布 SOP"“PR review 清单"这类多步骤内容,就很难继续塞在同一个 always-on 文件里。下一个自然的问题是:skill 到底是怎么被 agent 挑中的?

Claude Code 是怎么决定要不要用某个 skill 的?#

我只展开 Claude Code 这一家——它的官方文档把加载过程写得最清楚(见文末 Anthropic Skills 文档)。Qwen / Copilot / Codex 的具体实现我没做过内部验证,只能确认它们也都实现了"按需加载"的总体思路。

按 Anthropic 的描述,大致六步:

  1. 启动扫描 —— agent 启动时扫 ~/.claude/skills/<project>/.claude/skills/,把每个 SKILL.md 的 frontmatter 读一遍。
  2. 注册 —— 只把 name + description 放进系统上下文,正文不加载。这一步叫 progressive disclosure——只暴露目录,不暴露内容。
  3. 匹配 —— 用户消息进来后,模型靠 description 判断要不要用这个 skill。隐式触发看语义匹配,显式触发靠 /<skill-name>
  4. 加载 —— 决定使用后,SKILL.md 正文被读进上下文。skill 真正进入模型脑子里的时刻就是这一步。
  5. 按需扩展 —— 正文里如果引用了 references/scripts/,模型用普通 Read / Bash 工具按需加载。这是 progressive disclosure 的第二层——长内容不自动进预算。
  6. 执行 —— 剩下的部分,模型就按正文的步骤跑。对模型而言,正文是一段临时注入的指令。

这几个小规矩为什么有必要?#

把流程拆开看,那些听起来有点教条的"skill 写法约定"就顺了:

  • description 是触发器 —— 至少在 Claude Code 这里,第 3 步的匹配主要靠它,糊了要么漏触发、要么误触发。
  • SKILL.md 短就是省钱 —— 第 4 步每次命中都把整段正文读入上下文,长了就是每次都付长 token 成本。
  • When NOT to use 值得写 —— 第 3 步匹配时模型看不到正文,到第 5 步才有机会"撤回”——反向触发条件就是撤回的依据。
  • 长内容放 references/ —— 第 5 步按需加载,没被引用到就不花钱。

举一个我自己的小观察:写这篇文章时让 Claude 顺手 review 了一轮。我本地装过一个叫 caveman-review 的 skill,description 明确限定在 “review this PR / review the diff / code review” 这类词上。Claude review 文章时没有触发它。我不能 100% 确定原因,但最可能的解释就是 description 写得够窄——限定在 PR / diff / 代码上,而我给的是一篇博文。反过来,如果当初描述写成 “review anything”,误触发概率会高不少。

那为什么不把所有东西都塞到 CLAUDE.md 里?#

“写一个巨型 always-on 文件就完了"的想法我也试过。问题是内容的性质不同

类型 适合放什么 典型载体
Always-on 规则 项目背景、代码规范、测试命令、目录约定 CLAUDE.mdAGENTS.md.github/copilot-instructions.md
On-demand 技能 调试手册、PR review、发布流程、文档生成 SKILL.md + references/ + scripts/
一次性任务入口 “生成 PR 描述"“跑安全检查"“写 onboarding 计划” Copilot prompt files、手动 slash commands

判断方法非常简单:

  • 这条内容每次都该生效吗? → always-on。
  • 这条内容是多步骤流程、只有某类任务才用得上吗? → skill。
  • 这条内容是我偶尔手动触发一次的吗? → prompt file 或显式调用。

三类混在同一个文件里,后面想拆出来比塞进去难得多。

skill 能不能一份源文件同时供四家 agent 用?#

可以,但别贪心。业内常用的说法叫 “canonical source + projection”——一份源(canonical),映射(projection)到各个目标位置

我现在的做法是:skill 只写一份通用源,再复制到不同 agent 的原生目录;always-on 则每家自己手写

flowchart LR A[Canonical skill source] --> B[Claude Code
CLAUDE.md + .claude/skills] A --> C[GitHub Copilot
instructions + prompts + skills] A --> D[Qwen Code
.qwen/skills] A --> E[Codex
AGENTS.md + .agents/skills]

按我现在的用法,关键不是"所有 agent 完全共用同一套文件”,而是三条小约束:

  1. skill 流程只写一份。
  2. 每个 agent 的 always-on 自己手写,别硬跨 agent 投影。
  3. always-on 规则和按需技能分开维护。

为什么 always-on 不值得硬合并?#

这一点我走过弯路。最初也想把 CLAUDE.md / AGENTS.md / copilot-instructions.md 用一份源文件渲染出来,但各 agent 的默认行为、能力边界、触发机制差得够多,强行合并的结果是每份都不太好用。后来我接受了"always-on 各写各的"这个现实——只有 skill 层坚持做"一份源 + 多处复制”。

目录怎么组织才不至于后期推倒重来?#

我目前在用的结构长这样:

my-agent-skills/
├── skills/
│   ├── spring-boot-review/
│   │   ├── SKILL.md
│   │   ├── references/
│   │   │   ├── checklist.md
│   │   │   └── hotspots.md
│   │   └── scripts/
│   │       └── collect-diff.sh
│   └── incident-postmortem/
│       └── SKILL.md
├── overlays/
│   ├── claude/
│   │   └── CLAUDE.md
│   ├── copilot/
│   │   ├── copilot-instructions.md
│   │   └── prompts/
│   └── codex/
│       └── AGENTS.md
└── bin/
    └── install.js

几个地方值得单独解释:

  • skills/我这里唯一的能力源,其他位置都是它的投影。
  • references/ 专门放长文档,把 SKILL.md 本体压短。
  • scripts/ 只放确实需要脚本化的步骤——不是越多越好,每多一段都是一份维护账。
  • overlays/ 是我自己的命名,不是任何 agent 的官方目录——它是 always-on 手写版本的集中地,交由安装脚本复制到目标位置(比如把 overlays/claude/CLAUDE.md 放到仓库根目录)。叫 per-agent/ 也完全可以。

如果想看一个更完整的真实例子,可以参考 obra/superpowers:它把 skills/commands/agents/hooks/ 当成并列的一等目录,并且为 Claude、Codex、Gemini 各写了一份独立的顶层文件(CLAUDE.mdAGENTS.mdGEMINI.md)。它提供的是工程方法论(TDD、brainstorm、plan、review 这些 meta-skill),定位和"个人领域 skill 库"不一样。如果你装了 obra/superpowers,就不用再在自己的仓库里重写那些通用 meta-skill——让 obra 做上游,自己的仓库专注领域特化的 skill 会更省事。

一份 SKILL.md 怎么写才能四家都能用?#

跨 agent 兼容时,关键是把最小公共集合写对,别为单个 agent 写花哨 frontmatter。我把 portable core 限制在三件事:

  1. name——稳定的 kebab-case 名称。
  2. description——同时写清"做什么"和"什么时候用”。
  3. 正文——只写步骤、判断条件、输出格式、引用的 supporting files。

我后来加进模板的一个默认段:一小段 “When NOT to use”。description 是自然语言匹配触发的,写清楚反向条件按道理能降低误触发概率。实际体感上我这边跑下来,边界模糊的 skill 加了这段之后确实更少乱命中,但这是我个人经验,没做过严格对照。做法是从 obra/superpowers 里那些 meta-skill 抄来的。

下面这个模板基本可以作为跨 agent 的起点:

---
name: spring-boot-review
description: Review Java and Spring Boot pull requests for transaction boundaries, API contract drift, N+1 queries, and exception handling. Use when reviewing backend PRs, service refactors, or repository-layer changes.
---

# Spring Boot Review

## When to use

- Reviewing a backend PR that touches controller / service / repository layers
- Spring data / JPA changes that might introduce N+1 or paging issues

## When NOT to use

- Not for: non-Java PRs, or frontend-only changes
- Not for: infra-only changes (Dockerfile, CI) without app code changes

## Review goals

- Identify correctness and transaction boundary issues
- Identify persistence and query efficiency risks
- Flag API contract changes that may break clients

## Process

1. Read the changed controller, service, and repository files.
2. Check whether transaction boundaries are placed at the service layer.
3. Check whether changed queries introduce N+1 or missing pagination.
4. Compare request and response structures with previous API behavior.
5. Produce findings ordered by severity.

## References

- Use [references/checklist.md](./references/checklist.md) for the full checklist.
- Use [references/hotspots.md](./references/hotspots.md) for common Spring data pitfalls.

这样的 skill 有几个好处:

  • Claude Code、Qwen Code、Codex 的技能目录都是 SKILL.md + 子目录的形式,格式基本一样。
  • Copilot 的 Agent Skills 官方文档里也把 SKILL.md 列为可识别格式之一(见参考资料里的 VS Code Agent Skills 文档)。
  • 后面要为某家 agent 加专属能力时,不用回头重写核心流程。

具体到每个 agent,规则、技能、入口分别该放哪?#

真正落地时,我按下面这张表来布置。读表前先约定:

  • ~/$HOME/ 开头 = 个人级(所有项目共享,装在 home 目录下)。
  • . 开头、不带 ~ = 项目级(在仓库里,只对这个仓库生效)。
  • 有些条目同时给出两者,意思是两种层级都能用,按需选。
Agent Always-on 层 Skill 层 我的建议
Claude Code CLAUDE.md(项目级)、~/.claude/CLAUDE.md(个人级) ~/.claude/skills/(个人级)、.claude/skills/(项目级) 项目事实放 CLAUDE.md,流程放 skills
GitHub Copilot .github/copilot-instructions.md(项目级)、.github/instructions/**/*.instructions.md(项目级、按路径过滤)、AGENTS.md(项目级) .github/skills/(项目级)、~/.copilot/skills/(个人级,有限)、.claude/skills/.agents/skills/(Copilot 目前也能读) 规则、prompt、skills 三层并存比较稳
Qwen Code 以项目约定为主 ~/.qwen/skills/(个人级)、.qwen/skills/(项目级) 当成 skill-first agent 用就行
Codex ~/.codex/AGENTS.md(个人级)、仓库内 AGENTS.md(项目级) $HOME/.agents/skills(个人级)、.agents/skills(项目级) AGENTS.md 写规则,skills 写流程

我自己比较在意两点:

  • Claude / Codex——适合"规则文件 + 技能目录"双层结构。
  • Copilot——虽然现在也支持 Agent Skills,但日常工作流里 copilot-instructions.md.github/prompts/*.prompt.md 仍然有用,两者分别对应"默认行为"和"显式调用入口”。

两个容易被忽略的边界:

  • Qwen Code —— 我在本文里把它当 skill-first agent 主要是因为目前它公开文档里讲得最清楚的就是 Skills 体系。
  • Copilot prompt files —— 目前主要面向 VS Code、Visual Studio、JetBrains,仍在 public preview;如果你的主要入口是 GitHub.com,把重心放在 instructions 和 agent instructions 上更实际。

想一键安装所有 skill,应该怎么做?#

要把这套个人 skill set 做成一个可一键安装的仓库,一个可行的思路是:

  1. 所有技能统一维护在 skills/<name>/SKILL.md
  2. 安装时按目标 agent 把同一份 skill 复制到它的原生路径。
  3. always-on 规则按 agent 分别维护手写版本:Claude 的 CLAUDE.md、Codex 的 AGENTS.md、Copilot 的 .github/copilot-instructions.md
  4. 需要显式入口的工作流,再为 Copilot 额外生成 .github/prompts/*.prompt.md

一句话:别让 SKILL.md 同时承担 repo rules、聊天入口和项目约束。这几类内容放一起维护起来会很吃力。

如果不想自己写安装器,vercel-labs/skills 这个通用 CLI 已经能把 skills/<name>/SKILL.md 形式的仓库一键装到 40 多家 agent——我自己的仓库就是靠它分发的。可以参考文末"相关文章"里那篇。

新增一个 skill 时,应该按什么顺序做?#

我自己的习惯动作:

  1. 先判断它是不是 skill,而不是规则。 如果内容是"这个仓库一直怎么做",放 always-on;如果是"遇到某类任务时怎么做",才是 skill。
  2. 把它限制在清晰的能力边界里。 好的 skill 名字通常长得像 pr-reviewschema-migration-checkincident-postmortem,而不是 backend-helper 这种大杂烩。
  3. description 写成触发器,不是摘要。 最好同时包含"任务类型 + 触发词 + 使用场景"。这会直接决定 agent 能不能自动命中。
  4. 长内容搬去 references/ SKILL.md 保持短而清楚;长 checklist、样例输出、领域知识移到 supporting files。
  5. 只有确实需要脚本化时才加 scripts/ 很多 skill 靠 instructions 就够了;脚本越多,维护成本越高。
  6. 分别测 implicit 和 explicit 两种触发。 既要测"正常提问时会不会自动命中",也要测手动 slash 或显式点名时是否稳定。

某条内容到底该写成 rule 还是 skill?#

我自己最常用的判断表:

你想沉淀的内容 放哪里
“这个仓库通常用哪个命令跑测试” CLAUDE.md / AGENTS.md / copilot-instructions.md
“所有 TypeScript 文件都要遵守哪些约定” Claude 下放在 CLAUDE.md 的分节里;Copilot 下用 .github/instructions/*.instructions.md
“遇到 Spring Boot PR 怎么做结构化 review” SKILL.md
“帮我生成一份 PR 描述” Copilot prompt file 或手动调用 skill
“这个团队处理线上事故的标准流程” SKILL.md + references/

两条经验法则:

  • 如果你发现自己总在同一个 agent 的聊天窗口里反复粘贴 checklist —— 那就是 skill。
  • 如果你发现自己希望 agent 每次都默认遵守某条规则 —— 那通常更像 always-on instruction。

所以结论是?#

用这套方法跑了一段时间之后,对我最有帮助的并不是"找到一个万能文件",而是接受不同 agent 有各自的职责分层:规则文件更适合放默认行为,skills 更适合放按需能力,prompt files 更适合放显式入口

把 skill 层做成 canonical source 之后,安装、分享、版本管理、跨 agent 迁移都会容易一些。至于每个 agent 的 always-on 文件,我不再强求跨 agent 复用——各写各的反而更清爽。

参考资料#

下面这些链接我都按本文里的结论逐页核对过,只保留和正文直接对应的页面:

相关文章#