我们团队的沟通基本都在飞书上,平时最常用的桌面开发环境是 Windows,主力 AI 编程工具是 Claude Code。项目越来越多之后,我发现自己有一个逃不掉的需求:人不在电脑前的时候,也想让 Claude Code 继续帮我处理代码——比如群里发来的 bug 反馈、测试报告、临时需求,总不能每次都先跑回工位,把命令粘贴到终端里跑一遍。折腾了几套方案之后,我最终用 MetaBot 在 Windows 上把飞书和 Claude Code 串了起来,实现的效果是:在飞书群里直接 @ 机器人,它就能调用我这台 Windows 机器上的 Claude Code 干活,然后把结果贴回群里。整个过程我用了大半个月,从安装、配置到踩坑基本都摸过一遍。这篇文章就是把 Windows 版的完整实战过程整理出来,包括链路原理、配置细节、真实跑通示例和排错清单,适合想在飞书里接入 Claude Code、又必须在 Windows 上运行的开发者参考。
1. 为什么我会选择在 Windows 上保留 Claude Code,还把它接进飞书
1.1 一个很具体的痛点:代码在本地,人不在电脑前
我手头的项目大部分跑在本地 Windows 开发机上,不是我不愿意用云服务器,而是很多工作依赖本地环境:项目缓存、未提交的代码分支、开发工具链、测试数据库,甚至公司内网的某些资源,都只在办公电脑上能访问。Claude Code 这类终端 Agent 被设计成“在项目目录里工作”的模式,它要读代码、跑命令、多轮修改文件,所以直接跑在本地项目目录里效率最高,而不是放在遥远的服务器上去挂载目录。
痛点发生在通勤、开会、午休这种场景。别人在飞书群里问我“这个 bug 你方便看一眼吗”,我只能说“回电脑前我看”。偶尔家里有急事远程连一次办公电脑,体验也一般:远程桌面软件要解锁屏幕、找终端、重新粘贴命令,网络波动时画面卡顿,消息来回也很慢。后来我意识到,我需要的不是“远程控制电脑”,而是“一个挂在飞书里的入口,它背后就是 Claude Code”。
1.2 为什么不是远程桌面,或者直接在飞书里调模型 API
先说远程桌面这类方案。它解决的问题是把整个桌面搬到手机或另一台电脑上,听起来很完整,实际用起来很笨重。首先要保持两台设备屏幕状态同步,其次 Windows 锁屏、休眠、网络策略都可能中断连接,更不用说从手机上的小屏幕去操作终端,体验非常痛苦。它适合“偶尔远程处理一次故障”,不适合“高频、轻量、会话式地让 AI 干活”。
再说直接调用 API 自研机器人。技术上,飞书开放平台确实支持自建应用,接上 Anthropic API 就能做一个简单的问答机器人,但离“能干活”还很远。一个真正能帮我处理代码的机器人,需要读懂项目结构、定位问题、生成代码、执行测试,还要一轮轮跟踪上下文。这些东西如果从零开发,等于把 Claude Code 重新实现一遍。我当时的判断是:要把 Claude Code 的能力暴露到飞书里,最好的方式不是绕开它,而是给它加一个“远程消息接口”。
1.3 这套链路适合谁,边界在哪里
如果你符合下面几种情况,这套方案大概率对你有用:
- 主力开发机是 Windows,电脑具备常开条件;
- 已经在用 Claude Code 写代码,希望增加手机/飞书端入口;
- 团队或客户在飞书上沟通,需要把 AI 能力接入现有协作流;
- 你更希望 Claude Code 在本地读取真实项目,而不是复制代码片段到网页。
也有不适合的场景要提前说清。飞书里跑的是“文字交互版”Claude Code,它不会把你的 IDE 界面搬进飞书,也不会自动推送整个工程给你。它更适合发指令、看结果、提交代码审查、生成文档、跑一轮测试这类任务。对“实时盯着文件变化然后改代码”这种交互,还是得老老实实坐在电脑前。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. MetaBot 在整个链路里具体管哪几件事:一次请求的四跳
2.1 MetaBot 不是大模型服务,它是“胶水层”
MetaBot 的角色就像是飞书和 Claude Code 之间的消息调度员。它不负责推理,也不生成代码,真正的执行者是 Claude Code CLI。MetaBot 做的核心事情是:接收飞书消息,解析成任务,按配置找到对应的工作目录,调用 Claude Code 执行,再把输出整理回传给飞书用户。理解这一点很重要,因为你在排查问题时,每一步失败都能快速定位是飞书的问题、MetaBot 的问题、还是 Claude Code 本身的问题。
我一开始也想自己写一个这样的小程序,但越看越发现没必要。飞书开放平台的鉴权、事件订阅、长连接重连、消息格式转换,这些代码虽然不难,但都很琐碎,自己写一遍要耗费大量时间,之后还要持续维护。MetaBot 属于把这块通用能力封装好的开源机器人网关,我只需要把“飞书应用凭证”和“要执行的命令”告诉它即可。
2.2 一条消息从飞书群到 Claude Code,再到返回结果
去掉技术细节,完整链路可以拆成四跳。
第一跳,用户在飞书群里 @ 机器人,或者在单聊里直接给机器人发消息。这条消息会触发飞书开放平台的事件系统,推送到应用侧。MetaBot 通过长连接第一时间收到这个事件,事件里包含消息内容、聊天 ID、发送者 ID,以及消息类型。群消息和单聊消息在飞书侧的权限点不同,这一点后面配置权限时要注意。
第二跳,MetaBot 解析消息。它会判断这条消息是不是真的触发指令:单聊大概率可以全部响应,群里则需要 @ 机器人或带某个前缀词。通过之后,MetaBot 会根据配置选择本次任务去哪个项目目录执行,并生成一个会话 ID。这里也是整个链路中最重要的安全边界:不是任何人都能在群里让 MetaBot 跑任意命令,需要白名单限制,工作目录也最好固定映射。
第三跳,MetaBot 在指定目录下启动 Claude Code CLI,把用户消息作为提示词传进去。注意这里用的是非交互模式,比如 claude -p "你的需求",Claude Code 会在后台执行,读取项目文件、调用工具、生成代码,然后输出结果。这个过程可能需要几十秒甚至几分钟,取决于任务复杂度。
第四跳,MetaBot 捕获 Claude Code 的输出,截断或格式化后,调用飞书消息 API 把结果发回原来的聊天。如果输出的内容很长,需要做摘要或分片,因为飞书单条消息长度有限制。我实际使用中给 MetaBot 配置了“超长结果只回前 3000 字摘要,完整结果写入本地日志文件”的策略,群聊体验会好很多。
2.3 Windows 下为什么更推荐长连接,而不是 Webhook 回调
飞书事件订阅提供了两种接收方式:Webhook 回调地址和长连接。很多第一次接飞书的人会在这一步卡住,因为早期教程大多以 Webhook 为主,要求你提供一个能公网访问的 HTTP 回调地址。但问题来了,普通 Windows 办公电脑没有固定公网 IP,路由器 NAT 后面根本收不到飞书服务器主动发来的请求,于是只能引入内网穿透工具。
这带来两个隐患:一是穿透服务本身不稳定,偶尔断连会导致消息丢失;二是内网穿透相当于把本机端口暴露到公网,如果没做好鉴权,存在被探测的风险。MetaBot 走飞书官方支持的“长连接”模式就简单很多:由 MetaBot 主动向飞书服务器建立 WebSocket 连接,事件推送主动发给这个连接,Windows 只需要出网能力,不需要入网端口,也就不用折腾穿透工具了。配置事件订阅时,订阅方式选择“使用长连接接收事件”,后面 MetaBot 启动后会自动连上去。
3. 先把底座铺好:Windows 上装好 Claude Code,再建好飞书自建应用
3.1 三条命令装好 Claude Code
如果你之前没在 Windows 上装过 Claude Code,这一步很快。建议先安装 Node.js 18 或更高版本,版本管理器推荐用 nvm-windows,这样切换 Node 版本会方便不少。安装完成后,在 PowerShell 或 CMD 里执行:
bash复制npm install -g @anthropic-ai/claude-code
然后验证:
bash复制claude --version
能输出版本号,说明安装成功。如果提示找不到命令,很可能是 npm 的全局 bin 目录没有加入 PATH。可以执行 npm config get prefix 查看全局安装路径,然后把对应的 bin 目录手动加到系统 PATH。安装完成后做一次最小验证:新建一个空目录,进入后执行 claude,随便问一句简单问题,确保 CLI 本身能正常输出。
很多人会忽略登录授权。Claude Code 有两种常见授权方式:订阅账号登录,或者通过环境变量 ANTHROPIC_API_KEY 配置 API Key。我个人选择用 API Key 方式,因为更适合后台进程调用,也方便 MetaBot 在子进程环境里继承。设置方法:在 Windows 搜索“编辑账户的环境变量”,新建用户变量 ANTHROPIC_API_KEY,填入你的 Key,保存后重启终端。如果你之前用过别的模型配置,建议先确认终端中执行 claude 能正常选择 Claude 模型,再进入下一步。
3.2 在飞书开放平台创建企业自建应用
MetaBot 接收和发送消息,本质上是调用飞书开发者的应用接口。所以必须先在飞书开放平台创建一个应用。操作路径大致是:打开飞书开放平台后台,选择“企业自建应用”,创建一个新应用。名字可以随意,比如“AI 编码助手”,头像上传一个容易识别的图标。创建完成后,进入“凭证与基础信息”,记下两个关键值:App ID 和 App Secret。这两个值会填进 MetaBot 的配置文件,相当于飞书识别你这个应用的账号和密码。
接着要在应用能力里添加“机器人”,这是必须的。添加后,应用会获得一个机器人身份,之后在飞书里搜索这个应用名称,就能找到它并进行单聊或拉群。创建应用的人通常自动是应用管理员,但如果你们的飞书租户有严格的管理流程,可能需要企业管理员审核通过后,机器人才能在组织内被使用。
3.3 事件订阅与权限点:这里漏一步消息就到不了 MetaBot
进入应用的“事件与回调”页面。订阅方式选择“使用长连接接收事件”,然后在事件列表里添加你需要接收的事件。最基本的两个事件:
接收消息 im.message.receive_v1:这个是机器人收到单聊或群聊消息时触发的事件;接收群聊中@机器人消息 im.message.group_at_msg:如果要在群里通过 @ 触发,这个权限点也要开。
开通事件需要关联对应的权限范围。权限点是飞书控制“谁能做什么”的机制。以下是我实际用到的权限点,供参考:
| 权限点 | 用途 |
|---|---|
im:message:send_as_bot |
以机器人身份发送消息,回传结果必须要有 |
im:message.group_at_msg:readonly |
读取群聊中 @ 机器人的消息 |
im:message.p2p_msg:readonly |
读取机器人与用户单聊的消息 |
im:chat:readonly |
获取群基本信息,主要用来解析 chat_id |
contact:user.base:readonly |
获取发送者基础信息,做用户白名单时很有用 |
权限点添加后,还需要发布应用版本。很多新手在这里踩坑,以为自己配置好了,但实际没有走完发布流程,机器人一直收不到消息或发不出消息。发布时如果提示需要管理员审核,自己如果没有管理员权限,就找管理员通过一下。发布后稍等一两分钟,再去飞书里给机器人发一条消息测试。
3.4 把机器人拉进群里,先手动验证收发生效
为了确认飞书侧的配置完全正确,不要急着连 MetaBot。先在单聊里给机器人发了一句“你好”,如果它没有自动回复,这是正常的——现在还没接入任何逻辑。关键是你要在飞书开放平台后台的“调试”或事件列表中,能看到收到了消息事件,说明链路已经通了。
然后在飞书群里添加机器人,发一条“@机器人 测试”。如果应用权限配置正确,后台能看到 im.message.receive_v1 事件被触发。看到事件后,就可以进入 MetaBot 配置环节了。前期的环境验证做得越细,后面接 MetaBot 时越容易定位问题。我见过不少人把 MetaBot 配好了,发现问题在飞书权限没发布,回头再查就绕了一圈。
4. MetaBot 在 Windows 上的配置逐项落地
4.1 下载与目录规划:Windows 路径是第一个坑
从 MetaBot 的 Release 页面下载 Windows amd64 版本,把它放到一个固定目录。目录名有个硬性要求:不要包含中文和空格。我看到很多人喜欢建 D:\软件\AI助手\汇总\ 这种路径,后面 Claude Code 跑起来会出现各种诡异问题,比如找不到工作目录、输出乱码、配置文件读取失败。建议直接放在 C:\tools\metabot 或 D:\tools\metabot,简单干净。
MetaBot 通常还会生成日志文件、会话缓存文件,这些文件默认放在当前工作目录。所以我会单独创建一个数据目录,比如 C:\tools\metabot\data,让日志输出有明确归属,方便之后用 NSSM 注册成服务时排查问题。这也是 Windows 上做常驻程序的经验:尽量让程序的所有产物都收敛到一个固定目录里,不要散落在用户目录和系统临时目录。
4.2 配置文件的核心字段:理解四个映射关系
不同版本的 MetaBot 配置字段名可能有差异,但概念上一定是四块内容:飞书应用凭证、事件模式、Claude Code 调用参数、项目工作目录映射。下面是我当前使用的配置结构简化示例,用 YAML 表示:
yaml复制feishu:
app_id: "cli_a1b2c3"
app_secret: "your_app_secret"
event_mode: "websocket" # 使用长连接接收飞书事件
claude:
cli_path: "C:/Users/me/AppData/Roaming/npm/claude.cmd"
args_mode: "non-interactive"
allowed_tools:
- "Read"
- "Glob"
- "Grep"
- "Bash(npm run build)"
timeout_seconds: 600
projects:
"demo": "D:/workspace/feishu-demo"
"blog": "D:/workspace/blog-site"
trigger:
group_at_only: true # 群里只响应 @ 机器人
allowed_users: [] # 空表示不限制,建议填写用户 ID
cli_path 值得专门说。在 Windows 上,npm 全局安装的 Claude Code 本质是一个 claude.cmd 脚本,如果你在 Node.js 的 child_process 里直接 spawn 一个 .cmd 文件,通常会失败或表现异常,因为系统不会自动用命令解释器去执行它。所以我把这里的路径写成 claude.cmd,并且在 MetaBot 的进程调用层会通过 cmd /c 去执行。如果你的 MetaBot 版本不支持自动加 cmd /c,就要自己在配置里带上,比如:
yaml复制claude:
command: "cmd"
args: ["/c", "claude", "-p"]
allowed_tools 是安全边界。Claude Code 在自动化模式下可能会申请各种工具权限,如果直接跳过所有权限确认,确实跑得顺畅,但风险极大。建议明确允许它使用 read、grep 类只读工具,对有副作用的 Bash 操作做限制。我这里只给了一条示例:允许 Bash(npm run build),意味着 Claude Code 只能执行 npm 构建命令,其他 Bash 命令需要请求权限,而 MetaBot 在无人值守时通常会因为拿不到权限而放弃。这个取舍很重要。
4.3 工作目录映射:别让飞书用户拿到任意路径
我在配置里用一个 projects 映射表,给每个项目设置一个简称。飞书用户不需要发送本机绝对路径,只需要说“去 demo 项目跑一下构建”,MetaBot 会帮我把 demo 翻译成 D:/workspace/feishu-demo。这样做的原因有两个:
一是安全问题。如果你允许飞书消息里直接传目录路径,一旦机器人被拉进大群,任何能 @ 它的人都能尝试让它去读 C:/Users/... 甚至执行危险命令。我在真实环境中把项目目录限制在 D:/workspace 下的几个固定目录,白名单之外的路由请求直接拒绝。
二是 Windows 路径分隔符和空格问题。在飞书消息里输入全角反斜杠路径很容易出错,D:\work\my project 这种带空格的路径在传给 CLI 时还需要额外加引号,处理起来极不优雅。用简称映射之后,路径问题直接被屏蔽在配置层,稳定得多。
如果你只是自己一个人用,也不想建多个项目目录,也可以只保留一个默认工作目录,所有消息都去这个目录执行。这算是最小可行配置。
4.4 启动 MetaBot,做最小链路验证
配置写好后,启动 MetaBot。正常情况下,日志里会依次出现几行关键信息:读取配置成功、获取飞书 tenant_access_token 成功、长连接建立成功。如果卡在“获取 token”,优先检查 App ID 和 App Secret 是否复制正确;如果长连接建立后立刻断开,检查是否在飞书后台选择了“长连接”模式,以及应用版本是否已发布。
此时到飞书单聊里给机器人再发一条消息。如果 MetaBot 配置了“单聊直接响应”,它应该会自动回复类似“已收到,可以开始任务”的提示。群聊则需要 @ 机器人再发送,并且要确保机器人已经在群里。看到回复说明全链路已经通了。如果没回复,可以去 MetaBot 日志里看最后一条事件有没有被打印出来,这能快速区分是“事件没到”还是“配置执行有问题”。
5. 真跑一单任务:从飞书发消息到收到结果的全过程
5.1 设定一个真实场景
为了验证最终效果,我用一个实际场景测试:本地有一个前端项目 D:\workspace\feishu-demo,最近构建一直报错,我想让 Claude Code 自己去排查。但此时我不在公司电脑前,手里只有手机。于是我打开飞书,找到机器人所在的项目群,发了一条消息:
“@AI编码助手 请到 demo 项目目录,先运行 npm run build,如果构建失败,把第一个报错的完整堆栈和修复建议发给我。”
MetaBot 收到后,会做以下几件事。首先它识别这是在群里 @ 机器人,触发条件满足;接着它解析出要去的项目简称 demo,映射到 D:/workspace/feishu-demo;然后把用户这条消息原封不动地拼进 Claude Code 的提示词,开始执行:
bash复制cd /d D:\workspace\feishu-demo
claude -p "请到 demo 项目目录,先运行 npm run build ..."
注意这里有个细节,我消息里已经带了“请到 demo 项目目录”,但 MetaBot 的工作目录已经在调用前切换过去了,所以即使 Claude Code 不主动切换目录,也不会跑偏。建议把路径信息放在 MetaBot 的路由层处理,不要依赖提示词来完成。
5.2 执行过程中的队列与并发控制
Claude Code 执行同一目录下的任务时,不能同时在多个进程并行跑,否则会相互覆盖会话文件或冲突。MetaBot 对这种场景的处理是串行队列:同一项目目录的任务会排队执行,前一个任务结束,后一个才开始。
在日志里可以看到:
text复制[12:01:02] receive message from chat=oc_xxx sender=ou_xxx
[12:01:02] dispatch task to project demo
[12:01:03] task queued, waiting for previous task to finish
[12:01:10] exec claude: claude -p "..." in D:/workspace/feishu-demo
[12:03:27] exec finished, code=0, duration=137s
[12:03:28] send response to chat=oc_xxx
如果你遇到两个不同群同时触发任务,要考虑的是:项目目录不同,可以并行;项目目录相同,必须串行。我最初没启用队列,结果有一次一个任务正在修改 package.json,另一个任务又开始读它,Claude Code 直接看到了不一致的文件状态。后来我把 MetaBot 的队列粒度设置为“按项目目录隔离”,再没出过类似问题。
5.3 结果返回与超长文本处理
Claude Code 完成一轮任务后,输出往往不是一句两句话。它可能会给出完整的排查过程、代码片段,甚至是很长的日志。如果直接原样发回飞书,大概率会被单条消息长度限制截断,或造成刷屏。
MetaBot 处理策略通常是设置一个 max_output_length,比如 3000 字。超出部分默认截断,只把前 3000 字发回。同时完整结果会写入本地日志文件,方便后续查看。我用了一段时间后,给 MetaBot 加了一个小改进:当结果太长时,先发一条提示“结果较长,已写入本地日志,这里返回摘要”,再贴出关键结论。这么做不会丢失信息,群里也不会爆炸。
实际跑刚才那个任务时,Claude Code 的输出会告诉我构建失败的原因:某个依赖包的导出路径不兼容。它会建议我修改 import 语句,或者升级依赖包。我让它在群里输出“修复建议”后,再补一条指令:“确认修复方案后,直接帮我改掉并重新构建”。这样一轮轮推进的过程,比单纯把长文本甩到群里高效很多。
5.4 常用工作流模板:让指令更可控
在自己真实使用的过程中,我并不建议每次都打一大段自然语言让 Claude Code 自由发挥。与其让模型猜我的意图,不如准备几个高频模板,然后结合具体项目信息补充参数。下面是我在飞书里最常用的指令格式:
| 用途 | 指令模板 |
|---|---|
| 代码审查 | @AI编码助手 到 demo 项目,对比最近 10 次 git 提交,输出审查结论和风险点 |
| 补单元测试 | @AI编码助手 到 demo 项目,为 src/utils/format.ts 写单元测试,运行并确保通过 |
| 生成发布说明 | @AI编码助手 到 demo 项目,读取最近 20 条 git log,生成 CHANGELOG 并写入文件 |
| 处理构建失败 | @AI编码助手 到 demo 项目,运行 npm run build,定位首个报错并给出修复建议 |
| 回答问题 | @AI编码助手 到 demo 项目,解释 auth 模块的登录流程,给出关键文件路径 |
工作流模板的好处是它给了 Claude Code 一个相对狭窄的目标,比如“只做审查”“只生成文档”。否则模型很容易把范围扩大,比如让你让它“看一下这个项目”,它可能一边改文件一边读代码,最后做了很多你并不想让它做的改动。实际使用中,我记得 MetaBot 配置里有一个“仅回复模式”,开启后 Claude Code 只分析和回复,不产生文件修改,非常适合代码审查和答疑场景。
5.5 多轮上下文:会话恢复和它的局限
Claude Code 的 CLI 本身支持 --resume 恢复历史会话,MetaBot 也可以按聊天维度映射会话 ID。这意味着,你在同一个飞书对话里连续提问,Claude Code 能记住之前讨论的上下文,这比每次开新会话省 token,也更自然。
我配置的映射规则是:同一个 chat_id 使用同一个 Claude Code 会话。也就是说,你在单聊里连续问问题,它会基于前面的排查继续回答;你在群里每发一条,也会延续群里最近一次任务的上下文。这看起来很好,但有一个限制:Windows 上同一个项目目录的 Claude Code 会话文件是单点资源,同一时刻只能有一个进程恢复该会话,如果前一个任务还挂着,后一个任务想访问同一个会话就会被阻塞。所以 MetaBot 的串行队列在多轮场景下是必须的。
如果你更看重稳定性而不是上下文连续性,可以让每次消息都开新会话,也就是不给 MetaBot 配置 session 恢复。代价是每次它都要重新理解项目,可能反复问你已经说过的基础信息。折中方案是:关键项目任务沿用固定会话,日常闲聊或临时任务全开新会话。我实际就是这么做的。
