开源 Agent 套件 ECC 的根目录说明文件怎么写:一套可复制的结构
本文基于 ECC 仓库 commit 591ab5c(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/affaan-m/ECC 最新代码与文档为准。
根目录那份给 Agent 看的说明文件,质量不取决于你写了多少条规则,而取决于每一条能不能被当场核对为真。 规则一旦和仓库现状脱节,Agent 不会报错,它会照着过期的说明去调一个已经不在默认加载路径里的命令,然后把失败原因归到别处。ECC 这个 MIT 许可证的开源套件把这类文件写得比多数项目细,也正因为写得细,它同时把这类文件最典型的失效方式暴露在了明面上——两件事都值得抄。
站内已经有两篇讲通用方法论的文章:CLAUDE.md 怎么写 讲的是从零起草一份说明文件的原则,Cursor Rules 最佳实践 讲的是规则文件在另一套工具里的组织方式。本篇不重复那两套方法论,它做的是另一件事:拿一个任何人都能 clone 下来逐行核对的真实项目,看它把说明文件切成了几层、每层放什么、哪些地方已经和仓库对不上,从这些具体决定里反推出一套你能直接搬走的结构。
一、它把”说明文件”切成了几层
打开 ECC 仓库根目录,跟 Agent 说明相关的入口不止一个,而是分工明确的一组。这个切法本身就是第一个可复制的决定:不要指望一份文件同时服务”在这个仓库里改代码的人”和”把这套东西装到自己项目里的人”。
| 组成部分 | 它负责什么 | 对应仓库位置 | 你什么时候会碰到它 |
|---|---|---|---|
| 仓库自身的 CLAUDE.md | 在 ECC 这个仓库里干活时的指引:怎么跑测试、目录职责、贡献格式、文件命名 | CLAUDE.md | 你要给 ECC 提 PR,或想看它自己怎么约束自己 |
| 跨工具的 AGENTS.md | 通用操作规则:核心原则、可用 agent 一览、安全清单、编码风格、测试要求、工作流 | AGENTS.md | 你用的编码工具读这个通用文件,而不是 Claude 专属文件 |
| 常驻规则目录 | 按主题和语言拆开的长期规则,避免全塞进一份文件 | rules/(rules/common/ 下有 agents.md、security.md、testing.md、git-workflow.md 等,另有 python/golang/rust/react 等语言子目录) | 你想把规则模块化,只在相关语言的项目里加载对应部分 |
| 可抄走的模板 | 给使用者直接复制到自己项目根目录的样例 | examples/CLAUDE.md、examples/user-CLAUDE.md、examples/saas-nextjs-CLAUDE.md、examples/go-microservice-CLAUDE.md 等 | 你要给自己的项目起草第一版说明文件 |
| 规则速查 | 把”必须做/绝不做”和各类资产的格式约定压缩成一页 | RULES.md | 你要快速确认 agent、skill、hook 的文件格式要求 |
| 当下工作状态 | 记录默认分支、当前约束、进行中的队列 | WORKING-CONTEXT.md | 你想知道这个仓库此刻在忙什么、有哪些禁区 |
README 里那张跨工具对照表把这层关系写死了:Claude Code 一侧的上下文文件是 CLAUDE.md 加 AGENTS.md,而 Cursor、Codex、OpenCode 一侧只认 AGENTS.md,GitHub Copilot 走 copilot-instructions.md。同一份文档还特意说明,ECC 不会把根 AGENTS.md 装进 .cursor/,理由是 Cursor 会把嵌套的 AGENTS.md 当成目录级上下文,这样做会把 ECC 自己的仓库身份污染进宿主项目。
这个细节比它看上去重要。它说明作者在设计时区分了两种内容:“这个仓库是什么” 和 “在任何仓库里都该守什么”。前者绝不能外流到别人的项目里,后者才是可移植的。你自己写说明文件时也该做这道切割——把”本项目的部署地址、内部约定、当前迭代重点”和”通用工程纪律”分开放,否则模板一复制就是一堆噪声。
二、一份项目级说明文件该有哪些块
examples/ 目录里那几份模板是这篇文章最有复制价值的部分。把通用模板和真实技术栈模板并排看,能反推出一套稳定骨架。
examples/CLAUDE.md 是骨架版,块序是:Prompt Defense Baseline(提示注入防御基线)、Project Overview、Critical Rules(下分代码组织、代码风格、测试、安全四小节)、File Structure、Key Patterns、Environment Variables、Available Commands、Git Workflow。Project Overview 那一栏直接留的是方括号占位符,摆明了要你自己填。
examples/saas-nextjs-CLAUDE.md 是同一骨架填上真实技术栈之后的样子,块名几乎一一对应,但内容颗粒度完全不同。它的 Project Overview 只有两行:Stack 一行列清 Next.js(App Router)、TypeScript、Supabase、Stripe、Tailwind CSS、Playwright;Architecture 一行说清”默认 Server Components,只有需要交互时才用 Client Components,webhook 走 API routes,写操作走 server actions”。这两行干的事,是把后面所有规则的适用前提一次交代完。
examples/user-CLAUDE.md 则是另一个维度——它示范的是用户级(~/.claude/CLAUDE.md)该放什么:个人编码偏好、你希望在所有项目里都生效的通用规则、以及指向模块化规则文件的索引表。文件里那张表把 ~/.claude/rules/ 下每个文件负责的内容列了出来,本身就是一种”目录即导航”的写法。
把三份放在一起,可复制的骨架是这样的:
- 技术栈与架构判断(两三行,不写历史沿革)
- 关键规则(按数据库、认证、计费、代码风格这类真实边界分节,不按”好习惯”分节)
- 目录结构(带注释的树,注释写职责不写重复的目录名)
- 关键模式(真实存在于代码里的类型定义和函数骨架)
- 环境变量(分组列出,敏感项标注”仅服务端”)
- 测试策略(怎么跑、跑哪几类、关键流程有哪些)
- 工作流与 Git 约定(提交前缀、分支策略、CI 跑什么)
注意第 4 项的写法。examples/saas-nextjs-CLAUDE.md 里的 API 响应格式不是泛泛描述,而是一段真实的判别联合类型:
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string; code?: string }
examples/go-microservice-CLAUDE.md 同理,直接给出 domain 层哨兵错误和 handler 层映射到 gRPC 状态码的完整函数。这类片段的作用不是教学,而是消歧义——Agent 生成新接口时有一个可对齐的形状,不用猜。
三、规则写到什么颗粒度才有约束力
对比两类写法就能看出差距。AGENTS.md 里的 Coding Style 那节写的是”函数小于 50 行、文件小于 800 行、嵌套不超过 4 层”,这类规则可判定,Agent 能自查。而同一节里”Readable, well-named identifiers”这种就只是态度表达,落不了地。
真正有约束力的规则集中在语言与技术栈模板里,特征是每条都能被一次 grep 或一次 code review 判定真伪:
- SaaS 模板的数据库节:查询必须走开启了 RLS 的 Supabase 客户端,不得绕过;迁移只能放
supabase/migrations/,不许直接改库;select()必须写显式列名而不是select('*');面向用户的查询必须带.limit()。 - 认证节里那条尤其典型:受保护路由用
getUser()校验,不要单独信任getSession()。这是一条真实踩过坑才写得出来的规则,Agent 照做就能避开一类安全问题。 - Go 模板的错误处理节:用
%w包装错误、禁止对错误做字符串匹配、禁止init()函数、context必须是第一个参数并贯穿各层。
同样值得抄的是 ECC 自己 CLAUDE.md 末尾那张表——它把文件模式直接映射到该调用的技能:
| File(s) | Skill |
|---------|-------|
| `README.md` | `/readme` |
| `.github/workflows/*.yml` | `/ci-workflow` |
| `*.tsx`, `*.jsx`, `components/**` | `react-patterns`, `react-testing` — for React-specific work invoke `/react-review`, `/react-build`, `/react-test` |
紧跟着一句 When spawning subagents, always pass conventions from the respective skill into the agent's prompt.(派生专项 agent 时,务必把对应技能里的约定带进它的提示词)。这句话解决的是委派场景下最常见的丢失:主线程知道规则,被派出去的 agent 不知道。关于这类委派的机制细节,可以对照 Claude Code 的专项 agent 用法 和 Skills 机制 一起看。
顺带一提,这套仓库里技能的落盘位置有专门的策略文件 docs/SKILL-PLACEMENT-POLICY.md,它把技能分成 curated、learned、imported、evolved 四类,只有 curated 那类放在仓库 skills/ 下并随安装清单分发,其余三类一律落在用户主目录、不进仓库,且来源必须可追溯——learned 与 imported 强制要求在 SKILL.md 旁放一个 .provenance.json,evolved 则从它的来源继承。这是个值得学的分界:仓库里的东西必须是经过审的,机器生成的东西留在本机、并且要带着自己是从哪来的记录。
四、边界与代价:这套写法放弃了什么
写得细是有账要还的,ECC 仓库里能直接看到这笔账。
第一笔是文档漂移。 CLAUDE.md 的 Key Commands 一节列了 /tdd、/plan、/e2e、/code-review、/build-fix、/learn、/skill-create。但仓库里 commands/ 目录下并没有 tdd.md 和 e2e.md——它们躺在 legacy-command-shims/commands/ 里。那个目录的 README 写得很清楚:这些入口”不再由默认插件命令面加载”,只为还有肌肉记忆的老用户保留,建议直接用规范技能。legacy-command-shims/commands/tdd.md 自己也标注了维护中的工作流在 skills/tdd-workflow/SKILL.md。同样,CLAUDE.md 里映射表提到的 /readme 和 /ci-workflow 也不在 commands/ 目录中。这就是本文开头那句判断的现场证据:说明文件跑在了仓库前面。
漂移不止一处。AGENTS.md 开头写着 67 个 agent、281 个技能、94 个命令,与 agents/、skills/、commands/ 目录实际数量对得上;但 WORKING-CONTEXT.md 顶部那行 Last updated 时间戳停在了几个月前,它 Current Truth 一节里记录的公开目录规模也明显是更早的一版,和 AGENTS.md 自己的数字对不上。这个仓库自己的 docs/ARCHITECTURE-IMPROVEMENTS.md 干脆把”说明文件里的计数与仓库实际不一致”列成了待办条目。这不是黑它,而是说明一件事:凡是写进说明文件的可数事实,都会过期,要么用脚本生成,要么别写。
第二笔是指令与执行的落差。 CLAUDE.md 和 examples/CLAUDE.md 开头那段 Prompt Defense Baseline,内容是让模型不要变更身份、不要泄露密钥、把外部抓取的内容一律当不可信数据处理。这是一段文字约定,不是一道拦截。README 的对照表里也承认,Codex 一侧因为没有钩子执行能力,ECC 的约束只能是指令式的,靠 AGENTS.md 和沙箱审批设置来补。你如果需要真正的强制,得走钩子和权限那条路,可参考 Claude Code hooks 的机制。
第三笔是它往你机器上写东西。 这类套件的本质是把大量文件铺到你的项目和主目录:仓库根有 install.sh 与 install.ps1,有 hooks/hooks.json 和 mcp-configs/ 下的外部服务配置,技能策略文件里还明确规定生成物落在 ~/.claude/skills/learned/ 之类的路径。钩子意味着某些工具调用前后会执行本机脚本,MCP 配置意味着可能连出外部服务。装之前值得先看清这三处,不是因为它有问题,而是因为你要为自己机器上跑的每一行脚本负责。
它明确不管的部分也要说清:这套说明文件不管你的业务领域知识,examples/CLAUDE.md 的 Project Overview 就是个空占位符;它给的硬指标(80% 覆盖率、文件 200 到 400 行典型上限、不可变更新优先)是一种取向,脚本工具、原型仓库、数据分析项目照搬多半会难受;它也不替你决定模型和服务商,涉及额度与限制的部分各家规则不同且会调整,以官方最新说明为准。
五、上手与避坑清单
别把命令名当稳定接口写进说明文件。 会踩,是因为斜杠命令看起来像 API,实际上它是随仓库结构迭代的软链接——ECC 自己就把 /tdd 挪进了兼容层。避法:说明文件里写”做 TDD 时使用测试驱动工作流技能”,把具体入口名放在一个单独的、离实现最近的位置,或者干脆让 CI 校验命令名存在。
别在说明文件里手写可数事实。 会踩,是因为写下”目前有 N 个模块”的那一刻它就开始过期,而 Agent 会照着这个数字做判断。避法:要么让脚本生成这段,要么改写成不依赖数字的描述。
通用模板和真实栈模板要分开维护。 会踩,是因为你会忍不住把公司内部路径、部署地址写进那份准备给所有项目复用的文件。ECC 的处理是 examples/ 下按栈拆成独立文件,并且刻意不把仓库自身身份注入到宿主项目。避法:起草时先问一句”这条规则换个项目还成立吗”,不成立的进项目级文件,成立的才进通用层。
规则要写成能判定的句子。 会踩,是因为”代码要可读""注意性能”这类句子读起来很对,但 Agent 无法据此做取舍,最后等于没写。避法:照 SaaS 模板那条”用 getUser() 校验、不要单独信任 getSession()”的格式改写——给出该做的动作、不该做的动作、以及边界。
给关键结构留一段真实代码。 会踩,是因为纯文字描述接口形状时,Agent 每次生成的字段名和错误处理方式都会飘。避法:像那份判别联合类型一样,直接贴出项目里真实存在的类型定义或函数骨架,贴的必须是仓库里跑得通的版本,不能是顺手编的。
装之前先读安装脚本和钩子配置。 会踩,是因为这类套件默认会改动主目录和项目目录,而钩子会在工具调用时执行本机命令。避法:先看 install.sh / install.ps1 干了什么、hooks/hooks.json 注册了哪些触发点、mcp-configs/ 里有哪些外部连接,确认能接受再装;不确定的部分优先用选择性安装而不是全量铺开。
收束
真要从这个仓库带走一件东西,是这个判断顺序:说明文件的每一条规则,先问”它可判定吗”,再问”它会过期吗”,最后才问”它写得好不好看”。前两问不过关,写得再漂亮也是给 Agent 制造幻觉。
给你一份落地前的自检清单:技术栈与架构前提是否在开头两三行讲清;关键规则是否每条都能被一次检查判定真伪;目录树的注释写的是职责还是重复目录名;关键接口有没有一段仓库里真实存在的代码;有没有手写会过期的计数;通用规则和本项目专属内容是不是分开放的;说明文件里提到的每一个入口名,是不是刚刚亲自确认过它还在。
想继续往下看,仓库里三份文件的信息密度最高:RULES.md 是压缩到一页的格式约定,docs/SKILL-PLACEMENT-POLICY.md 讲清了”审过的进仓库、生成的留本机”这条分界,WORKING-CONTEXT.md 则示范了如何把”当前约束和进行中的队列”单独成文——这一份恰恰是多数项目缺的那层。
本文属于 ECC 开源 Agent 套件专题(共 40 篇,从选择性安装一直拆到内部机制)。同一批还写了另一种取向的项目——不给你资产、只给你纪律的 superpowers 方法论专题。