npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tengxiaohtx/connect

v1.2.7

Published

CLI tool for managing cc-connect-router configuration

Readme

🤖 cc-connect-router

English | 简体中文

Monitor and control multiple coding-agent sessions (Claude Code / qodercli) running on your machine — straight from DingTalk on your phone. Read/write split · one-to-many · messenger agent for intent dispatch · human-confirmed writes.

📖 Intro site: https://xinyuehtx.github.io/connect/

Send one message in DingTalk to see the status of every agent session on your machine, pull results read-only, and inject follow-up instructions into a specific task. A lightweight messenger agent (built on the Vercel AI SDK, any OpenAI-compatible model) reads your intent, decides read vs. write, and targets the right session — every mutation of a worker session waits for your confirmation. Messages ride cc-connect for DingTalk ⇄ local transport; a companion cc-router serve provides a web console.


🏗️ Architecture

Three layers, one job each:

  • Messenger Agent (dispatch, not a re-router) — built on the AI SDK, decoupled from Claude Code. It only decides read vs. write / which session / which verb and calls the control plane via tools; the task itself still runs in the worker agent. The messenger keeps its own conversation context (shared by web + DingTalk) and never enters a worker's context — that's what makes read/write separation work for natural-language input.
  • Read / write planes — reads (list/read) only touch Claude Code's on-disk session registry and transcripts: zero side effects, never the worker process. Writes (send/takeover/run) go through tmux, gated by a propose → confirm → execute state machine.
  • Transport — still cc-connect. Because cc-connect only accepts custom programs through its acp agent type, the messenger plugs in as a thin ACP bridge (cc-router acp) that forwards to the cc-router serve daemon.
DingTalk ─Stream─► cc-connect ─exec─► cc-router acp (bridge) ─HTTP─► cc-router serve (daemon)
                                                                        │
   ┌─────────────────────────────────────────────────────────────────┐ │
   │  Web console + SSE + config       gate (allowlist / prefix / confirm) │◄┘
   │        │  shared conductor / pending / messenger context           │
   │  AgentConductor  ( propose → confirm → execute )                   │
   │  Messenger Agent ( AI SDK, OpenAI-compatible )                     │
   │        │  read tools  /  propose tools                             │
   │  ControlPlane: listSessions·getMessages · sendMessage·takeover·run │
   └──┬──────────────────┬──────────────────┬─────────────────────────┘
   registry.js       transcript.js         tmux.js

Evolution: earlier versions argued for “no routing agent” (forward chat straight to the worker, let it interpret). But controlling other sessions from chat that way pollutes the worker's context and lacks a safety gate. The current design uses a separate messenger for addressing/dispatch (it never re-interprets or re-executes the task) plus plane separation plus human confirmation — keeping the “just say it” UX while staying safe.


📦 Install

npm install -g @tengxiaohtx/connect

🚀 Quick start

# 1. Create default config at ~/.cc-connect-router/config.toml
cc-router init

# 2. Start the web console daemon (prints an access token on first run)
cc-router serve
#   Open http://127.0.0.1:8787 → log in with the printed token
#   Settings → LLM Provider: base_url / api_key / model (any OpenAI-compatible endpoint)
#   Settings → IM connector: DingTalk client_id / client_secret + gate (prefix / allowlist)

# 3. In another terminal, start cc-connect (DingTalk ⇄ local)
cc-router start

Everything is configurable via CLI too (equivalent to the settings page):

cc-router config set messenger.base_url "https://your-gateway/v1"
cc-router config set messenger.api_key  "sk-..."
cc-router config set messenger.model    "gpt-4o-mini"
cc-router config set projects.0.platforms.0.options.client_id     "your-dingtalk-client-id"
cc-router config set projects.0.platforms.0.options.client_secret "your-dingtalk-client-secret"

DingTalk credentials come from an internal app / bot on the DingTalk Open Platform with Stream mode enabled. The default config already wires the messenger as cc-connect's acp agent (cmd = "cc-router", args = ["acp"]) — no manual edit needed.

In DingTalk, messages need the /ai prefix to reach the messenger (e.g. /ai list sessions). Reply 确认/取消 (yes/no) to a pending action. The prefix is configurable, or leave it empty to process every message.


🧠 Messenger agent (dispatch + safety gate)

The messenger is not a re-router — it never re-interprets or executes your task. It does three things: decide read vs. write, locate which session, pick which verb, then call control-plane tools. The task still runs in the worker agent.

  • Read tools (list_sessions / read_session / get_status) — always available, read on-disk files only, zero pollution.
  • Propose tools (propose_send / propose_takeover / propose_run) — stage only, never execute. The messenger returns a pending list; you reply “确认” to run it through tmux, or “取消”/timeout (5 min default) to drop it.

The LLM uses the Vercel AI SDK. First-class support is OpenAI-compatible (base_url + api_key + model), covering self-hosted gateways, proxies, and most compatible endpoints — fully decoupled from Claude Code. Switch it in the web settings page or the config file.


🌐 Any IM (not just DingTalk)

Because cc-connect bridges many platforms (DingTalk, Feishu, Telegram, Slack, Discord, WeChat Work, QQ, LINE…), and our messenger plugs in as its platform-agnostic acp agent, cc-connect-router works with any of them. The ACP bridge reads the platform from cc-connect's CC_SESSION_KEY and applies the matching gate.

To add an IM:

  1. Configure that platform in the cc-connect side of ~/.cc-connect-router/config.toml (its own [[projects.platforms]] + credentials — see cc-connect docs).
  2. (Optional) Add a gate for it: [im.platforms.<name>] with enabled / command_prefix / allowed_sender_ids / confirm words. If omitted, defaults apply (enabled, empty allowlist = allow all).

The messenger, read/write planes, and confirm gate are identical across platforms — only the transport differs.

📇 Access control & clear denials

When a sender isn't in allowed_sender_ids, the bot replies with an explicit “not authorized” message (instead of silence), telling you which ID to add. Empty allowlist = allow all. The sender ID is whatever the platform reports (e.g. DingTalk senderStaffId).

🖌️ Streaming AI card (DingTalk, optional)

For a typewriter-style streaming reply, create an AI card template on the DingTalk Open Platform and set its id — card_template_id (+ optional card_template_key, card_throttle_ms) under the DingTalk platform options, or via the web Settings → IM connector → Streaming AI card. If unset, replies fall back to normal messages (fully functional, just not streamed).

📸 Rich replies & screenshots

Replies are sent as Markdown (tables, bold, code blocks, emoji status), so the session list shows project / agent / status / latest input at a glance. The messenger can also send images: snapshot_session renders a session's terminal pane to a PNG (via headless Chrome, auto-detected; set messenger.chrome_path to override) and posts it to the chat; send_image delivers any local image file. Both go out via cc-connect send --image. If no renderer is found, snapshots fall back to a Markdown code block.


📖 CLI reference

| Command | Description | |---------|-------------| | cc-router init [--force] | Create config dir + default config (--force overwrites) | | cc-router serve [-H host] [-p port] | Start web console + messenger daemon (planes + gate; prints token on first run) | | cc-router acp | ACP bridge for cc-connect (spawned by cc-connect; don't run by hand) | | cc-router start | Start cc-connect (DingTalk ⇄ local transport) | | cc-router config get/set/remove/list | Read/write config (dot-path keys, sensitive fields masked) | | cc-router project add/remove/list | Manage cc-connect projects | | cc-router agent list [-a] [--json] | List running agent sessions | | cc-router agent read <id> [--full] | Read status + latest reply (read-only, no pollution) | | cc-router agent send <id> "<text>" | Inject an instruction into a tmux session | | cc-router agent takeover <id> [--force] | Adopt a non-tmux session (kill + resume in tmux) | | cc-router agent run ["<prompt>"] [-w dir] | Spawn a new remote-controllable session in tmux |


📋 Prerequisites

| Dependency | Purpose | Link | |------------|---------|------| | Node.js ≥ 18 | Runs the cc-router CLI and serve daemon | https://nodejs.org | | cc-connect | Gateway; forwards DingTalk to the messenger via acp | https://github.com/chenhg5/cc-connect | | OpenAI-compatible LLM | The messenger's model (base_url + api_key + model) | self-hosted gateway / proxy | | tmux | Needed for the write plane; reads don't need it | brew install tmux | | Claude Code / qodercli | The worker agents being controlled (at least one) | — | | DingTalk developer account | Create a bot, get client_id/client_secret, enable Stream mode | https://open.dingtalk.com |

🛠️ Development

npm test            # node --test
node bin/cli.js --help

📂 Layout

src/lib/control-plane.js   read/write planes (reuses registry/transcript/tmux)
src/lib/messenger/         agent (AI SDK) / conductor / provider / pending / history
src/lib/im/                gate (routing) / session-key (CC_SESSION_KEY parsing)
src/server/                Fastify: http / routes / sse / auth  (web + /im/handle)
web/                       console front-end
docs/                      GitHub Pages intro site

License

MIT



🤖 cc-connect-router (简体中文)

English | 简体中文

从手机(钉钉)监控并控制本机上运行的多个 coding agent 会话(Claude Code / qodercli):读写分离 · 一对多 · 信使 Agent 做意图分派 · 写操作人工确认。

📖 使用介绍网站: https://xinyuehtx.github.io/connect/

在钉钉里发一句话,就能查看本机所有 agent 任务的状态、只读拉取结果、并把后续指令注入到指定的那个任务。一个轻量的信使 Agent(Vercel AI SDK,可配置任意 OpenAI 兼容模型)理解你的意图、决定读还是写、定位到哪个会话;任何变更 worker 会话的操作都要你确认后才执行。基于 cc-connect 做钉钉 ↔ 本地的消息传输,配套 cc-router serve 提供 Web 控制台。


🏗️ 架构

三层,各司其职:

  • 信使 Agent(寻址分派,非重路由):用 AI SDK 实现、与 Claude Code 解耦。它只判断「读还是写 / 哪个会话 / 哪个动词」,用工具调用控制面;任务本身仍由 worker agent 执行。信使自己一个独立会话上下文(Web 与钉钉共享),永不进入 worker 会话的上下文——这正是读写分离在自然语言输入下的守门人。
  • 读写双平面:读(list/read)只读 Claude Code 落盘的 sessions 注册表与 transcript,零副作用、不碰 worker 进程;写(send/takeover/run)经 tmux,且必须经**「提议 → 人工确认 → 执行」**安全闸。
  • 通信:继续用 cc-connect。因 cc-connect 只能通过 acp agent 类型接入自定义程序,信使以一个 ACP 薄桥cc-router acp)作为它的 agent,把消息转发给 cc-router serve 守护。
钉钉 ─Stream─► cc-connect ─exec─► cc-router acp(薄桥)─HTTP─► cc-router serve(守护)
                                                                  │
   ┌──────────────────────────────────────────────────────────┐ │
   │  Web 控制台 + SSE + 配置页        闸门(白名单/前缀/确认词)   │◄┘
   │        │  共享 conductor / pending / 信使会话上下文         │
   │  AgentConductor(提议→确认→执行 安全闸)                    │
   │  Messenger Agent(AI SDK,OpenAI-compatible)              │
   │        │ 只读工具 / 提议工具                                │
   │  ControlPlane: listSessions·getMessages·sendMessage·takeover·run │
   └──┬───────────────┬──────────────┬────────────────────────┘
   registry.js     transcript.js    tmux.js

演进说明:早期版本主张「无路由 Agent」(普通消息直连 worker,由其自行理解)。但那样从聊天做跨会话控制会污染 worker 上下文,且缺少安全闸。现改为独立信使做寻址分派(不重新理解/执行任务)+ 读写分离 + 人工确认,兼顾「发一句话就行」的体验与安全。


📦 安装

npm install -g @tengxiaohtx/connect

🚀 快速开始

# 1. 初始化配置(生成 ~/.cc-connect-router/config.toml)
cc-router init

# 2. 启动 Web 控制台守护(首次会打印访问令牌)
cc-router serve
#   浏览器打开 http://127.0.0.1:8787 → 用打印出的令牌登录
#   设置 → LLM Provider:填 base_url / api_key / model(任意 OpenAI 兼容端点)
#   设置 → IM 连接器:填钉钉 client_id / client_secret + 闸门(前缀 / 白名单)

# 3. 另开一个终端,拉起 cc-connect(钉钉 ↔ 本地)
cc-router start

也可以全用 CLI 配置(等价于 Web 配置页):

cc-router config set messenger.base_url "https://your-gateway/v1"
cc-router config set messenger.api_key  "sk-..."
cc-router config set messenger.model    "gpt-4o-mini"
cc-router config set projects.0.platforms.0.options.client_id     "your-dingtalk-client-id"
cc-router config set projects.0.platforms.0.options.client_secret "your-dingtalk-client-secret"

钉钉凭证 client_id / client_secret 需在钉钉开放平台创建企业内部应用(或机器人应用),并启用 Stream 模式。默认配置已把信使接成 cc-connect 的 acp agent(cmd = "cc-router", args = ["acp"]),无需手改。

钉钉里默认要带前缀 /ai 才会路由给信使(如 /ai 列出会话);待确认时直接回「确认 / 取消」。前缀可改或留空(留空 = 处理所有消息)。


🧠 信使 Agent(寻址分派 + 安全闸)

信使不是重路由——它不重新理解或执行你的任务,只做三件事:判断读还是写、定位哪个会话、选择哪个动词,然后调用控制面工具。任务本身仍交给 worker agent。

  • 读工具list_sessions / read_session / get_status):随时可用,只读落盘文件,零污染。
  • 提议工具propose_send / propose_takeover / propose_run):只暂存,不执行。信使会回一张待确认清单,你回「确认」才真正经 tmux 执行,「取消」或超时(默认 5 分钟)则作废。

LLM 用 Vercel AI SDK,首批支持 OpenAI-compatiblebase_url + api_key + model),覆盖自建网关/代理/多数兼容端点,与 Claude Code 完全解耦。可在 Web 配置页或 config 文件切换。


🌐 支持任意 IM(不止钉钉)

cc-connect 本身桥接多种平台(钉钉、飞书、Telegram、Slack、Discord、企业微信、QQ、LINE…),而我们的信使以平台无关acp agent 接入,所以 cc-connect-router 对任意平台都适用。ACP 薄桥从 CC_SESSION_KEY 解析出平台名,套用对应闸门。

接入一个新 IM:

  1. ~/.cc-connect-router/config.toml 的 cc-connect 部分配好该平台(它自己的 [[projects.platforms]] + 凭证,见 cc-connect 文档)。
  2. (可选)给它加一段闸门:[im.platforms.<平台名>],含 enabled / command_prefix / allowed_sender_ids / 确认词。不配则用默认(启用、空白名单=允许所有)。

信使、读写平面、确认闸在所有平台完全一致,只有传输层不同。

📇 访问控制与明确拒绝

当发送者不在 allowed_sender_ids 时,机器人会明确回复「无权限」(而不是静默),并提示该把哪个 ID 加进名单。名单留空 = 允许所有。发送者 ID 取平台上报值(如钉钉 senderStaffId)。

🖌️ 流式 AI 卡片(钉钉,可选)

想要打字机式流式回复:在钉钉开放平台创建 AI 卡片模板,把它的 id 填到钉钉平台选项的 card_template_id(另可选 card_template_keycard_throttle_ms),或在 Web 设置 → IM 连接器 → 流式 AI 卡片 里填。不填则回退为普通消息(功能不受影响,只是非流式)。

📸 富文本回复与截图

回复以 Markdown 发送(表格、加粗、代码块、emoji 状态),会话列表因此能一眼看到 项目 / Agent / 状态 / 最近输入。信使还能发图片snapshot_session 把某会话的终端画面渲染成 PNG(用自动探测的无头 Chrome;可用 messenger.chrome_path 指定)并发到聊天里;send_image 发送本机任意图片文件。二者都经 cc-connect send --image 投递。若本机没有渲染器,截图会退回为 Markdown 代码块。


📖 CLI 命令参考

| 命令 | 说明 | |------|------| | cc-router init [--force] | 初始化配置目录与默认配置(--force 覆盖) | | cc-router serve [-H host] [-p port] | 启动 Web 控制台 + 信使守护(读写平面 + 安全闸;首启打印令牌) | | cc-router acp | ACP 薄桥,供 cc-connect 拉起(勿手动运行) | | cc-router start | 启动 cc-connect(钉钉 ↔ 本地 消息传输) | | cc-router config get/set/remove/list | 读写配置(点号路径,敏感字段遮掩) | | cc-router project add/remove/list | 管理 cc-connect 项目 | | cc-router agent list [-a] [--json] | 列出运行中的 agent 会话 | | cc-router agent read <id> [--full] | 只读查看状态与最新回复(不污染上下文) | | cc-router agent send <id> "<text>" | 向 tmux 会话注入指令 | | cc-router agent takeover <id> [--force] | 接管非 tmux 会话(kill + resume 进 tmux) | | cc-router agent run ["<prompt>"] [-w dir] | 在 tmux 中新建可远控会话 |


📋 前置条件

| 依赖 | 说明 | 链接 | |------|------|------| | Node.js ≥ 18 | 运行 cc-router CLI 与 serve 守护 | https://nodejs.org | | cc-connect | 消息网关,把钉钉消息经 acp 转发到信使 | https://github.com/chenhg5/cc-connect | | OpenAI 兼容 LLM 端点 | 信使 Agent 的模型(base_url + api_key + model) | 自建网关 / 代理 | | tmux | 写平面所需;读平面不需要 | brew install tmux | | Claude Code / qodercli | 被控制的 worker agent(至少装一个) | — | | 钉钉开发者账号 | 创建机器人,获取 client_id/client_secret,启用 Stream 模式 | https://open.dingtalk.com |

🛠️ 开发

npm test            # node --test
node bin/cli.js --help

📂 目录结构

src/lib/control-plane.js   读写平面(复用 registry/transcript/tmux)
src/lib/messenger/         信使栈:agent(AI SDK)/conductor/provider/pending/history
src/lib/im/                gate(闸门路由)/ session-key(CC_SESSION_KEY 解析)
src/server/                Fastify:http/routes/sse/auth(Web + /im/handle)
web/                       控制台前端
docs/                      GitHub Pages 使用介绍网站

许可证

MIT · 基于 cc-connect,设计参考 lifestream