开源 Agent 套件 ECC 的仓库结构导读:这堆目录该从哪读起

2026-07-29

本文基于 ECC 仓库 commit 591ab5c(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/affaan-m/ECC 最新代码与文档为准。

这个仓库不是一个程序,它是一份被拆成文件的工程流程;决定目录怎么排的不是编程语言,而是两件事——每份内容什么时候进上下文,以及它会被复制到你机器的哪个位置。 你如果按读普通开源项目的习惯先找 src/、再顺着 import 往下追,在 ECC 上会立刻卡住:src/ 下面只有一个 llm 子目录,而真正承载功能的是 agents/skills/commands/rules/hooks/ 这一堆装满 Markdown 的目录。搞清楚它们之间是什么关系,比读懂任何一个文件都重要。

站内的 看懂一个遗留系统的方法 讲的是通用读码路径,Agent 框架横向对比 讲的是选型时该看哪些维度;这篇不重复方法论,只做一件事——把 ECC 这一个具体项目的目录关系落到实处,让你打开仓库时知道先看哪几个文件、哪些目录可以先跳过。

一、顶层目录先分成三类,别混着看

ECC 根目录下有三十多个条目,混着读会觉得杂乱。按”这个东西最终去哪儿”来分,其实只有三类。

第一类是会被复制到你的 harness 配置目录里的资产agents/skills/commands/rules/hooks/mcp-configs/。这些几乎全是 Markdown 和 JSON,模型读得懂,运行时不需要编译。

第二类是决定”怎么复制”的机器scripts/manifests/schemas/,以及根目录的 install.shinstall.ps1。这一层是 Node.js 写的,package.json 里用 engines 字段圈定了可用的 Node 运行时范围(具体下限以该字段当前值为准),运行期依赖只有三个——@iarna/tomlajvsql.js。TOML 解析是为了合并 Codex 的 config.toml,ajv 是为了拿 schemas/ 里的 JSON Schema 做校验,sql.js 对应会话状态存储。看依赖就能倒推出这一层在干什么。

第三类是给各家 harness 做适配的壳.claude-plugin/.codex/.cursor/.opencode/.kimi/ 之类的点目录,以及 plugins/。README 里那句话是理解全局的关键——根目录是事实来源,平台适配层是打包或映射同一批工作流,而不是各自维护副本。

组成部分它负责什么仓库位置你什么时候会碰到它
agent 定义带独立上下文与工具权限的专职角色,用于把规划、审查、修构建分派出去agents/(如 agents/planner.md想改某个角色能用哪些工具、跑哪个模型时
技能按需加载的可复用工作流,每个技能一个目录,入口是 SKILL.mdskills/(如 skills/tdd-workflow/SKILL.md想新增或裁剪一条工作流时
斜杠命令兼容期保留的入口层,仓库明确它是遗留面commands/legacy-command-shims/老命令名突然找不到时
规则常驻加载的标准,按 common/ 加语言包组织rules/排查上下文被吃掉时
钩子由 harness 事件触发、在模型上下文之外执行的脚本hooks/hooks.jsonscripts/hooks/某个操作被莫名拦下时
安装编排组件、模块、profile 三张清单加校验 schemamanifests/schemas/想只装一部分内容时
控制面原型Rust 写的会话管理脚手架,仓库自称 alphaecc2/你想管多个并行会话时

二、四份文件把坐标定下来,顺序别反

读这个仓库最省力的顺序,是先把边界读清楚,再看内容。

package.json 优先于 README。 这听起来反直觉,但 package.json 里的 files 数组是整个仓库唯一一份”什么算正式产物”的白名单——它逐条列出了 agents/commands/hooks/rules/manifests/schemas/mcp-configs/,以及具体到单个文件的 scripts/ecc.jsscripts/install-plan.jsscripts/install-apply.js,还有几百条 skills/xxx/ 路径。反过来说,没出现在这张表里的顶层目录(比如 research/workflows/scaffolds/integrations/)就不进 npm 包,读的时候可以先放一放。bin 字段同样有信息量:对外暴露的命令是 eccecc-control-paneecc-installecc-memory-mcpecc-plan-canvas 五个,各自指向 scripts/ 下的一个文件,想追某条命令的实现直接从这里跳。

再读 AGENTS.md 它是这个项目里最短也最硬的一份文件,其中”Workflow Surface Policy”一节把资产之间的优先级说死了:skills/ 是规范的工作流面,新的工作流贡献应该先落在 skills/commands/ 是遗留的斜杠入口兼容面,只在迁移或跨 harness 对齐还需要垫片时才动。你看到 commands/ 里有 94 个命令、skills/ 里有 281 个技能,不要理解成两套并列体系,而是一套正在收敛、一套在维持兼容。

然后是 README 的 What’s Inside 一节。 它给了带注释的目录树,但注意它是文档,不是生成物,读的时候当索引用、别当契约用。

最后读 docs/ECC-2.0-REFERENCE-ARCHITECTURE.md 这份文档解释的是”为什么会有 ecc2/ 这个目录”。它把目标形态画成五层:操作者界面、harness 适配层、worktree 与会话及队列运行时、可观测与评估回路、安全与商业平台。当前仓库里能对上号的,大致是适配层和资产层已经成型,运行时那层还在 ecc2/ 里做原型。这份文档的 Non-Goals 一节反而更值得看:本地事件模型跑通之前不做托管遥测、没有验证证据不自动改用户的 harness 配置、不把任何一个 harness 当作规范界面。

三、五类资产的分工,是按上下文成本切出来的

如果只记一句话:这五类东西的区别不在功能,在什么时候进上下文、以及进不进上下文。

rules/ 是常驻加载的。README 反复提醒只装 common/ 加一个你真在用的语言包,原因就在这——它每次会话都占位置。skills/ 是按需加载的,一个技能一个目录,skills/tdd-workflow/ 里就只有一个 SKILL.md,前置元数据用 namedescriptionargument-hint 这几个键,另有 metadata.origin 标着 ECCdescription 写得怎么样直接决定它会不会在该用的时候被选中,这一点和 Claude Code 技能机制 里讲的判定逻辑是一致的。

agents/ 是另一种隔离方式。看 agents/planner.md 的前置元数据就明白:namedescriptiontoolsmodel 四个键,planner 的 tools 只给了 Read, Grep, Glob——一个做规划的角色不需要写文件的权限。这种”每个角色带自己的上下文和自己的工具白名单”的做法,落到实处就是这四行 YAML。

hooks/ 完全在模型上下文之外。hooks/hooks.json 里注册的事件有 PreToolUsePostToolUsePostToolUseFailurePreCompactSessionStartSessionEndStop,其中 PreToolUse 下挂了 8 条、Stop 下挂了 6 条。hooks/README.md 说得很直白:PreToolUse 能用退出码 2 阻断工具执行,PostToolUse 只能分析、不能拦。实际拦的是什么?比如 tmux 之外启动开发服务器会被挡下来(理由是拿不到日志),git commit 之前会跑一轮质量检查,检出 console.log、debugger 或疑似密钥就按关键项阻断。这是确定性执行,不依赖模型是否记得住某条提醒——把哪些约束交给钩子、哪些留给提示词,就是 Agent 上下文预算怎么分 里那笔账在具体项目上的落法。想看更多钩子事件的语义,可以对照 Claude Code hooks 机制

mcp-configs/mcp-servers.json 是目录里最克制的一处。README 写明这套东西默认只带一个连接器 chrome-devtools,其余都是包装 CLI 或 REST 的技能、或者按需取用的目录条目;插件安装还刻意不自动启用捆绑的 MCP 定义。同一个仓库里,.claude-plugin/plugin.jsonmcpServers 是个空对象,skillscommands 各指向一个目录——插件清单只声明了这两类,其余靠别的路径落地。

四、安装层才是这个仓库真正的骨架

大多数人第一次读会跳过 manifests/schemas/,但这两个目录才是把散装 Markdown 变成”可安装产品”的地方。

manifests/ 下是三份 JSON:install-modules.json 定义模块,install-components.json 定义面向用户的组件,install-profiles.json 把模块打包成 profile。模块条目的字段值得逐个看——idkinddescriptionpathstargetsdependenciesdefaultInstallcoststabilitypaths 就是这个模块对应仓库里的哪些目录(比如 agents-core 对应 .agentsagentsAGENTS.md 三条),targets 是它支持装到哪些 harness,coststability 则是给选择器用的标签。profile 那份文件里列着 minimalcoreopencodedevelopersecurityresearchfull 这几档,每档的内容简单到有点意外——一句 description 加一串模块 id,没有别的。minimal 的模块串里没有 hooks-runtime,这就是 README 里”低上下文、不带钩子运行时”那条路径的真实定义;opencode 那档也同样把钩子运行时排除在外,并在描述里注明要用得显式加 --modules hooks-runtime。换句话说,README 里那些听起来像营销分级的名字,落到文件里就是几行数组,你完全可以照着自己拼一份。install-components.json 则是给人看的那一层:条目带 family 分组和面向用户的描述,再映射回模块 id,安装器的交互选择靠它,真正决定拷哪些路径的还是模块清单。

schemas/ 下有 11 份 JSON Schema,包括 install-components.schema.jsoninstall-modules.schema.jsoninstall-profiles.schema.jsoninstall-state.schema.jsonhooks.schema.jsonmemory.schema.jsonstate-store.schema.jsonprovenance.schema.json 等。其中 install-state.schema.json 最能说明设计取向:它的 schemaVersion 是个常量 ecc.install.v1,必填字段包括 targetrequestresolutionsourceoperations——也就是说,每次安装都会落一份”我装了什么、装到哪、由哪次请求推导出来”的记录。README 里那句”卸载只会移除安装状态里记录过的文件,不认领你 harness 目录下的其它文件”,靠的就是这份状态。npm run test 那条脚本里串了 validate-install-manifests.js 等一长串校验,清单和 schema 是被 CI 卡着的。

ecc2/ 和上面这些不在一个平面上。它是 Rust 写的,有自己的 Cargo.tomlrust-toolchain.tomlecc2/README.md 列出当前已有的东西:终端 UI 面板、SQLite 支撑的会话存储、会话启停与恢复、后台守护模式、可观测与风险评分原语、worktree 相关的会话脚手架。命令面是 dashboardstartsessionsstatusstopresumedaemon。这份 README 里有一条写给维护者自己的规则很少见——不要因为脚手架能编译就把 ecc2/ 当成完成品来宣传,并且明确列出还缺的部分:更强的多 agent 编排、agent 之间的显式交接与摘要、可视化 worktree 与 diff 审查界面、发布打包与安装路径。你把这段和参考架构文档里的五层图对照着看,就知道 ecc2/ 对应的是中间那层运行时,且还没到能替代现有安装体系的程度。

五、边界与代价:它放弃了什么

这套设计是有取舍的,而且代价大多写在明面上。

它往你的机器里写文件,并挂钩子。 这不是可选副作用,是它起作用的方式。安装会把资产复制到 harness 的配置目录(Claude 家目录安装是 ~/.claude/skills/<技能名>/ 这样的直接子目录),钩子运行时会注册能拦截工具调用的脚本。好处是约束确定性执行,代价是你的开发环境多了一层你没写的自动化。仓库提供了 list-installeddoctorrepairuninstall --dry-run 这些自查入口,但前提是你知道去用。

它不做”装一次全都有”。 插件安装分发不了 rules,README 让你自己 clone 仓库再手动拷贝规则包;multi- 开头的那批命令需要另装一个叫 ccg-workflow 的运行时才能跑;内存库的 CLI 在纯技能安装、最小安装、手动安装和插件安装下都不在 PATH 上,要单独装 npm 运行时。这种”分层可选”换来的是上下文可控,代价是安装路径分叉多、容易装了一半以为装全了。

跨 harness 是适配,不是等价。 仓库自己列的对照表里,Codex 那一栏在钩子事件上写的是”None yet”,并且明说 Codex 还没有 Claude 式的钩子执行对等能力,那边的约束靠 AGENTS.md、可选的指令文件覆盖和沙箱审批设置来实现。Cursor 那边则刻意不安装根 AGENTS.md,理由是 Cursor 把嵌套的 AGENTS.md 当目录上下文、会污染宿主项目。你如果指望在所有 harness 上拿到同一套行为,会失望。

记忆层明确不承担正确性。 仓库对内存库的定性是:这是未经审核的上下文,不是可执行策略;项目作用域的记忆有 fail-closed 的 .gitignore 兜着,团队作用域即使提交进版本库,内容仍然算未审核。它要求把重要结论回到权威来源核对、把确认的知识提升成受治理的项目文档,而不是靠记忆条目本身取得可信度。

涉及外部服务的那部分被单独隔离。 与算力供应商对接的那条命令会发出真实的、带认证的询价请求,需要显式配置可执行文件路径的环境变量并注入 API 密钥,而且仓库写明不会通过 PATH 去发现这个携带凭据的客户端;对应的 CLI 包目前也未发布。这类地方它的写法是把能力边界一条条列出来(不能预留容量、不能采购、不能替代失败的实时调用),而不是含糊带过。

它不管的事:不替你选模型服务商,也不在自身里硬编码传输配置——网关和模型映射交给 harness 自己的配置去做,各家规则不同且会调整,以官方最新说明为准。它也不承诺替你判断某条建议对不对,工作流给的是流程与证据链(计划、失败的测试、通过的测试、审查结论、最终验证),不是结论正确性的担保。

六、上手清单:会踩的坑和绕法

别叠装。 README 把这条放在安装章节最前面,因为同一个 harness 装两遍会出现重复的技能、命令、钩子和配置。会踩的原因很实在:插件装完之后,你在别的文档里看到 ./install.sh --profile full 又跑了一遍。绕法是每个 harness 只选一条路径;已经叠了就先移除插件安装,再从仓库根目录跑卸载,最后删掉自己手动拷的规则目录,然后只用一条路径重装。

别把仓库里的 hooks/hooks.json 直接抄进 harness 配置。 会踩是因为这文件看起来就是一份现成的钩子配置,复制粘贴最省事。但它是面向仓库和插件的,里面的命令路径没有针对你的家目录重写;而且 Claude Code 新版本会自动加载插件自带的钩子配置,你再往设置里抄一份就是重复执行。绕法是走安装器的 hooks-runtime 模块,让它把路径解析好再写入。

规则包按需装,不要全量拷。 会踩是因为 rules/ 目录看着不大、干脆全拷。但规则是常驻上下文,装得越多每次会话的固定开销越高。绕法是从 common/ 加一个你当前项目真在用的语言目录开始;另外拷的时候要拷整个语言目录,而不是把里面的文件挑出来平铺,否则相对引用会断、文件名还可能撞车。

在同一台机器上跑多个 harness 时,先隔离数据根目录。 会踩是因为记忆持久化相关的钩子默认把会话摘要、学到的技能、会话别名、指标都写到同一个根目录下,两个环境互相覆盖时你很难第一时间意识到。绕法是用仓库提供的数据根目录环境变量给其中一个环境单独指一个位置。

别拿仓库里的数字当准。 这条最容易吃亏。同一个仓库里,AGENTS.md 和 README 写的是 67 个 agent、281 个技能、94 个命令,而 SOUL.md 的开篇自述里还留着一组明显更小的旧数没同步;WORKING-CONTEXT.md 顶上标的”最后更新”停在几个月前,正文里说的公开发布面也和根目录 VERSION 文件里的字符串对不上号。会踩是因为这些文件长得都像权威说明——一份叫”灵魂”、一份叫”工作上下文”,语气比 VERSION 还笃定。绕法是把数量和版本一律以 VERSIONpackage.json 和你本地 ls | wc -l 数出来的为准,散落在 Markdown 里的数字只当叙述背景。这类”文档数字与产物数字漂移”在快速迭代的资产型仓库里几乎是必然的:资产是一个个文件加进来的,而汇总数字要靠人手改,两者没有任何机制强制同步——npm run test 里那串校验脚本卡的是清单结构和资产格式,不是散文里的计数。

看清楚哪些目录不进发布包。 会踩是因为你在 research/workflows/scaffolds/ 里读到点什么,以为装完之后本地也有。绕法是先查 package.jsonfiles 数组——不在里面的目录,只有 clone 仓库才看得到。

读完之后接着看哪个文件

如果你只打算再读三个文件:manifests/install-modules.json 告诉你这套东西可以被切成多细;hooks/README.md 告诉你它会在你机器上拦什么;schemas/install-state.schema.json 告诉你它对”我改了你哪些文件”这件事负多大责任。这三份读完,你对它的信任边界就有了自己的判断,而不是照搬 README 的自述。

再往下就是取舍问题了:你要的是一整套流程约束,还是只想借走某两条工作流。前者按 profile 装,后者直接去 skills/ 里挑目录拷。这个仓库的结构本身允许后一种用法——每个组件独立,这是它写在安装章节里的话,也是它把资产和安装机器分成两层的直接结果。

本文属于 ECC 开源 Agent 套件专题(共 40 篇,从选择性安装一直拆到内部机制)。同一批还写了另一种取向的项目——不给你资产、只给你纪律的 superpowers 方法论专题

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。