这里是视频的译文:
序言与开场
Hey,大家好。是时候来一段更长的视频了——请别因此讨厌我。过去几个月,Emacs 生态里涌现了许多与 LLM 协作的包。上一期我和 GPEL 的作者聊了很久。GPEL 很棒,写作和研究都很强,但它并不是一个“编码助理”。最近,我像很多人一样试了各种代码助理,比如 Cloth Code 等,其中让我觉得既有意思又好用的就是 ECA(我更喜欢叫它 “Eka”,全称 Editor Code Assistant)。
如果你不是刚接触 Emacs,你肯定听说过或用过同一个作者做的工具——他叫 Eric Dalo,来自巴西,是一位非常优秀的软件工程师。我们认识很多年了,最近终于在 Clojure Con 上线下碰面,他做了很精彩的演讲。那些演讲还没公开,上线后我会把链接加到本视频的描述里。
先为音质道歉。我们前面花了二十分钟测试设备,Zoom 在 Linux 上有时真是让人抓狂,最后换到了 Google Meet。小样录出来的声音还行,但正式录制时音乐被过度混响和回声毁了。我尽力把它抹平了,但仍不够理想。下次会更好。好了,这是我和 Eric 的对话——希望你喜欢。我是 Ag,你正在观看 Emacs Propaganda。
介绍与嘉宾登场
[音乐] 你好。今天我们请到传奇的 Eric Dalo。他是 Clojure LSP 的作者,也是 lsp-mode 的维护者,做过 Dart 相关项目。我们今天聊 ECA(或者你称它为 Eka)。Eric,先介绍一下你自己吧。
你好,Luigi。我是 Eric Alo,住在巴西,在 Nubank 工作,主要用 Clojure,现在在开发者工具团队。我一直热爱开发者工具,我做和贡献的开源项目基本都跟 Dev tooling 相关,尤其服务 Clojure 社区。
关于那个“Greg”的外号,来自我的第一家公司。有次大家在日报里把我参与你的项目“Aggregator”的名字和我的名字混了,笑作一团,从此很多同事就叫我 Greg。甚至有些人不知道我真名是 Eric。
名字与初衷
我喜欢把 ECA 读作 “Eka”,在巴西语境里就是这么念的。这个名字是我用 AI 辅助挑出来的,顺口、好记、直指“Editor Code Assistant”。当时我在想:如何把现在这些强大的 AI 能力,以编辑器原生、顺滑的 UX 接入进来——像 LSP 之于语言服务那样,AI 之于编辑器也应该有一个统一的协议与抽象,而不是仅在终端里蹦跶一堆脚本。
于是我做了 ECA:在本地跑一个服务(Server),编辑器作为客户端(Client)连接它;服务端再去对接不同的 AI 提供方和能力。架构上和 LSP 类似,但为 AI 的特性重做了“App 层”的抽象,把各家 API 的差异、响应方式、特性集成在一个统一界面里,让用户获得一致、原生的体验。
协议与文档
我写了很完整的协议文档,也画了很多图。你会看到典型的请求(如 rewrite、completion、plan/agent)、响应以及通知流(例如进度和审批)。客户端需要把用户选择的文本、位置、上下文等信息发到服务端,服务端返回结果并可能继续推送通知。由于各家的 API 和能力差异很大,“App 层”要做的事很多,但正因如此,统一起来之后的 UX 才会稳。
文档都在 GitHub,安装步骤很简单。即便我在公司的电脑上暂时打不开某个域名,我从家用机仍能很快装好。基本没怎么读文档就跑起来了:装服务端、加 Emacs 包、配置提供方,几个月以来都很顺畅。
Emacs 的力量与上下文
Emacs 的力量在于:它给了你几乎完全的文本控制。代码本质上就是结构化文本,对 LLM 来说,输入的上下文决定输出的质量。ECA 的 Cursor Context 会跟踪我光标所在位置、所处文件与片段,让模型“知道”我在说什么,不必我每次把细节都铺陈。
同时它是完全可控的。你可以删掉默认上下文、注入你自己的上下文、结合 LSP 的诊断等,把上下文做成你真正需要的样子。这比在终端里折腾更原生,也更高效。
Hooks (不是 Emacs hooks )
我们提到的 hooks 不是 Emacs 的 hook,而是 ECA 服务端的事件钩子,和具体编辑器无关。它们写在 JSON 配置里:某次请求前注入额外内容、某个响应后触发某动作、匹配条件时拒绝某调用、或者在需要时发通知提醒用户审批。对话、计划、审批都可以挂钩。Clojure MCP(以及 MCP Light)也采用类似的思想,这让集成更强大。
与 Clojure MCP 的结合:原生 diff
举个具体例子:通过 MCP 做结构化改动时,我希望在编辑器里看到 Clojure 的 diff。很多 AI 客户端并不了解 MCP 的变更语义,无法正确在编辑器或终端里展示 diff。ECA 的可扩展性让我们为特定工具定义“如何展示 diff”,效果就像原生功能一样自然。
MCP 的变更通常类似“在某结构里进行精准的查找与替换”,ECA 让这些在编辑器里变得直观,可以在改动前后看到清晰的 diff。
我的 ECA 配置与提供方
我的 ECA 配置放在 dotfiles 里。我们做了一个“瀑布式”的默认配置:从 base(默认)开始,合并进用户的全局配置,再合并项目的本地配置。这个深合并策略让默认就很好用,我几乎不需要再去改动。默认里包含了常见的提供方和行为,比如 agent/plan 的开关、调用审批等。
提供方方面,OpenAI、企业内模型、GitHub Copilot 等都能统一挂载。你可以在默认基础上为自己的环境加密钥、设模型、改行为。配置是透明的、可扩展的,这也是我从 LSP 学到的原则:好的默认、清晰的扩展点。
现场演示与协议图
我分享了浏览器标签页,展示 eca.dev 上的协议图与文档结构:请求、响应、通知、上下文、行为、hooks、提供方、审批流。以 rewrite 为例,客户端要传递选中的文本和位置,服务端返回重写结果,并可能继续发通知。整个流程和 LSP 的思路相通,但针对 AI 的交互做了很多专门设计。
再谈上下文与行为:为什么原生更重要
回到 Emacs,我强调上下文的原生整合:Cursor Context 让模型知道“我在什么位置、看着哪段代码”。行为系统(Behaviors)定义了不同任务的默认做法,比如 rewrite、completion、plan/agent、approval 等。
CLI 工具也很好,但当你需要在编辑器里选中一段代码、重写函数、自动补全映射、或者把 LSP 诊断纳入上下文时,原生整合的速度与顺滑度会显著提升工作体验。
变更与可扩展性:原生展示、轻改即可
我们聊了 diff 展示、MCP 变更“查找与替换”的语义、原生与非原生的差异。通过 ECA 的配置与 hooks,这些都能在编辑器里显得自然。默认覆盖了大多数需求,用户只在局部覆写就能适应自己环境。开放、透明、易扩展,是我在 LSP 时代形成的设计准则。
挑战与路线图: CLI**、桌面与浏览器形态**
目前还没有面向服务端的独立 CLI,但我计划添加一个类似 “doctor” 的诊断工具来调试和定位问题。我们也考虑做 “ECA Desktop”、“ECA Browser” 这些形态——同一协议层,挂在不同前端之上。ECA 一开始就按插件化、可组合、可扩展来设计,这让向外延展变得轻松。
回滚与审批:把安全与可控做成默认
审批是默认行为之一。请求可以要求用户确认;变更可以查看差异并回滚。计划(plan)与代理(agent)也在默认集里,结合 hooks 可以编排复杂的工作流。安全、可控、可审查,是我希望默认就具备的品质。
收尾
今天的讨论从名字到协议、从上下文到 hooks、从默认配置到 MCP 的 diff 展示,我的目标就是:把 AI 的力量以好的 UX 带回编辑器,让它像 LSP 一样成为自然的能力层。谢谢观看。