Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
Bridge library for Claude Code in IM chats
Claude-to-IM connects Claude Code SDK to Telegram, Discord, and Feishu without tying you to one database or app framework. It keeps the IM plumbing in the library and asks your host app to implement storage, LLM streaming, permission handling, and lifecycle hooks.
Builders who want to run Claude Code through chat apps instead of a separate terminal tool.
You can add Claude-driven chat workflows to your app without rebuilding message delivery, approvals, or platform-specific formatting.
What it does
Multi-platform adapters
Supports Telegram long polling, Discord Gateway WebSocket, and Feishu/Lark WSClient.
Streaming previews
Edits messages as Claude produces output, with throttling per platform.
Permission management
Shows inline allow and deny buttons for Claude Code tool approval flows.
Session binding
Maps each IM chat to a persistent session with working directory and model settings.
Markdown rendering
Renders output in platform-native formats for Telegram, Discord, and Feishu.
Reliable delivery
Chunks long messages, retries failed sends, deduplicates output, and falls back on parse errors.
Security controls
Validates input, rate limits chats, and supports authorization whitelists and audit logs.
Host-agnostic interfaces
Uses four dependency-injection interfaces so you supply persistence, LLM access, permissions, and lifecycle hooks.
How to get it
- 1Run
npm install claude-to-im
- 2Or clone this repo and install dependencies
git clone https://github.com/op7418/Claude-to-IM.git cd Claude-to-IM npm install
- 3A self-contained example with in-memory store and echo LLM is included
npx tsx src/lib/bridge/examples/mock-host.ts
README
Claude-to-IM
English | 中文
Claude-to-IM is a host-agnostic bridge library that connects Claude Code SDK to IM platforms, allowing users to interact with Claude through Telegram, Discord, and Feishu (Lark).
This library handles all IM-side complexity — message routing, streaming previews, permission approval flows, Markdown rendering, chunking, retry, rate limiting — while delegating persistence, LLM calls, and permission resolution to the host application through a set of dependency injection interfaces.
Out-of-the-Box Solution
If you want a ready-to-use desktop application without writing any integration code, check out CodePilot — a desktop GUI client for Claude Code with built-in IM bridge support. CodePilot implements all the host interfaces for you and provides a complete UI for managing sessions, settings, and bridge connections.
Claude-to-IM was extracted from CodePilot as a standalone library for developers who want to embed the IM bridge capability in their own applications.
Features
- Multi-platform adapters: Telegram (long polling), Discord (Gateway WebSocket), Feishu/Lark (WSClient)
- Streaming previews: Real-time response drafts via message editing, with per-platform throttling
- Permission management: Interactive inline buttons for Claude Code tool approvals (allow / deny / allow for session)
- Session binding: Each IM chat maps to a persistent conversation session with working directory and model settings
- Markdown rendering: Platform-native formatting — HTML for Telegram, Discord-flavored Markdown, Feishu rich text cards
- Reliable delivery: Auto-chunking at platform limits, retry with exponential backoff, HTML fallback on parse errors, message deduplication
- Security: Input validation, token bucket rate limiting (20 msg/min per chat), user authorization whitelists, full audit logging
- Host-agnostic: All host dependencies abstracted via 4 DI interfaces — no database driver, no LLM client, no framework lock-in
Architecture
IM Platform (Telegram / Discord / Feishu)
|
| InboundMessage
v
+-----------+ +------------------+
| Adapter |---->| Bridge Manager | (orchestrator)
+-----------+ | |- Channel Router -> session binding
| |- Conversation Engine -> LLM streaming
| |- Permission Broker -> tool approval flow
| |- Delivery Layer -> chunking, retry, dedup
+------------------+
|
| Host Interfaces (DI)
v
+------------------+
| Host Application | (implements BridgeStore,
| | LLMProvider, etc.)
+------------------+
All bridge modules access host services through a DI context (getBridgeContext()), never through direct imports. This means you can plug the bridge into any Node.js application by implementing four interfaces.
Quick Start
1. Install
npm install claude-to-im
Or clone this repo and install dependencies:
git clone https://github.com/op7418/Claude-to-IM.git
cd Claude-to-IM
npm install
2. Implement Host Interfaces
The bridge requires four interfaces. See docs/development.md for the full specification of each interface.
import { initBridgeContext } from 'claude-to-im/context';
import type { BridgeStore, LLMProvider, PermissionGateway, LifecycleHooks } from 'claude-to-im/host';
const store: BridgeStore = { /* your persistence layer (~30 methods) */ };
const llm: LLMProvider = { /* wraps Claude Code SDK streamChat */ };
const permissions: PermissionGateway = { /* resolves pending tool permissions */ };
const lifecycle: LifecycleHooks = { /* optional start/stop callbacks */ };
initBridgeContext({ store, llm, permissions, lifecycle });
3. Start the Bridge
import * as bridgeManager from 'claude-to-im/bridge-manager';
await bridgeManager.start();
const status = bridgeManager.getStatus();
// { running: true, adapters: [{ channelType: 'telegram', running: true, ... }] }
4. Run the Example
A self-contained example with in-memory store and echo LLM is included:
npx tsx src/lib/bridge/examples/mock-host.ts
Configuration
All settings are read through BridgeStore.getSetting(key). Your host application decides how to store and surface these values (database, env vars, config file, UI settings panel, etc.).
Required Settings
| Key | Description |
|---|---|
remote_bridge_enabled | Master switch — "true" to enable the bridge |
bridge_{adapter}_bot_token | Bot token for the platform (e.g. bridge_telegram_bot_token) |
bridge_{adapter}_allowed_users | Comma-separated user IDs authorized to use the bridge |
Optional Settings
| Key | Description | Default |
|---|---|---|
bridge_auto_start | Auto-start bridge on app launch | "false" |
bridge_{adapter}_enabled | Per-adapter toggle | "false" |
bridge_{adapter}_stream_enabled | Enable streaming previews | "true" |
bridge_default_cwd | Default working directory for new sessions | $HOME |
bridge_model | Default Claude model | Host decides |
Replace {adapter} with telegram, discord, or feishu.
Limitations
Before adopting this library, be aware of the following constraints:
You Must Implement the Host Interfaces
This is a library, not a standalone application. You need to provide:
BridgeStore— A persistence layer with ~30 methods covering settings, sessions, messages, channel bindings, audit logs, dedup tracking, permission links, and channel offsets. This is the largest integration surface. See the full interface definition insrc/lib/bridge/host.ts.LLMProvider— A wrapper around your LLM client that returns aReadableStream<string>of SSE-formatted events. The stream format must match the Claude Code SDK's event protocol (text, tool_use, tool_result, permission_request, status, result events). Seedocs/development.mdfor the full event format spec.PermissionGateway— A way to resolve pending tool permissions from the Claude Code SDK.LifecycleHooks— Optional callbacks for bridge start/stop events.
LLM Stream Format
The LLMProvider.streamChat() must return SSE-formatted strings matching the Claude Code SDK's event protocol. If you are not using the Claude Code SDK, you need to adapt your LLM client's output to match this format. This is not a generic "chat completion" interface.
No Built-in Persistence
The bridge does not bundle any database driver. You provide all persistence through BridgeStore. This gives you full control but means you need to implement storage for sessions, messages, bindings, audit logs, dedup keys, permission links, and channel offsets.
Session Locking
The bridge uses a session lock mechanism (acquireSessionLock / renewSessionLock / releaseSessionLock) to serialize messages within the same session. Your BridgeStore implementation must provide atomic lock operations. For single-process deployments, in-memory locks work fine. For multi-process deployments, you need distributed locking (e.g., database-backed).
Platform Bot Setup
You still need to create bots on each platform and obtain tokens:
- Telegram: Create a bot via @BotFather
- Discord: Create an application in the Developer Portal with Message Content Intent enabled
- Feishu: Create an app in the Developer Console with IM permissions
Documentation
| Document | Description |
|---|---|
| Development Guide | Host interface specs, SSE format, adapter development, step-by-step integration tutorial |
| Architecture | Module dependency graph, message flows, design decisions |
| Security | Threat model, mitigations, deployment recommendations |
| Contributing | Dev setup, code style, testing guide |
| Migration | Before/after import patterns for migrating from direct imports |
Project Structure
src/
lib/bridge/
context.ts # DI container (initBridgeContext / getBridgeContext)
host.ts # Host interface definitions (BridgeStore, LLMProvider, etc.)
types.ts # Shared type definitions (messages, bindings, status)
bridge-manager.ts # Orchestrator — start/stop, message dispatch, session locks
channel-adapter.ts # Abstract base class + adapter registry
channel-router.ts # ChannelAddress -> ChannelBinding resolution
conversation-engine.ts # LLM stream processing, SSE consumption
delivery-layer.ts # Reliable outbound delivery (chunk, retry, dedup, audit)
permission-broker.ts # Tool permission forwarding and callback handling
adapters/
telegram-adapter.ts # Telegram Bot API long polling
discord-adapter.ts # Discord.js Gateway WebSocket
feishu-adapter.ts # Feishu/Lark WSClient
telegram-media.ts # Telegram file download/attachment handling
telegram-utils.ts # Telegram API helpers
index.ts # Side-effect imports for adapter self-registration
markdown/
ir.ts # Intermediate representation for Markdown AST
render.ts # Generic IR -> platform string renderer
telegram.ts # Markdown -> Telegram HTML
discord.ts # Markdown -> Discord-flavored Markdown
feishu.ts # Markdown -> Feishu rich text / cards
security/
validators.ts # Input validation (path traversal, injection, sanitization)
rate-limiter.ts # Token bucket rate limiter (per chat)
examples/
mock-host.ts # Runnable example with InMemoryStore + EchoLLM
__tests__/unit/
bridge-channel-router.test.ts
bridge-delivery-layer.test.ts
bridge-manager.test.ts
bridge-permission-broker.test.ts
Testing
# Type checking
npm run typecheck
# Unit tests (28 tests)
npm run test:unit
# Both
npm run test
Tests use Node.js built-in test runner (node:test) with mock implementations of all host interfaces — no real database or LLM required.
License
MIT
Files in the repo
- docs
- src
- .gitignore
- LICENSE
- package-lock.json
- package.json
- README.md
- README.zh-CN.md
- tsconfig.build.json
- tsconfig.json
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More connectors
High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.

Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code
Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300µs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.
Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.
Stop your AI from making things up — it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.