把 Claude Code 接进微信:躺在沙发上让 AI 帮我改服务器

wxcc - 微信与 Claude Code 的桥梁

图:wxcc 桥接微信与 Claude Code,实现远程服务器管理

起因

Claude Code 很好用,但它有个"缺点":必须坐在电脑前开着终端才能使唤它。

有天我在刷 NousResearch/hermes-agent 的源码,发现它有一个微信通信渠道——走的是腾讯官方的 iLink Bot API(个人微信机器人接口,不是 hook 也不是协议逆向)。我突然想到:能不能把这层微信接入抽出来,后端换成 Claude Code?

这样我就可以在公交车上发一条微信:“帮我看看服务器上那个定时任务为什么没跑”,回家的时候问题已经修好了。

于是有了 wxccgithub.com/noobprogrammewhy/wxcc

整体架构

微信

腾讯 iLink Bot API

wxcc 长轮询

Claude Agent SDK

Claude Code 进程

shell / 文件 / 编辑工具

两头各用一个官方接口,中间自己写胶水:

用什么 职责
微信接入 iLink Bot API(从 hermes-agent 抽取,MIT) 扫码登录、35s 长轮询收消息、AES-128 加密的 CDN 媒体收发
桥接 自己写的 bridge.py 访问控制、按会话串行、! 命令拦截、媒体桥接
Agent 官方 claude-agent-sdk 每个微信会话对应一个可 resume 的 Claude Code 会话

消息进来 → Claude Code 带着完整工具权限干活 → 结果切段发回微信。Claude 想发文件给我,只要在回复里写一行 MEDIA:/绝对路径,桥接层就会把文件原生发过来。

几个关键设计

常驻客户端,而不是每条消息起一个进程

最初的版本每收到一条微信消息就 query() 一次——等于每次冷启动一个 claude 子进程。实测下来一句"你好"要等十几秒,体验很差。

改成每个会话持有一个常驻的 ClaudeSDKClient

class ChatSession:
    async def ask(self, prompt):
        await self._ensure_connected()   # 首条消息时 connect,之后复用
        await self._client.query(prompt)
        return await self._drain()       # 收 AssistantMessage 直到 ResultMessage

子进程只在第一条消息时启动,之后的每一轮都是热的。进程挂了就重连一次,用记下来的 session id resume,上下文不丢。

会话要能"切回去"

Claude Code 本身支持按 session id 恢复会话。我把这个能力做成了微信里的 !resume 命令:每个逻辑对话在本地记一条历史(标题就是这个对话的第一句话),随时列出、随时切回:

!resume
历史会话(新→旧):
1. 帮我把服务器上的定时任务修一下 · 2026-07-03 09:1 ←当前
2. 写一个爬虫抓豆瓣书评 · 2026-07-02 22:40
用法: !resume <编号> 切回该会话

有个小细节:同一个对话每聊一轮 session id 都会变。如果傻乎乎地每轮记一条历史,列表马上就被刷爆。所以记录时先查"上一个 id 是不是已有条目",是就原地更新——一个逻辑对话永远只占一条。

没有终端,命令怎么办

/model/compact 这些是交互式 CLI 的内建命令,Agent SDK 这条路走不通。所以在桥接层拦一套 ! 命令,微信里直接发:

命令 作用
!model sonnet 切模型(丢掉热进程,带新模型重连并 resume,上下文保留)
!compact 保留部署步骤 压缩上下文,回报前后占用百分比
!context 上下文窗口占用(SDK 的 get_context_usage(),带进度条)
!usage 本会话花费、token、轮次
!cwd / !perm 切工作目录 / 权限模式
!stop 打断正在跑的回复

切模型不丢上下文的原理和断线重连是同一套:把热进程丢掉,下次连接时带上新参数 + resume=当前会话id

踩过的三个坑

坑一:GBK 控制台打不出二维码

扫码登录要在终端渲染 ASCII 二维码。Windows 控制台默认 GBK 编码,qrcode 库输出里有 \xa0 字符,直接 UnicodeEncodeError 崩掉。

解法:先渲染到 StringIO,再以 UTF-8 字节写 sys.stdout.buffer,同时无条件保存一份 qr.png 兜底——终端花了没关系,扫图片文件一样能登录。

坑二:start.bat 双击闪退

写启动脚本时文件是 LF 换行。Windows 批处理文件必须 CRLF,否则 cmd.exe 解析错乱,窗口一闪就没。这种坑排查起来最费劲,因为文件内容看起来完全正常。

发布到 GitHub 时顺手加了一行 .gitattributes 防止别人 clone 下来复现这个坑:

*.bat text eol=crlf

坑三:延迟高得离谱,原来是代理

联调时总觉得消息一来一回慢得不正常。查了半天发现:机器上配置了系统代理(环境变量 HTTP_PROXY),而 aiohttp 建会话时写了 trust_env=True——腾讯国内的接口流量也被塞进了翻墙隧道

实测对比(curl 直连 vs 走代理访问 iLink 接口):

路径 耗时
直连 约 0.1s
走代理 约 2.1s

慢 20 倍,而且发消息、"正在输入"状态、媒体传输、长轮询重建,每次请求都在付这 2 秒。

修复很简单但要想清楚边界:iLink 会话改 trust_env=False 永远直连;Claude 子进程的代理必须保留——它连的是 api.anthropic.com,在国内没代理反而不通。两条链路各走各路。

安全:这等于把 shell 交给微信

必须想清楚:任何能给这个机器人发消息的人,等于拿到了你机器上一个带完整工具权限的 Claude Code。所以访问控制是硬需求,不是可选项:

  • 默认策略 first:绑定后第一个私聊的人成为持久 owner,其他人的消息一律忽略——绑完自己先发一条消息把位置占了;
  • 更严格可以配白名单;
  • open 模式(谁都能用)只适合演示,真实环境别碰。

另外登录产物(二维码图片、含账号 id 的日志)一定要进 .gitignore,发布前用关键字全库扫一遍敏感信息,这个习惯救过我一次。

效果

现在的日常是这样的:手机上发一条微信,Claude Code 在家里的机器上翻代码、跑命令、把结果(包括截图和文件)发回来。配合 !resume 切换话题、!compact 压上下文,一个微信号就是一个随身终端。

在这里插入图片描述

代码全部开源(MIT):github.com/noobprogrammewhy/wxcc

如果你也想搭一个,README 里有完整步骤,大概十分钟:装依赖 → wxcc login 扫码 → wxcc run → 给机器人发第一条消息锁定 owner,完事。

唯一的硬性要求:需要一个独立的微信号给机器人用(iLink 的 token 同一账号只允许一个轮询者),别拿大号试。


微信 iLink 协议实现改编自 NousResearch/hermes-agent1(MIT License);Agent 能力来自官方 Claude Agent SDK2


  1. hermes-agent 仓库 ↩︎

  2. Claude Agent SDK 文档 ↩︎

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐