Tribute: 本项目在整体思路和使用形态上受 cc-connect 启发,感谢原项目提供的方向参考。
d-connect 是一个运行在本机上的守护进程,用来把本地 Agent CLI 桥接到 IM 平台。
Note
所有 Agent 以 SOLO 形式运行
- 在 IM 里直接让本地 Agent 看代码、改代码、回答问题。
- 把巡检、日报、提醒等任务交给 loop 定时执行,并自动回投聊天窗口。
|
定时任务 聊天内直接发送 /loop,把自然语言需求转成可执行的定时任务。
|
语音输入 语音识别结果自动纳入同一会话流程,适合移动端快速提问。
|
图片识别与理解 直接发图给 Agent,适合看图说明、读截图排障等场景。
|
Guard 安全拦截 支持按项目开启 Guard,在请求进入 Agent 前拦截敏感内容。
|
| 类别 | 当前支持 |
|---|---|
| IM 平台 | DingTalk、Discord |
| Agent CLI | claudecode、codex、opencode、qoder、iflow |
| 运行环境 | Node.js >=22 |
- Node.js
>=22 - 已安装并能直接执行至少一个 Agent CLI:
claude、codex、opencode、qodercli或iflow - 如果要接真实 IM,还需要对应平台的机器人凭证
- DingTalk 凭证获取参考
- Discord 凭证获取参考
- Discord 需要在 Developer Portal 创建 bot,拿到
bot token,并为 bot 开启MESSAGE CONTENT INTENT(群聊文本触发需要)
npm install -g @xinyuan0801/d-connectd-connect init执行后会进入一个交互式 TUI 向导,用来选择 Agent 类型、工作目录、IM 平台、allowFrom 访问范围(允许所有人或指定用户 ID)以及平台凭证:
d-connect start进程启动成功后,你便可以通过钉钉或 Discord 和你本地的 coding agent 对话
下面是一份常见的 Claude Code + DingTalk 配置:
{
"configVersion": 1,
"log": {
"level": "info"
},
"loop": {
"silent": false
},
"projects": [
{
"name": "my-backend",
"agent": {
"type": "claudecode",
"options": {
"workDir": "/path/to/repo",
"cmd": "claude",
"model": "claude-sonnet-4-20250514"
}
},
"guard": {
"enabled": false
},
"platforms": [
{
"type": "dingtalk",
"options": {
"clientId": "dingxxxx",
"clientSecret": "xxxx",
"allowFrom": "*",
"processingNotice": "处理中..."
}
}
]
}
]
}如果你想接 Discord,可以把 platforms 改成下面这样:
[
{
"type": "discord",
"options": {
"botToken": "discord-bot-token",
"allowFrom": "123456789012345678",
"requireMention": true
}
}
]如果你想接 Codex CLI,可以把 agent 改成下面这样:
{
"type": "codex",
"options": {
"workDir": "/path/to/repo",
"cmd": "codex",
"model": "gpt-5-codex",
"mode": "full-auto",
"reasoning_effort": "high",
"search": true
}
}如果你想接 OpenCode CLI,可以把 agent 改成下面这样:
{
"type": "opencode",
"options": {
"workDir": "/path/to/repo",
"cmd": "opencode",
"model": "anthropic/claude-sonnet-4"
}
}| 字段 | 含义 |
|---|---|
name |
项目名,后续命令通过 -p 使用 |
agent.type |
Agent CLI 类型,当前支持 claudecode / codex / opencode / qoder / iflow |
agent.options.workDir |
Agent 实际工作的仓库目录 |
agent.options.cmd |
可执行命令名或完整路径 |
agent.options.model |
Agent 使用的模型名;留空则走对应 CLI 默认值 |
agent.options.mode |
codex 专用,支持 suggest / full-auto / yolo |
agent.options.reasoning_effort |
codex 专用,支持 low / medium / high / xhigh |
agent.options.search |
codex 专用,是否打开 live web search |
agent.options.addDirs |
codex 专用,额外可写目录列表 |
guard.enabled |
是否启用项目级 Guard |
guard.rules |
自定义 Guard 规则,优先级高于默认规则 |
platforms[].options.allowFrom |
允许访问的用户 ID 列表;逗号分隔,"*" 表示全部允许;init 向导会显式询问此项 |
DingTalkclientId/clientSecret:平台凭证processingNotice:处理中反馈开关;非"none"时会在原消息上贴🤔思考中表情并在处理结束后撤回,设为"none"可关闭
DiscordbotToken:Discord bot token,鉴权方式与 openclaw 一样是标准 Bot TokenrequireMention:群聊里是否要求显式@bot或回复 bot 消息;DM不受此项影响,默认true
- 当前
codex适配按本地验证过的codex-cli 0.114.0接入。 - 非交互执行走
codex exec --json,续聊走codex exec resume <thread_id> ...。 mode: "full-auto"会映射到--full-auto,mode: "yolo"会映射到--dangerously-bypass-approvals-and-sandbox。reasoning_effort会映射到当前 CLI 的-c model_reasoning_effort="..."配置覆盖。
- 当前
opencode适配按本机验证过的opencode-ai 1.2.26CLI 接入。 - 非交互执行走
opencode run --format json,续聊走opencode run --session <session_id> <prompt>。 - 会话 ID 与消息内容从 CLI 的顶层
sessionID/part流式事件里提取。 agent.options.model会映射到--model。
- Claude Code agent team 仍然复用当前聊天 session;lead 继续作为默认聊天入口,teammate 活动会以结构化进度卡片回投到同一条 IM 时间线。
d-connect会默认替claudecode打开 agent team 所需的环境开关;只有你自己显式覆盖时才会使用自定义值。- Claude 本地 team 状态目录位于
~/.claude/teams/*,任务文件位于~/.claude/tasks/*;d-connect会读取这些文件来恢复/team状态和 teammate 摘要。
在 IM 中发送 / 开头消息即可:
| 命令 | 作用 |
|---|---|
/help |
查看命令帮助 |
/new [name] |
新建并切换到一个逻辑 session |
/list |
列出当前聊天对象下的 session |
| `/switch <id | name>` |
/stop |
停止当前活跃 session 对应的 Agent 进程 |
/team |
查看当前 Claude agent team 状态 |
/team members |
查看当前 team 成员 |
/team tasks |
查看当前 team 任务 |
/team ask <member> <message> |
让 lead 把任务转给指定 teammate |
/team stop <member> |
让 lead 停掉指定 teammate 的当前任务 |
/team cleanup |
让 lead 清理并收尾当前 team |
/loop <request> |
用自然语言描述定时任务 |
/loop list |
列出当前聊天对象下的 loop |
/loop add <expr> <prompt> |
直接创建 loop |
/loop del <id> |
删除 loop |
这些命令的回执默认是中文提示,偶尔会夹带一点不影响下班的冷幽默。
loop 默认每次执行都会使用全新的独立上下文,不继承当前聊天 session,也不会复用该任务上一次执行的历史;任务结果仍会回投到创建它的那个聊天对象。
/team 系列命令目前只对 claudecode 生效:/team、/team members、/team tasks 会优先读取本地 ~/.claude snapshot,/team ask|stop|cleanup 则转发固定 prompt 给 lead agent,不会直接改写 Claude 的 mailbox 文件。
| 命令 | 作用 |
|---|---|
d-connect init |
创建配置文件 |
d-connect add |
给现有配置追加一个项目 |
d-connect start |
启动本地守护进程 |
d-connect restart |
重启本地守护进程 |
d-connect send -p <project> -s <sessionKey> "hello" |
从本地直接向某个会话发送消息 |
d-connect loop add -p <project> -s <sessionKey> -e "*/30 * * * * *" "status" |
添加 loop |
d-connect loop list -p <project> |
查看项目下的 loop |
d-connect loop del -i <job-id> |
删除 loop |
运行数据固定写入 .d-connect/:
- 配置文件是普通路径,例如
./config.json,则运行目录是配置文件同级的.d-connect/ - 配置文件本身位于
.d-connect/config.json,则直接复用该目录
常见文件:
.d-connect/ipc.sock.d-connect/sessions/sessions.json.d-connect/loops/jobs.json.d-connect/logs/d-connect.log
pnpm install
pnpm run build
pnpm test
pnpm run dev init -c ./config.json
pnpm run dev add -c ./config.json
pnpm run dev start -c ./config.json
pnpm run dev send -p <project> -s local:debug "hello"
pnpm run dev loop add -p <project> -s local:debug -e "*/30 * * * * *" "status"
pnpm run dev loop list -p <project>先启动 daemon:
pnpm run dev start -c ./config.json另一个终端发送消息:
pnpm run dev send -p my-backend -s local:alice "请给我当前项目结构"
pnpm run dev send -p my-backend -s local:bob "你好"再加一个 loop 验证调度:
pnpm run dev loop add -p my-backend -s local:alice -e "*/20 * * * * *" "输出一次状态"src/bootstrap/**:CLI 入口与 daemon 启动编排src/config/**:配置加载、校验、init/add向导src/services/**:会话、命令、消息 relaysrc/adapters/agent/**:各类 Agent CLI 适配器src/adapters/platform/**:DingTalk / Discord 适配器src/ipc/**:本地 IPCsrc/scheduler/**:loop 调度与持久化tests/**:Vitest 测试
init/add交互向导支持 DingTalk 和 Discord;--yes以及start自动生成的兜底模板仍默认是 DingTalk- 机器人消息走
CALLBACK,不是普通EVENT - 收到 callback 后需要显式回执,否则平台大约 60 秒后可能重投
- 当前实现按
msgId做 10 分钟去重 - 即时回复仍使用入站消息里的
sessionWebhook - 异步回投/loop 会直接走机器人主动发送:群聊用
/v1.0/robot/groupMessages/send,单聊用/v1.0/robot/oToMessages/batchSend,不再尝试sessionWebhook - 历史旧版
DeliveryTarget若缺少conversationType、群聊所需的openConversationId或单聊所需的userId,会被直接忽略,不再尝试发送 - 图片、视频、文件等入站内容会下载到
agent.options.workDir/.d-connect/dingtalk-media
- 认证使用标准
Bot Token - 群聊文本触发依赖
MESSAGE CONTENT INTENT;如果没开,群消息可能只能看到 mention/事件元信息,看不到正文 - 当前实现默认只处理两类群聊消息:显式
@bot,或回复 bot 的消息;把requireMention设为false后,allow-list 命中的用户在群里发言都会触发 DM不要求 mention,只要allowFrom放行就会进入同一条平台链路- 即时回复会在开始处理该条用户消息时立刻补一个
👀reaction,回复成功结束后移除它并补一个💯;正文仍走引用回复,异步回投/loop 仍然只走POST /channels/{channel.id}/messages - 持久化
DeliveryTarget只依赖channelId;如果历史 target 缺失channelId,loop 不会尝试回投 - 出站消息默认禁用
allowed_mentions.parse,避免 Agent 文本意外触发@everyone或角色 mention
pnpm test
pnpm run build如果你改了配置、平台适配器、IPC、调度或公共运行链路,建议不要跳过这两步。
- 确认对应 CLI 已安装且可以在终端里直接执行
- 或在
agent.options.cmd填完整命令路径
- 同一逻辑 session 正在处理上一条请求
- 等处理完成,或先
/new新开一个 session
d-connect会在检测到AskUserQuestion工具调用后结束当前这一轮,避免 CLI 一直阻塞- 聊天窗口会收到问题摘要,直接回复你的选择(例如
dev/prod)即可继续同一session
- 确认 daemon 已启动
- 确认
.d-connect/ipc.sock已生成
- 确认该
sessionKey最近收到过至少一条真实平台消息 loop默认使用按job.id隔离的执行会话;如果你在排查“为什么没继承上一轮聊天上下文”,这是当前设计,不是故障- DingTalk 场景下,优先检查
.d-connect/sessions/sessions.json里的DeliveryTarget是否带有conversationType、robotCode,以及群聊所需的openConversationId或单聊所需的userId - 若历史 DingTalk target 缺这些主动发送字段,会被直接忽略
- Discord 场景下,优先检查
.d-connect/sessions/sessions.json里的DeliveryTarget是否带有channelId



