An opencode plugin that connects instant messaging bots to opencode AI via a unified multi-channel architecture.
Currently supported: Feishu (Lark) via WebSocket long connection — no public IP required.
Skeleton ready: WeCom (企业微信) — see src/channels/wecom/index.ts.
User sends message (Feishu / WeCom / ...)
↓ Channel adapter (WebSocket / HTTP callback / ...)
chat-channel plugin (this repo)
↓ client.session.prompt()
opencode AI (Sisyphus)
↓ text reply
User receives reply
- Each user (
open_id/ user ID) gets their own persistent opencode session - Sessions expire after 2 hours of inactivity (auto-cleanup)
- Replies longer than 4000 characters are automatically split
Since this is an opencode plugin, opencode handles installation automatically via npm. No scripts needed.
Edit ~/.config/opencode/opencode.json and add the plugin:
{
"plugin": [
"opencode-chat-channel@latest"
]
}opencode will pull and install the package automatically on next startup.
Add CHAT_CHANNELS to ~/.config/opencode/.env to control which channels are active:
# ~/.config/opencode/.env
# Enable Feishu only (recommended to start)
CHAT_CHANNELS=feishu
# Enable multiple channels at once
# CHAT_CHANNELS=feishu,wecom
# Leave unset or empty = auto mode: any channel with valid credentials starts automatically
# CHAT_CHANNELS=Then configure credentials for each enabled channel (see sections below).
See the Feishu Configuration section below.
- Visit Feishu Open Platform and create a self-built app
- Note your App ID and App Secret
- Under "Add App Capabilities", enable Bot
- Under "Permissions", add:
im:message(read/send messages)im:message.group_at_msg(receive group @ messages, optional)
- Under "Event Subscriptions":
- Select "Use long connection to receive events" (no webhook URL needed)
- Add event:
Receive Message v2.0(im.message.receive_v1)
- Publish the app version
App ID (non-sensitive, store in .env):
# ~/.config/opencode/.env
FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxx
# Optional: custom opencode API URL (default: http://localhost:4321)
# OPENCODE_BASE_URL=http://localhost:4321App Secret — choose the method for your platform:
| Platform | Method | Command |
|---|---|---|
| macOS | Keychain (recommended) | security add-generic-password -a chat-channel -s opencode-chat-channel -w <secret> -U |
| Windows / Linux | .env file |
Add FEISHU_APP_SECRET=<secret> to ~/.config/opencode/.env |
| All platforms | Environment variable | Set FEISHU_APP_SECRET=<secret> before launching opencode |
Priority: environment variable → macOS Keychain →
.envfile value (already loaded as env var). The plugin tries each in order and uses the first one found.
⚠️ If you store the secret in.env, ensure the file has restricted permissions:chmod 600 ~/.config/opencode/.env
macOS Keychain (verify):
security find-generic-password -a chat-channel -s opencode-chat-channel -wopencodeYou should see in the logs:
[feishu] 飞书机器人已启动(长连接模式),appId=cli_xxx***
chat-channel 已启动,活跃渠道: feishu
The plugin uses a ChatChannel interface. To add a new channel:
- Create
src/channels/<name>/index.tsimplementingChatChanneland exporting aChannelFactory - Register the factory in
src/index.ts→CHANNEL_FACTORIESarray
// src/channels/myapp/index.ts
import type { ChatChannel, ChannelFactory } from "../../types.js";
class MyAppChannel implements ChatChannel {
readonly name = "myapp";
async start(onMessage) { /* connect, call onMessage on each msg */ }
async send(target, text) { /* send reply */ }
}
export const myappChannelFactory: ChannelFactory = async (client) => {
// read credentials, return null if not configured
return new MyAppChannel(...);
};// src/index.ts — add to CHANNEL_FACTORIES
import { myappChannelFactory } from "./channels/myapp/index.js";
const CHANNEL_FACTORIES: ChannelFactory[] = [
feishuChannelFactory,
myappChannelFactory, // ← add here
];Q: Plugin starts but bot receives no messages
- Ensure event subscription is set to "long connection", not "HTTP callback URL"
- Ensure the app version is published and online
- Verify App ID / Secret are correct
Q: Replies are slow
- AI processing takes time; complex tasks may need 10–30 seconds
- Simple conversations typically 3–8 seconds
Q: How to reset conversation history
- Restart opencode (sessions follow process lifecycle)
- Or wait 2 hours for session TTL to expire
用户发消息(飞书 / 企业微信 / ...)
↓ 渠道适配器(WebSocket 长连接 / HTTP 回调 / ...)
chat-channel 插件(本仓库)
↓ client.session.prompt()
opencode AI (Sisyphus)
↓ 回复文本
用户收到回复
- 每个用户独享一个 opencode session,对话历史持久保留
- session 闲置 2 小时后自动回收,下次对话开新 session
- AI 回复超过 4000 字时自动分段发送
本项目是 opencode 插件,opencode 通过 npm 自动管理安装,无需额外脚本。
编辑 ~/.config/opencode/opencode.json,在 plugin 数组中添加:
{
"plugin": [
"opencode-chat-channel@latest"
]
}下次启动 opencode 时会自动拉取并安装。
在 ~/.config/opencode/.env 中配置 CHAT_CHANNELS,指定要开启哪些渠道:
# ~/.config/opencode/.env
# 只开启飞书(初始推荐)
CHAT_CHANNELS=feishu
# 同时开启多个渠道
# CHAT_CHANNELS=feishu,wecom
# 留空或不配置 = 自动模式:凭证存在的渠道自动启用
# CHAT_CHANNELS=然后配置对应渠道的凭证(见下方各渠道配置说明)。
参见下方各渠道的配置说明。
- 访问 飞书开放平台,新建企业自建应用
- 记录 App ID 和 App Secret
- 在「添加应用能力」中开启机器人
- 在「权限管理」中添加以下权限:
im:message(读取/发送消息)im:message.group_at_msg(接收群组 @ 消息,按需)
- 在「事件订阅」中:
- 选择使用长连接接收事件(无需填写请求地址)
- 添加事件:
接收消息 v2.0(即im.message.receive_v1)
- 发布应用版本
App ID(非敏感,明文存 .env):
# ~/.config/opencode/.env
FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxx
# 可选:自定义 opencode API 地址(默认:http://localhost:4321)
# OPENCODE_BASE_URL=http://localhost:4321App Secret—按使用的平台选择存储方式:
| 平台 | 方式 | 命令 |
|---|---|---|
| macOS | 钒匙串(推荐,不落盘明文) | security add-generic-password -a chat-channel -s opencode-chat-channel -w <secret> -U |
| Windows / Linux | 写入 .env 文件 |
在 ~/.config/opencode/.env 中添加 FEISHU_APP_SECRET=<secret> |
| 所有平台 | 环境变量 | 启动 opencode 前设置 FEISHU_APP_SECRET=<secret> |
读取优先级:环境变量 → macOS 钒匙串 →
.env文件(已在插件启动时自动读入环境变量)。 插件依次尝试,找到第一个有效值即停止。
⚠️ 如果将 Secret 写入.env,建议限制文件权限:chmod 600 ~/.config/opencode/.env
macOS 钒匙串验证:
security find-generic-password -a chat-channel -s opencode-chat-channel -wopencode启动后日志中会看到:
[feishu] 飞书机器人已启动(长连接模式),appId=cli_xxx***
chat-channel 已启动,活跃渠道: feishu
插件基于 ChatChannel 接口设计,新增渠道步骤:
- 新建
src/channels/<渠道名>/index.ts,实现ChatChannel接口并导出ChannelFactory - 在
src/index.ts的CHANNEL_FACTORIES数组中注册工厂函数
参见 src/channels/wecom/index.ts — 企业微信骨架,含详细的实现 TODO 注释。
src/
├── index.ts # 插件入口,注册所有渠道
├── types.ts # ChatChannel 接口 & 公共类型
├── session-manager.ts # opencode session 管理 & 工具函数
└── channels/
├── feishu/
│ └── index.ts # 飞书渠道实现(已完成)
└── wecom/
└── index.ts # 企业微信渠道骨架(待实现)
Q: 插件启动后收不到消息
- 确认飞书应用事件订阅选择的是「长连接」而非「HTTP 请求地址」
- 确认应用已发布且版本已上线
- 确认 App ID/Secret 正确
Q: 回复很慢
- AI 处理需要时间,复杂问题可能需要 10-30 秒
- 简单对话通常 3-8 秒
Q: 想重置对话历史
- 关闭 opencode 重启即可(session 随进程生命周期)
- 或等待 2 小时 session 超时自动重置
MIT