你的 agent 和技能能不能换工具用:开源套件 ECC 的适配拆解
本文基于 ECC 仓库 commit 591ab5c(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/affaan-m/ECC 最新代码与文档为准。
换编码工具时你真正会丢的,不是知识,是纪律的自动执行。 写在技能文件里的工作流描述几乎可以原样搬到任何工具上,因为它本质是一段约束文本;而”提交前必须跑类型检查""禁止绕过 git 钩子”这类靠运行时事件强制的东西,换个工具就从”卡住你”退化成”提醒你”。ECC 这套装在编码 Agent 之上的增强件把这条分界线画得很明确,值得拿来当参照——它是 MIT 许可的开源仓库,你可以自己打开逐条核对。
站内《Agent 框架怎么选》(/learn/agent-kuangjia-duibi/)和《Cursor 与 Claude Code 怎么选》(/learn/cursor-vs-claude-code/)讲的是选型层面的通用方法论;这篇不做选型,只拆一个真实项目把”同一套 agent 与技能跨工具复用”落到目录、脚本、清单这一层的具体做法。
一、它要解决的问题:工作流被绑死在单一工具上
任何一个用 AI 编程工具干了半年活的团队,都会积累出一堆不属于代码仓库、但离了就难受的东西:几十条项目约定、若干个专门干某类活的 agent、一批”遇到这种情况就走这个流程”的技能、几个提交前的强制检查。问题是这些东西通常是按某一个工具的格式写的。换工具、或者团队里有人用 A 有人用 B,就得重写一遍。
ECC 的定位写得很直白:它把自己当作可复用的工作流层,把各家编码工具当作执行面(harness)。真正需要长期维护的东西——技能、规则与指令、钩子、MCP 配置、安装清单、会话与编排模式、以及与工具无关的记忆文档——都只保留一份共享源,各家工具在边缘做适配,而不是每换一个工具就重新发明一套工作流模型。
它自己就是这么长大的:仓库的 agents 目录下有 67 个 agent,skills 目录下有 281 个技能,commands 目录下有 94 个命令。这个体量下如果每个工具维护一份副本,维护成本会立刻失控。所以文档里给了一条非常好用的判据:如果一次改动需要你去改三个工具各自的同一份工作流副本,说明共享源放错了位置,应该把工作流退回 skills/,只在边缘适配加载方式、事件形状或命令路由。
二、共享源与适配器分别在哪
先把地图摆出来。下面这张表里的仓库位置都是可以直接打开确认的:
| 组成部分 | 它负责什么 | 对应仓库位置 | 你什么时候会碰到它 |
|---|---|---|---|
| 技能 | 描述某类活该怎么干、什么时候该激活 | skills/*/SKILL.md | 沉淀一条团队打法时;这是最可移植的单位 |
| 规则与指令 | 项目级约定、语言/框架规范 | rules/、AGENTS.md | 想让模型少犯同一类低级错误时 |
| 钩子 | 在事件点上做强制检查 | hooks/hooks.json、scripts/hooks/ | 要把”必须做”从口头变成拦截时 |
| 工具端钩子适配 | 把某家工具的事件转成共享脚本能吃的形状 | .cursor/hooks.json、.cursor/hooks/adapter.js | 换到非原生工具、发现钩子不触发时 |
| MCP 配置 | 外部工具接入的参考配置 | mcp-configs/mcp-servers.json、.mcp.json | 接数据库、抓取、记忆服务时 |
| 命令 | 把一段固定流程封成可调用的入口 | commands/ | 想少打字、想让流程可复述时 |
| 记忆 | 跨工具的持久上下文与交接 | 工作流源在 skills/unified-memory/SKILL.md;库目录 .ecc/memory/、~/.ecc/memory/ 由运行时创建,仓库里并没有这两个目录 | 换工具接着干上一段活时 |
| 安装档位 | 决定这次装哪些模块 | manifests/install-profiles.json | 第一次安装、以及排查”为什么钩子没生效” |
| 安装目标适配器 | 每家工具往哪写、写成什么样 | scripts/lib/install-targets/registry.js | 想知道到底支持哪些工具时 |
| 合规矩阵 | 每家工具支持到什么程度、怎么验证 | docs/architecture/harness-adapter-compliance.md | 迁移前做尽调时 |
registry.js 里注册的安装目标包括 claude-home、claude-project、cursor-project、antigravity-project、codex-home、gemini-project、hermes-home、opencode-home、openclaw-home、codebuddy-project、joycode-project、kimi-project、qwen-home、zed-project。名字里的 home 与 project 后缀区分了写到用户级还是项目级,这个区别在多人协作时很要紧——写到项目里的东西会进版本库,写到用户目录的不会。
三、带得走的是文本,带不走的是强制力
架构文档里说得很干脆:SKILL.md 是最可移植的单位。一个写得住的技能文件应当用 YAML frontmatter 声明 name 和 description,说明什么时候该用它,列出需要的工具或连接器但不嵌入密钥,示例保持仓库相对路径或足够通用,除非明确标注否则不假设某家工具独有的命令。仓库里的技能确实是这么写的,skills/unified-memory/SKILL.md 和 skills/tdd-workflow/SKILL.md 的 frontmatter 都带 name、description,并在 metadata 下标了 origin。同一份技能源之所以能装进多家工具,是因为它主体就是指令、约束和流程形状。
被适配掉的是加载与执行方式。项目把工具的支持程度分成四个状态:Native(能直接安装或校验这个面)、Adapter-backed(有一层薄适配,但各家对齐程度不同)、Instruction-backed(文件和指导都能给,但工具本身没有暴露出可供强制的运行时钩子/会话面)、Reference-only(作为设计参照有价值,但今天还没有直接的安装器或适配器)。在公开矩阵里,Claude Code 与纯终端路径是 Native,OpenCode、Cursor、Zed、dmux 是 Adapter-backed,Codex 与 Gemini 是 Instruction-backed,Orca、Superset、Ghast 是 Reference-only。
Instruction-backed 这个词是整篇文档最诚实的地方。它的含义是:钩子还在,但只是策略文本。矩阵里给 Codex 的风险注记原话就是把钩子当政策文本对待,除非出现原生的钩子面。也就是说,同一条”提交前不许绕过校验”的规则,在有原生钩子的环境里是一次拦截,在只有指令的环境里是一句期望——模型多数时候会听,但你不能拿它当审计证据。
薄适配到底薄到什么程度,看事件名最清楚。共享的 hooks/hooks.json 用的是 PreToolUse、PostToolUse、PostToolUseFailure、PreCompact、SessionStart、SessionEnd、Stop 这一组事件;而 .cursor/hooks.json 用的是 sessionStart、beforeShellExecution、afterShellExecution、afterFileEdit、beforeMCPExecution、beforeSubmitPrompt、subagentStart 等等,两边的粒度和命名都不一样。适配层做的事写在 .cursor/hooks/adapter.js 的注释里——把工具侧的输入转换后,委派给已有的 scripts/hooks/*.js。检查逻辑一份,事件翻译在边上。这就是”共享行为 + 边缘适配”落到代码上的样子,也是你自己搭同类东西时值得抄的分层。
对你的意味是:迁移前先给自己的资产分类。纯文本约束这一层,换工具的成本接近于零;依赖事件触发的强制这一层,换工具就要重新评估,并且要接受在某些环境里它只能降级成提示。如果你的质量保障完全建立在钩子上,跨工具这件事就不只是拷贝文件。关于钩子这层能做到什么、代价是什么,可以对照《Claude Code hooks 怎么用》(/learn/claude-code-hooks/)里的机制讲解。
四、跨工具的记忆:一个被刻意做窄的共享面
换工具最难带走的其实是上下文。ECC 的做法是把记忆做成文件优先的本地库,存 ecc.memory.v1 格式的 Markdown 文档,分三个作用域:项目级在 <repo>/.ecc/memory/project/,团队级在 <repo>/.ecc/memory/team/,用户级在 ~/.ecc/memory/。这几个目录是运行时在你的机器上创建的,克隆下来的仓库里看不到它们——换句话说,这层共享面的代价是每台机器上多出一个会被写入的本地目录,其中项目作用域那份还落在你的工作区里。要求是所有工具用同一个仓库工作目录,或者用同样的 ECC_MEMORY_PROJECT_ROOT 与 ECC_MEMORY_USER_ROOT 覆盖值。基线接口是确定性的 ecc memory 命令行;支持 MCP 的工具可以改为启动 ecc-memory-mcp,用 memory_save、memory_search、memory_read、memory_doctor 这几个工具。
召回的范围也做了收窄:常规检索只在项目与团队作用域里查处于活跃状态的条目,按 ID 直读才能看到非活跃条目,用户作用域必须显式请求。这条设计的用意是让”默认能读到什么”小于”库里存了什么”,免得一次泛泛的检索把陈旧结论重新灌回上下文。
这个 MCP 服务是 opt-in 的。参考条目放在 mcp-configs/mcp-servers.json,条目名是 ecc-memory-vault:
"ecc-memory-vault": {
"command": "ecc-memory-mcp",
"env": { "ECC_MEMORY_HARNESS": "YOUR_LOWERCASE_HARNESS_SLUG_HERE" }
}
它被刻意排除在默认 .mcp.json 之外,理由文档写明了:不让安装动作悄悄多出一个可写的上下文面,也不让人白付它的工具 schema 开销。每个 MCP 进程必须带一个小写的 ECC_MEMORY_HARNESS,这个身份绑在服务进程上,调用方无法自选;用户作用域默认不可达,除非操作者用 ECC_MEMORY_ALLOW_USER_SCOPE=1 启动进程。
信任边界那一段更值得抄进你自己的设计:首发写入的条目一律是 create-only 且状态为 unreviewed;召回出来的记忆是数据,不是可执行指令;疑似密钥形状的写入会被尽力拦掉,读取方不跟随符号链接;如果记忆库那份保护性的 .gitignore 被改动,项目作用域的写入就停止;人的接受动作把知识提升为受治理的仓库产物,而不是让记忆的 frontmatter 自己声明自己已获批准。还有一句容易被忽略但很关键——命令行上的 target 标志是调用方选择的路由过滤器,不是授权边界。把过滤器当权限用,是这类系统里最常见的误判之一。
工作流本身由 skills/unified-memory/SKILL.md 持有,Codex 与 Cursor 拿到的是行为一致的打包副本,分别放在 .agents/skills/ 和 .cursor/skills/,没有哪个工具拥有独立的权威记忆存储。分层记忆的通用取舍可以参考《Agent 记忆分层》(/learn/agent-jiyi-fenceng/)。
五、边界与代价:它明确不管的事
它放弃了”处处一致”的承诺。 换来的是共享源只有一份。文档从头到尾没有说各家工具体验相同,反而反复强调差异,甚至把”不要在适配器有了安装路径和验证命令之前,就把某家工具叫作 Native”写成了操作规则。
钩子的精确对齐还在成熟中。 项目自己列出的未完成项包括:跨全部工具的精确钩子对齐、技能自动同步到 Hermes、ecc2/ 的发布打包、跨工具的会话恢复语义、可选的语义重排与受治理的记忆提升流程。ecc2/ 这个 Rust 控制面在文档里标的是 alpha,会话这一整行在可移植性表里也标着 Alpha。要拿它当生产依赖,得自己先验。
非原生工具只能走手动降级,而且是二等公民。 面向 Grok 这类只能接受系统提示、上传文件或粘贴内容的聊天式界面,仓库单独给了手动适配指南:你要复现的其实只有四件事——聚焦的上下文而不是整仓库倾倒、技能激活线索、命令意图、以及钩子纪律。做法是在系统提示或会话前言里定义一个命令注册表,把 /plan、/tdd、/review、/verify 这类调用把手映射到对应行为;再把钩子意图写成常驻指令,比如动手写代码前先判断该激活哪个技能、检查是否涉及安全敏感改动、可行时先写测试,收尾前重读需求、核对主要改动路径、说清哪些验证过哪些没有。指南自己承认这不是真正的自动化,只是保住了操作纪律。明确会丢的东西写成了清单:自动安装与同步、原生钩子执行、真正的命令管道、运行时可靠的技能发现、内建的多 agent 与工作树编排。
记忆不承担活跃执行状态。 文档明确:活跃的执行状态留在 GitHub 或 Linear,不能只放在记忆里。这条边界划得很好——记忆是为了让下一个工具接得上,不是任务系统。
Reference-only 那几个工具没有安装器。 它们在矩阵里的作用是设计压力,风险注记也提醒不要把某个产品特有的假设直接引进来,而应转化为 ECC 自己的事件字段。
它不解决模型能力与服务商配额的差异。 换工具往往同时换了背后的模型与计费方式,各家规则不同且会调整,以官方最新说明为准。这套东西能保住你的流程,保不住模型行为一致。
还有一件必须说清的:这类套件会往你机器里写文件、挂钩子、可能连外部服务,代价是实打实的。项目级的安装目标写进工作区,那些文件会进版本库,也可能碰到你已有的规则文件;用户级的安装目标写进 home 目录,好处是不污染仓库,坏处是这部分改动不会出现在任何一次 code review 里,团队成员之间的环境差异从此不可见。钩子模块一旦装上,就会在工具调用边界上拉起本地进程;MCP 那一层连的是本地或外部服务。装之前请当作一次真实的环境变更来对待,而不是”装个插件试试”——最起码先看清这次装的档位包含哪些模块、各自往哪个目录写。
六、上手与避坑清单
先跑一遍记分卡,再谈自动化程度。 合规矩阵给了一段固定的检查序列,含义不是产品徽章,而是”当前环境到底支持到哪一步”的体检:
npm run harness:adapters -- --check
npm run harness:audit -- --format json
npm run observability:ready
node scripts/session-inspect.js --list-adapters
node scripts/loop-status.js --json --write-dir .ecc/loop-status
第一条证明公开矩阵还和适配器源数据一致(连必需的证据字段一起校验),第二条给工具覆盖、上下文效率、质量门、记忆持久化、评测覆盖、安全护栏与成本效率打分,第三条证明本地的状态、会话、工具活动、风险台账、发布入口这些信号还在,第四条告诉你当前环境里哪些会话面真的可检查,最后一条把交接与状态导成机器可读的载荷、供较长的自主运行使用。文档专门提醒把结果读成”这套配置目前支持到哪一步”的记分卡,而不是产品徽章——这个措辞差别,决定了你会拿它去排查还是拿它去宣传。
别默认装完就有钩子。 会踩是因为”装好了”给人一种全套生效的错觉。manifests/install-profiles.json 里 minimal 档位的描述明写了不含钩子运行时,opencode 档位更是明确说它有意排除 hooks-runtime,要用得靠 --modules hooks-runtime 显式加。避的办法:装完立刻跑一次审计,看钩子到底在不在,别靠感觉。
别把 Instruction-backed 当成等价物。 会踩是因为文档里同一行既列了”支持的资产”也列了”不支持或不同的面”,只看前半截就会误判。避的办法:把这类环境下的钩子当成策略文本,凡是需要证据的验收动作,改由人或 CI 来做。
别顺手把记忆 MCP 塞进默认配置。 会踩是因为它就躺在参考配置里,复制粘贴很自然。代价是安装静默获得一个可写的上下文面,外加工具 schema 的开销。避的办法:保持 opt-in,真要用就单独启动进程并填好那个小写身份值,用户作用域除非确有必要否则不开。
别拿路由过滤器当权限。 会踩是因为命令行标志看起来像访问控制。避的办法:记住真正的边界是进程启动时的身份与作用域开关,过滤器只影响查什么。
别把召回的记忆当指令执行。 会踩是因为记忆和提示词都是文本,进了上下文就容易被当命令。这正是提示注入的入口。避的办法:把召回结果当数据看待,需要动作时由人或明确的流程发起。相关思路可参考《提示注入防御》(/learn/agent-tishi-zhuru-fangyu/)。
别让 Cursor 这类项目级安装覆盖你已有的规则。 会踩是因为项目里往往已经有一份自己写的规则文件。矩阵给 Cursor 的风险注记就是适配器必须保住既有项目规则、避免静默覆盖。避的办法:安装前保证工作区干净,安装后逐文件看 diff。
别把本地操作者的私货推上去。 文档对 Hermes 这类操作者外壳划了明确红线:可以发的是脱敏的安装文档、仓库相对的演示提示、通用操作者技能、不依赖私有凭据的示例;不能发的是 OAuth 令牌与 API 密钥、原始的本地导出、个人工作区记忆、私有数据集、未经审阅的仅限本地的自动化包。这条对任何要把内部工作流开源的团队都适用。
别在三个工具副本里各改一遍同一段流程。 会踩是因为改副本比重构共享源快。避的办法:一旦发现自己在改第二份,就停下来把行为退回共享源,边缘只留加载、事件形状、命令名映射和平台限制这四类适配。
收个尾
要判断一套 agent 工作流值不值得跨工具用,问自己四个问题就够了:durable 的行为是不是只有一份源;靠强制才成立的部分有多少,换到没有原生钩子的环境后你还能不能接受;跨工具的上下文交接是不是有一个被写死了信任边界的载体;以及有没有一条能跑出结果的验证命令,而不是只有一份说明文档。
想继续往下看,docs/architecture/harness-adapter-compliance.md 是最实用的一份——它把每个适配器要求暴露 id、state、supported_assets、unsupported_surfaces、install_or_onramp、verification_commands、risk_notes、last_verified_at、owner、source_docs 这些字段,并且校验器会在某条公开声明缺少安装路径、验证命令、风险注记、负责人、来源文档或验证日期时直接失败。把”公开声明必须带验证证据”写进校验,比任何支持列表都可信。这条做法你今天就能搬到自己的项目里,不必等到迁移那天。
本文属于 ECC 开源 Agent 套件专题(共 40 篇,从选择性安装一直拆到内部机制)。同一批还写了另一种取向的项目——不给你资产、只给你纪律的 superpowers 方法论专题。