Cline Hub 浏览器控制台:管理本地 Cline Hub 的客户端、会话与守护进程
Cline Hub 是 Cline 本地架构中的中枢守护进程,负责在 CLI、VS Code、menubar 等多个客户端之间共享会话与事件。apps/cline-hub 为这个本地 hub 提供了一个浏览器仪表盘:你可以实时查看谁连在 hub 上、哪些会话正在运行、在聊天框里直接驱动会话,并在需要时一键重启 hub 守护进程。读完本文,你将掌握 Cline Hub 仪表盘的完整启动与配置方式、LAN/隧道共享的安全模型,以及会话 provider/model 解析、hub 重启等机制在源码中的具体实现。
功能概览
Cline Hub 仪表盘(README)提供的核心能力包括:
- 实时客户端列表:展示当前连在 hub 上的所有客户端(通过
HubUIClient.subscribeUI订阅); - 实时会话列表:展示活跃会话的状态、模型与标题;
- 会话详情与流式输出:点击某个会话查看其消息历史,并以流式方式接收新的 assistant 输出;
- 发起新会话:用一条初始 prompt 创建新会话,workspace/provider/model 会从最近一次会话复用,或回退到
CLINE_PROVIDER/CLINE_MODEL环境变量; - 向选中会话发送消息,并观察返回的增量分块;
- Restart Hub 按钮:优雅停止当前本地 detached hub 并重新拉起一个新的;
- 可选的 LAN/隧道暴露,由共享的
ROOM_SECRET保护。
从源码结构看,仪表盘启动时会向 hub 注册两个客户端,分工明确(见 attachHub 实现):
- 一个通过
ClineCore创建,clientType为cline-hub-chat,用于实际驱动会话(start/send/abort/fork/restore),并且把requestToolApproval能力指向 webview,使工具审批请求能弹到浏览器 UI; - 另一个通过
HubUIClient创建,clientType为cline-hub-server,用于管理视图(列举客户端/会话、订阅onClientRegistered/onSessionCreated/onSessionUpdated/onSessionDetached等 hub 级事件)。
快速启动
在仓库的 apps/cline-hub 目录下运行:
cd apps/cline-hub
bun run start
对应 package.json 中的 "start": "bun run src/server.ts"。打开 http://127.0.0.1:8787 并点击 Connect。服务启动时会通过 ensureDetachedHubServer(workspaceRoot) 发现或拉起一个本地 detached hub(该函数来自 @cline/core,内部使用启动锁防止并发拉起);hub endpoint 会打印到控制台并显示在侧边栏。
Vite 热重载开发模式
开发 webview 时可以使用:
cd apps/cline-hub
bun run dev
这会启动 Vite webview 开发服务器(http://127.0.0.1:5173)和 hub 仪表盘(http://127.0.0.1:8787)。打开仪表盘 URL 后,页面从 Vite 加载 webview 模块,src/webview/src 下的改动无需重新构建即可热更新。从 dev 脚本 可以看到,它同时 spawn 了 Vite 子进程和 src/server.ts,并通过 VITE_DEV_SERVER_URL 环境变量把 Vite 地址传给仪表盘;可用 CLINE_HUB_WEBVIEW_DEV_PORT 或 CLINE_HUB_WEBVIEW_DEV_HOST 修改 Vite 的绑定地址。
新会话的 provider/model 从哪里来
发起一个全新会话时,仪表盘必须知道使用哪个 provider 和 model。它的解析顺序(见 resolveLaunchContext)是:
- 浏览器端随请求提交的配置(用户在下拉框里选择的 provider/model);
- 最近一次 hub 会话解析出的上下文(
ctx.lastSessionContext,由listSessions按updatedAt排序取最新); ProviderSettingsManager记录的上次使用设置;- 环境变量
CLINE_PROVIDER与CLINE_MODEL。
如果以上都拿不到,会抛出 No provider/model available 错误。因此 README 建议:在没有最近会话时,先设置 CLINE_PROVIDER 和 CLINE_MODEL 再运行。
配置项
所有配置通过环境变量注入,由 resolveClineHubServerOptions 集中解析:
| 变量 | 默认值 | 说明 |
|---|---|---|
HOST |
127.0.0.1 |
仪表盘的绑定地址。本机开发保持默认;只有确需通过 LAN/隧道暴露时才设置为 0.0.0.0。 |
CLINE_HUB_DASHBOARD_PORT |
8787 |
仪表盘 HTTP/WebSocket 端口。源码校验必须为 1–65535 的整数,否则启动即报错。 |
PUBLIC_URL |
http://<HOST>:<PORT>(绑定 0.0.0.0 时回退为 127.0.0.1) |
打印给人打开/复制的 URL,可设为 LAN 地址或隧道地址。 |
ROOM_SECRET |
未设置 | 当 HOST 非本机地址时,浏览器 WebSocket 连接必须携带此共享邀请密钥。 |
WORKSPACE_ROOT |
当前目录 | 传给 hub 的 workspace 根目录。 |
CLINE_PROVIDER |
未设置 | 无最近会话可复用时的 provider id 回退值。 |
CLINE_MODEL |
未设置 | 无最近会话可复用时的 model id 回退值。 |
几个值得注意的实现细节(均在 options.ts):
- PUBLIC_URL 规范化:必须为合法的 http(s) URL;若 URL 是
localhost或 IP 且未显式指定端口,会自动补上仪表盘端口(如http://100.82.5.118变成http://100.82.5.118:8787);协议默认端口(http 80 / https 443)则不重复追加; - 邀请 URL 构造:
buildInviteUrl在设置了ROOM_SECRET时向 PUBLIC_URL 追加?roomSecret=...,浏览器 UI 也支持手动粘贴密钥; - 启动即打印 bind URL 与 public/invite URL(见 printClineHubDashboardServerInfo)。
可以不用真正起服务、只校验选项解析逻辑:
bun run smoke:options
它对应 validate-options.ts,断言了默认值、LAN 场景的解析结果、直连 IP 自动补端口,以及"非本机绑定缺少 ROOM_SECRET""非法端口""非法协议"三种必须抛错的场景。
LAN 共享
选择一个足够强的房间密钥,并显式绑定所有网卡:
cd apps/cline-hub
HOST=0.0.0.0 \
CLINE_HUB_DASHBOARD_PORT=8787 \
PUBLIC_URL=http://YOUR_LAN_IP:8787 \
ROOM_SECRET='use-a-long-random-secret' \
bun run start
把打印出的邀请 URL 分享给同一 LAN 的其它机器。ROOM_SECRET 对 HOST=0.0.0.0 是强制的——缺少它时,仪表盘在 listen 之前就会退出(源码中直接 throw,错误信息会提示改用 HOST=127.0.0.1 或先设置密钥)。
认证是如何生效的
浏览器侧的访问控制实现在 browser-auth.ts:
- 哪些请求需要认证:
requiresBrowserRequestAuth规定所有 WebSocket 升级请求、所有非GET/HEAD/OPTIONS方法,以及所有非公开路由都必须通过认证;公开静态路径(如/health、/version、/config.json、/assets/*等,见 server.ts 的 PUBLIC_BROWSER_PATHS)免认证; - Host/Origin 白名单:允许的 origin 与 host 包括 PUBLIC_URL 的 origin、绑定地址对应的 origin,本地绑定时额外放行
127.0.0.1/localhost/::1; - roomSecret 校验:
isAuthorizedBrowserRequest依次校验Host头、Origin头,最后比对 URL 查询参数中的roomSecret是否与服务端一致。任一环节不通过,请求会被以403 unauthorized_browser拒绝。
隧道共享
在本地以显式密钥启动仪表盘:
cd apps/cline-hub
ROOM_SECRET='use-a-long-random-secret' bun run start
在另一个终端用任意隧道工具暴露本地端口,例如:
ngrok http 8787
然后把隧道地址设为 PUBLIC_URL 重新启动,使打印出的邀请 URL 可直接复制:
PUBLIC_URL=https://YOUR-TUNNEL.example \
ROOM_SECRET='use-a-long-random-secret' \
bun run start
只把打印出的邀请 URL 分享给受信任的参与者。
重启 Hub
点击侧边栏的 Restart Hub,浏览器向服务端发送 restart_hub 帧(协议定义见 webview-protocol.ts),服务端的 restartHub 依次执行:
- 广播 "Hub restarting" 通知并调用
detachHub,把仪表盘的ClineCore与HubUIClient从当前 hub 上摘除(同时拒绝所有挂起的工具审批); stopLocalHubServerGracefully():从 hub discovery 记录中读取当前 hub 的 URL 与 token,向POST /shutdown发起带 Bearer token 的请求,优雅关停本地 detached hub(见 client/index.ts);ensureDetachedHubServer(workspaceRoot):重新拉起一个全新的 hub 守护进程,该函数带启动锁,并在发现旧 hub 无法自动退场时抛出提示运行cline doctor fix的错误(见 daemon/index.ts);- 重连并广播新 hub 状态到所有打开的浏览器标签页,随后广播 "Hub restarted" 通知(附带新的
hubUrl)。
需要注意:运行在旧 hub 上的会话会随 hub 一起停止;其它连到该 hub 的客户端(CLI、VS Code、menubar)会看到连接断开,并在下次请求时重连到新守护进程。
服务端架构速览
仪表盘服务由 startClineHubDashboardServer 启动,基于 Bun.serve 提供 HTTP + WebSocket:
- HTTP 路由:
/version返回 core 版本、/health实时同步并返回 hub 健康状态、/browser升级 WebSocket、/config.json返回浏览器配置(inviteRequired、publicUrl)、/api/marketplace/catalog代理 marketplace 目录,其余路径交给 webview 静态资源(生产构建位于dist/webview,可用CLINE_HUB_WEBVIEW_DIST_DIR覆盖); - 健康轮询:启动后每 5 秒调用
syncHubHealth(向 hub 的 health 端点发请求,见 hub.ts)并广播 hub 状态,保证侧边栏的启动时间、core 版本、uptime 等信息常新; - WebSocket 帧协议:浏览器上行帧包括
ready(初始化对端)、send(发消息)、attachSession、deleteSession、updateSessionMetadata、abort、reset、approval_response、forkSession、restore(按 checkpoint 恢复)、restart_hub,以及 provider 相关的loadModels/saveProviderSettings/runProviderOAuthLogin;下行帧包括assistant_delta、reasoning_delta、tool_event、turn_done(带 token 用量与成本)、approval_request、hub_state等,完整类型定义见 WebviewInboundMessage / WebviewOutboundMessage。
会话驱动的具体行为在 sessions.ts:createSession 会构造 ClineCoreStartInput,其中启用了 checkpoint(checkpoint: { enabled: true })、默认 autoApprove 工具策略、teamName 固定为 cline-hub,并设置 mission log 的采样间隔(每 3 步或 120 秒);sendMessage 在未选中会话时会自动先创建会话;forkPeerSession 读取源会话全部消息后以 initialMessages 方式 start 新会话,并写入 forkedFromSessionId 元数据;restorePeerSession 则调用 ctx.cline.restore 按 checkpointRunCount 恢复消息与 workspace。
安全须知
README 明确指出:这是一个示例仪表盘,不是生产级管理工具。在 LAN 或隧道上暴露它意味着任何持有邀请密钥的人都可以列出你 hub 上的客户端/会话、驱动会话、并重启 hub。建议:
- 使用足够长的随机
ROOM_SECRET; - 只把邀请 URL 分享给受信任的参与者;
- 使用完毕即停止进程;
- 牢记 hub 与 agent 运行时的所有权始终在宿主机器上,仪表盘只是它的远程视图。
小结
apps/cline-hub 展示了如何用 @cline/core 的 ClineCore、HubUIClient、ensureDetachedHubServer 与 stopLocalHubServerGracefully 组合出一个完整的浏览器管理端:启动即发现/拉起本地 hub,通过 5 秒健康轮询与 UI 事件订阅保持多端状态同步,用 Origin/Host 白名单加 roomSecret 查询参数控制远端访问,并提供会话创建、流式聊天、工具审批、fork/checkpoint 恢复与一键重启 hub 的完整闭环。所有配置项、命令与协议在上述文件中均可对照验证,便于在此基础上扩展自己的 hub 管理界面。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00