ACP协议实战:让Claude Code无缝接入JetBrains与Zed编辑器

发布时间:2026/10/1 6:58:23
ACP协议实战:让Claude Code无缝接入JetBrains与Zed编辑器
1. 从一个痛点说起为什么你的编辑器里没有 Claude Code如果你最近半年在折腾 AI 辅助编程大概率已经听过 Claude Code 这个名字。它跟普通的代码补全插件不太一样——它能读整个项目、能跑命令、能改多个文件、能自己规划任务用起来更像一个坐在你旁边的结对程序员而不是一个只会猜下一行的自动补全。但问题也随之而来这东西默认是跑在终端里的官方主推的交互方式也是命令行。对于习惯了 JetBrains 全家桶、Zed、VS Code 这类图形化编辑器的人来说切来切去非常割裂。我自己就是重度 JetBrains 用户IntelliJ IDEA 和 GoLand 常年开着写代码的时候根本不想离开 IDE 去开一个终端窗口。之前试过在 IDE 内置终端里跑 Claude Code能用但体验很别扭终端面板小、滚动难受、复制粘贴容易出错而且 IDE 的上下文当前打开的文件、光标位置、选中的代码它完全感知不到。这就引出了今天要聊的核心——ACP 协议全称 Agent Client Protocol一个专门用来把 AI 编程代理接进任意编辑器的开放协议。标题里说的一个协议让 Claude Code 住进任何编辑器说的就是这件事。ACP 做的事情本质上是定义了一套编辑器客户端和 AI 代理服务端之间的通信标准。只要编辑器实现了 ACP 客户端代理实现了 ACP 服务端两者就能对接跟具体是哪家编辑器、哪个代理没关系。这跟 LSPLanguage Server Protocol的思路是一脉相承的——当年 LSP 让任意编辑器都能接入任意语言的智能提示现在 ACP 想让任意编辑器都能接入任意 AI 代理。这篇文章适合谁看三类人。第一类是想在 JetBrains、Zed 这些编辑器里用上 Claude Code但被终端劝退的普通开发者第二类是对 ACP 协议本身感兴趣想搞清楚它怎么工作、能不能自己写个客户端的技术人第三类是想把自家 AI 代理接进各种编辑器需要理解协议对接细节的工具开发者。我会从协议设计思路讲起然后落到 JetBrains 和 Zed 的具体配置再补充实操中踩过的坑和排查方法。全程按我自己的实际操作经验来写不堆概念。2. ACP 协议到底解决了什么问题2.1 编辑器与代理之间的翻译官困境在 ACP 出现之前如果你想在某个编辑器里用 AI 代理基本只有两条路。第一条是编辑器官方自己做集成比如某些编辑器内置了自家的 AI 助手但这就锁死了——你只能用它的代理换不了。第二条是代理方针对每个编辑器单独写插件比如 Claude Code 如果要在 JetBrains 里跑就得写一个 JetBrains 插件要在 Zed 里跑就得再写一个 Zed 扩展。这是典型的 M×N 问题M 个编辑器乘以 N 个代理每个组合都要单独维护成本高得离谱。ACP 的思路是把 M×N 降成 MN。编辑器只需要实现一次 ACP 客户端就能对接所有实现了 ACP 服务端的代理代理只需要实现一次 ACP 服务端就能被所有支持 ACP 的编辑器调用。中间那层协议就是翻译官双方都按同一套语言说话谁也不用关心对方内部怎么实现的。这个设计哲学跟 LSP 完全一致也是为什么业内对 ACP 的接受度比较高——大家已经被 LSP 教育过一轮了知道这种协议层解耦的好处。你想想当年没有 LSP 的时候每个编辑器都要为每种语言写语法高亮、跳转、补全累得要死有了 LSP 之后语言服务器写一次所有编辑器都能用。ACP 想复刻这个成功路径。2.2 ACP 的通信模型谁主动、谁被动理解 ACP 最关键的一点是搞清楚通信的方向和角色。在 ACP 里编辑器是客户端代理是服务端但这个服务端不是传统意义上等着被请求的 HTTP 服务器而是一个由编辑器启动的子进程双方通过标准输入输出stdio交换 JSON-RPC 消息。这一点非常重要因为它决定了部署方式——你不需要单独起一个常驻服务编辑器启动代理进程进程活着的时候双方就能通信编辑器关了进程也就结束了。为什么用 stdio 而不是网络端口我个人的理解是几个考虑。第一是安全本地进程间通信不涉及网络暴露不用担心端口被外部访问。第二是简单不用处理端口占用、防火墙、跨平台网络差异这些破事。第三是生命周期好管理代理进程的生死跟编辑器绑定不会出现编辑器关了代理还在后台跑的僵尸进程。当然代价是代理必须跟编辑器在同一台机器上但对于 AI 编程代理这种场景本地运行本来就是主流。消息格式用的是 JSON-RPC 2.0这是个体面的选择。JSON-RPC 足够简单请求、响应、通知三种消息类型覆盖了绝大多数交互需求而且各种语言都有成熟的库。ACP 在 JSON-RPC 之上定义了自己的方法名和参数结构比如初始化会话、发送用户消息、接收代理的流式回复、请求权限确认等等。2.3 一次完整交互长什么样我拿一个典型场景来串一下流程这样你能直观感受到 ACP 在干什么。假设你在 Zed 里打开了一个项目想让 Claude Code 帮你重构某个函数。第一步是初始化。编辑器启动 Claude Code 的 ACP 服务端进程发送一个initialize请求里面带上编辑器支持的协议版本、自己的能力比如支持哪些文件操作、能不能弹权限对话框。代理回一个响应告诉编辑器自己支持什么。这一步相当于双方握手确认咱俩说的是同一版协议。第二步是建立会话。编辑器发session/new带上当前工作目录、项目上下文。代理创建一个会话返回一个 session id。之后所有交互都挂在这个 session 上。第三步是发送用户消息。你在编辑器里输入帮我把这个函数拆成两个编辑器把这条消息通过session/prompt发给代理。代理开始干活过程中会通过session/update通知不断往回推流式内容——可能是思考过程、可能是它打算读哪个文件、可能是它准备执行的命令。第四步是权限确认。如果代理想执行一个有副作用的操作比如写文件、跑 shell 命令它会发一个权限请求编辑器弹个对话框问你允许吗。你点了允许编辑器回一个响应代理继续。第五步是结束。代理干完活发一个完成通知编辑器把结果显示出来。整个过程中编辑器负责 UI 呈现和用户交互代理负责实际的 AI 推理和工具调用职责分得很清楚。这套流程听起来不复杂但真正落地的时候细节决定成败。比如流式更新的粒度、权限请求的超时处理、会话中断后的恢复这些都是实操中会碰到的问题。3. 在 JetBrains 里接入 Claude Code 的完整实操3.1 前置准备版本、依赖和安装路径先说环境。我实测下来JetBrains 这边接入 Claude Code 走 ACP 的路径主要依赖两个东西一个是 JetBrains IDE 本身的版本要够新另一个是 Claude Code 的 CLI 要装好并且能被 IDE 找到。IDE 版本这块建议用最近半年内的稳定版太老的版本可能没有内置 ACP 客户端支持。我用的 IntelliJ IDEA 是较新的稳定版GoLand 同理。Claude Code 的安装官方推荐的方式是通过 npm 全局安装。如果你机器上已经有 Node.js 环境直接一条命令搞定npm install -g anthropic-ai/claude-code装完之后在终端里跑一下claude --version能打印出版本号就说明装好了。这一步很关键因为 JetBrains 的 ACP 客户端本质上是要去调用这个 CLI 的如果 CLI 不在 PATH 里IDE 找不到它后面配置就会失败。提示如果你用的是 Windowsnpm 全局安装的包默认在用户目录下的 AppData 里有时候 PATH 不会自动刷新。装完之后最好重开一个终端或者手动确认where claude能定位到可执行文件。还有一个容易被忽略的点Claude Code 首次运行需要认证。你可以在终端里先跑一次claude按提示完成登录流程确认它能正常工作。别等到 IDE 里配置好了才发现认证没过那样排查起来会多绕一圈。3.2 配置 ACP 连接让 IDE 找到代理JetBrains 这边接入 ACP 代理通常是在设置里找到 AI 助手或者外部工具相关的配置项。不同版本的具体入口位置可能略有差异但核心逻辑是一样的你需要告诉 IDE 三件事——用哪个命令启动代理、启动参数是什么、工作目录怎么定。启动命令就是claude参数方面ACP 模式通常需要指定一个特定的子命令或者标志让 Claude Code 以 ACP 服务端的方式启动而不是进入普通的交互式终端。这个标志的具体写法会随版本变化我建议你直接查一下当前版本 Claude Code 的文档确认 ACP 模式的启动方式。工作目录一般设成项目根目录这样代理能感知到整个项目的结构。配置好之后IDE 会尝试启动这个进程。如果一切正常你会在 IDE 的某个面板里看到代理已经连接的状态。这时候你就可以在 IDE 里直接跟 Claude Code 对话了不用再切终端。我踩过的一个坑是工作目录设错了。有一次我把工作目录设成了用户主目录结果 Claude Code 启动后把整个 home 目录当成项目来扫描又慢又乱还差点改到不该改的文件。后来改成项目根目录就正常了。所以这一步千万别偷懒一定要指向你真正在开发的那个项目。3.3 权限模型哪些操作需要你点头ACP 的权限模型是我觉得设计得比较克制的地方。代理不是想干嘛就干嘛涉及副作用的操作都要经过编辑器这一层确认。具体来说读文件这种只读操作通常不需要确认但写文件、执行 shell 命令、删除文件这些代理会发权限请求编辑器弹窗问你。这个设计的好处是安全坏处是如果你在做一个大重构代理可能要改十几个文件每个都弹一次窗点得手酸。我的做法是分场景探索性任务比如帮我看看这个 bug 在哪保持严格确认因为代理可能只是读读文件确定性任务比如把这个函数重命名成 xxx可以适当放宽减少打断。注意放宽权限要谨慎。我见过有人图省事把所有权限都设成自动允许结果代理在执行一个清理任务时删掉了一个它认为没用的配置文件。虽然能恢复但那种心跳漏一拍的感觉不值得。建议至少保留写文件和执行命令的确认。JetBrains 这边的权限对话框通常会显示代理想做什么、影响哪些文件你点允许或拒绝。拒绝之后代理会收到通知它会尝试换个方式或者告诉你它做不了。这个交互闭环是 ACP 协议里比较重要的一环没有它AI 代理在编辑器里跑就跟脱缰野马一样。3.4 上下文感知IDE 能传给代理什么这是 ACP 相比在终端里跑 Claude Code最大的优势之一。终端里的 Claude Code 只能看到你手动告诉它的信息或者它自己去读文件。但在 IDE 里编辑器可以把当前打开的文件、光标位置、选中的代码片段这些上下文通过 ACP 传给代理。举个例子你在编辑器里选中一段代码然后跟 Claude Code 说解释一下这段编辑器会把选中的内容作为上下文一起发过去代理不用再去猜你指的是哪段。再比如你打开了一个文件光标停在某个函数里问这个函数有什么问题代理能直接定位到那个函数。这个能力依赖编辑器实现了 ACP 的上下文传递部分。不同编辑器实现的程度不一样有的传得全有的只传当前文件路径。JetBrains 这边我实测下来当前文件和选区是能传过去的光标位置有时候也能具体看版本。这个细节你在用的时候可以留意一下如果发现代理答非所问可能是上下文没传对。4. Zed 里的接入体验与差异4.1 Zed 对 ACP 的原生支持Zed 这个编辑器本身就是用 Rust 写的主打性能和协作它对 ACP 的支持相对更原生一些。因为 Zed 团队在协议设计早期就参与了讨论所以它的 ACP 客户端实现比较完整。在 Zed 里接入 Claude Code流程比 JetBrains 更顺滑——Zed 有专门的代理配置界面你填上启动命令它就能自动管理进程生命周期。Zed 的配置文件是 JSON 格式的代理相关的配置通常放在设置文件里。你需要指定代理的名称、启动命令、参数。Zed 启动的时候会读取这个配置按需拉起代理进程。跟 JetBrains 相比Zed 这边的配置更声明式你写清楚要什么它帮你处理进程管理、重连这些琐事。我个人的感受是Zed 的接入体验更接近开箱即用JetBrains 那边因为 IDE 本身功能庞杂配置入口藏得深一些第一次找要花点时间。但两边一旦配好日常使用的差异不大核心都是 ACP 那套东西在跑。4.2 中文界面与本地化的那些事热词里提到了 Zed 的中文界面和本地化项目这块我顺带说两句。Zed 本身是英文界面社区有做本地化的项目通过替换语言文件的方式实现中文显示。如果你英文没问题其实用英文原版更省事因为本地化项目更新往往滞后于主程序版本一升级可能就出现部分文案没翻译或者翻译错位的情况。但如果你确实需要中文界面操作思路一般是找到 Zed 的语言资源目录把社区提供的中文语言包放进去然后在设置里切换语言。这个过程不涉及 ACP纯粹是 UI 层面的替换。要注意的是本地化文件跟主程序版本要匹配版本对不上可能启动报错。我建议在折腾本地化之前先备份原始语言文件出问题了能快速回滚。提示本地化项目通常是社区维护的更新频率看维护者心情。如果你发现某个版本没有对应的中文包要么等要么自己动手补翻译。别指望它跟官方版本同步发布。4.3 两个编辑器的实操对比我把 JetBrains 和 Zed 在 ACP 接入上的关键差异整理成一张表方便你按自己的情况选。对比维度JetBrains 系列ZedACP 支持程度较新版本内置配置入口较深原生支持配置声明式进程管理IDE 管理偶有重连问题自动管理生命周期清晰上下文传递当前文件、选区基本可用传递较完整含光标信息配置复杂度中等需要找对入口较低改配置文件即可适合人群已深度使用 JetBrains 的开发者追求轻量、性能的用户这张表是我自己用下来的主观感受不是官方数据。实际体验还会受版本、插件、系统环境影响。我的建议是如果你本来就重度依赖 JetBrains 的调试、重构、数据库工具那就留在 JetBrains 里接 ACP如果你更看重编辑器的响应速度和简洁Zed 是更好的选择。没必要为了用 Claude Code 专门换编辑器ACP 的意义恰恰是让你在顺手的工具里用上它。5. 实操中踩过的坑与排查手册5.1 代理启动失败从日志入手最常见的故障是代理进程起不来。表现是 IDE 里显示代理未连接或者一直转圈。这时候别瞎猜先看日志。JetBrains 和 Zed 都会把 ACP 相关的日志写到某个目录通常是 IDE 配置目录下的 log 文件夹。日志里会记录它尝试执行的命令、进程的 stdout/stderr 输出、退出码。我遇到过一次启动失败日志里显示command not found: claude。原因是我在 IDE 里配置的启动命令是claude但 IDE 启动时的 PATH 跟我终端里的 PATH 不一样找不到这个可执行文件。解决办法是填绝对路径比如/usr/local/bin/claude或者 Windows 下的完整路径。这个坑很典型尤其是用 nvm 管理 Node 版本的人全局包路径经常变。还有一种情况是代理启动了但立刻退出。日志里能看到退出码非零的话基本是认证或者配置问题。这时候回到终端手动跑一次同样的命令看报什么错通常能直接定位。5.2 权限弹窗不出现或卡住权限请求是 ACP 交互里比较容易出问题的一环。表现有两种一种是代理明明要写文件但编辑器没弹窗代理就一直卡着等另一种是弹窗出现了你点了允许但代理没收到还是卡着。第一种情况先确认编辑器版本是否支持权限请求这个 ACP 方法。老版本可能没实现那代理发过来的请求就被忽略了。升级编辑器通常能解决。第二种情况多半是消息通道出了问题可能是 stdio 缓冲没刷新或者 JSON-RPC 消息格式有误。这种比较难自己修通常等编辑器或代理更新。我的经验是如果权限交互频繁出问题可以先在代理配置里把权限模式调成每次询问虽然烦但至少不会卡死。等确认稳定了再调回去。5.3 上下文丢失代理答非所问有时候你明明选中了一段代码问问题代理却像没看见一样回答得驴唇不对马嘴。这通常是上下文没传过去。排查思路是先确认你用的编辑器版本支持上下文传递再确认你选中的内容确实在传递范围内有些实现只传当前文件不传跨文件选区。还有一个隐蔽的原因是文件没保存。编辑器传递的上下文通常是磁盘上的文件内容如果你改了没保存代理读到的是旧版本。这个坑我踩过改了半天代码问代理这样对不对它基于旧代码回答把我带沟里了。养成习惯问之前先 CtrlS。5.4 常见问题速查表现象可能原因排查方向代理未连接命令路径不对、PATH 问题看日志改用绝对路径启动即退出认证失败、配置错误终端手动跑同命令看报错权限弹窗不出现编辑器版本旧、方法未实现升级编辑器权限点了没反应消息通道异常等更新或调权限模式代理答非所问上下文未传、文件未保存确认版本先保存文件响应特别慢项目太大、上下文过多缩小工作目录减少上下文这张表覆盖了我遇到的大部分问题。实际排查的时候日志永远是第一手信息别跳过它去猜。ACP 的交互是结构化的日志里能看到完整的消息流比瞎试高效得多。6. 关于 ACP 的一些延伸思考6.1 协议标准化对工具生态的影响ACP 这类协议的出现对整个 AI 编程工具生态的影响是深远的。它把编辑器和AI 代理这两个原本耦合的东西解开了。以前你想用某个代理得看它支持哪些编辑器现在只要双方都支持 ACP任意组合都能跑。这意味着代理开发者不用再为每个编辑器写插件编辑器开发者也不用为每个代理做适配大家把精力放在自己的核心能力上。这个模式在 LSP 上已经被验证过。当年 LSP 出来之后语言服务器的数量爆发式增长因为写一个服务器就能被所有编辑器用投入产出比高。ACP 大概率会走同样的路未来可能会出现一批专门做 ACP 代理的团队也可能有更多编辑器加入 ACP 阵营。6.2 自己写一个 ACP 客户端难不难如果你好奇 ACP 客户端怎么实现我可以给个大致思路。核心就是三件事启动代理进程、按 JSON-RPC 格式收发消息、把代理的流式更新渲染到 UI 上。启动进程用各语言的标准库就行JSON-RPC 有现成的库难的是 UI 渲染和状态管理——你要处理流式文本、权限弹窗、会话切换这些交互。我试过用 Python 写一个极简的 ACP 客户端原型大概几百行能跑通基本流程。当然能跑通和好用是两回事真正产品级的客户端要考虑重连、错误恢复、多会话管理、性能优化工作量不小。但如果你想理解 ACP 的工作原理写个原型是很好的学习方式。6.3 未来可能的方向从协议本身看ACP 还有不少可以演进的空间。比如多代理协作——一个编辑器同时连多个代理让它们分工干活再比如更细粒度的上下文协商编辑器告诉代理我能提供这些上下文你需要哪些还有会话持久化编辑器重启后能恢复之前的会话状态。这些方向有的已经在讨论中有的可能还在早期。我个人比较期待的是代理能力的标准化描述。现在编辑器接入一个代理基本是盲接不知道这个代理擅长什么、支持哪些工具。如果 ACP 能定义一套能力声明机制编辑器就能根据任务类型智能路由到合适的代理那体验会再上一个台阶。最后分享一个我自己的使用习惯我通常会把 Claude Code 的 ACP 连接和 IDE 的版本控制结合起来用。代理改完代码我先在 IDE 的 diff 视图里过一遍确认没问题再提交。这样既享受了 AI 的效率又保留了人工审查的关卡。ACP 让代理住进了编辑器但最终拍板的还是你自己这个边界感很重要。