@gucvii/claude-to-im
v0.1.0
Published
Host-agnostic bridge connecting Claude Code SDK to IM platforms (Telegram, Discord, Feishu)
Maintainers
Readme
Claude-to-IM
English | 中文
Claude-to-IM 是一个与宿主应用解耦的桥接库,用于将 Claude Code SDK 连接到 IM 平台,让用户可以通过 Telegram、Discord 和飞书直接与 Claude 交互。
这个库处理了 IM 侧的所有复杂性——消息路由、流式预览、权限审批流程、Markdown 渲染、消息分块、重试、速率限制——同时通过一组依赖注入接口将持久化、LLM 调用和权限解析委托给宿主应用。
开箱即用方案
如果你想要一个无需编写集成代码就能直接使用的桌面应用,请查看 CodePilot——一个带有内置 IM 桥接支持的 Claude Code 桌面 GUI 客户端。CodePilot 已经实现了所有的宿主接口,并提供完整的会话管理、设置和桥接连接的 UI 界面。
Claude-to-IM 从 CodePilot 中提取出来作为独立库,供需要在自己的应用中嵌入 IM 桥接能力的开发者使用。
功能特性
- 多平台适配器:Telegram(长轮询)、Discord(Gateway WebSocket)、飞书(WSClient)
- 流式预览:通过消息编辑实现实时响应草稿,支持按平台定制的节流策略
- 权限管理:通过交互式内联按钮实现 Claude Code 工具审批(允许 / 拒绝 / 本次会话允许)
- 会话绑定:每个 IM 聊天映射到一个持久化的会话,支持工作目录和模型配置
- Markdown 渲染:平台原生格式化——Telegram 用 HTML、Discord 用 Discord 风格 Markdown、飞书用富文本卡片
- 可靠投递:按平台限制自动分块、指数退避重试、HTML 降级、消息去重
- 安全机制:输入验证、令牌桶速率限制(每个聊天 20 条/分钟)、用户授权白名单、完整审计日志
- 宿主无关:所有宿主依赖通过 4 个 DI 接口抽象——不绑定数据库驱动、不绑定 LLM 客户端、不绑定框架
架构
IM 平台 (Telegram / Discord / 飞书)
|
| InboundMessage(入站消息)
v
+-----------+ +------------------+
| Adapter |---->| Bridge Manager | (编排器)
| 适配器 | | |- Channel Router -> 会话绑定
+-----------+ | |- Conversation Engine -> LLM 流式调用
| |- Permission Broker -> 工具审批流程
| |- Delivery Layer -> 分块、重试、去重
+------------------+
|
| Host Interfaces(宿主接口,DI)
v
+------------------+
| Host Application | (实现 BridgeStore、
| 宿主应用 | LLMProvider 等)
+------------------+所有桥接模块通过 DI 上下文(getBridgeContext())访问宿主服务,不直接导入宿主模块。这意味着你只需实现四个接口,就可以将桥接功能接入任何 Node.js 应用。
快速开始
1. 安装
npm install claude-to-im或者克隆仓库并安装依赖:
git clone https://github.com/op7418/Claude-to-IM.git
cd Claude-to-IM
npm install2. 实现宿主接口
桥接系统需要四个接口。完整的接口规范见 docs/development.zh-CN.md。
import { initBridgeContext } from 'claude-to-im/context';
import type { BridgeStore, LLMProvider, PermissionGateway, LifecycleHooks } from 'claude-to-im/host';
const store: BridgeStore = { /* 你的持久化层(约 30 个方法) */ };
const llm: LLMProvider = { /* 包装 Claude Code SDK 的 streamChat */ };
const permissions: PermissionGateway = { /* 解析待处理的工具权限 */ };
const lifecycle: LifecycleHooks = { /* 可选的启动/停止回调 */ };
initBridgeContext({ store, llm, permissions, lifecycle });3. 启动桥接
import * as bridgeManager from 'claude-to-im/bridge-manager';
await bridgeManager.start();
const status = bridgeManager.getStatus();
// { running: true, adapters: [{ channelType: 'telegram', running: true, ... }] }4. 运行示例
项目包含一个自包含的示例,使用内存存储和 Echo LLM:
npx tsx src/lib/bridge/examples/mock-host.ts配置
所有设置通过 BridgeStore.getSetting(key) 读取。你的宿主应用决定如何存储和暴露这些值(数据库、环境变量、配置文件、UI 设置面板等)。
必需配置
| Key | 说明 |
|-----|------|
| remote_bridge_enabled | 总开关——设为 "true" 启用桥接 |
| bridge_{adapter}_bot_token | 平台的 Bot Token(如 bridge_telegram_bot_token) |
| bridge_{adapter}_allowed_users | 逗号分隔的授权用户 ID |
可选配置
| Key | 说明 | 默认值 |
|-----|------|--------|
| bridge_auto_start | 应用启动时自动启动桥接 | "false" |
| bridge_{adapter}_enabled | 按适配器的开关 | "false" |
| bridge_{adapter}_stream_enabled | 启用流式预览 | "true" |
| bridge_default_cwd | 新会话的默认工作目录 | $HOME |
| bridge_model | 默认 Claude 模型 | 由宿主决定 |
将 {adapter} 替换为 telegram、discord 或 feishu。
局限性
在采用这个库之前,请注意以下限制:
必须自行实现宿主接口
这是一个库,不是独立应用。你需要提供:
BridgeStore——一个包含约 30 个方法的持久化层,涵盖设置、会话、消息、通道绑定、审计日志、去重跟踪、权限链接和通道偏移量。这是最大的集成面。完整的接口定义见src/lib/bridge/host.ts。LLMProvider——一个 LLM 客户端包装器,返回ReadableStream<string>格式的 SSE 事件流。流的格式必须匹配 Claude Code SDK 的事件协议(text、tool_use、tool_result、permission_request、status、result 事件)。完整的事件格式规范见docs/development.zh-CN.md。PermissionGateway——用于解析来自 Claude Code SDK 的待处理工具权限。LifecycleHooks——可选的桥接启动/停止事件回调。
LLM 流格式
LLMProvider.streamChat() 必须返回与 Claude Code SDK 事件协议匹配的 SSE 格式字符串。如果你没有使用 Claude Code SDK,需要将你的 LLM 客户端输出适配为这种格式。这不是一个通用的"聊天补全"接口。
不内置持久化
桥接不打包任何数据库驱动。所有持久化通过 BridgeStore 提供。这给你完全的控制权,但意味着你需要自行实现会话、消息、绑定、审计日志、去重键、权限链接和通道偏移量的存储。
会话锁
桥接使用会话锁机制(acquireSessionLock / renewSessionLock / releaseSessionLock)来串行化同一会话内的消息。你的 BridgeStore 实现必须提供原子锁操作。单进程部署可以使用内存锁。多进程部署需要分布式锁(如基于数据库的锁)。
平台 Bot 设置
你仍然需要在各平台上创建 Bot 并获取 Token:
- Telegram:通过 @BotFather 创建 Bot
- Discord:在 Developer Portal 创建应用,启用 Message Content Intent
- 飞书:在开发者后台创建应用,配置 IM 权限
文档
| 文档 | 说明 | |------|------| | 开发指南 | 宿主接口规范、SSE 格式、适配器开发、分步集成教程 | | 架构 | 模块依赖图、消息流、设计决策 | | 安全 | 威胁模型、缓解措施、部署建议 | | 贡献指南 | 开发环境、代码风格、测试指南 | | 迁移 | 从直接导入迁移到 DI 的前后对比 |
项目结构
src/
lib/bridge/
context.ts # DI 容器 (initBridgeContext / getBridgeContext)
host.ts # 宿主接口定义 (BridgeStore, LLMProvider 等)
types.ts # 共享类型定义 (消息、绑定、状态)
bridge-manager.ts # 编排器——启停、消息分发、会话锁
channel-adapter.ts # 抽象基类 + 适配器注册表
channel-router.ts # ChannelAddress -> ChannelBinding 解析
conversation-engine.ts # LLM 流处理、SSE 消费
delivery-layer.ts # 可靠的出站投递(分块、重试、去重、审计)
permission-broker.ts # 工具权限转发和回调处理
adapters/
telegram-adapter.ts # Telegram Bot API 长轮询
discord-adapter.ts # Discord.js Gateway WebSocket
feishu-adapter.ts # 飞书 WSClient
telegram-media.ts # Telegram 文件下载/附件处理
telegram-utils.ts # Telegram API 辅助函数
index.ts # 副作用导入,用于适配器自注册
markdown/
ir.ts # Markdown AST 中间表示
render.ts # 通用 IR -> 平台字符串渲染器
telegram.ts # Markdown -> Telegram HTML
discord.ts # Markdown -> Discord 风格 Markdown
feishu.ts # Markdown -> 飞书富文本/卡片
security/
validators.ts # 输入验证(路径穿越、注入、消毒)
rate-limiter.ts # 令牌桶速率限制器(按聊天)
examples/
mock-host.ts # 可运行示例,含 InMemoryStore + EchoLLM
__tests__/unit/
bridge-channel-router.test.ts
bridge-delivery-layer.test.ts
bridge-manager.test.ts
bridge-permission-broker.test.ts测试
# 类型检查
npm run typecheck
# 单元测试(28 个测试)
npm run test:unit
# 全部
npm run test测试使用 Node.js 内置测试运行器(node:test),配合所有宿主接口的 mock 实现——不需要真实数据库或 LLM。
License
MIT
