Cline SDK ClineCore 编程模式详解:从单会话启动到 Hub 多客户端部署
本篇技术指南系统讲解 Cline SDK 中 ClineCore 的十大常用编程模式,覆盖基础会话、流式更新、多轮对话、分级权限、自定义工具、插件加载、会话回放、优雅停机、无状态 Worker 与 Hub 多客户端接入。读完后你可以直接照着文中可复制的示例搭建基于 @cline/sdk 的自动化编码代理应用,并理解每种模式背后在 Cline 仓库源码中的落点。
ClineCore 实例创建与 backendMode 选择
所有模式都从 ClineCore.create() 开始。它是 SDK 的主工厂方法,负责根据选项初始化运行时宿主(local、hub 或 remote)并返回一个可用于启动会话的实例。入口实现位于 ClineCore.ts,类上的 JSDoc 也给出了最小示例:
import { ClineCore } from "@cline/core";
const cline = await ClineCore.create({ clientName: "my-app" });
const session = await cline.start({ ... });
ClineCoreOptions 的完整定义在 cline-core/types.ts,关键字段与语义如下:
| 字段 | 类型 | 说明 |
|---|---|---|
clientName |
string |
客户端标识,用于遥测与日志归因 |
distinctId |
string? |
机器/用户稳定标识,默认使用系统 machine ID,回退为持久化在 ~/.cline/data/machine-id 的 cl-<nanoid> |
backendMode |
"auto" | "local" | "hub" | "remote" |
运行时选择策略,详见下文 |
hub / remote |
HubOptions / RemoteOptions |
对应模式下的连接选项 |
capabilities |
RuntimeCapabilities |
客户端侧交互回调(如工具审批),实现一次、多后端复用 |
toolPolicies |
Record<string, ToolPolicy> |
实例级工具审批策略 |
automation |
boolean | ClineCoreAutomationOptions |
启用后通过 cline.automation.* 访问定时/事件驱动自动化 |
fetch |
typeof fetch |
注入自定义 HTTP 行为(代理、重试、测试桩),仅对本进程内执行的会话生效 |
telemetry / logger / featureFlags |
服务实例 | 省略时分别为 no-op |
prepare |
会话启动前钩子 | 返回可改写会话输入的 StartSessionBootstrap |
backendMode 的四种取值(来自 types.ts 的字段注释):
"auto"(默认)——若存在兼容的本地 hub 则优先使用,否则回退到本进程内执行;"hub"——要求有兼容的 websocket hub 运行时,不可达时抛错;"remote"——要求显式的远端 websocket hub 端点;"local"——总是使用本地进程内执行与本地 SQLite/文件存储。
这个选择在模式 8(无状态 Worker)和模式 10(Hub 多客户端)中会反复出现,是理解整篇指南的前提。
模式一:使用内置工具的基础会话
最小可用场景:创建实例、以 Anthropic 模型启动一次带工具的会话,读取结果并释放资源。
import { ClineCore } from "@cline/sdk"
const cline = await ClineCore.create({ clientName: "my-app" })
const session = await cline.start({
prompt: "Read package.json and summarize the dependencies",
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
apiKey: process.env.ANTHROPIC_API_KEY,
cwd: process.cwd(),
enableTools: true,
},
})
console.log(session.result?.text)
await cline.dispose()
要点拆解:
start()返回StartSessionResult,包含sessionId、manifest、manifestPath、messagesPath,以及可选的result?: AgentResult(完整字段见 api.md);config.cwd决定代理的工作目录,enableTools: true才会挂载内置工具集;AgentResult除了text,还提供usage、toolCalls、iterations、finishReason("completed" | "max_iterations" | "aborted" | "mistake_limit" | "error")、durationMs等,生产代码建议检查finishReason而非只看text是否存在;dispose()会关停运行时宿主、断开连接并清理所有会话与 bootstrap,ClineCore.ts 中的实现会先Promise.allSettled地清理所有活跃 bootstrap 再解绑事件订阅。
模式二:带 UI 更新的流式会话
如果应用需要在会话运行过程中实时渲染输出,用 subscribe() 注册事件监听,而不是等 start() 返回。
const cline = await ClineCore.create({ clientName: "my-app" })
cline.subscribe((event) => {
switch (event.type) {
case "chunk":
if (event.payload.type === "text") {
ui.appendText(event.payload.text)
}
break
case "ended":
ui.showComplete(event.payload.finishReason)
break
}
})
await cline.start({
prompt: "Refactor the auth module",
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
cwd: "/path/to/project",
enableTools: true,
},
})
subscribe(listener, options?) 返回一个取消订阅函数(见 ClineCore.ts),options 可传 { sessionId } 过滤指定会话。CoreSessionEvent 的完整联合类型(同见 api.md):
type CoreSessionEvent =
| { type: "chunk"; payload: SessionChunkEvent }
| { type: "agent_event"; payload: { sessionId: string, event: AgentEvent } }
| { type: "ended"; payload: SessionEndedEvent }
| { type: "team_progress"; payload: SessionTeamProgressEvent }
| { type: "status"; payload: { sessionId: string, status: string } }
| { type: "hook"; payload: SessionToolEvent }
一个容易忽略的细节:ClineCore 构造函数内部本身就订阅了 "ended" 事件,用于在会话结束时自动清理该会话对应的 bootstrap 资源(ClineCore.ts),所以你的业务监听器可以放心只管渲染,不必担心 bootstrap 泄漏。
模式三:多轮会话
会话启动后,用 send({ sessionId, prompt }) 在同一会话上继续对话。send 在源码中直接转发到运行时的 runTurn(ClineCore.ts),返回 AgentResult | undefined。
const cline = await ClineCore.create({ clientName: "my-app" })
const session = await cline.start({
prompt: "Create a new Express server",
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
cwd: "/path/to/project",
enableTools: true,
},
})
// Follow-up
const result = await cline.send({
sessionId: session.sessionId,
prompt: "Now add a health check endpoint",
})
console.log(result?.text)
await cline.dispose()
多轮语义的关键是复用 session.sessionId:后续每轮共享同一份消息历史与工作目录上下文。若需要中途打断,还可以用 abort(sessionId)(中止当前工具执行但保留会话)与 stop(sessionId)(彻底结束会话,二者区别见 ClineCore.ts 的 JSDoc 与 api.md)。
模式四:分级权限模型(Tiered Permission Model)
这是生产环境最实用的模式:读类操作自动放行,写类操作必须经人确认。做法是两层配合——实例级的 toolPolicies 声明"哪些工具自动批准",capabilities.requestToolApproval 处理"没被自动批准的请求"。
const cline = await ClineCore.create({
clientName: "my-app",
toolPolicies: {
read_files: { autoApprove: true },
search: { autoApprove: true },
fetch_web: { autoApprove: true },
bash: { autoApprove: false },
editor: { autoApprove: false },
apply_patch: { autoApprove: false },
},
capabilities: {
requestToolApproval: async (request) => {
const approved = await promptUser(
`Allow ${request.toolName}?\n${JSON.stringify(request.input, null, 2)}`
)
return { approved }
},
},
})
ToolPolicy 只有两个开关(见 api.md):
interface ToolPolicy {
enabled?: boolean // false = 工具对模型完全隐藏
autoApprove?: boolean // false = 必须走审批回调
}
即策略空间是三维的:enabled: false(模型根本看不到该工具)、autoApprove: true(静默执行)、autoApprove: false(执行前调用 requestToolApproval)。工具策略还可以下放到单次会话,start() 的入参本身就支持 toolPolicies 与 capabilities 字段,可覆盖实例级设置。
一个源码层面的注意点:内置工具名常量定义在 constants.ts,包括 read_files、search_codebase、run_commands、fetch_web_content、apply_patch、editor、skills、ask_question、submit_and_exit。从源码结构看,示例中出现的 bash、search、fetch_web 等键名与常量表中的 run_commands、search_codebase、fetch_web_content 并不完全一致;编写真实策略时,建议以运行时实际注册的工具名为准,或先用 cline.settings.list() 查看当前生效的工具清单(api.md 的 Settings API 一节),避免把策略打到不存在的工具名上。此外 presets.ts 中提供了 "yolo" 预设,用 * 通配全部工具并设为 autoApprove: true,适合受控沙箱场景。
模式五:自定义工具与内置工具并存
用 createTool 定义应用专属工具(如部署、工单系统对接),通过 config.tools 与内置工具一起注入。createTool 的完整签名在 tools/create.ts:
export function createTool<TInput, TOutput>(config: {
name: string;
description: string;
inputSchema: Record<string, unknown> | z.ZodTypeAny; // Zod 或原始 JSON Schema
execute: (input: TInput, context: AgentToolContext) => Promise<TOutput>;
lifecycle?: AgentTool<TInput, TOutput>["lifecycle"];
timeoutMs?: number;
retryable?: boolean;
maxRetries?: number;
}): AgentTool<TInput, TOutput>
Zod schema 会在内部通过 zodToJsonSchema 转换后注册给模型(create.ts),所以推荐直接用 Zod 获得类型推导。完整示例:
import { ClineCore, createTool } from "@cline/sdk"
import { z } from "zod"
const deployTool = createTool({
name: "deploy",
description: "Deploy the application to the specified environment.",
inputSchema: z.object({
environment: z.enum(["staging", "production"]),
}),
execute: async (input) => {
const result = await runDeployment(input.environment)
return { url: result.url, status: "deployed" }
},
})
const cline = await ClineCore.create({ clientName: "my-app" })
await cline.start({
prompt: "Deploy the app to staging",
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
cwd: process.cwd(),
enableTools: true,
tools: [deployTool],
},
})
注意 enableTools 与 tools 互不排斥:前者控制内置工具集,后者追加自定义工具,二者可以并存——这正是该模式标题的含义。对耗时操作,记得利用 timeoutMs 与 retryable/maxRetries 防止工具卡死整个会话。
模式六:带插件的会话
插件有两种加载方式:extensions 直接传入插件对象,pluginPaths 指向目录形式的插件包。同时必须提供 extensionContext.workspace,插件的 setup() 才能拿到 ctx.workspaceInfo——不提供时 ctx.workspaceInfo 为 undefined(见 api.md 对 CoreSessionConfig 的说明)。
import { ClineCore } from "@cline/sdk"
import myPlugin from "./my-plugin"
const cline = await ClineCore.create({
clientName: "my-app",
backendMode: "local",
})
await cline.start({
prompt: "Do the thing my plugin enables",
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
cwd: process.cwd(),
enableTools: true,
extensions: [myPlugin],
extensionContext: {
workspace: { rootPath: process.cwd(), cwd: process.cwd() },
},
},
})
await cline.dispose()
目录形式的插件包改用 pluginPaths:
config: {
pluginPaths: ["./my-cline-plugin"],
extensionContext: {
workspace: { rootPath: process.cwd(), cwd: process.cwd() },
},
}
pluginPaths 指向的目录需要在 package.json 中声明 cline.plugins 字段。CoreSessionConfig 还提供 extensionLoading?: "isolated" | "direct" 控制插件的执行隔离方式,以及 enableSpawnAgent、enableAgentTeams、teamName 等与子代理/团队协调相关的开关。完整的插件编写指南见 plugins/REFERENCE.md。
模式七:会话列表与回放
本地模式的会话持久化在 SQLite/文件中,实例提供了完整的查询、回放与用量统计接口。
const cline = await ClineCore.create({ clientName: "my-app" })
// List recent sessions
const sessions = await cline.list(10)
for (const session of sessions) {
console.log(`${session.id}: ${session.title}`)
}
// Read messages from a past session
const messages = await cline.readMessages(sessions[0].id)
for (const msg of messages) {
console.log(`[${msg.role}] ${msg.content}`)
}
// Check usage
const usage = await cline.getAccumulatedUsage(sessions[0].id)
console.log(`Total tokens: ${usage.aggregateUsage.totalInputTokens + usage.aggregateUsage.totalOutputTokens}`)
源码层面的补充(ClineCore.ts):
list(limit = 200, options?)默认最多返回 200 条历史记录,支持额外过滤参数;readMessages读取的是规范化消息历史,是 resume、fork 与 compaction 使用的模型表示;若要在 UI 中展示含"观测型模型工具活动"的完整转录,应改用readDisplayMessages;如果会话仍在内存中驻留且需要包含尚未落盘的最新一轮,用readLiveMessages——持久化转录只在助手消息/轮次边界追赶落盘,readMessages可能漏掉进行中的轮次;getAccumulatedUsage返回两个口径:usage只含根/主代理,aggregateUsage额外包含队友与子代理,计费与配额展示时不要混用;- 同一实例上还有
update(改元数据)、delete(彻底删除,不可逆)、restore(从 checkpoint 分叉恢复,输入含checkpointRunCount与可选的start)等会话管理方法,对应 api.md 的 Session Management 一节。
模式八:优雅停机
长驻进程(守护、队列消费者、API 服务)应在收到终止信号时主动 dispose 并传入原因,让运行时把进行中的状态收尾,而不是被信号直接杀掉:
const cline = await ClineCore.create({ clientName: "my-app" })
process.on("SIGTERM", async () => {
await cline.dispose("SIGTERM received")
process.exit(0)
})
// Run sessions...
dispose(reason?) 会关闭运行时宿主、断开连接并清理所有活跃会话与 bootstrap;调用后实例不可复用(ClineCore.ts)。如果启用了 automation,dispose 会先清理内部的 CronService 再交给宿主。
模式九:无状态 Worker 模式
面向请求/响应型负载(API 端点、队列消费者):一个长生命周期的 ClineCore 实例 + 每请求一个新会话,是简单且隔离性好的组合。
import { ClineCore } from "@cline/sdk"
const cline = await ClineCore.create({
clientName: "worker",
backendMode: "local",
})
async function handleRequest(prompt: string, workspace: string) {
const session = await cline.start({
prompt,
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
cwd: workspace,
enableTools: true,
},
})
return {
text: session.result?.text,
usage: session.result?.usage,
sessionId: session.sessionId,
}
}
设计要点:
ClineCore实例只创建一次(初始化成本在create阶段,会话创建远比实例创建轻);- 每次请求返回
sessionId,为事后审计、回放(模式七)与恢复保留句柄; usage回传便于按请求计费/限流;- 由于
backendMode: "local",会话数据落在本机 SQLite/文件存储,无需额外部署 hub 组件。
模式十:Hub 后端的多客户端接入
当需要"多个客户端挂在同一个会话上"(例如后端进程跑长任务、前端面板实时观察),把 backendMode 切到 "hub" 即可。
// Process 1: start session
const cline = await ClineCore.create({
clientName: "backend",
backendMode: "hub",
})
const session = await cline.start({
prompt: "Long running refactor task",
config: { ... },
})
// Process 2: attach and stream events
const viewer = await ClineCore.create({
clientName: "dashboard",
backendMode: "hub",
})
viewer.subscribe((event) => {
dashboard.render(event)
}, { sessionId: session.sessionId })
这背后是 Cline 的 Hub-Spoke 架构(完整讲解见 hub-spoke.mdx):
- Hub 是每台机器单例的守护进程,负责会话协调、事件路由与审批转发,自身不跑 agent 循环;
- Spoke 是 worker 进程,执行 agent 循环、调用工具、流式输出,并把事件汇报给 hub;
- Client(CLI、IDE 或任意自定义应用)经 WebSocket 注册后附着到会话,发送输入、接收事件流;
- 客户端来去不会打断执行:进程 1 退出后 spoke 继续运行,进程 2(dashboard)通过
subscribe(..., { sessionId })在中途接管事件流。
从源码结构看,hub 的发现基于 ~/.cline/locks/hub/owners/ 下的锁文件;"auto" 模式下 ClineCore 会在没有 hub 时自动启动它,因此模式一~九的示例代码在开发机上往往已经隐式受益于这一机制,只有明确要求多进程共享时才需要显式 backendMode: "hub"。
模式选型速查
| 场景 | 模式 | 关键 API |
|---|---|---|
| 一次性脚本/CI 任务 | 模式一 | start → session.result |
| 带实时 UI 的桌面/TUI 应用 | 模式二 | subscribe + chunk/ended 事件 |
| 对话式产品 | 模式三 | send({ sessionId, prompt }) |
| 生产环境、需人机边界 | 模式四 | toolPolicies + requestToolApproval |
| 接入内部系统(部署、工单) | 模式五 | createTool + config.tools |
| 复用 Cline 插件生态 | 模式六 | extensions / pluginPaths + extensionContext |
| 审计、回放、计费 | 模式七 | list / readMessages / getAccumulatedUsage |
| 常驻服务 | 模式八 | dispose(reason) + 信号处理 |
| API/队列负载 | 模式九 | 单实例 + 每请求新会话 |
| 多端观察/接管同一会话 | 模式十 | backendMode: "hub" + subscribe({ sessionId }) |
延伸阅读
以上模式均出自 clinecore/patterns.md,配套资料:
- api.md —— 完整 API 参考(
ClineCoreOptions、CoreSessionConfig、AgentResult、Settings/Automation API); - gotchas.md —— 常见陷阱;
- tools/REFERENCE.md —— 工具创建指南;
- plugins/REFERENCE.md —— 插件系统完整指南;
- scheduling/REFERENCE.md —— 定时代理;
- 核心实现:ClineCore.ts、cline-core/types.ts、extensions/tools/constants.ts、shared/tools/create.ts。
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