LogoDevToolkit Hub
Blog Post Image

Cursor 开源平替 Cline 到底是如何实现的?本文带你刨根问底

Cline源码学习

提示词上下文管理工具调用为核心的工具。
查找参考内容用工具, MCP 是工具,操作文件的是工具,执行任务是工具。

前言

Cline 是一个基于 VS Code 的智能助手插件,它通过 AI 技术为开发者提供智能化的任务处理能力。在现代软件开发中,开发者经常需要在多个工具间切换,处理大量重复性工作,同时还要维持对代码和业务的深入理解。这不仅降低了开发效率,还增加了认知负担。

Cline 正是为解决这些问题而设计。它将 AI 能力与开发工具深度集成,提供了一个统一的智能化开发环境。通过智能理解开发者意图,自动化执行开发任务,并保持对项目上下文的持续理解,Cline 显著提升了开发效率和体验。

概述

Cline 插件采用模块化设计,主要由以下核心组件构成:

  • ClineProvider:负责状态管理和 UI 交互
  • Cline:核心业务逻辑处理
  • 外部服务集成:包括 AI 服务、认证服务等
  • 工具系统:提供文件操作、命令执行等能力

通过这些组件的协同工作,Cline 实现了四个核心目标:

  1. 工具统一
  • 在 VS Code 中集成文件操作、命令执行、浏览器控制等能力
  • 提供统一的界面来执行各种开发任务
  • 减少工具切换带来的认知负担
  1. 智能自动化
  • 通过 AI 理解开发者意图
  • 自动完成重复性工作
  • 智能化的代码理解和生成
  1. 上下文保持
  • 维护对项目结构的持续理解
  • 在任务执行过程中保持状态连贯
  • 支持长时间运行的复杂任务
  1. 安全可控
  • 提供操作确认机制
  • 支持任务的暂停和恢复
  • 实现关键操作的回滚能力

一、整体架构概览

  • VS Code Extension Layer
  • extension.ts: 插件入口点
  • 用户界面组件:
  • Webview Panel
  • Sidebar
  • Commands
  • Core System
  • ClineProvider: 状态管理和视图控制
  • Cline: 核心业务逻辑
  • 核心模块:
  • assistant-message:消息处理
  • ignore:忽略规则
  • prompts:提示管理
  • sliding-window:对话管理
  • webview:UI 交互
  • State Management
  • Global State:全局状态
  • Workspace State:工作区状态
  • Secrets Storage:密钥存储
  • External Services
  • AI Services:
  • Anthropic API
  • OpenAI API
  • OpenRouter
  • Authentication:认证服务
  • Browser Control:浏览器控制

1.1 核心架构图

graph TB  
subgraph VSCode[VS Code Extension]  
EXT[extension.ts]  
subgraph UI[User Interface]  
WP[Webview Panel]  
SB[Sidebar]  
CMD[Commands]  
end  
end
 
subgraph Core[Core System]  
CP[ClineProvider]  
CL[Cline]  
  
subgraph Modules[Core Modules]  
AM[assistant-message]  
IG[ignore]  
PR[prompts]  
SW[sliding-window]  
WV[webview]  
end  
end
 
subgraph State[State Management]  
GS[Global State]  
WS[Workspace State]  
SS[Secrets Storage]  
end
 
subgraph Services[External Services]  
AI[AI Services]  
subgraph APIs  
ANT[Anthropic API]  
OAI[OpenAI API]  
OR[OpenRouter]  
end  
AUTH[Authentication]  
BROW[Browser Control]  
end
 
%% Main Flow  
EXT -->|activates| CP  
EXT -->|registers| UI  
CP -->|initializes| CL  
  
%% Core Interactions  
CP -->|manages| State  
CL -->|uses| Modules  
  
%% UI Flow  
UI -->|communicates via| CP  
CP -->|updates| UI  
  
%% Service Integration  
CL -->|calls| APIs  
CP -->|manages| AUTH  
CL -->|controls| BROW
 
classDef vscode fill:#e1f3ff,stroke:#333,stroke-width:2px  
classDef core fill:#ffe1e1,stroke:#333,stroke-width:2px  
classDef state fill:#e1ffe1,stroke:#333,stroke-width:2px  
classDef service fill:#fff0db,stroke:#333,stroke-width:2px
 
class VSCode,UI vscode  
class Core,Modules core  
class State state  
class Services,APIs service  
  
  
  
  

1.3 插件入口

export function activate(context: vscode.ExtensionContext) {  
// 1. 创建输出通道  
outputChannel = vscode.window.createOutputChannel("Cline");
 
// 2. 初始化日志系统  
Logger.initialize(outputChannel);
 
// 3. 创建侧边栏提供者  
const sidebarProvider = new ClineProvider(context, outputChannel);
 
// 4. 注册侧边栏视图  
context.subscriptions.push(  
vscode.window.registerWebviewViewProvider(  
ClineProvider.sideBarId,  
sidebarProvider,  
{  
webviewOptions: {  
retainContextWhenHidden: true  
}  
}  
)  
);  
}
 
// 注册了多个VS Code命令:  
- "cline.plusButtonClicked" // 新建对话  
- "cline.mcpButtonClicked" // MCP按钮  
- "cline.popoutButtonClicked" // 弹出到新标签页  
- "cline.settingsButtonClicked" // 设置  
- "cline.historyButtonClicked" // 历史记录  
- "cline.accountLoginClicked" // 账号登录  

1.4 ClineProvider.ts

graph TB  
subgraph ClineProvider[ClineProvider.ts]  
direction TB  
  
subgraph VSCodeIntegration[VS Code Integration]  
WV[Webview View]  
WP[Webview Panel]  
URI[URI Handler]  
end
 
subgraph StateSystem[State Management System]  
GS[Global State]  
SS[Secrets Storage]  
WS[Workspace State]  
end
 
subgraph TaskSystem[Task Management]  
TI[Task Init]  
TC[Task Control]  
TH[Task History]  
CK[Checkpoints]  
end
 
subgraph AuthSystem[Authentication & API]  
AM[Auth Manager]  
AC[API Config]  
MC[Model Config]  
MH[MCP Hub]  
end
 
subgraph EventSystem[Event Handling]  
ML[Message Listener]  
EH[Event Handler]  
CB[Callbacks]  
end
 
subgraph DataManagement[Data Management]  
ST[State]  
CF[Config]  
HI[History]  
SE[Secrets]  
end  
end
 
%% External Systems  
ExtVSCode[VS Code API]  
ExtAuth[Auth Services]  
ExtAPI[External APIs]  
Cline[Cline.ts]
 
%% Internal Connections  
StateSystem --> DataManagement  
TaskSystem --> StateSystem  
AuthSystem --> StateSystem  
EventSystem --> TaskSystem  
EventSystem --> AuthSystem  
VSCodeIntegration --> EventSystem
 
%% External Connections  
VSCodeIntegration --> ExtVSCode  
AuthSystem --> ExtAuth  
AuthSystem --> ExtAPI  
TaskSystem --> Cline
 
%% State Flow  
DataManagement --> ST  
DataManagement --> CF  
DataManagement --> HI  
DataManagement --> SE
 
classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px  
classDef system fill:#ffe1e1,stroke:#333,stroke-width:2px  
classDef external fill:#e1f3ff,stroke:#333,stroke-width:2px  
classDef data fill:#e1ffe1,stroke:#333,stroke-width:2px
 
class VSCodeIntegration,StateSystem,TaskSystem,AuthSystem,EventSystem system  
class ExtVSCode,ExtAuth,ExtAPI,Cline external  
class DataManagement data  

1.5 cline.ts

graph TB  
subgraph Cline[Cline.ts]  
direction TB  
  
subgraph Settings[Settings]  
CFG[API & System Config]  
end
 
subgraph Core[Core]  
TM[Task Manager]  
FM[File Manager]  
BM[Browser Manager]  
CM[Checkpoint Manager]  
end
 
subgraph Operations[Operations]  
TC[Task Control]  
FO[File Operations]  
AI[API Integration]  
TE[Tool Execution]  
end
 
subgraph UI[UI Interface]  
COM[Communication]  
end  
end
 
%% Main flows  
Settings --> Core  
Core --> Operations  
Operations --> UI
 
%% Cross-functional flows  
TC -->|uses| CM  
FO -->|uses| FM  
TE -->|uses| BM  
AI -->|via| COM
 
classDef settings fill:#e1f3ff,stroke:#333,stroke-width:2px  
classDef core fill:#ffe1e1,stroke:#333,stroke-width:2px  
classDef ops fill:#e1ffe1,stroke:#333,stroke-width:2px  
classDef ui fill:#fff0db,stroke:#333,stroke-width:2px
 
class Settings settings  
class Core core  
class Operations ops  
class UI ui  

1.6 提示词

分为几个部分:

  1. 角色定义:定义角色信息
  2. 工具调用:
  3. 工具定义
  4. 内置工具列表:
  5. 文件操作:读文件,写文件(覆盖),替换文件内容(diff形式),查文件,list 文件,list代码定义
  6. 浏览器操作:浏览器操作(使用 puppeteer访问和点击操作,执行操作并且返回截图和控制台日志)
  7. 终端操作:执行命令
  8. MCP 操作:MCP 工具调用和资源请求
  9. 基础操作:询问用户问题,输出命令结果(用于展示任务完成后的结果,标志结束)
  10. 规划模式:规划模式定义(帮助用户规划和脑暴解决方案)
  11. 调用例子和调用指南
  12. MCP 服务:MCP 定义, 动态注入 MCP服务器列表,MCP 创建示例和指南
  13. 替换文件和创建文件的区别:两者的定义和使用场景以及优势,考虑改写之后用户编辑器的自动格式化(直接输出最终状态),工作流程的一些建议
  14. ACT模式和 PLAN 模式:让 AI 理解 act 模式和 plan 模式,act 模式可以调用除plan_mode_response工具之外的所有工具,而 plan 模式则使用plan_mode_response
  15. 能力:指定 AI 具有什么能力,比如能调用哪些工具以及这些工具是干什么的
  16. 规则:指定 AI 需要遵守的规则,能做什么,不能做什么
  17. 系统信息:操作系统、默认 shell,home 目录,当前工作目录
  18. 目标:宏观指定AI 完成任务的步骤
  19. 用户自定义指南
    源代码位置:https://github.com/cline/cline/blob/main/src/core/prompts/system.ts

二、核心执行流程

2.1 任务执行流程

  1. 任务初始化
  • 用户通过 Webview 界面输入任务
  • Webview 将消息传递给 ClineProvider
  • ClineProvider 创建和初始化 Cline 实例
  1. 任务执行循环
  • Cline 向 AI 服务发送请求
  • AI 服务返回响应和可能的工具调用
  • Cline 解析响应并执行相应的工具
  • 需要用户确认的操作会请求用户确认
  • 工具执行结果返回给 Cline
  • Cline 将结果返回给 AI 服务继续处理
  1. 任务完成
  • 当所有必要的步骤都完成后
  • Cline 向用户返回最终结果
  • 任务执行完成
sequenceDiagram  
participant User  
participant Webview  
participant ClineProvider  
participant Cline  
participant Tools  
participant AI
 
User->>Webview: 输入任务  
Webview->>ClineProvider: 发送消息  
ClineProvider->>Cline: 创建实例
 
activate Cline  
loop Task Loop  
Cline->>AI: 发送请求  
AI-->>Cline: 返回响应  
Cline->>Tools: 执行工具  
Tools->>User: 请求确认  
User-->>Tools: 确认执行  
Tools-->>Cline: 返回结果  
Cline->>AI: 返回执行结果  
end  
Cline-->>User: 任务完成  
deactivate Cline
 

2.2 工具执行流程

flowchart TD  
A[AI 请求] --> B{AI 进行工具类型判断}  
B -->|Command| C[命令执行]  
B -->|File| D[文件操作]  
B -->|API| E[API 调用]  
B -->|Browser| F[浏览器操作]  
C --> G{需要确认?}  
G -->|Yes| H[用户确认]  
G -->|No| I[直接执行]  
H --> I  
I --> J[收集结果]  
D --> K[权限检查]  
K --> L[执行操作]  
L --> J  
E --> M[验证参数]  
M --> N[调用 API]  
N --> J  
F --> O[浏览器会话]  
O --> P[执行动作]  
P --> J  
J --> Q[返回给 AI]
 

三、核心组件实现

3.1 ClineProvider Cline 核心类

class ClineProvider implements vscode.WebviewViewProvider {  
private cline?: Cline  
private view?: vscode.WebviewView  
private context: vscode.ExtensionContext
 
// 核心管理功能  
async initClineWithTask(task?: string)  
async handleMessage(message: Message)  
async updateState(state: State)  
  
// 定义全局文件名  
export const GlobalFileNames = {  
apiConversationHistory: "api_conversation_history.json", // API对话历史  
uiMessages: "ui_messages.json", // UI消息  
openRouterModels: "openrouter_models.json", // OpenRouter模型  
mcpSettings: "cline_mcp_settings.json", // MCP设置  
clineRules: ".clinerules", // Cline规则  
}  
}  
class ClineProvider {  
constructor(context: vscode.ExtensionContext) {  
this.context = context  
this.cline = undefined // 延迟初始化  
}
 
async initClineWithTask(task?: string) {  
await this.clearTask() // 清理现有任务
 
// 获取配置  
const config = await this.getState()
 
// 创建新实例  
this.cline = new Cline(  
this,  
config.apiConfiguration,  
config.autoApprovalSettings,  
config.browserSettings,  
config.chatSettings,  
config.customInstructions  
)  
}  
}
 
export class Cline {  
// 核心属性  
readonly taskId: string;  
api: ApiHandler;  
private terminalManager: TerminalManager;  
private urlContentFetcher: UrlContentFetcher;  
browserSession: BrowserSession;
 
// 状态控制  
private didEditFile: boolean = false;  
private abort: boolean = false;  
private consecutiveMistakeCount: number = 0;
 
// 历史记录  
apiConversationHistory: Anthropic.MessageParam[] = [];  
clineMessages: ClineMessage[] = [];
 
// 配置系统  
autoApprovalSettings: AutoApprovalSettings;  
private browserSettings: BrowserSettings;  
private chatSettings: ChatSettings;
 
// 任务执行核心方法  
async startTask(task?: string, images?: string[]): Promise<void> {  
// 初始化状态  
this.clineMessages = [];  
this.apiConversationHistory = [];
 
// 更新界面  
await this.providerRef.deref()?.postStateToWebview();
 
// 显示任务  
await this.say("text", task, images);
 
// 标记初始化完成  
this.isInitialized = true;
 
// 构建初始消息  
let imageBlocks = formatResponse.imageBlocks(images);
 
// 启动任务循环  
await this.initiateTaskLoop(  
[{  
type: "text",  
text: `<task>\\n${task}\\n</task>`,  
},  
...imageBlocks],  
true // isNewTask 标记  
);  
}  
}
 

3.2 任务循环实现

private async initiateTaskLoop(  
userContent: UserContent,  
isNewTask: boolean  
): Promise<void> {  
let nextUserContent = userContent;  
let includeFileDetails = true;
 
while (!this.abort) {  
// 核心请求处理  
const didEndLoop = await this.recursivelyMakeClineRequests(  
nextUserContent,  
includeFileDetails,  
isNewTask  
);
 
includeFileDetails = false;
 
if (didEndLoop) {  
break;  
} else {  
// 处理未使用工具的情况  
nextUserContent = [{  
type: "text",  
text: formatResponse.noToolsUsed(),  
}];  
this.consecutiveMistakeCount++;  
}  
}  
}  

3.3 任务结束的条件

// 1. this.abort 为 true 的情况:  
- 用户手动中止  
- 发生严重错误  
- Cline 实例被销毁
 
// 2. didEndLoop 为 true 的情况:  
- 任务成功完成(使用 attempt_completion 工具)  
- 达到最大错误次数  
- 任务被标记为完成
 
// 3. 其他终止条件:  
- 连续错误次数过多  
- API 调用失败  
- 工具执行失败
 

四、请求处理系统

4.1 递归请求处理

private async recursivelyMakeClineRequests(  
userContent: UserContent,  
includeFileDetails: boolean,  
isNewTask: boolean  
): Promise<boolean> {  
// 1. 错误检查  
if (this.consecutiveMistakeCount >= MAX_CONSECUTIVE_MISTAKES) {  
throw new Error("Too many consecutive mistakes")  
}
 
try {  
// 2. 准备消息  
const messages = this.prepareMessages(userContent, includeFileDetails)
 
// 3. 发送 API 请求  
const response = await this.api.sendRequest(messages)
 
// 4. 处理响应  
if (response.type === "completion") {  
return true // 任务完成  
} else if (response.type === "tool_use") {  
await this.handleToolUse(response.tool)  
return false // 继续执行  
}  
} catch (error) {  
this.handleError(error)  
return true  
}  
}
 

4.2 消息准备

private prepareMessages(  
userContent: UserContent,  
includeFileDetails: boolean  
): MessageParam[] {  
// 1. 构建基础消息  
const messages = [...this.apiConversationHistory]
 
// 2. 添加环境详情  
if (includeFileDetails) {  
messages.push({  
type: "environment_details",  
content: this.getEnvironmentDetails()  
})  
}
 
// 3. 添加用户内容  
messages.push({  
type: "user_content",  
content: userContent  
})
 
return messages  
}
 

4.3 API 通信系统

class ApiHandler {  
async *attemptApiRequest(previousApiReqIndex: number) {  
// 1. 系统提示准备  
let systemPrompt = await SYSTEM_PROMPT(  
cwd,  
this.api.getModel().info.supportsComputerUse,  
mcpHub,  
this.browserSettings  
);
 
// 2. 上下文预处理  
const { truncatedHistory, deletedRange } = this.truncateHistoryToFitContext(  
previousApiReqIndex  
);
 
// 3. 流式通信  
const stream = this.api.createMessage(systemPrompt, truncatedHistory);  
yield* this.handleStreamResponse(stream);  
}
 
private truncateHistoryToFitContext(previousIndex: number) {  
const totalTokens = this.calculateTokensUsage();
 
switch (this.contextWindow) {  
case 64_000: // deepseek models  
this.maxAllowedSize = this.contextWindow - 27_000;  
break;  
case 128_000: // most models  
this.maxAllowedSize = this.contextWindow - 30_000;  
break;  
}
 
if (totalTokens >= this.maxAllowedSize) {  
return this.performTruncation();  
}
 
return { truncatedHistory: this.history };  
}  
}
 

4.4 工具

export const toolUseNames = [  
"execute_command",  
"read_file",  
"write_to_file",  
"replace_in_file",  
"search_files",  
"list_files",  
"list_code_definition_names",  
"browser_action",  
"use_mcp_tool",  
"access_mcp_resource",  
"ask_followup_question",  
"plan_mode_response",  
"attempt_completion",  
] as const  

4.5 终端命令执行工具

async executeCommandTool(command: string): Promise<[boolean, ToolResponse]> {  
// 1. 终端管理  
const terminalInfo = await this.terminalManager.getOrCreateTerminal(cwd)  
terminalInfo.terminal.show()
 
// 2. 执行命令  
const process = this.terminalManager.runCommand(terminalInfo, command)
 
// 3. 输出处理  
process.on("line", (line) => {  
result += line + "\\n"  
if (!didContinue) {  
sendCommandOutput(line)  
} else {  
this.say("command_output", line)  
}  
})
 
// 4. 等待完成  
await process
 
// 5. 返回结果  
return [completed, formatResult(result)]  
}
 

4.6文件操作工具

class FileOperations implements Tool {  
// 文件读取  
async readFile(path: string): Promise<string> {  
return fs.readFile(path, 'utf8');  
}
 
// 文件写入  
async writeFile(path: string, content: string): Promise<void> {  
await this.ensureDirectoryExists(path);  
await fs.writeFile(path, content);  
}
 
// 文件替换  
async replaceInFile(path: string, diff: string): Promise<void> {  
const content = await this.readFile(path);  
const newContent = await constructNewFileContent(diff, content);  
await this.writeFile(path, newContent);  
}
 
// 文件列表  
async listFiles(path: string, recursive: boolean): Promise<string[]> {  
if (recursive) {  
return this.recursiveListFiles(path);  
}  
return fs.readdir(path);  
}  
}
 

五、安全机制实现

5.1 文件操作安全

class FileOperationApproval {  
async checkFileAccess(operation: FileOperation): Promise<boolean> {  
// 1. 路径安全检查  
if (!this.isPathSafe(operation.path)) {  
return false;  
}
 
// 2. 操作权限检查  
if (!this.hasPermission(operation.type)) {  
return false;  
}
 
// 3. 内容安全检查  
if (operation.type === 'write' && !this.isContentSafe(operation.content)) {  
return false;  
}
 
return true;  
}
 
private isPathSafe(path: string): boolean {  
// 检查路径是否在工作目录内  
// 防止目录遍历攻击  
const normalizedPath = normalizePath(path);  
return isWithinWorkspace(normalizedPath);  
}  
}
 

5.2 命令执行安全

class CommandSecurity {  
private readonly restrictedCommands: Set<string> = new Set([  
'rm -rf',  
'format',  
'shutdown',  
// ... 其他危险命令  
]);
 
async validateCommand(command: string): Promise<boolean> {  
// 1. 检查是否是受限命令  
if (this.isRestrictedCommand(command)) {  
return false;  
}
 
// 2. 检查命令权限  
if (!await this.checkCommandPermissions(command)) {  
return false;  
}
 
// 3. 检查资源限制  
if (!this.checkResourceLimits(command)) {  
return false;  
}
 
return true;  
}
 
private isRestrictedCommand(command: string): boolean {  
return Array.from(this.restrictedCommands).some(  
restricted => command.includes(restricted)  
);  
}  
}
 

5.3 检查点系统

三种情况:task(恢复任务消息)、workspace(恢复工作区文件)、taskAndWorkspace(同时恢复任务消息和工作区文件)

核心机制:ShadowGit(主仓库的变更不会影响到Shadow 仓库,shadow 仓库的变更会形成主仓库的未提交的更改

核心流程:

  1. 如果恢复 workspace 或 taskAndWorkspace,则会首先初始化 checkpointTracker,并通过 resetHead 直接将工作区恢复到指定 git commit。
  2. 对于 task 或 taskAndWorkspace,我们还需要恢复 task 历史消息记录,同时记录回滚的 APi 资源消耗
class CheckpointSystem {  
private checkpoints: Map<string, Checkpoint> = new Map();
 
// 创建检查点  
async createCheckpoint(): Promise<string> {  
const checkpoint = {  
id: generateId(),  
timestamp: Date.now(),  
state: await this.captureCurrentState(),  
files: await this.captureFileState()  
};
 
this.checkpoints.set(checkpoint.id, checkpoint);  
return checkpoint.id;  
}
 
// 恢复检查点  
async restoreCheckpoint(id: string): Promise<void> {  
const checkpoint = this.checkpoints.get(id);  
if (!checkpoint) {  
throw new Error('Checkpoint not found');  
}
 
await this.restoreState(checkpoint.state);  
await this.restoreFiles(checkpoint.files);  
}  
}
 

六、文件存储

文件存储主要分为以下几类:

Task对话流,配置文件(主要是 mcp服务器信息),mcp 服务端代码,自定义prompt(.clinerules)

Task 存储

~/Library/Application\ Support/Code/User/globalStorage/扩展名/tasks/任务ID

  • api_conversation_history.json:存储消息和上下文

  • ui_messages.json:存储 UI 上显示的信息

  • checkpoints:检查点信息

  • .git:存储记录检查点的影子仓库数据

配置信息存储

~/Library/Application\ Support/Code/User/globalStorage/扩展名/settings

  • cline_mcp_settings.json:存储 mcp 的信息,包括ID、参数,环境变量等信息

mcp服务端代码存储位置

  • ~/Documents/Cline/MCP:这个文件夹存储 mcp 服务器的代码位置

七、一些细节

TreeSitter:使用 web-tree-sitter 进行代码文件的解析和提取

微信公众号二维码

🚀 关注我的公众号

与我一同探索独立开发与技术精进之路
获取最新的技术分享和开发心得

📱 扫码关注💡 技术分享🎯 独立开发

Publisher

zjy365
zjy365

2025/07/25

Categories

    Newsletter

    Join the Community

    Subscribe to our newsletter for the latest news and updates