关于 improve-agents-md
这是用于逐步改进或从零建立项目 Agent 指令文件的技能,面向希望整理 Claude Code 或其他 Agent 项目规则的开发者。它以 CLAUDE.md 为规范文件,并通过 AGENTS.md 符号链接让不同 Agent 共用一份内容。
主要功能
- 01审查并精简指令文件
- 02从代码库引导创建文件
- 03按相关条件组织规则
- 04处理 CLAUDE.md 与 AGENTS.md
- 05比较改写前后文件指标
适用场景
- 01精简过长的项目 Agent 规则
- 02为新项目建立指令文件
- 03统一 Claude Code 与其他 Agent 的指引
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ desplega-ai/ ai-toolbox --skill improve-agents-md安装后在 Claude Code 中输入/improve-agents-md确认已加载。
详细介绍
improve-agents-md
逐步改进(或从头引导创建)项目的 Agent 指令文件。支持 AGENTS.md(由 OpenAI Codex 提出的厂商中立惯例,Cursor、Claude Code 等也会读取)和 CLAUDE.md(Claude 专用)。磁盘上只保留一个规范文件,并将另一个文件设为符号链接,确保所有 Agent 读取相同的权威来源。
适用场景
- 用户调用
/improve-agents-md(或将/improve-claude-md指向此处) - 用户要求你“清理”“缩短”“审查”或“重写”他们的 CLAUDE.md / AGENTS.md
- 用户抱怨 Claude(或其他 Agent)总是忽略项目规则
- 用户准备接入新的 Agent,并希望检查其指令是否合适
- 不存在 AGENTS.md / CLAUDE.md,且用户想妥善创建一个文件
核心问题
Claude Code(以及大多数其他 Agent)会在注入项目 Agent 文件时附带一条系统提醒:
“此上下文可能与任务相关,也可能无关。除非它与你的任务高度相关,否则不要回应此上下文。”
因此,Agent 会忽略它认为不相关的部分。与当前任务无关的内容越多,Agent 忽略整个文件的可能性就越大——包括此刻真正重要的部分。冗长、缺乏区分的 Agent 文件会适得其反。
有两种方法可以解决这个问题:
- 果断删减。 Linter、格式化工具或 pre-commit 钩子能够强制执行的内容,不应写在这里。能从现有代码模式中发现的内容(LLM 会从上下文中学习),不应写在这里。含糊的要求(“编写整洁的代码”“遵循最佳实践”),也不应写在这里。
- 按条件包装。 针对特定领域的指导应放在
<important if="...">块中,并使用范围明确、具体的条件。这样可以借用 Claude Code 在系统提示词中使用的 XML 标签模式,为模型明确标示相关性,从而弱化“可能相关,也可能无关”的表述带来的影响。
最终得到的是一份简短文件:基础上下文始终可见,领域指导则只会在符合当前任务时“亮起”。
文件解析:哪个文件是规范文件?
此技能在 Claude Code 中运行,因此磁盘上的规范文件是 CLAUDE.md。AGENTS.md 是指向 CLAUDE.md 的符号链接,以便不依赖特定厂商的 Agent(Codex、Cursor、Copilot workspace)读取相同的权威来源。
每次运行开始时的解析逻辑:
- 检查仓库根目录(以及用户从子目录调用时的该子目录)中的
CLAUDE.md和AGENTS.md。 - 根据现有文件选择处理方式:
- 只有
CLAUDE.md→ 对其进行操作;结束时询问是否创建指向CLAUDE.md的AGENTS.md符号链接。 - 只有
AGENTS.md(真实文件,而非符号链接)→ 询问是否将其重命名为CLAUDE.md,并创建指向CLAUDE.md的AGENTS.md符号链接。如果用户不同意重命名,则直接编辑AGENTS.md。 - 两者都存在,其中一个是符号链接 → 编辑真实文件;保留符号链接不变。
- 两者都存在,且都是独立文件 → 这是内容漂移问题。使用 AskUserQuestion 询问哪个文件是规范文件;编辑后询问是否将另一个文件替换为符号链接。
- 两者都不存在 → 使用 AskUserQuestion:1. 根据代码库引导创建新的
CLAUDE.md;2. 中止。
- 只有
务必使用 ls -la(或等效命令)检测符号链接;切勿仅凭文件名判断。
交互流程
此技能是渐进式的,而非一次性操作。在决策节点使用 AskUserQuestion,让用户始终掌握主动权。以下是默认流程;如果输入文件已经简洁明了,或用户要求加快进度,可跳过相应步骤。
第 1 步——解析目标文件
遵循上述解析逻辑。明确说明你将编辑哪个文件以及原因。
步骤 2 — 阅读并分类
通读整个文件。将每个顶级章节归入以下类别之一:
| 类别 | 示例 | 处理方式 |
|---|---|---|
| 基础内容(始终相关) | 项目身份(1 句话)、项目结构(目录列表)、技术栈(1-2 行) | 原样保留在顶部。 |
| 命令 | 构建 / 测试 / lint / 开发命令 | 用一个 <important if="you need to run commands to build, test, lint, or generate code"> 块包裹。保留所有命令。 |
| 条件规则 | “使用 Zod 验证请求”“API 路由放在 X 中” | 用单独的 <important if> 块包裹,并设置明确的触发条件。 |
| 领域章节 | 测试设置、状态管理、i18n、身份验证 | 每个章节分别用一个 <important if> 包裹。 |
| Lint / 格式化范畴 | camelCase、优先用 const 而非 let、严格相等、JSDoc | 删除。建议改用 pre-commit hook。 |
| 空泛的倡议 | “遵循最佳实践”“善用 X Agent”“仔细思考” | 删除。 |
| 过时的代码片段 | 20 行的组件示例 | 删除。替换为文件路径引用(参见 src/utils/example.ts)。 |
步骤 3 — 提议删减内容
重写之前,使用 AskUserQuestion 确认可能引发争议的删除项。不要询问每一项删减——只询问那些合理的人可能有不同意见的内容。将这些内容合并为一个带多选列表的问题:
示例:
“我打算从你的 CLAUDE.md 中删除以下内容,因为它们属于 lint 范畴,或过于空泛而无法执行。你可以接受删除哪些内容?”
- camelCase / PascalCase 规则(属于 lint 范畴)
- “为所有公开函数编写 JSDoc”(lint 可以强制执行,而且内容也已过时)
- “遵循整洁代码原则”(过于空泛)
- 仍然全部保留
如果没有争议性内容要删除,则跳过此步骤。
步骤 4 — 提议新结构
向用户展示建议的章节列表及其 <important if> 条件——暂时不要展示完整的重写内容,只展示大纲。这样成本低,也能在完整重写前发现意见分歧。
使用 AskUserQuestion 征求确认,选项可包括:
- “看起来不错——重写”
- “修改一些条件”(收集具体修改)
- “添加我遗漏的章节”(收集具体章节)
步骤 5 — 快照原文件
在进行任何修改之前,复制当前文件,以便计算修改前后的指标,并为用户保留回滚副本:
cp CLAUDE.md /tmp/CLAUDE.md.before-$(date +%s)
记住快照路径——步骤 7 会用到。
步骤 6 — 重写并比较差异
写入新文件。向用户简要说明差异摘要(新增 / 删除 / 重写的章节)。不要在聊天中贴出完整文件——用户可以在磁盘上查看。
步骤 7 — 报告指标
计算并展示修改前后的对比。需要关注以下四项:
| 指标 | 计算方式 |
|---|---|
| 字符数 | wc -c <file> |
| 行数 | wc -l <file> |
| KB | ls -lk <file>(或 du -k <file>) |
| Token 数(估算) | chars / 4——这是粗略的英语估算方法。足以反映变化方向;不必过度追求精确。 |
分别对 before(/tmp/... 快照)和 after(重写后的文件)运行计算。以紧凑表格呈现:
before after Δ
chars 8,412 3,104 −63%
lines 247 92 −63%
KB 8.2 3.0 −63%
tokens (est.) 2,103 776 −63%
一次性 Bash 辅助脚本(按需调整路径):
metrics() {
local f=$1
local chars=$(wc -c < "$f" | tr -d ' ')
local lines=$(wc -l < "$f" | tr -d ' ')
local kb=$(awk "BEGIN {printf \"%.1f\", $chars/1024}")
local tokens=$((chars / 4))
printf "%s\tchars=%s lines=%s kb=%s tokens~%s\n" "$f" "$chars" "$lines" "$kb" "$tokens"
}
metrics /tmp/CLAUDE.md.before-XXXXX
metrics CLAUDE.md
如果 after 文件没有明显变短(例如,缩减不到 10%),且用户一开始希望进行清理,这就说明删减可能还不够彻底——可考虑在最终确定前再检查一遍。如果文件变长了,可能是你新增了臆造的规则;请对照“不要做什么”列表重新检查输出。
判定阈值
为 after 文件标注判定结果,让用户一眼就能了解结论。Token 数是主要指标;行数/字符数是次要信号。
| Token 数(估算) | 判定 | 含义 |
|---|---|---|
| < 500 | 精简 ✓ | 基础内容 + 少量聚焦的 <important if> 块。适用于大多数项目。 |
| 500 – 1,000 | 良好 | 适合中型项目。模型仍能充分关注。 |
| 1,000 – 2,000 | 臃肿 ⚠ | 几乎肯定包含 linter 涉及的内容、过时片段,或缺少精确触发条件的分组规则。应大幅精简。 |
| > 2,000 | 过度臃肿 ✗ | 大部分内容都会被归入“可能相关,也可能不相关”而忽略。需要大幅重写。 |
以下注意事项需酌情应用,不要机械遵循:
- Monorepo 根目录文件通常会比单个包的文件更长。覆盖多个不同领域的根目录文件即使被判为“臃肿”,也未必有问题。
- 标记完善的文件实际成本更低。一份 1,500-token 的文件,如果大部分内容都由精确的
<important if>触发条件限定,就比一份 900-token 的纯文本文件更合理——模型只会“花费注意力”处理条件匹配的块。 - 行数与章节数的比例是次要判断信号:25 个块共 300 行没问题;3 个块共 300 行则需要重写。
在前后对比表旁报告判定结果,让用户一眼看到方向、幅度和标签。
第 8 步 — 符号链接
如果配套的符号链接不存在,询问是否创建:
ln -s CLAUDE.md AGENTS.md # from repo root
使用 ls -la CLAUDE.md AGENTS.md 验证符号链接是否指向真实文件。
第 9 步 — 提供后续选项
使用 AskUserQuestion 提供以下选项:
- “在 file-review 中打开结果,以便我留下评论” (
/file-review:file-review) - “也扫描此仓库中的子目录 CLAUDE.md 文件”
- “完成”
原则
1. 基础上下文保持原样,领域指导使用条件包裹
如果内容与 90% 以上的任务相关,就将其作为普通 Markdown 放在顶部。如果只与特定类型的工作相关,就用 <important if> 包裹。
2. 条件必须具体且精准
错误 — 一个宽泛条件囊括所有内容:
<important if="you are writing or modifying any code">
- Use absolute imports
- Use functional components
- Use camelCase filenames
</important>
正确 — 每条规则都有各自精准的触发条件:
<important if="you are adding or modifying imports">
- Use `@/` absolute imports (see tsconfig.json for path aliases)
- Avoid default exports except in route files
</important>
<important if="you are creating new components">
- Use functional components with explicit prop interfaces
</important>
<important if="you are creating new files or directories">
- Use camelCase for file and directory names
</important>
这种机制的核心是精确。与“任何时候编写代码”匹配的条件毫无信息价值。
3. 保持内联 — 不要逐步拆分
不要将文件拆分成需要 Agent 额外调用工具才能找到的单独引用文档,除非额外内容确实很长(例如超过 200 行),且极少相关。<important if> 块就是渐进式披露机制;它们让所有内容都可见,同时根据条件调整权重。
4. 少即是多
前沿模型能可靠遵循几百条指令;Claude Code 自身的系统提示词和工具已经占用了约 50 条指令的预算。你的文件应保持精简。
- 删除 linter、格式化工具或钩子可以强制执行的内容。
- 删除 Agent 可以从现有代码模式中发现的内容。
- 删除代码片段——它们会过时。改为引用文件路径。
- 删除含糊的劝诫。
5. 保留所有命令
命令是唯一需要优先保证完整性的部分。即使某个命令很少使用,Agent 也需要知道它的存在。保留原文件中的每条命令;可以删除重复的说明,但不能删除命令本身。
6. 为不明显的规则说明“原因”
如果一条规则的含义不言自明,就不必额外解释。如果不明显,就简要说明原因。Use prismaMock from packages/db/test 可改得更清楚:Use prismaMock from packages/db/test — real DB connections in tests flake on CI。原因能帮助 Agent 在处理边缘情况时做出更好的判断。
输出结构
重写时以此为目标布局。将其用作框架:
# CLAUDE.md
[one-line project identity — what it is, what it's built with]
## Project map
[directory listing with brief descriptions — keep bare]
<important if="you need to run commands to build, test, lint, or generate code">
[commands table — ALL commands from the original]
</important>
<important if="<specific trigger for rule 1>">
[rule 1]
</important>
<important if="<specific trigger for rule 2>">
[rule 2]
</important>
<important if="<specific trigger for domain area 1>">
[guidance for that domain]
</important>
... more sections, each with its own targeted condition ...
注意:
- 标题(
# CLAUDE.md或# AGENTS.md)应与规范文件的名称一致。 - 第 3 行的项目信息应为一句话,而非一段话。
<important if>块内的空行有助于部分 Agent 的渲染效果——请保留。
引导模式(全新项目)
当文件尚不存在,且用户选择了引导模式时:
- 读取仓库根目录:运行
ls,查看cat package.json/pyproject.toml/ 等效文件,确定主要语言和运行时。 - 检测脚本:解析
package.json中的 scripts,或Makefile/justfile/Taskfile中的目标,或pyproject.toml中的工具配置。将其整理为命令表。 - 浏览一层深的目录树(如果是单体仓库,则浏览两层),以绘制项目结构图。
- 对无法推断的信息,通过 AskUserQuestion 询问用户:
- 这是单体仓库、单个服务还是库?
- 是否有不明显的约定(例如,“路由位于 X”)?
- 是否使用了测试框架?Agent 需要了解哪些测试配置?
- 起草一个最简文件——仅包含基础信息和命令。不要编造用户未提供的规则。Agent 文件中规则少一些,也好过添加编造的规则。
转换示例
输入(之前的 CLAUDE.md):
# CLAUDE.md
This is an Express API with a React frontend in a Turborepo monorepo.
## Commands
| Command | Description |
|---|---|
| `turbo build` | Build all packages |
| `turbo test` | Run all tests |
| `turbo lint` | Lint all packages |
| `turbo dev` | Start dev server |
| `turbo db:generate` | Generate Prisma client |
| `turbo db:migrate` | Run database migrations |
## Project Structure
- `apps/api/` - Express REST API
- `apps/web/` - React SPA
- `packages/db/` - Prisma schema and client
- `packages/ui/` - Shared component library
## Coding Standards
- Use named exports
- Use functional components with TypeScript interfaces for props
- Use camelCase for variables, PascalCase for components
- Prefer `const` over `let`
- Always use strict equality (`===`)
- Write JSDoc comments for all public functions
## API Development
- All routes go in `apps/api/src/routes/`
- Use Zod for request validation
- Use Prisma for database access
- Error responses follow RFC 7807 format
- Authentication via JWT middleware
## Testing
- Jest + Supertest for API tests
- Vitest + Testing Library for frontend
- Mock database with `prismaMock` from `packages/db/test`
输出(之后的 CLAUDE.md):
# CLAUDE.md
Express API + React frontend in a Turborepo monorepo.
## Project map
- `apps/api/` — Express REST API
- `apps/web/` — React SPA
- `packages/db/` — Prisma schema and client
- `packages/ui/` — Shared component library
<important if="you need to run commands to build, test, lint, or generate code">
Run with `turbo` from the repo root.
| Command | What it does |
|---|---|
| `turbo build` | Build all packages |
| `turbo test` | Run all tests |
| `turbo lint` | Lint all packages |
| `turbo dev` | Start dev server |
| `turbo db:generate` | Regenerate Prisma client after schema changes |
| `turbo db:migrate` | Run database migrations |
</important>
<important if="you are adding or modifying imports or exports">
- Use named exports (no default exports).
</important>
<important if="you are creating new components">
- Functional components with TypeScript interfaces for props.
</important>
<important if="you are adding or modifying API routes">
- Routes live in `apps/api/src/routes/`.
- Use Zod for request validation.
- Use Prisma for database access.
- Error responses follow RFC 7807.
- Auth via JWT middleware — see `apps/api/src/middleware/auth.ts`.
</important>
<important if="you are writing or modifying tests">
- API: Jest + Supertest.
- Frontend: Vitest + Testing Library.
- Mock database with `prismaMock` from `packages/db/test` — real DB in tests flakes on CI.
</important>
删减内容及原因:
- camelCase/PascalCase、
const与let、严格相等、JSDoc → 属于代码检查器/格式化工具的范畴。 - 将“编码规范”作为一个分组部分 → 拆分到针对性更强的
<important if>块中。 - 填充性文字(“这是一个……”)→ 精简为一行。
保留内容:
- 每条命令。
- 项目结构图(简洁、基础)。
- 所有特定领域的规则,并按更具体的触发条件重新分组。
不要这样做
- 不要编造规则。 如果原文中没有某条规则,且用户也未确认,就不要添加。
- 不要删掉命令。 每条命令都要保留。
- 不要将无关规则归到同一个
<important if>下。具体性才是关键。 - 不要在先向用户展示差异摘要之前就替换文件。
- 没有明确确认,不要删除真实文件来换成符号链接。
- 引导过程中不要递归遍历
node_modules/、dist/、.git/、vendor/。