news 2026/10/8 5:53:30

微信 ClawBot 直连 Claude — 独立桥接方案完整实现(TaoToken 统一 Key 接入)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信 ClawBot 直连 Claude — 独立桥接方案完整实现(TaoToken 统一 Key 接入)

1. 微信 ClawBot 直连 Claude 的桥接场景与核心难点

微信 ClawBot 直连 Claude 这件事,本质上是在解决一个很具体的需求:你希望在自己的微信里,像跟朋友聊天一样把问题丢给 Claude,然后拿到回复,而不是每次打开网页、复制粘贴、再切回来。这个方案适合三类人:一是日常在微信里处理大量文字、需要随手调用大模型的人;二是想研究微信 ilink API 与 CLI 工具如何对接的开发者;三是希望把 Claude 的代码能力接进自己工作流、但又不想依赖官方 Channels 功能的人。

我试过几条路,最后落到「独立桥接」这条线上。原因很直接:Claude Code Channels 功能对账号有开放限制,不是所有人都有;直接走 Anthropic API Key 又需要额外申请和计费配置;而 OpenClaw 这类方案虽然能接模型,但用不上 Claude Code 的代码工具链。所以最终选择自己写一个 Node.js 桥接脚本,直接对接微信 ilink API,再通过claude -pCLI 调用 Claude,形成一条完全自控的链路。

整条链路是这样的:微信用户发消息 → 微信服务器(ilink API)→wechat-claude-bridge.mjs桥接脚本 →claude -pCLI → Claude 返回 → 桥接脚本 → ilink API → 微信用户收到回复。中间没有任何第三方中转,所有凭据、上下文、历史都落在你自己的机器上。

这里有个关键点:桥接脚本本身不直接调用 Claude 的 HTTP API,而是调用本地的claude -p命令。claude -p是 Claude CLI 的非交互模式,它可以从 stdin 读取 prompt,然后把结果以文本形式输出。这样做的好处是,你不需要单独管理 Anthropic API Key,CLI 自己会处理认证;同时你还能用上 Claude Code 的代码工具能力,比如读写文件、执行命令等。

但这条路也有它的坑。最典型的就是 Windows 环境下多行 Unicode 文本传给子进程的问题,以及 ilink API 返回空字符串导致??运算符穿透的 bug。这些在后面会详细展开。先把前置条件说清楚:你需要一个能跑 Node.js 的环境(建议 18+),一个已经登录 Claude CLI 的终端,以及一个微信 ClawBot 的 bot_token。如果你还没有 Claude CLI,可以先装好并完成一次交互式登录,确保claude -p "hello"能正常返回。

另外,这个方案不依赖任何特殊网络手段,所有请求都是正常的 HTTPS 调用。你只需要保证机器能正常访问微信 ilink API 和 Claude CLI 所需的端点即可。接下来我会从 TaoToken 统一 Key 的接入开始,把配置、验证、排错一步步走完。

2. TaoToken 统一 Key 接入与 Node.js 桥接前置配置

在开始写桥接脚本之前,先把 Key 和模型接入这一层理清楚。TaoToken 在这里的角色是统一管理你的模型访问凭据,让你不用在多个地方散落 API Key。你可以把它理解成一个「凭据中枢」:桥接脚本、Claude CLI、以及后续可能加进来的其他工具,都从同一个地方拿 Key 和 Base URL。

首先去官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册并登录,然后在控制台里创建一个 API Key。创建的时候注意选择对应的模型权限,如果你主要用 Claude 系列,就勾选 Claude 相关的模型。创建完成后,你会拿到一串以sk-开头的 Key,以及一个 Base URL。这个 Base URL 在后续配置里会用到,通常是https://taotoken.net/api这种形式。

拿到 Key 之后,你需要把它配置到 Claude CLI 能读取的地方。Claude CLI 的配置方式取决于你用的版本,常见的是通过环境变量或者配置文件。如果你用的是 Claude Code 的 CLI,可以在项目目录下创建一个.claude/settings.json,内容如下:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoTokenKey" } }

这个文件的作用是告诉 Claude CLI:所有请求都走 TaoToken 的 Base URL,并且用这个 Key 做认证。注意路径要和你的实际项目结构一致,如果你是在全局配置,可以放到用户目录下的.claude/settings.json。配置完之后,先在终端里验证一下:

claude -p "用一句话说明你现在用的是哪个模型"

如果返回正常,说明 Key 和 Base URL 都生效了。如果报 401,先检查 Key 有没有复制完整,以及 Base URL 有没有多写或少写斜杠。这一步是整个桥接方案的地基,地基不稳后面全白搭。

接下来是 Node.js 桥接层的准备。桥接脚本本身是零依赖的,但你需要 Node.js 18 以上版本,因为用到了原生的fetch和crypto模块。检查版本:

node -v

如果低于 18,建议升级。然后创建一个工作目录,比如wechat-claude-bridge,在里面初始化一个package.json:

mkdir wechat-claude-bridge && cd wechat-claude-bridge npm init -y

这个目录后面会放桥接脚本、凭据文件、历史记录等。凭据文件默认会写到~/.claude/channels/wechat/下,包括account.json(bot token)、context_tokens.json(回复所需的 context token 缓存)、sync_buf.txt(消息同步游标)等。这些文件不要提交到 Git,建议在.gitignore里加上~/.claude/channels/wechat/或者对应的本地路径。

还有一点要注意:如果你在 Windows 上跑,claude -p需要 git-bash 的支持。Claude Code on Windows 会去找 git-bash 的路径,如果装在非标准位置,需要手动指定环境变量CLAUDE_CODE_GIT_BASH_PATH。这个在后面排错部分会详细说。现在你只需要确认claude -p在终端里能跑通,并且 Node.js 版本达标,就可以进入下一步了。

3. 可复制的桥接配置与 ilink API 对接实现

这一节是核心,我会把桥接脚本的关键配置和 ilink API 对接的代码片段给出来,你可以直接复制到自己的项目里。整个桥接脚本大约 600 行,零依赖,主要分三块:ilink API 请求封装、消息长轮询、以及claude -p调用。

先看 ilink API 的请求封装。所有请求都需要三个 Header:Content-Type: application/json、Authorization: Bearer <bot_token>、AuthorizationType: ilink_bot_token,以及一个X-WECHAT-UIN,它是随机 base64 编码的 uint32。封装函数大概长这样:

import crypto from "crypto"; function generateWechatUin() { const uint32 = crypto.randomBytes(4).readUInt32BE(0); return Buffer.from(String(uint32)).toString("base64"); } async function apiFetch({ baseUrl, endpoint, body, token, timeoutMs = 35000 }) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); try { const resp = await fetch(`${baseUrl}/${endpoint}`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}`, "AuthorizationType": "ilink_bot_token", "X-WECHAT-UIN": generateWechatUin(), }, body, signal: controller.signal, }); const raw = await resp.text(); return { status: resp.status, raw }; } finally { clearTimeout(timer); } }

注意这里没有直接JSON.parse,而是先把原始文本拿出来,因为后面要检查业务错误码。ilink API 有个特点:HTTP 状态码是 200,但响应体里可能有ret或errcode不为 0 的情况。如果你只看 HTTP 状态码,就会漏掉这些错误。

接下来是长轮询拉取消息。ilink API 的getupdates端点支持 35 秒长轮询,你需要带上get_updates_buf作为同步游标:

const raw = await apiFetch({ baseUrl, endpoint: "ilink/bot/getupdates", body: JSON.stringify({ get_updates_buf: getUpdatesBuf, base_info: { channel_version: "0.2.0" }, }), token, timeoutMs: 35000, });

拿到消息后,解析出msg对象,里面有from_user_id、group_id、context_token等字段。这里有个关键点:group_id可能是空字符串"",而不是null。如果你用??来做默认值,空字符串会直接穿透,导致contextKey变成空字符串,后续发送消息时to_user_id为空,微信侧收不到任何东西。正确的写法是用||:

const groupId = msg.group_id; const senderId = msg.from_user_id || "unknown"; const contextKey = groupId || senderId;

这个坑我在后面排错部分会再展开,这里先记住:当 API 可能返回空字符串表示「无值」时,必须用||而不是??。

然后是调用claude -p。这是整个方案里最容易出问题的地方,尤其是在 Windows 上。核心思路是通过 stdin 把完整 prompt 传给claude -p,而不是作为命令行参数:

import { spawn } from "child_process"; function callClaude(fullPrompt) { return new Promise((resolve, reject) => { const proc = spawn("claude", ["-p", "--output-format", "text"], { shell: true, stdio: ["pipe", "pipe", "pipe"], }); let stdout = ""; let stderr = ""; proc.stdout.on("data", (d) => (stdout += d.toString())); proc.stderr.on("data", (d) => (stderr += d.toString())); proc.on("close", (code) => { if (code === 0) resolve(stdout.trim()); else reject(new Error(`claude exited ${code}: ${stderr}`)); }); proc.stdin.write(fullPrompt); proc.stdin.end(); }); }

为什么不用参数传?因为在 Windows 上,cmd.exe无法正确传递包含换行符和特殊字符的多行 Unicode 文本。你如果写成spawn("claude", ["-p", fullPrompt], { shell: true }),cmd.exe会把多行 prompt 搞乱,Claude 收到空 prompt,回复「有什么可以帮你的?」。而通过 stdin 管道传递,就绕过了 shell 的参数解析,稳定得多。

发送消息的配置也要注意。sendmessage端点需要带上context_token,没有它无法回复:

await apiFetch({ baseUrl, endpoint: "ilink/bot/sendmessage", body: JSON.stringify({ msg: { to_user_id: to, client_id: generateClientId(), message_type: 2, message_state: 2, item_list: [{ type: 1, text_item: { text } }], context_token: contextToken, }, base_info: { channel_version: "0.2.0" }, }), token, });

context_token的规则是:每条收到的消息可能携带,第一条通常没有,需要等下一条收到后缓存起来,按user_id或group_id分开存储。群消息中同时缓存group_id和sender_id的 token 标签。这些缓存写到~/.claude/channels/wechat/context_tokens.json,重启后还能复用。

最后,发送消息后一定要检查响应体:

const resp = JSON.parse(raw); const isError = (resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0); if (isError) { throw new Error(`sendmessage API error: ret=${resp.ret} errcode=${resp.errcode}`); }

别信任 HTTP 状态码,很多 API 返回 200 但 body 里有业务错误码。这一步加上之后,之前那种「日志显示成功但微信收不到」的问题就能被及时暴露出来。

4. 端到端验证:从扫码登录到消息收发成功

配置写完之后,最重要的一步是验证整条链路能不能跑通。我会按顺序把扫码登录、启动桥接、发消息、收回复这几个动作走一遍,每一步都给出预期结果和检查点。

第一步是扫码登录。运行:

node wechat-claude-bridge.mjs setup

终端会显示一个二维码和一个扫码链接。用微信扫描二维码并确认。如果终端二维码扫不了,就用输出的链接在手机浏览器打开,然后用微信「从相册选取」扫描。登录成功后,凭据会保存到~/.claude/channels/wechat/account.json,下次启动不需要重复登录。你可以打开这个文件确认里面有bot_token字段,但不要把它泄露出去。

第二步是启动桥接:

node wechat-claude-bridge.mjs

看到「Bridge 就绪,开始监听微信消息...」就说明启动成功了。这时候桥接脚本会开始长轮询getupdates,等待微信消息。你可以在另一个终端里观察日志,正常情况下会看到类似[bridge] 开始长轮询的输出。

第三步是在微信里给 ClawBot 发一条消息,比如「你好,帮我写一个 Python 的快速排序」。发送后,桥接脚本的日志里应该出现:

[bridge] 处理私消息 [text]: from=o9cq803kQV5QpHeoBLqIKT2XMlUk "你好,帮我写一个 Python 的快速排序" [bridge] 调用 claude -p --output-format text (stdin: 896 chars) [bridge] 已回复 (1 段, 28 chars)

如果看到这三行,说明消息已经成功传给 Claude,并且拿到了回复。然后回到微信,应该能看到 ClawBot 发回来的代码和说明。如果微信侧没收到,但日志显示「已回复」,那大概率是context_token或to_user_id的问题,回到上一节检查contextKey的取值逻辑。

第四步是验证图片消息。给 ClawBot 发一张图片,日志里应该出现图片下载和解密的记录。微信 CDN 上的图片经过 AES-128-ECB 加密,需要用消息中的aes_key(base64)解密:

function decryptAesEcb(data, keyBase64) { const key = Buffer.from(keyBase64, "base64"); const decipher = crypto.createDecipheriv("aes-128-ecb", key, null); decipher.setAutoPadding(true); return Buffer.concat([decipher.update(data), decipher.final()]); }

解密后保存为本地文件,再传给claude -p作为图片参数。如果你发图片后 Claude 回复「只能看见一点儿」,说明图片没有正确下载和解密,检查aes_key是否拿到,以及解密后的文件是否完整。

第五步是验证对话历史。连续发几条消息,比如先问「我叫什么名字」,然后说「我叫张三」,再问「我叫什么名字」。如果 Claude 能记住「张三」,说明历史记录生效了。历史按用户或群组保存最近 20 轮对话,存在~/.claude/channels/wechat/history/下。你可以打开对应的 JSON 文件确认内容。

第六步是验证断点续传。在桥接脚本运行时,直接 Ctrl+C 停掉,然后再启动。之前没处理完的消息不应该丢失,因为get_updates_buf会持久化到sync_buf.txt。重启后桥接脚本会从上次的游标继续拉取。这个特性在调试时很有用,不用担心重启丢消息。

最后一步是验证错误恢复。你可以故意把claude命令改成一个不存在的路径,然后发消息。桥接脚本应该连续失败 3 次后进入 30 秒退避,而不是无限重试刷屏。日志里会看到退避提示。恢复claude路径后,再发消息应该能正常处理。

走完这六步,整条链路就算跑通了。如果中间某一步卡住,先看日志里的具体报错,然后对照下一节的常见错误排查。

5. 常见报错排查:401、local proxy failed、reading choices 与 OAuth

这一节把我在实际搭建过程中遇到的报错按类型整理出来,每个都给出原因和解决动作。你遇到问题时可以先在这里对照,大概率能直接定位。

401 错误:通常出现在claude -p调用或 ilink API 请求时。如果是claude -p报 401,先检查.claude/settings.json里的ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL是否正确。Key 要以sk-开头,Base URL 要是https://taotoken.net/api这种形式,不要多写斜杠。如果是 ilink API 报 401,检查AuthorizationHeader 里的bot_token是否过期。bot_token存在account.json里,如果过期就重新跑setup扫码登录。

local proxy failed:这个报错通常和网络环境有关。先确认你的机器能正常访问https://taotoken.net/api和微信 ilink API 的端点。如果你在公司网络或特殊网络环境下,可能会有代理拦截。检查环境变量里有没有HTTP_PROXY或HTTPS_PROXY,如果有,先临时取消再试。另外,Claude CLI 本身可能也会读代理配置,可以在.claude/settings.json里显式设置"NO_PROXY": "taotoken.net"来排除。

reading choices 报错:这个通常出现在claude -p返回的 JSON 解析阶段。如果你用的是--output-format json,返回的结构里应该有choices字段。如果报reading choices,说明返回体不是预期的 JSON 格式,可能是 CLI 版本不匹配,或者 Base URL 返回了错误页面。先单独跑claude -p "test" --output-format json,看返回的原始内容是什么。如果是 HTML 错误页,说明 Base URL 或 Key 有问题。

OAuth 相关报错:如果你在 Claude CLI 里同时配置了 OAuth 登录和 API Key,可能会冲突。Claude CLI 优先用 OAuth 凭据,如果 OAuth 过期或无效,就会报错。解决方法是先退出 OAuth 登录,或者显式在.claude/settings.json里指定用 API Key。具体命令取决于你的 CLI 版本,一般是claude logout然后再用 Key 认证。

MODULE_NOT_FOUND:这个最简单,就是运行目录不对。确认你在wechat-claude-bridge目录下运行node wechat-claude-bridge.mjs,而不是在其他目录。如果你把脚本放在了子目录里,路径也要对应调整。

spawn EINVAL:在 Windows 上直接spawn("claude.cmd", args, { shell: false })会报这个错,因为.cmd文件不能直接CreateProcess,必须通过 shell。解决方法是改成shell: true,并且用 stdin 传 prompt,而不是作为参数。

claude -p 找不到 git-bash:报错信息是Claude Code on Windows requires git-bash。这是因为 git-bash 装在非标准路径。桥接脚本会自动检测几个常见路径,也支持通过环境变量CLAUDE_CODE_GIT_BASH_PATH手动指定。注意路径要用 Windows 风格,比如F:\\tools\\Git\\bin\\bash.exe,而不是F:/tools/...。Unix 风格路径会导致unable to find CLAUDE_CODE_GIT_BASH_PATH path。

消息发送成功但微信收不到(ret=-2):这是最隐蔽的 bug。日志显示「已回复」,但微信侧什么都没收到。根因是contextKey用了??运算符,而 ilink API 返回的group_id是空字符串"","" ?? senderId结果是"",导致to_user_id为空。修复方法是用||:const contextKey = groupId || senderId;。同时给sendmessage加上响应体检查,发现ret !== 0就抛错。

图片不可见:Bot 回复「只能看见一点儿」,说明图片消息只转成了文本描述,没有下载实际图片。检查aes_key是否拿到,以及 AES-128-ECB 解密是否正确。解密后的文件要保存到本地,再传给claude -p。

消息被截断(got cut off):这是 Windows 上多行 Unicode 文本传递的问题。不要用命令行参数传 prompt,改用 stdin 管道。spawn("claude", ["-p", "--output-format", "text"], { shell: true, stdio: ["pipe", "pipe", "pipe"] }),然后proc.stdin.write(fullPrompt); proc.stdin.end();。

把这些报错对照一遍,基本能覆盖 90% 的搭建问题。如果还有没覆盖到的,先看日志里的原始错误信息,再回到对应的配置环节检查。

6. 长期运行与 Coding Plan 接入建议

桥接跑通之后,下一步就是让它稳定地长期运行。这里有几个实践建议,都是我在实际使用中踩过坑之后总结的。

首先是进程守护。桥接脚本本身没有内置守护机制,如果你直接node wechat-claude-bridge.mjs跑在终端里,关掉终端就断了。建议用pm2或者systemd来守护。用pm2的话:

npm install -g pm2 pm2 start wechat-claude-bridge.mjs --name wechat-claude-bridge pm2 save pm2 startup

这样即使机器重启,桥接脚本也会自动拉起。日志可以用pm2 logs wechat-claude-bridge查看。

其次是凭据轮换。bot_token和 TaoToken 的 API Key 都有有效期,建议定期检查。account.json里的bot_token如果过期,重新跑setup扫码即可。TaoToken 的 Key 可以在控制台里轮换,轮换后更新.claude/settings.json里的ANTHROPIC_API_KEY,然后重启桥接脚本。

第三是历史记录清理。~/.claude/channels/wechat/history/下的对话历史会随着时间增长,建议定期清理或者设置保留天数。你可以在桥接脚本里加一个定时任务,删除超过 30 天的历史文件。或者直接用系统的cron或计划任务来做。

第四是消息分段。ilink API 对单条消息有长度限制,超过 2048 字符需要自动按换行分割发送。桥接脚本里已经处理了这个逻辑,但你要注意,如果 Claude 返回的代码块很长,分段后可能会在代码中间断开。可以在分段前先按代码块边界切分,保证代码完整性。

第五是错误恢复策略。桥接脚本默认连续失败 3 次后退避 30 秒。如果你的网络环境不稳定,可以适当调大退避时间,比如 60 秒。同时建议加一个告警机制,比如失败次数超过阈值时发一封邮件或者写一条系统日志,方便你及时发现。

最后说说 Coding Plan 的接入。如果你打算长期用这个桥接方案做编码辅助,建议把 TaoToken 的 Coding Plan 用起来。它适合高频调用场景,比按次计费更划算。接入方式很简单,在 TaoToken 控制台里开通 Coding Plan,然后把生成的 Key 配置到.claude/settings.json里就行。Base URL 和普通 Key 一样,都是https://taotoken.net/api。

如果你还想进一步扩展,比如把桥接脚本接到 Cline MCP 或者 Codex 的auth.json,核心三件套是一样的:Base URL、Key、Model ID。Base URL 用https://taotoken.net/api,Key 用 TaoToken 生成的,Model ID 根据你用的模型填,比如claude-sonnet-4-20250514这种。配置好之后,Cline 或 Codex 就能通过 TaoToken 统一走 Claude 模型。

验证模型是否生效,可以直接在模型对话页面里发一条测试消息,看返回的模型标识是否正确。如果返回的是你配置的模型,说明接入成功。长期编码或 Agent 场景,建议直接用 Coding Plan,省去每次调用的计费烦恼。

整个方案的核心就是:用自己的桥接脚本把微信和 Claude 连起来,用 TaoToken 统一管理 Key,用claude -p调用模型。链路完全自控,不依赖任何官方未开放的功能。跑通之后,你可以在微信里随时调用 Claude 的代码能力,也可以把它接到其他工具里,扩展性很好。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 5:53:27

哪个AI模型写代码最省钱又高效?TaoToken统一Key实测GPT与Claude

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 5:52:42

游戏引擎基础架构:模块依赖、生命周期与主循环设计之道

1. 引擎基础架构&#xff1a;一句话讲清楚它到底在解什么题游戏引擎架构这个词&#xff0c;听起来像是“用幼儿园积木拼高达”一样高不可攀&#xff0c;但拆开看&#xff0c;引擎要解决的问题其实非常朴素&#xff1a;怎么让一堆美术资源、一段游戏逻辑、一帧一帧的画面输出&am…

作者头像 李华
网站建设 2026/10/8 5:52:09

AI 应用的 SLO 怎么定:质量、延迟与成本三类目标

说明&#xff1a;本文讨论的是 AI 应用的服务等级目标怎么定与怎么维护&#xff0c;属于 AI 运维话题&#xff0c;不涉及具体模型版本与价格。AI 领域版本迭代极快&#xff0c;凡涉及版本号、价格、可用性&#xff0c;请以你阅读时的官方页面为准。文中代码为结构示意&#xff…

作者头像 李华
网站建设 2026/10/8 5:52:04

贴秋膘别盲目!这份秋季进补小贴士请收好

暑气慢慢褪去&#xff0c;秋风悄然登场&#xff0c;不少朋友已经准备开启贴秋膘模式。但进补可不是大鱼大肉随便吃&#xff0c;讲究循序渐进&#xff0c;吃不对反而给身体添负担✨。经历漫长盛夏&#xff0c;很多人脾胃状态偏弱&#xff0c;骤然大量食用油腻荤食&#xff0c;肠…

作者头像 李华