分析对象:cline(
github.com/cline/cline),Apache-2.0,本分析基于 main 分支 2026-08 检出。仓库无统一版本号:apps/cli为 v3.0.49(下文提到的 v3.0.49 均指 CLI),apps/vscode(包名claude-dev)为 4.1.3,sdk/packages/*(shared/llms/agents/core)同为 0.0.69,根package.json(@cline/packages)不带 version。 代码规模:稀疏检出核心 27MB / 1749 个.ts+ 67 个.tsx= 1816 个 TS 源文件。@cline/core引擎约 14 万行,@cline/llms约 11.9 万行(含 8.7 万行自动生成的模型目录),VS Code 扩展约 12.8 万行,CLI 约 7.1 万行。 一句话定位:曾经的"VS Code 插件 Agent",如今重构为引擎(SDK)与界面(CLI/VS Code 扩展)分离的 monorepo——核心是一个进程内、可嵌入、无状态循环的AgentRuntime,外面套三层:会话编排、宿主驱动、应用界面。它和 Claude Code 共享"模型→工具→再模型"的主循环,但用显式而扁平的声明式工具目录 + per-model 路由取代了 Claude Code 的"连续前缀缓存排序"。 读者对象:已经读过本系列至少一份分析的读者。本文沿用统一框架,标注文件:行号,可回源码核对。
目录
- 项目概览:从 VS Code 插件到"引擎 + 界面" monorepo
- 全景架构:五层栈 + 三条宿主 + 一条事件链
- 启动流程:CLI / VS Code / hub daemon 三个入口
- 输入捕获与分流:交互、headless、steering 打断、pending prompt
- 上下文组装:MessageBuilder 的 API 安全整形
- Agent 主循环(心脏):AgentRuntime 的无状态 while loop
- 工具系统与审批:28 个工具 + 五套 preset + 桌面审批 IPC
- 安全护栏:loop-detection、mistake-tracker、subprocess-sandbox
- 会话、checkpoint 与版本化:git 快照回滚
- 上下文压缩:basic 确定性折叠 vs agentic LLM 摘要
- Provider 层:Vercel AI SDK + 约 180 Provider ID + 4118 个模型
- 生态:插件、MCP、hooks、多 agent 团队、cron、connectors、hub
- 存储:JSON 文件 + SQLite 混合
- 横向对比:与 Claude Code / opencode / CodePilot / pi / OpenWorker
- 总结:三个最独特的设计与取舍
第 1 章 项目概览:从 VS Code 插件到"引擎 + 界面" monorepo
Cline 是什么? 用 README 第一句话说:The open source coding agent in your IDE and terminal。它在 VS Code 侧边栏里住着(曾经的定位),如今也能在终端跑(CLI),甚至能 headless 跑在 CI/CD 里。核心能力:
- 跨项目编辑:读项目结构、理解文件关系、做协调一致的多文件修改,边做边盯 linter/编译器错误(
README.md)。 - Plan / Act 双模式:Plan 模式只探索、只提问、出方案;Act 模式执行,每个文件编辑和终端命令默认要审批(可 auto-approve)。
- 28 个内置工具(9 默认 + spawn_agent + 18 个 team_*),支持 MCP、插件、技能(skills)、
.clinerules规则。 - 约 180 个可注册 Provider ID / 4118 个模型:Anthropic/OpenAI/Gemini/OpenRouter/Bedrock/Vertex/Ollama/LM Studio/任何 OpenAI 兼容端点(
ids.ts无 Azure 独立枚举项)。 - 多 agent 团队:coordinator 拆任务 → 委派 specialist(
cline --team-name ...)。 - 定时自动化(
cline schedule create --cron ...)、IM 接入(cline connect telegram/slack/discord/...)、hub 本地协作中心。
它和 Claude Code 的关系:Claude Code 是终端里的编程 Agent(Ink TUI),Cline 现在也做终端(OpenTUI),但根子仍在 IDE 插件。两个项目的架构哲学分叉得很清楚:Claude Code 是单体(一个包,工具前缀缓存排序、命令式 driver);Cline 重构后是分层可嵌入引擎(agents 无状态循环 / core 有状态编排 / 界面层可插拔)。
它和 open-design 的关系:open-design 是"不写 Agent 主循环的宿主";Cline 恰恰相反——主循环本身(AgentRuntime)被提炼成库,宿主(CLI/VS Code)都只是它的驱动者。
数字化的项目形状
| 维度 | 数字 | 说明 |
|---|---|---|
| 包 | 6 个 SDK 包 + 2 应用 | shared/llms/agents/core/sdk/ui + apps/cli + apps/vscode |
| 依赖方向 | 单向 | shared ← llms ← agents ← core ← 应用(sdk/ARCHITECTURE.md) |
| 主循环 | agent-runtime.ts 1969 行 | AgentRuntime.execute() 显式 while loop(L641) |
| 工具 | 28 个内置 | 9 默认 + 1 spawn_agent + 18 team_* |
| Provider | 约 179 唯一 ID | BUILT_IN_PROVIDER 枚举约 50 + models.dev 生成 163(重叠去重后约 179,不是 48+163=211) |
| 模型目录 | catalog.generated.ts 87274 行 | 4118 个模型,含 contextWindow/pricing |
| 存储 | JSON + SQLite 混合 | sessions.db / cron.db / connectors.db / secrets.json |
| 许可 | Apache-2.0 | 商业友好 |
第 2 章 全景架构:五层栈 + 三条宿主 + 一条事件链
官方 sdk/ARCHITECTURE.md 画的分层图(单向依赖,不允许反向):
flowchart LR
SH["@cline/shared
低层契约:storage/llms/db/cron/hooks/tools"] --> LL["@cline/llms
Provider 运行时:AI SDK 适配 + 模型目录"]
LL --> AG["@cline/agents
无状态主循环:AgentRuntime"]
AG --> CO["@cline/core
有状态编排:会话/存储/hub/插件/compaction"]
CO --> APPS["宿主应用:CLI · VS Code 扩展 · hub"]
五层栈(自下而上):
- shared(20553 行)——纯契约层。路径解析(
~/.cline/data)、estimateRequestInputTokens(3 chars/token 保守估算)、SQLite connector-store、事件枚举、工具类型、hook 事件。 - llms(118772 行)——Provider 层。基于 Vercel AI SDK(
ai@7+@ai-sdk/*) 的适配;catalog.generated.ts(87274 行)是 build:models 自动生成的模型目录;gateway 做统一 usage/流式归一化。 - agents(4635 行)——无状态 Agent 循环。
AgentRuntime(agent-runtime.ts:1969)是唯一核心:execute()显式 while loop。禁止持有持久化、宿主生命周期。 - core(140027 行)——有状态编排。
SessionRuntime(会话门面)、LocalRuntimeHost(宿主)、MessageBuilder(API 整形)、compaction、plugin、cron、connectors、hub。 - 应用层——CLI(OpenTUI + commander)、VS Code 扩展(单 WebView React)、hub daemon(WebSocket 协作中心)。
三条宿主(RuntimeHost)(core/src/runtime/host/host.ts):LocalRuntimeHost(进程内)、HubRuntimeHost(连本地 hub 服务器,跨进程共享)、RemoteRuntimeHost(远程)。createRuntimeHost()(host.ts:137)在 auto 模式下自动发现 hub 并降级 local——同一引擎可以三种方式被驱动。
贯穿全栈的一条事件链:
AgentRuntime 的 while loop 每步发出 AgentRuntimeEvent
→ SessionRuntime.handleRuntimeEvent(core/src/runtime/orchestration/session-runtime-orchestrator.ts:1061)
→ RuntimeEventAdapter.translate(runtime-event-adapter.ts:183,14 种新事件(含 `run-failed`)→ 9 种 legacy AgentEvent)
→ AgentEventBridge → CoreSessionEvent
→ UI(CLI TUI / VS Code webview)消费
🧠 一句话:把"会转的循环"(agents,无状态)和"记得住状态的编排"(core,有状态)硬拆成两个包,是 Cline 重构后的根架构决策——这让同一个循环引擎能被 CLI、VS Code、hub 三种宿主反复驱动,而循环本身不知道宿主是谁。
第 3 章 启动流程:CLI / VS Code / hub daemon 三个入口
入口一:CLI(apps/cli/src/index.ts,94 行)
#!/usr/bin/env bun,package.json bin: { cline: "src/index.ts" }。index.ts 做进程分支决策(worker / hub daemon / connector 进程),转发 SIGINT 到 active-runtime,然后动态 import("./main") 的 runCli()(src/main.ts,1197 行)。框架是 commander v14 + @clack/prompts(wizard 交互)+ OpenTUI(@opentui/core + @opentui/react + react-reconciler + react 19)。
命令全部注册在 main.ts:auth、config、plugin、skill、connect、mcp、doctor、hook、schedule、hub、dashboard、history、team + 默认 chat。共享根选项在 commands/program.ts(--plan、--json、--auto-approve、-c --cwd、-P --provider、-k --key、-z --zen、--config)。
和 core 的集成:session/session.ts 的 createCliCore() → ClineCore.create()(来自 @cline/core)。默认 backendMode 连 hub(传 hub: {clientType: "cli"}),forceLocalBackend 可进程内直跑。
入口二:VS Code 扩展(apps/vscode/src/extension.ts,753 行)
activate(L66)顺序:① setupHostProvider(必须最先)→ ② legacy 存储迁移 → ③ exportVSCodeStorageToSharedFiles 统一到 ~/.cline/data/(与 CLI/JetBrains 共享)→ ④ initialize 创建 VscodeWebviewProvider → ⑤ 注册 commands。
和 core 的连接是进程内直接 import:extension.ts 与 SdkController.ts(2110 行)直接 import @cline/core,引擎跑在扩展宿主进程里。hosts/vscode/hostbridge/(gRPC)只是宿主能力桥(diff/terminal/workspace),不承载 core。整个 Cline UI 是单个 WebView 内的 React 应用(claude-dev.SidebarProvider,activitybar 容器)。
入口三:hub daemon(apps/cli/src/commands/hub.ts → daemon/entry.ts)
独立守护进程,本地 WebSocket 服务器(core/src/hub/server/hub-websocket-server.ts,ws 库,协议版本协商)。connectors、cron schedule、UI 都是 hub 客户端——实现跨进程共享会话/审批/通知。
鉴权与数据
登录走 WorkOS Device Flow + OAuth(auth/cline.ts,api.workos.com/user_management/*),本地 OAuth server 回调端口 48801-48811;Provider 密钥存 ~/.cline/data/secrets.json(chmod 0o600)。
第 4 章 输入捕获与分流:交互、headless、steering 打断、pending prompt
Cline 的"输入"来源比终端 Agent 多:交互输入框、piped stdin(headless)、运行中 steering 打断、pending prompt 队列、IM 连接器(Slack/Telegram…)、cron 定时、团队委派。分流机制:
① 交互模式:apps/cli/src/runtime/run-interactive.ts 起 TUI,用户输入 → session.send() → host runTurn()。
② headless 模式(main.ts ~944 行判定):--json || (!stdin.isTTY && !interactive)。runtime/run-agent.ts(425 行)是单发执行器;--json 输出 NDJSON(每行一个 JSON 事件:run_start/run_abort_requested/message/error…,由 utils/output.ts 的 emitJsonLine 逐行写 stdout)——CI 可逐行消费并以退出码收尾。--zen 更进一步:任务 fire-and-forget 给后台 hub daemon,CLI 立即退出。
③ steering 打断(运行中插话)(core/src/runtime/turn-queue/pending-prompt-service.ts:372-379):PendingPromptService(L54)纯队列——enqueue 按 prompt 去重、steer 插队到头部;PendingPromptsController(L207)在 agent.canStartRun() 时 scheduleDrain()(L281)派发 drain()(L295)串行发 turn。steer 通道:consumePendingUserMessage(host L695)被 AgentRuntime.generateAssistantMessage 在 iteration>1 时消费(agent-runtime.ts:968-979)——运行中打断注入。
对比:OpenWorker 的收件箱是持久异步邮箱;CodePilot 的 turn-lock 直接拒绝并发。Cline 是进程内会话队列 + 可 steering——既允许排队,又允许实时打断,且不影响正在跑的循环(steering 在下一次迭代被消费)。
④ IM 连接器(apps/cli/src/connectors/):slack / discord / telegram / gchat / whatsapp / linear 六平台,每平台独立 adapter 进程,注册到 hub,经 HubRuntimeHost 执行会话。
第 5 章 上下文组装:MessageBuilder 的 API 安全整形
MessageBuilder(core/src/session/services/message-builder.ts,1727 行,L108)是"会话消息 → provider API 请求"的整形器,入口 buildForApi(messages)(L166)。它做的事比想象的多:
① 增量 reindex(L278):tail 引用比对,命中则只索引新增部分,否则全量重建。② commitOutdatedRewrites(L336):读过的文件后来被改,把旧内容批量替换为 [outdated - see the latest file content];超过 minOutdatedRewriteBytes(默认 64KB)才一次性提交——避免频繁破坏 provider 前缀缓存。③ addMissingToolResults(L502):中断场景给孤儿 tool_call 补 is_error: true 的伪结果。④ 逐 block 截断:assistant 文本 12K(重复工具 markup)/200K(普通)、file 块 50K、tool_result 8K(保留首尾)、嵌套字符串深截断。⑤ applyMediaBudget(L1332):图片按字节预算限流,超限替换 IMAGE_OMITTED_PLACEHOLDER。⑥ truncateToTotalTextBudget(L1162):全局 6MB 字节兜底。
系统提示(不在 MessageBuilder 内):由会话编排层 session-runtime-orchestrator.ts 的 composeSystemPrompt()(约 L679)= config.systemPrompt(buildClineSystemPrompt 拼 IDE/工作区元数据/rules/mode 等段)+ 插件规则 mergeSystemPromptRules(约 L102)。工具定义由 orchestrator 单独传给 provider,不塞进消息数组。
🧠 一句话:MessageBuilder 的所有设计都围绕一个目标——保住 provider 前缀缓存:增量索引、outdated 批量重写、截断顺序、6MB 兜底,全是"少动 transcript 中部"的工程化体现。这比 Claude Code 的"内置工具排连续前缀"更通用(Cline 面向约 180 个可注册 Provider ID / 4118 模型,不能赌每个 provider 都做前缀缓存)。
第 6 章 Agent 主循环(心脏):AgentRuntime 的无状态 while loop
主循环在 @cline/agents 包的 agent-runtime.ts(1969 行),不在 core。AgentRuntime/Agent 是同一类的两个名字(stateless loop)。核心 execute()(L641,循环体 L677-789):
flowchart TD
START["execute()
emit run-started"] --> TURN["while 循环
emit turn-started"]
TURN --> GEN["generateAssistantMessageWithOverflowRecovery()
(L876,for await 消费 model.stream 流式事件)"]
GEN --> TOOL{"模型要工具?"}
TOOL -->|否| STEER{"steering 打断?"}
STEER -->|有| CONSUME["consumePendingUserMessage
(iteration>1 时,agent-runtime.ts:968)"] --> TURN
STEER -->|没有| DONE["finishRun(completed)"]
TOOL -->|要| EXEC["executeToolCalls()
(L1455,sequential/parallel)"]
EXEC --> WRITE["写回 tool_result 消息"] --> TURN
TOOL -->|terminal 完成工具
(submit_and_exit)| FINISH["finishRun(completed)"]
每个 turn = 一次 generateAssistantMessageWithOverflowRecovery() + 若干 executeToolCalls()。无 tool-call 或命中 submit_and_exit(lifecycle.completesRun: true)即完成。
与 Claude Code 的本质区别:
- 循环被封装为可复用类,会话层反复重入。Claude Code 是一个长驻的 while-loop driver;Cline 每次 run 都
new AgentRuntime(),会话层把每条用户消息当一次独立 run,用全量转录播种(initialMessages)后runtime.run("")——多轮 = 反复重入循环,而非单对象长驻。 - 循环内部同步,外部全事件化。所有进展经
AgentRuntimeEvent订阅流出——这是"双层架构"的关键:引擎不知道谁在听。 - prepare-turn 投影 seam:core 把 compaction 策略作为 prepareTurn 注入(agent-runtime 提供 seam,
@cline/agents保持无状态)。
config:判别联合(WithModel/WithProvider);createAgentRuntimeConfig(core/src/runtime/config,纯函数);agent-message-codec 做 AgentMessage↔Message 编解码。
第 7 章 工具系统与审批:28 个工具 + 五套 preset + 桌面审批 IPC
工具清单(28 个)
extensions/tools/constants.ts 的 ALL_DEFAULT_TOOL_NAMES(9 个):read_files、search_codebase、run_commands、fetch_web_content、apply_patch、editor、skills、ask_question、submit_and_exit(工厂在 definitions.ts L247/343/457/518/611/660/723/780/801)。另有 spawn_agent(team/spawn-agent-tool.ts)和 18 个 team_* 工具(team-tools.ts:195)。
对比 Claude Code 的 40 个:少了 WebSearch/Glob/TodoWrite/NotebookEdit/Task 等(web 搜索退化为仅 fetch_web_content,glob 靠 search_codebase+run_commands);多了 ask_question(交互提问)、submit_and_exit(无头结束运行)、skills(技能调用)、spawn_agent 与全套 team_* 多智能体工具。
编辑双雄:editor vs apply_patch
Cline 把编辑拆成两个互斥工具(definitions.ts:917 同一时刻只启用其一):
- editor(最接近 Claude Code 的 Edit):
old_text→new_text字面替换、insert_line行插入或建文件,单文件精确编辑。 - apply_patch:aider 风格自由格式补丁(
*** Begin Patch / *** Update File / +- 上下文行 / Add/Delete/Move),无行号、基于上下文匹配,一次调用批量编辑多文件(executors/apply-patch.ts+apply-patch-parser.ts)。
审批链路(tool-approval.ts,102 行)
流程:模型发出工具调用 → SessionRuntime 按 toolPolicies 合并全局 * 与工具级策略(session-runtime-orchestrator.ts:117-133)判 enabled → beforeTool 钩子(含循环检测)→ 若 autoApprove !== true 且宿主提供 requestToolApproval 能力 → 审批 → 执行 → afterTool。
requestDesktopToolApproval(tool-approval.ts:29)是桌面 IPC 实现:向 approvalDir 写 <sessionId>.request.<id>.json,每 200ms 轮询 decision 文件,5 分钟超时——一种"文件即 IPC"的朴素但可靠机制。ToolPolicy = {enabled?, autoApprove?}(sdk/packages/shared/src/llms/tools.ts:7),默认 enabled + autoApprove。
五套 preset(presets.ts)
act / plan / search / minimal / yolo。分级通过 ToolPolicyPresetName = "default"|"yolo"(presets.ts:137)实现——yolo 对 * 及全部默认工具 autoApprove: true。
工具注册:扁平声明式目录 vs 连续前缀
Claude Code 用 trie 做连续前缀匹配缓存。Cline 相反:runtime.ts 的 BASE_TOOL_CATALOG(9 条:工具 id/描述/headlessToolNames)→ 经 preset + model-tool-routing(按 provider/model 禁用工具的规则)+ disabledToolIds 解析出启用集合(getCoreBuiltinToolCatalog/resolveCoreSelectedToolIds,206-245 行)→ createDefaultTools 按"开关 flag && 有 executor"实例化 AgentTool[](createTool 封装 name/description/inputSchema/execute/timeoutMs/retryable/maxRetries/lifecycle,sdk/packages/shared/src/tools/create.ts:81)。模型请求端是普通 JSON Schema 数组,无前缀排序——替代方案是 per-model 路由规则显式决定哪些工具可见。
第 8 章 安全护栏:loop-detection、mistake-tracker、subprocess-sandbox
死循环检测(runtime/safety/loop-detection.ts,162 行)
toolCallSignature 对 input 做排序键 JSON 序列化(L50);checkRepeatedToolCall 统计连续相同"工具名+签名"次数,soft=3 / hard=5(L113)。LoopDetectionTracker.inspect(L136)返回 ok/soft/hard 三档;SessionRuntime 中 soft→往对话注入"换种方式"提示,hard→以 forceAtLimit: true 喂给 MistakeTracker 并中止运行(orchestrator:1244-1273)。
MistakeTracker(runtime/safety/mistake-tracker.ts,229 行)
三种原因:api_error / invalid_tool_call / tool_execution_failed。record() 累加 consecutiveMistakes,达上限经 onLimitReached 回调决策(默认 stop);continue 则清零并附加恢复指引;stop 则写停止信息并 activeRuntime.abort()。所有 record 经 activeTrackerWork Promise 链串行化保证顺序。
SubprocessSandbox(runtime/tools/subprocess-sandbox.ts,346 行)
解决"插件/浏览器沙箱代码在主进程跑不安全、不可控":spawn node/bun 子进程走 IPC,父进程发 {type:"call"}、子进程回 {type:"response"|"event"};call 超时则 SIGTERM→SIGKILL 强杀(210-274 行);resolveSubprocessRuntimeExecutable(L73)解析 node/bun 运行时。崩溃隔离 + 超时强制 + 事件转发。
规则系统(.clinerules,runtime/safety/rules.ts,49 行)
从 UserInstructionConfigWatcher 取快照,过滤 disabled、按名字排序,渲染为 ## 名称\n指令,拼到 system prompt 的 # Rules 段。
第 9 章 会话、checkpoint 与版本化:git 快照回滚
会话数据模型(session/models + stores)
- 索引:
sessions.index.json(file-session-service.ts L50)——{version:1, sessions: {sessionId: SessionRow}}单文件全量 JSON,atomicWriteJson 临时文件+rename 原子替换,statusLock乐观并发(CAS)。 - manifest:
sessions/<id>/session.json——会话元数据(Zod 校验)。 - 消息:
sessions/<id>/<id>.json——{version:1, updated_at, agent, sessionId, messages[], system_prompt}(session-data.ts L304)整体重写(非追加)。 SessionPersistenceAdapter抽象存储层,默认文件实现;hub/remote 可换。
checkpoint(git 实现!)
checkpoint-diff.ts(150 行):compareCheckpointToWorkspace(L142)→ listChangedPaths(L76)用 git diff --name-only -z <ref> + git ls-files --others 找变更文件,逐个对比产出 CheckpointContentDiff[]。有路径逃逸防护(L44)。
checkpoint-restore.ts(413 行):
- readSessionCheckpointHistory(L156):从 metadata 解析 {ref, createdAt, runCount, kind} 历史。
- findCheckpointForRun(L202):runCount 之前最近一个 checkpoint。
- trimMessagesToCheckpoint(L245):用 getUserRunSpan 定位第 runCount 次用户回合,截断消息。
- beginWorktreeRestoreTransaction(L50):回滚前用 git stash push --include-untracked 快照当前工作区,对象转移到私有 ref refs/cline/restore-transactions/<uuid>——commit 时删 ref、rollback 时 reset --hard + clean -fd + stash apply --index 还原。
- applyCheckpointToWorktree(L357):区分 stash 与普通 commit 的 reset 路径;仅当快照含第三个父提交(<ref>^3,捕获了 untracked)才 clean -fd,避免不可恢复删除。
存什么:工作区完整快照存成 git commit/stash(含 untracked 时三父提交),会话消息本身不存(靠截断保留)。怎么回滚:SessionVersioningService.restoreCheckpoint(session-versioning-service.ts:134)编排全流程:验证 → 恢复计划 → 事务快照 → apply → 以截断消息启动新会话 → commit 事务;失败则 rollback 工作区 + 清理新会话。
🧠 一句话:checkpoint 直接复用 git 对象库做"可回滚的工作区快照",且把回滚本身做成可回滚的事务(先 stash 再动)——这是 Cline 最优雅的工程之一。
第 10 章 上下文压缩:basic 确定性折叠 vs agentic LLM 摘要
触发(extensions/context/compaction.ts,710 行):createContextCompactionPrepareTurn(L256)每次模型请求前估算 requestInputTokens,trigger = maxInputTokens * 0.9(COMPACTION_TRIGGER_RATIO)——90% 阈值,比 Claude Code 的 microcompact 激进得多。三种 mode:auto / manual(用户 /compact)/ overflow_recovery(provider 拒绝后的强制恢复)。
basic(basic-compaction.ts,711 行,L452):不调 LLM。typed 用户提示必保留;最新回合保留"最新消息 + 符合预算的后缀"(对齐 assistant 边界不断开工具对);旧回合保留各自最终 assistant 答复(最近 3 条原文);其余丢弃,折叠进相邻用户消息的 <SYSTEM_NOTICE> dropped-work 摘要;冻结上次压缩产物(compaction: preserved)不重复折叠。确定性、零成本,用于 overflow 恢复兜底。
agentic(agentic-compaction.ts,283 行,L97):调用 summarize 模型(默认当前 provider)。findCutIndex 按 preserveRecentTokens(默认 20K)切分,旧段序列化发给 LLM 生成 "continuation note",替换为一条 metadata.kind=compaction_summary 的用户消息,userRunSpan=被折叠回合数;已有 summary 则只折叠其后的新消息(增量)。失败自动回退 basic(L518)。
状态持久化(createCompactionStateAwarePrepareTurn,L643):每次压缩后把 {compacted messages, source_prefix_hash(sha256), source_message_count, system_prompt} 存入侧车(session-compaction.ts),下一轮 projectSessionCompactionState(L161)校验前缀哈希匹配后 = 压缩产物 + 新消息尾部,避免每轮全量重建。
与 Claude Code microcompact 对比:Cline 触发阈值高(0.9× vs microcompact 约 0.5-0.6× 即时压缩);agentic 每次一次完整 LLM 摘要(成本高但信息保留好),basic 零成本;Claude Code 的 microcompact 是轻量即时小压缩,Cline 更接近"检查点 + 全文摘要 + 可回滚"的宏观设计。
第 11 章 Provider 层:Vercel AI SDK + 约 180 Provider ID + 4118 个模型
@cline/llms(118772 行 / 66 文件)是 Provider 核心,基于 Vercel AI SDK(依赖 ai@^7 + @ai-sdk/anthropic/openai/google/google-vertex/amazon-bedrock/mistral/openai-compatible + ai-sdk-ollama + ai-sdk-provider-claude-code):
- Provider 数量:
ids.ts的BUILT_IN_PROVIDER枚举约 50 项 + models.dev 自动生成 163 个 ID;去重并集约 179 个可注册 ID(不是 48+163=211,也难称「200+」)。catalog.generated.ts约 87K 行 / 4118 个模型。 - 双注册 Factory:
factory-registry.ts(registerHandler/registerAsyncHandler)+createHandler(config):先查注册表,否则落到gateway.ts的createGatewayApiHandler;GatewayRegistry持有 manifest/defaults/createProvider。 - 关键子目录:
vendors/(anthropic/bedrock/google/vertex/mistral/ollama/openai-compatible 的 AI SDK 适配)、routing/(anthropic-compatible prompt cache、GLM/MiniMax thinking、reasoning-options)、middleware/(retry-empty-response、split-tool-images)、services/(Langfuse OTel 遥测)。 - 流式与 token:
ai-sdk.ts用streamText+formatMessagesForAiSdk;usage 归一化为GatewayNormalizedUsage(inputTokens/outputTokens/cacheReadTokens/cacheWriteTokens/reasoningTokenCount/totalCost)。 - 模型目录:
catalog/catalog.generated.ts(87274 行,163 provider / 4118 个模型,含 contextWindow/pricing/capabilities),由scripts/generate-models.ts从 models.dev catalog-live 抓取生成(根脚本bun run build:models)。
token 估算(shared/llms/tokens.ts):3 chars/token 保守估算 estimateRequestInputTokens——compaction 触发靠它。
第 12 章 生态:插件、MCP、hooks、多 agent 团队、cron、connectors、hub
插件系统(extensions/plugin/)
插件通过 SubprocessSandbox 子进程加载,JSON IPC 通信(initialize/executeTool/invokeHook/buildMessages)。插件可贡献:tools、commands、rules、messageBuilders、providers、automationEventTypes、mcpServers、shortcuts、flags。安装来源 npm / git / local / remote(plugin-install.ts,1218 行),含官方 slug 校验。
hooks(10 个生命周期事件)
外部 hook 事件(shared/hooks/events.ts):agent_start / agent_resume / agent_abort / agent_end / agent_error / tool_call / tool_result / prompt_submit / pre_compact / session_shutdown。运行时钩子 AgentHooks:beforeRun / afterRun / beforeModel / afterModel / beforeTool / afterTool / onEvent。实现:hook-file-hooks.ts(1010 行,读 .hooks/ 配置)+ subprocess-runner.ts(转发到 agent hook 子进程)。
多 agent 团队(extensions/tools/team/multi-agent.ts,1852 行)
AgentTeamsRuntime(协调器核心):内存态含 members / tasks / missionLog / mailbox / runs(队列+租约)/ outcomes / outcomeFragments;lead 通过团队工具(team-tools.ts 916 行:create_team_task、spawn_teammate、route_to_teammate、team_outcome 等)拆任务委派给 specialist(spawn-agent-tool.ts)。任务状态机 pending → in_progress → blocked(blockedBy)→ completed;运行队列 maxConcurrentRuns 限流 + 心跳 + buildRecoveredRunMessage 中断自动恢复。持久化:exportState()/hydrateState() 全量快照 → team-session-coordinator.ts(240 行)转发 TeamEvent,落 sqlite-team-store.ts(537 行)/ file-team-store.ts。
cron(31 个文件)
规范文件 .md 由 cron-watcher 监听、spec-parser 解析、reconciler 同步。sqlite-cron-store.ts(1719 行):独立 {data}/db/cron.db,表 cron_specs/cron_runs/cron_event_log;claim_token+claim_until_at 租约机制防多进程重复执行。触发:one_off / schedule(cron 表达式)/ event;schedule-service.ts(443 行)轮询+并发限流。
connectors(IM)
core 只管生命周期(active-connectors.ts);实际 IM 实现在 apps/cli/src/connectors/:slack/discord/telegram/gchat/whatsapp/linear 六平台,每平台独立 adapter 进程注册到 hub。
hub(46 个文件)——本地协作中心
本地 WebSocket 服务器,handlers 含 session/run/capability/approval/connector;hub-runtime-host.ts(2156 行)是 RuntimeHost 实现,hooks/tools/checkpoint/compaction 按 capability prefix 协商。
auth / account
auth/cline.ts:WorkOS Device Flow + OAuth;account/cline-account-service.ts:用户信息 RPC、featurebase token。
第 13 章 存储:JSON 文件 + SQLite 混合
| 数据 | 位置 | 实现 |
|---|---|---|
| 全局设置 | {data}/settings/global-settings.json |
JSON + Zod |
| Provider 设置 | {data}/settings/providers.json |
JSON(含 apiKey) |
| 密钥 | {data}/secrets.json |
JSON + chmod 0o600 |
| 会话索引/消息 | {data}/sessions/ |
JSON 文件(整体重写 + atomicWrite) |
| 会话 DB | {data}/db/sessions.db |
SQLite(sqlite-session-store.ts 292 行) |
| cron | {data}/db/cron.db |
SQLite + 租约 |
| 团队 | {data}/teams/ |
SQLite 或文件 |
| connectors | {data}/db/connectors.db |
SQLite |
路径由 @cline/shared/storage 的 resolveClineDataDir() 决定,可用 CLINE_DATA_DIR 覆盖。设计原则:会话消息要能整体读进内存重建(JSON 重写),但需要并发/租约/索引的用 SQLite。
第 14 章 横向对比:与 Claude Code / opencode / CodePilot / pi / OpenWorker
Cline 重构后(CLI v3.0.49 / VS Code 4.1.3 / SDK 0.0.69)处于一个微妙的位置:它既是 IDE 插件(历史基因),又是 CLI(新形态),还是 可嵌入引擎(@cline/sdk)。以下逐维度对比。
14.1 引擎架构:单体 vs 分层可嵌入
| 维度 | Claude Code | opencode | Cline v3 | CodePilot | pi | OpenWorker |
|---|---|---|---|---|---|---|
| 架构形态 | 单体(一个 CLI 包) | 单体 TUI | 分层 monorepo + SDK | Electron 桌面 + 3 Runtime | 9 包 monorepo | 本地 Python 服务 |
| 主循环归属 | 长驻 while-loop driver | 主循环 + doom_loop | 无状态 AgentRuntime(可反复重入) | Native 循环 in-process | 双层 while loop | TurnEngine 异步循环 |
| 引擎可嵌入 | 否(CLI 为主) | 否 | 是(@cline/sdk) | 半(Electron 内) | 是(npm 包) | 否(本地服务) |
| 语言/生态 | TS + Ink | TS + SolidJS | TS + bun | TS + Next.js | TS + bun | Python + Rust |
14.2 工具与权限
| 维度 | Claude Code | Cline v3 | OpenWorker |
|---|---|---|---|
| 工具数量 | 40(内置) | 28(9 默认 + spawn_agent + 18 team) | 40 个连接器描述符 + 家族工具 |
| 编辑工具 | Edit(单文件 old/new) | editor + apply_patch 双雄(后者批量多文件) | 窗口化 read_file / 自研 grep |
| 权限模型 | 命令式审批 + 工具三标记 | preset 分级(default/yolo)+ per-tool policy | 五档模式 + §25 精确 target |
| shell 防注入 | 前缀匹配白名单 | (经 run_commands 审批) | shlex 精确 token + 操作符拦截 |
| 审批 UI | 终端弹窗 | 桌面 IPC 文件轮询(200ms) | 内联卡 / 收件箱带外审批 |
14.3 上下文与缓存
| 维度 | Claude Code | Cline v3 |
|---|---|---|
| 缓存策略 | 内置工具排连续前缀(trie) | MessageBuilder 增量 reindex + outdated 批量重写 + 6MB 兜底(不赌 provider 缓存) |
| 压缩 | microcompact(0.5-0.6× 即时) | 90% 阈值 + basic 确定性 / agentic LLM 摘要 + 侧车前缀哈希 |
| 记忆 | 自动压缩为主 | 无显式记忆库,靠 checkpoint + 压缩 |
14.4 形态与目标
| 维度 | Claude Code | opencode | Cline | CodePilot | pi | OpenWorker |
|---|---|---|---|---|---|---|
| 主要界面 | 终端 TUI | 终端 TUI | IDE 侧边栏 + CLI + headless | 桌面 GUI | 终端 TUI | 桌面 + Slack + 无人值守 |
| 多模型 | 锁 Anthropic | 多 provider | 约 179 provider ID / 4118 模型 | 17+ provider | 38 provider | 十几家 + Ollama |
| 多 agent | 子 agent(Task) | 子 agent | 团队(coordinator + specialist) | Sub-agent | 无 | persona + explorer + self-wake |
| 定时 | 无(计划中) | 无 | cron(租约防重) | cron | 无 | 调度器(catch-up + 重叠跳过) |
| 无人值守审批 | 无 | 无 | headless 直接拒绝/auto-approve | 无 | 无 | 收件箱幂等状态机 |
| 协作中心 | 无 | 无 | hub(本地 WebSocket) | Bridge(IM) | server/client 协议 | 无(本地优先) |
14.5 一句话各自的分工
- Claude Code:Claude 深度优化的终端单体——工具前缀缓存、microcompact、命令式 driver 都是为"单一模型极致体验"服务的。
- opencode:干净的多 provider 终端 TUI,工程模式(doom_loop、permission 三态)值得抄。
- Cline:广度之王——模型最多、形态最多(IDE/CLI/CI)、引擎可嵌入。缺点:工具少而精(web/glob 退化)、bun 工具链。
- CodePilot:桌面三 Runtime 客户端——同一个前端跑 Claude SDK/Native/Codex 三条引擎。
- pi:协议驱动可组合基础设施——无状态循环 + 二进制线协议 + 自扩展 Extensions,理念与 Cline 的"引擎 SDK 化"最接近,但 pi 把 Agent 拆得更碎、走协议。
- OpenWorker:交付成品的数字同事——重心在无人值守审批/连接器/定时/收件箱,不为写代码优化。
🧠 一句话:Cline 重构后的位置是"Agent 引擎的中立供应商"——不绑模型(约 180 Provider ID)、不绑界面(IDE/CLI/hub)、不绑语言(SDK 任意嵌入)。如果你要挑一个项目学"怎么把一个 Agent 做成能给别人用的引擎",Cline 的 monorepo 分层(shared→llms→agents→core→apps)是最完整的教材。
第 15 章 总结:三个最独特的设计与取舍
三件事(如果只记三个设计)
1. 无状态主循环引擎(@cline/agents)与有状态编排(@cline/core)的硬分离。
AgentRuntime 不知道宿主是谁、不持有持久化;会话层反复 new AgentRuntime() 重入循环,用全量转录播种。这让同一个引擎被 CLI、VS Code、hub 三种宿主驱动成为可能——这是"引擎产品化"(@cline/sdk)的根。Claude Code 的单体架构做不出这个。
2. 事件链的三段翻译(AgentRuntimeEvent → legacy AgentEvent → CoreSessionEvent)。
引擎发出新事件,RuntimeEventAdapter(runtime-event-adapter.ts:183)做有状态翻译(usage 增量差值、tool durationMs),再经 AgentEventBridge 给 UI。重构期通过 adapter 保持对旧事件消费者的兼容——这是大型重构的教科书做法。
3. checkpoint 的 git 事务回滚。 工作区快照存成 git commit/stash(三父提交捕获 untracked),回滚本身先 stash 再动、可整体 rollback——"回滚回滚"的能力。比 Claude Code 的简单 diff 回滚强一个量级。
取舍与"适合谁"
| 维度 | Cline 的选择 | 代价 / 适合谁 |
|---|---|---|
| 形态 | IDE 插件 + CLI + headless 三栖 | 界面层最厚(12.8 万行 VS Code);纯终端体验不如 Claude Code 顺滑 |
| 引擎 | 分层可嵌入 SDK(@cline/sdk) | 架构清晰,但多包调试成本高;bun 生态(非 node 官方工具链) |
| 模型 | 约 179 Provider ID / 4118 模型,Vercel AI SDK | 广度优先;不像 Claude Code 深度优化单一模型的前缀缓存 |
| 工具 | 9+1+18 声明式目录 + per-model 路由 | 工具少而精;web 搜索/glob 能力被合并退化 |
| 权限 | preset 分级 + 桌面审批 IPC(文件轮询) | 简单可靠;无 OpenWorker 那种精确 target 级 standing rule |
| 压缩 | 90% 阈值 + basic/agentic 双策略 + 侧车缓存 | agentic 成本高;basic 信息损失大 |
一句话选型:想要一个住在 IDE 里、也能跑终端/CI、能嵌进自己产品的开源编程 Agent 引擎——Cline(尤其重构后的 @cline/sdk)是当前最完整的选择。想要极致深度的 Claude 优化单体,回 Claude Code;想要协议驱动的可组合基础设施,看 pi;想要桌面多引擎客户端,看 CodePilot。
🔍 源码指路(回源码核对)
| 想看 | 去这里 |
|---|---|
| 主循环(无状态 while loop) | sdk/packages/agents/src/agent-runtime.ts:641,677,876,1455,968 |
| 会话编排(跨轮状态) | sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:278,737,1061 |
| 本地宿主(驱动会话) | sdk/packages/core/src/runtime/host/local-runtime-host.ts:224,334,946,1551 |
| pending prompt / steering | sdk/packages/core/src/runtime/turn-queue/pending-prompt-service.ts:54,207,281,295,372 |
| 消息整形(缓存友好) | sdk/packages/core/src/session/services/message-builder.ts:108,166,278,336,1162 |
| 工具目录 + preset | sdk/packages/core/src/extensions/tools/definitions.ts:247,343,660,917 · runtime.ts:206-245 · presets.ts:137 |
| 审批 IPC | sdk/packages/core/src/runtime/tools/tool-approval.ts:29 |
| 循环检测 / 错误追踪 | sdk/packages/core/src/runtime/safety/loop-detection.ts:50,113,136 · mistake-tracker.ts |
| checkpoint 事务回滚 | sdk/packages/core/src/session/checkpoint-restore.ts:50,245,357 · session-versioning-service.ts:134 |
| 压缩(basic/agentic) | sdk/packages/core/src/extensions/context/compaction.ts:256 · basic-compaction.ts:452 · agentic-compaction.ts:97 |
| Provider/模型目录 | sdk/packages/llms/src/(vendors/ · catalog/catalog.generated.ts · factory-registry.ts) |
| CLI 入口/headless | apps/cli/src/index.ts · apps/cli/src/main.ts:941-946(isHeadless 判定)· apps/cli/src/runtime/run-agent.ts |
| VS Code 扩展 | apps/vscode/src/extension.ts:66 · sdk/SdkController.ts |
本分析基于 cline/cline main 分支 2026-08 实际检出源码撰写(CLI v3.0.49 / VS Code 4.1.3 / SDK 0.0.69),所有结论标注 文件:行号 可回源核对。与本系列其他分析同框架。