Everything Claude Code,这个拿下 220K Stars 的开源项目,近期确实备受关注。如果你已经使用 Claude Code 编写代码,大概率听说过它。但许多人对其理解仍停留在“一套配置文件”的层面——这就像把 Kubernetes 理解为“一组 YAML 文件”一样,不能说错,但远远不够。

ECC 的官方定位是 Claude Code 的工程化增强系统。它并非一个单纯的配置,而是一整套体系,包含五个核心层次:
层次 | 作用 | 通俗理解 |
|---|---|---|
Rules | 编码规范、安全策略、工作流标准 | 告知 AI 什么是正确的、什么是错误的 |
Agents | 可复用的专家角色(审查员、测试员、架构师等) | 拥有一队可随时调用的同事 |
Skills | 特定场景的深度知识包,旧版 Commands 的快捷入口 | 每个技能就是一个领域的“专家大脑” |
Hooks | 自动化的前后置触发器 | 将检查变为自动化门禁 |
MCP | 外部工具连接协议 | 让 AI 能够调用数据库、浏览器等真实工具 |
这篇文章不会面面俱到。重点聚焦于理解 ECC 最关键的 Rules、Agents、Hooks 三层——这三层是 ECC 的核心工程化能力,也是在实践项目中踩坑最深、收获最大的地方。Skills 是 Agents 的能力扩展,MCP 则是另一个可以单独展开的话题。
如果你正在使用 ECC 却感觉“好像没什么变化”,或者安装后反而觉得 Claude Code 变慢了,那这篇文章就是为你准备的。
第一章:规则体系的架构哲学
设计哲学:刻意解耦
ECC 的 Rules 分为两层——common/ 存放语言无关的通用规则(编码规范、安全、测试、Git 工作流等),语言层(typescript/、python/、golang/、web/ 等)存放各自专属的规则。
语言层文件通过一行引用关联到通用层:
> This file extends [common/coding-style.md](../common/coding-style.md) with Go-specific content.
这个 extends 不只是装饰。读取语言层文件时,必须同时读取它引用的通用层,才能理解完整的规则体系。
覆盖机制:像 CSS 优先级一样工作
两条规则:语言层覆盖通用层,项目级覆盖全局级。
举个例子。common/coding-style.md 的核心原则是不可变性——所有操作返回新对象,不修改原对象。但 Go 习惯用指针接收器进行 mutation,强行不可变反而写不出地道代码。所以 golang/coding-style.md 可以覆盖这条规则,优先采用 Go 的惯用方式。
第二章:Agent 编排——ECC 的调度引擎
Rules 定义了“应该怎么做”,而 Agents 定义了“谁来做”。这是 ECC 真正拉开差距的地方。
这一章是全文的核心,值得耐心看完。
先看一个贯穿全章的案例:你接到一个需求,要给一个 Python 服务添加 Redis 缓存层。
在没有 ECC 的世界里,你打开 Claude Code,输入需求,AI 直接开始写代码。你 review,发现有问题,让它改,改完提交。全靠你一个人盯着。
在 ECC 的世界里,整个过程是这样的:
你:需求描述 → planner(规划)→ tdd-guide(写测试)→ 你写代码 → code-reviewer(审查)→ build-error-resolver(修构建)→ security-reviewer(安全审查)→ 你确认 → 提交
每个环节都有专门的 Agent 介入,而且大部分是自动触发的。你不用在每一步去想要不要检查、怎么检查——Agent 自己跳出来了。
这就是 ECC Agent 编排的核心价值。
2.1 Agent 生态概览
ECC 目前内置了 67 个 Agent(具体列表随版本变化,以下是日常最常用的一组):
Agent | 用途 | 什么时候用 |
|---|---|---|
planner | 实施规划 | 复杂功能、重构 |
architect | 系统设计 | 架构决策 |
tdd-guide | TDD 引导 | 新功能、bug fix |
code-reviewer | 代码审查 | 写完代码后 |
security-reviewer | 安全分析 | 提交前 |
build-error-resolver | 构建错误修复 | 构建失败时 |
e2e-runner | E2E 测试 | 关键用户流程 |
refactor-cleaner | 死代码清理 | 代码维护 |
doc-updater | 文档更新 | 更新文档时 |
rust-reviewer | Rust 代码审查 | Rust 项目 |
每个 Agent 本质上是一个预定义的 Prompt,告诉 Claude Code 以某种角色执行某种任务。
2.2 自动触发机制:Agent 自己跳出来
ECC 在 agents.md 规则文件中定义了四个自动触发场景。你不用手动调用,当满足条件时,Claude Code 会主动建议使用对应的 Agent:
场景 | 触发条件 | 建议的 Agent |
|---|---|---|
你提了一个复杂需求 | 需求涉及多个文件、多个步骤 | planner |
你刚写完/修改了代码 | Write/Edit 操作完成 | code-reviewer |
你在修 bug 或加新功能 | 需求描述包含“fix/bug/new feature” | tdd-guide |
你在做架构决策 | 涉及系统设计、技术选型 | architect |
这个机制的实现方式并不神秘——agents.md 规则文件里写了类似这样的指令:
No user prompt needed: 1. Complex feature requests - Use **planner** agent 2. Code just written/modified - Use **code-reviewer** agent 3. Bug fix or new feature - Use **tdd-guide** agent 4. Architectural decision - Use **architect** agent
Claude Code 读到了这条规则,就会在执行完代码修改后主动建议:“要不要用 code-reviewer 审查一下?”
实际体验:你刚提交了一段代码修改,Claude Code 说“需要我对刚改的代码做个审查吗?”你说“好”,它就会启动 code-reviewer Agent,拉取变更 diff,逐行审查,输出审查结果。整个过程就像团队里有个 senior 一直在旁边盯着。
2.3 平行执行:同时让两个 Agent 干活
子 Agent 之间默认是独立的。这意味着你可以同时启动多个不冲突的 Agent。
场景:你准备对一个前端模块做大规模重构。同一时间你可以做两件事:
Agent A:code-reviewer 审查现有代码,找出质量问题
Agent B:planner 规划新架构,基于需求文档做实施方案
两个任务没有依赖关系,可以平行跑。这在 ECC 的 rules 里有明确的指导:
# GOOD: Parallel execution Launch 3 agents in parallel: 1. Agent 1: Security analysis of auth module 2. Agent 2: Performance review of cache system 3. Agent 3: Type checking of utilities # BAD: Sequential when unnecessary First agent 1, then agent 2, then agent 3
但注意:有依赖关系的任务不能平行。典型的场景是 TDD 流程——你不能一边让 tdd-guide 写测试、一边让 implementer 写实现代码,因为实现要以测试为驱动。
一个典型的教训:有一次在做数据库迁移,同时启动了 schema-reviewer(审查数据库变更)和 code-reviewer(审查代码变更)。两个 Agent 各自修改了不同的 ORM 文件,但一个改了字段名,另一个用了旧字段名——结果冲突了。
平行执行的原则:
- 可以平行:两个独立模块的审查、规划和审查、测试和安全审查
- 必须串行:有先后依赖的任务(TDD 流程)、操作同一批文件的任务、后一步依赖前一步输出的任务
2.4 上下文隔离:ECC 最被低估的设计
这是 ECC Agent 体系里最有意思的设计——也可能是最容易被忽略的。
子 Agent 零上下文启动。这意味着什么?当你调用 code-reviewer 时,它不会继承主会话里前面几万字的所有对话历史。它只看到它需要看到的东西:代码变更 diff、相关的规则配置、以及你显式传给它的上下文。
这不是缺陷,这是有意为之的设计。三个好处:
- 防止上下文污染:主会话里可能讨论了 20 个不相关的话题,这些对审查代码没有帮助,反而可能让 Agent 分心。
- 降低 Token 消耗:子 Agent 不需要知道你上周五下午讨论的那个 API 设计决策。省下来的 token 就是省下来的成本。
- 聚焦任务:每个 Agent 只看到自己需要的上下文,回复更精准、更少废话。
当然,代价也很明显:子 Agent 不知道你已经讨论过的决策。
场景:你在主会话里已经和 Claude Code 讨论决定了用 Redis 而不是 Memcached。然后你启动了 code-reviewer。code-reviewer 看到代码里有 Redis 的依赖,可能会建议“考虑用 Memcached”—它不知道你已经做出了选择。
解决方案:在调用子 Agent 时,显式传递关键上下文。
“请审查这段代码。已经确认的技术选型:Redis(已决定,不再讨论)、Docker Compose 本地开发。不需要审查这些决定。”
这种“显式传递”机制迫使你做一件好事:把关键决策写清楚。好过把几万字对话历史一股脑丢给子 Agent,让它自己猜什么是重要的。
2.5 子 Agent 成本模型:用 Haiku 省 80%
不是所有任务都需要 Sonnet 或 Opus 级别的模型。code-reviewer 审查一个简单的 bug fix、tdd-guide 写基础的测试脚手架、build-error-resolver 看编译错误——这些任务用 Haiku 完全够用。
Claude Code 原生支持通过环境变量 CLAUDE_CODE_SUBAGENT_MODEL 控制子 Agent 的模型选择(这不是 ECC 独有的特性,但 ECC 的文档中记录了这一配置):
# 子 Agent 全部使用 Haiku 4.5 export CLAUDE_CODE_SUBAGENT_MODEL=claude-haiku-4-5 # 子 Agent 使用 Sonnet 4.6 export CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-6
注意需要使用完整的模型 ID(如 claude-haiku-4-5),不能用简写 haiku。
实际效果:如果你的主会话用 Opus,子 Agent 全切到 Haiku,相对于 Sonnet 4.6 在简单审查任务上单次调用可节省约 80% Token 成本。按通常的使用量,一个月省下来的 token 够跑额外的 50-100 次子任务。
但要注意匹配任务复杂度:
子任务类型 | 推荐模型 | 原因 |
|---|---|---|
简单的代码审查(< 100 行 diff) | Haiku | 足够了 |
复杂的架构审查(跨多个文件) | Sonnet | 需要理解全局 |
build 错误修复(典型错误) | Haiku | 模式识别为主 |
安全审查 | Sonnet 或 Opus | 安全不容有失 |
实施规划(复杂功能) | Sonnet | 需要深度推理 |
一个实用的习惯:日常开发将 CLAUDE_CODE_SUBAGENT_MODEL 设成 Haiku,遇到关键的安全审查或架构决策时,临时切回 Sonnet。
2.6 链式编排:从单任务到流水线
ECC 的 Agent 不只是一个“功能列表”,它们可以串联成流水线。比如一次完整的 feature 开发流程:
planner(出方案)→ tdd-guide(写测试)→ 你写实现代码 → code-reviewer(审查代码)→ build-error-resolver(如果有构建错误)→ security-reviewer(安全审查)→ doc-updater(如果需要更新文档)→ 你最终确认 → 提交
每个 Agent 的输出是否触发下一个,取决于具体场景和你设置的规则。不一定每个环节都要走——如果你的功能不涉及安全敏感操作,security-reviewer 可以跳过。
这种链式编排在 ECC 的 development-workflow.md 里有明确的流程定义:
Research → Plan → TDD (RED → GREEN → IMPROVE) → Code Review → Commit & Push
每步都有对应的 Agent 负责。
2.7 踩坑实录
坑 1:上下文膨胀——Agent 虽然零上下文启动,但 Agent 的输出还是会回到主会话里的。如果你在一个会话里连续调了十几次 Agent,每次产生几百行输出,会话照样会迅速膨胀到接近上下文窗口上限。
一个典型的错误:一天下午在做全栈功能,连续用了 planner → code-reviewer → security-reviewer → code-reviewer(修改后再次审查)→ e2e-runner。到 e2e-runner 跑完的时候,会话已经接近上下文上限,后续的响应明显变慢。
应对:在关键节点开启新会话。planner 输出方案后,评审通过就开新会话开始实现,不把规划阶段所有讨论都带到实现阶段。
坑 2:平行错用——前面提到过。两个 Agent 各自改不同文件,但一个改了接口、另一个还在用旧接口。这个在平行执行时很难靠自动机制检测,因为每个 Agent 只看到自己的任务。
应对:给平行的 Agent 划定明确边界。如果两个任务有共享文件,就不要平行。
坑 3:权限冲突——子 Agent 默认继承了主会话的工具权限。如果主会话有文件写入权限,子 Agent 也能写文件。但有时候子 Agent 会操作到你没想到的文件——比如 code-reviewer 审查代码时发现格式问题,自动触发了格式化,改了 10 个本不该改的文件。
ECC 现在已经有了更细粒度的权限控制(通过 hooks 系统的 PreToolUse 做守卫),但在老版本里这确实是让人头疼的问题。
应对:在关键文件或目录上设置 PreToolUse 钩子做守卫。后面第三章会详细讲。
2.8 排障:Agent 没自动触发怎么办?
理想情况下 Agent 自动触发,但现实不一定。
第一步:检查规则文件是否存在
Claude Code 是读 rules 文件才知道要建议 Agent 的。如果 agents.md 文件不在正确的位置,自动触发就不会发生。
ls ~/.claude/rules/ecc/common/agents.md # 如果不存在,说明安装有问题,重新安装
第二步:检查触发条件是否匹配
规则里写的是“complex feature requests”触发 planner。如果你的需求是“把按钮颜色从蓝色改成红色”,这不属于 complex feature,planner 不会自动跳出来——这是对的。但如果你的需求是“加一个完整的用户认证系统”planner 也没出来,那需要检查你的 rules 配置。
第三步:检查是否有其他规则在静默拦截
如果你装了多个规则包,优先级冲突可能导致某条规则被静默覆盖。去 ~/.claude/rules/ 目录看看有没有非 ECC 的规则包以同名文件覆盖了 ECC 的 agents.md。
第四步:手动调用
如果自动触发怎么都调不通,直接手动调用 Agent 永远是备选方案。这也是 ECC 的设计理念——Agent 是工具,不是约束:
请用 code-reviewer Agent 审查这段代码 请用 planner Agent 帮我规划这个功能
自动触发是锦上添花,不是唯一路径。
第三章:Hooks——从“人肉检查”到“自动化门禁”
Rules 是标准,Agents 是人,Hooks 是自动化流水线。
ECC 的 Hooks 分三种类型:
Hook 类型 | 触发时机 | 典型用途 |
|---|---|---|
PreToolUse | 工具执行之前 | 校验、守卫、拦截 |
PostToolUse | 工具执行之后 | 格式化、lint、类型检查 |
Stop | 会话结束时 | 最终构建验证 |
自动化链条:写完代码后自动发生的事情
最实用的链条是 PostToolUse 的自动化检查。配置好之后,整个流程是这样的:
你写文件 → Write/Edit 完成 → PostToolUse 触发 prettier 格式化 → PostToolUse 触发 eslint --fix → PostToolUse 触发 tsc --incremental 类型检查 → 如果有问题,立即提示你
每次编辑后自动触发,不需要你手动运行任何命令。
配置示例(来自 ECC web/hooks.md):
{“hooks”: {“PostToolUse”: [{“matcher”: “Write|Edit”, “command”: “pnpm prettier --write “$FILE_PATH””, “description”: “Format edited frontend files”}, {“matcher”: “Write|Edit”, “command”: “pnpm eslint --fix “$FILE_PATH””, “description”: “Run ESLint on edited frontend files”}, {“matcher”: “Write|Edit”, “command”: “timeout 60 pnpm tsc --noEmit --pretty false --incremental --tsBuildInfoFile node_modules/.cache/tsc-hook.tsbuildinfo”, “description”: “Type-check after frontend edits (incremental + timeout-capped)”}]}}
tsc 的两个关键参数
注意 tsc 那行配置,两个细节值得展开。
--incremental 为什么重要?
没有 --incremental,每次 PostToolUse 触发 tsc 时,都会从头开始全量类型检查。在一个中型 Next.js 项目上实测(1000+ 文件),全量类型检查需要 30-60 秒。而你的编辑周期是 5-10 秒一次。结果就是:N 个 tsc 进程同时跑,每个都在全量检查,机器越来越慢,最后你可能直接把 hook 关掉了。
--incremental 会缓存上次的编译结果,只重新检查改动的文件。在一两次编辑后的增量检查,通常只需要 1-3 秒。
但注意:--noEmit 模式下,tsc 默认不会写 build info 文件。你必须用 --tsBuildInfoFile 显式指定路径,增量检查才生效。
timeout 60 为什么重要?
tsc 可能卡住。比如依赖图里有循环引用、某个类型递归过深、或者缓存文件损坏——tsc 可能跑几分钟都不结束。如果没有 timeout,PostToolUse 的 tsc 进程会一直挂在那里。多个挂起的 tsc 进程叠加,就是在吃你的内存。
timeout 60 确保任何一个 tsc 进程最多运行 60 秒。超时了,杀掉,下次编辑重新跑。这比一个永远不结束的进程要好得多。
文件大小守卫
这个 PreToolUse 钩子很实用——在文件写入之前检查行数。
{“hooks”: {“PreToolUse”: [{“matcher”: “Write”, “command”: “node -e “...检查文件行数...””, “description”: “Block writes that exceed 800 lines”}]}}
场景:你正在重构一个模块,从一个大文件里提取函数。AI 可能在一个文件里继续追加代码,让文件膨胀到 1000+ 行。PreToolUse 检查到写入的文件超过 800 行,直接阻止写入,提示你需要拆分。
这条规则强制你遵循 ECC 的“文件不超过 800 行”标准。拦截不是惩罚,是防止你(和 AI)无意间制造技术债务。
最常见的 Hook 失败原因
1. 命令路径不对
pnpm、npm、npx 容易混用。项目用 pnpm,但 hook 里写的是 npm。或者在 monorepo 里,子包用的包管理器跟根目录不一样。
# 错误:在 pnpm 项目里用 npm “command”: “npm run lint” # 正确:匹配项目的包管理器 “command”: “pnpm lint”
2. 环境变量不一致
Hook 在 Claude Code 的宿主进程中执行,不一定加载了你 shell 的 .zshrc/.bashrc。如果你的 lint 脚本依赖了 NODE_ENV 或 API_URL 这类环境变量,而 Claude Code 进程没有这些变量,命令可能失败。
3. 超时太短
timeout 60 对大多数项目足够。但如果你有个特别大的 monorepo(10000+ 文件),--incremental 缓存过期后的首次类型检查可能需要 2-3 分钟。这时候 60 秒 timeout 可能不够。调整时间阈值,或者安排定时清理缓存。
Hook 排障的通用框架:
Hook 失败了 → 命令能独立运行吗? → 不能:命令或路径问题 → 能:进下一步 → 文件路径权限有问题吗? → 有:修复路径或权限 → 没有:进下一步 → 超时了? → 是:调整 timeout 阈值 → 否:看报错日志具体分析
第四章:调试与排障——当 ECC 不按预期工作时
ECC 的调试主要是三件事:规则覆盖链、Hook 行为、Agent 触发。
规则覆盖链调试
当你发现某条规则没有生效时,90% 的情况是覆盖链出了问题。
检查方法 1:确认规则文件位置
ls -la ~/.claude/rules/ecc/common/testing.md ls -la .claude/rules/ecc/common/testing.md # 项目级可能覆盖了
两个地方都有?项目级覆盖全局级。
检查方法 2:确认没有非 ECC 规则包冲突
ls ~/.claude/rules/
正常情况下应该只有 ecc/ 一个目录(如果你也只装了 ECC)。如果还有其他规则包,检查它们的文件名是否与 ECC 冲突。两个规则包都有 coding-style.md,那就看谁在目录里的排序更靠前。
检查方法 3:用实际需求验证
如果你不确定 testing.md 是否生效,可以试着让 Claude Code 帮你写测试,看它是否遵循了 ECC 定义的 AAA 模式、80% 覆盖率等要求。
Hook 排障通用框架
Hook 失败的根因诊断可以用这个框架快速定位:
现象:Hook 执行报错 ├─ 命令本身能跑吗? │├─ 终端单独跑 → 正常 → 环境差异问题 │└─ 终端跑也报错 → 命令或参数写错了 ├─ 路径问题? │├─ $FILE_PATH 包含空格? │└─ 项目在 WSL 路径下? ├─ 超时? │└─ 调整 timeout 值、检查 --incremental 是否生效 └─ 权限? └─ 文件只读?目录没有写入权限?
Agent 行为追踪
Agent 没有自动触发,走这个排查路径:
- agents.md 存在吗? —
ls ~/.claude/rules/ecc/common/agents.md - agents.md 内容正确吗? — 确认文件里有自动触发的规则定义(“No user prompt needed” 那四条)
- 触发条件满足吗? — 如果你提的是简单问题,planner 不触发是正常的
- 被其他规则覆盖了吗? — 检查项目级
.claude/rules/有没有同名文件
MCP 连接诊断
MCP 的问题比较特殊,因为涉及外部服务注册。
常见失败场景:
MCP 服务注册失败:MCP 配置指向了一个不存在的路径,或者命令找不到。检查 MCP 配置中的 command 路径。如果用的是 npx,确保 npx 在 PATH 中。
Token 膨胀:MCP 工具调用的输入输出数据量大(比如数据库查询返回了 10000 行结果),导致上下文被迅速填满。在 MCP 配置中加上结果大小限制,或者配置只在必要时才调用。
权限模型边界:MCP 工具默认与主会话共享相同的权限集。如果 MCP 工具需要访问本地数据库,但会话权限只配置了 GitHub,API 调用会失败。确保 MCP 工具的权限与使用场景匹配。
第五章:定制实战——让规则真正适配你的项目
安装陷阱(重点踩坑)
ECC 的 README 有句被反复强调的话:
如果你用 cp -r rules/common/* ~/.claude/rules/ 平铺安装,三个问题会同时出现:
- 文件名冲突:common/ 和 typescript/ 都有
coding-style.md,平铺后后装的覆盖先装的,你以为两层叠加,实际只剩最后一层 - 引用断裂:语言层文件的
../common/相对路径指向全断 - 规则包冲突:装了两个规则包,同名文件互相覆盖
正确做法是用命名空间目录:
mkdir -p ~/.claude/rules/ecc cp -r rules/common ~/.claude/rules/ecc/ cp -r rules/typescript ~/.claude/rules/ecc/
这样 ~/.claude/rules/ecc/ 下保持 common/ 和 typescript/ 各自独立的目录结构,互不干扰。
定制红线与同步策略
铁律:永远不在全局规则文件里做定制。否则下次 git pull ECC 上游,你的修改可能被覆盖或产生冲突。
正确路径是项目级覆盖——在项目根目录的 .claude/rules/ecc/ 里放同名文件,它天然比全局规则优先级高。项目没放 common/ 目录也没关系,它会回退到全局的 common。
同步策略也很简单:全局规则保持纯上游不做修改,所有定制放项目级。每次升级 ECC 后,用 diff 对比上游新增内容,挑跟项目相关的 2-3 条同步过来就行。
收尾:ECC 在演化,你也要跟着演化
ECC 从早期版本到 v2.0 的变化非常大。以下数据来自 GitHub API(2026 年 6 月 23 日查询):
- 220K Stars,33K Forks
- 67 个 Agent,271 个 Skills,92 个 Commands
- 260+ 贡献者
- 21 个规则目录(common + 20 个语言/框架专属)
- MIT 协议,创建于 2026 年 1 月,日均活跃提交
对比早期只有几十个 Skill 和几个 Agent 的版本,规模已经是两个数量级的差异。
这种快速演化意味着:你三个月前的配置,可能已经不是最优解了。定期做三件事:
- 审视生效的规则——运行
ls ~/.claude/rules/ecc/查看已安装的规则集,确认每条规则还在发挥作用。第一章介绍了规则的分层架构,可以用来检查覆盖链是否合理。 - 评估裁剪空间——如果你的项目只有 Python,不需要装 typescript、golang、rust 等十几套语言规则。第五章的定制策略会帮你判断哪些可以精简。
- 跟上上游——定期
git pullECC 上游,用diff对比变化,挑跟项目相关的 2-3 条同步过来。第五章详细讲了同步方法。
ECC 是个工具集,不是固定配置。你的使用方式应该随着你对它的理解和项目的变化而调整。这也正是“从入门到精通”的最后一步:从“怎么配置 ECC”转变到“当前项目最需要哪部分能力”。
当你开始主动选择装哪些规则、不装哪些规则;当你知道什么时候该用 Agent、什么时候手动写代码更快、什么时候多层检查是过度设计——那时候你就是老用户了。
