
Cline 插件体系实战从官方示例看 Agent 插件的工具注册、生命周期钩子与消息压缩【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline本文以 Cline SDK 仓库中的官方插件示例目录sdk/examples/plugins/为核心系统讲解 Cline 插件Plugin的完整体系一个插件文件如何让 CLI、Kanban、VS Code 等所有基于 Core SDK 的 Cline Agent 同时获得新工具、生命周期钩子、自定义 Provider 和消息重写能力。读完本文你将掌握插件的目录结构与manifest.capabilities声明规则、setup(api, ctx)的完整 API 面、7 个运行时钩子的触发时机、沙箱子进程的生命周期管理并能直接复制官方示例安装到自己的工程中验证行为。插件能做什么Cline 的插件是单个文件或目录投放到任意 Cline AgentCLI、Kanban、VS Code、JetBrains 或任何构建于 Core SDK 之上的宿主中即可在宿主里注入新工具、钩子、Provider 或消息重写器。一个插件可以实现四类能力注册工具Register tools——给 Agent 提供新的可调用能力挂接生命周期Hook into the lifecycle——在关键执行点观察或干预运行重写 Provider 消息Rewrite provider messages——自定义压缩、脱敏、上下文塑形发出自动化事件Emit automation events——向运行时推送规范化事件。从源码结构看插件的基础类型定义在cline/shared的贡献注册表中ContributionRegistryExtension要求插件声明name、manifest含非空capabilities数组可选disabled、hooks与setup成员而宿主侧的加载入口resolveAndLoadAgentPlugins()位于 plugin-config-loader.ts它负责把「配置指定路径 自动发现路径」合并去重后按sandbox默认或in_process模式加载。官方示例插件全景sdk/examples/plugins/目录收录了 10 个单文件示例和 2 个目录型插件覆盖插件机制的各个切面示例展示的能力具体行为weather-metrics.ts工具注册 生命周期指标钩子。最佳入门起点添加 mockget_weather工具并记录 run/tool 指标、workspace git 上下文、token 用量与成本。同时演示在beforeTool钩子中拦截受保护分支上的git push以及通过ctx.telemetry.capture/recordCounter向宿主遥测服务发数据telemetry.ts插件可观测性ctx.telemetryctx.logger契约集中在一处添加roll_die演示工具发出遥测事件、计数器、直方图、仪表盘及结构化日志并文档化了规则两个通道都要做特性检测feature-detect、只传 JSON 数据、自动plugin.命名空间、宿主侧 opt-out沙箱内不要依赖isEnabled()做门禁、遥测保持低基数而细节交给 loggermac-notify.ts通过afterRun发 macOS 通知中心提醒运行成功完成时发送原生 macOS 通知用最终输出文本或迭代次数作为通知正文非 macOS 宿主上为空操作no-opcustom-compaction.ts通过registerMessageBuilder压缩 Provider 消息重写发往 Provider 的超长消息历史保留第一条用户消息与近期上下文把中间较旧历史替换为包含角色、工具、文件、高亮内容的结构化摘要background-terminal.ts带持久化日志与会话引导steering的后台 Shell 作业注册start_background_command、get_background_command、delete_background_command三个工具让 Agent 可启动长时命令、轮询 stdout/stderr 尾部、清理作业元数据并在命令结束后收到以 steer 消息形式推回的完成摘要automation-events.ts插件发出的自动化事件注册规范化的local.plugin_event自动化事件类型当设置CLINE_LOCAL_EVENT_INTERVAL_MS时周期性发出演示事件gitignore-read-files-guard.ts面向 workspace.gitignore边界的运行时钩子策略用beforeTool检查read_files、editor、apply_patch请求当目标路径命中 workspace.gitignore规则时跳过防止被忽略的文件被读取或修改env-blocker.ts通过beforeTool实现确定性密钥保护拦截读取.env密钥文件的read_files与run_commands如cat .env调用同时放行.env.example/.env.sample/.env.template。这是硬保证而 AGENTS.md 规则只是建议web-search.ts基于 Exa API Key 的web_search工具添加查询 Exa 公共网页结果的web_search工具支持可选的结果数量限制、域名过滤、时间窗口和国家本地化。需要EXA_API_KEYopenrouter-provider.ts通过registerProvider注册自定义模型 Provider注册一个指向 OpenRouter 的 OpenAI 兼容 Provider 及其模型目录使 Agent 可以直接对其做推理。替换 base URL、API Key 环境变量和模型列表即可接入任何 Cline 未内置的 OpenAI 兼容端点。需要OPENROUTER_API_KEYtypescript-lsp/由 TypeScript Language Service 驱动的goto_definition工具为 TS/JS 项目提供goto_definition(file, line)加载目标项目自己的 TypeScript 版本在指定行定位标识符并经由 import、re-export、别名等语言服务语义解析定义agents-squad/多 Agent 团队——启动拥有独立模型与人设的子代理提供启动、消息、轮询与协调后台子代理的工具附带打包的 agent 预设、技能发现/加载以及在同一会话内子代理之间传递笔记的共享交接存储通过ctx.logger和ctx.telemetry报告子代理生命周期启动计数器、完成事件、回合时长直方图运行时会话的压缩变体位于 custom-compaction-hook.example.ts与 message-builder 版本互为对照。用 CLI 安装与体验插件CLI 会自动从三处发现插件workspace 下的.cline/plugins、用户主目录~/.cline/plugins以及系统级 Plugins 目录。cline plugin install支持本地文件、文件 URL、包目录、git 仓库和 npm 包等多种来源。以最简单的单文件插件为例本地路径形式将文件路径换成任意单文件示例即可cline plugin install ./sdk/examples/plugins/weather-metrics.ts --cwd . cline -i Whats the weather like in Tokyo and Paris?--cwd .指定工作目录插件即对当前 workspace 生效。若要阻止 Agent 访问被 workspace.gitignore忽略的路径cline plugin install ./sdk/examples/plugins/gitignore-read-files-guard.ts --cwd . cline -i Read the ignored .env file该守卫基于beforeTool运行时钩子当read_files、editor或apply_patch调用指向被忽略的 workspace 文件时钩子返回{ skip: true }于是工具结果会记录一条策略错误policy error文件不会被访问。对于自带package.json的目录型插件安装方式相同cline plugin install ./sdk/examples/plugins/agents-squad接入 Web 搜索并让 Agent 实际调用它注意区分两类 Key 的职责cline plugin install ./sdk/examples/plugins/web-search.ts --cwd . export EXA_API_KEY... export OPENROUTER_API_KEY... cline auth --provider openrouter --apikey $OPENROUTER_API_KEY --modelid anthropic/claude-sonnet-4.6 cline -P openrouter -m anthropic/claude-sonnet-4.6 Search the web for recent Bun release notes, then fetch the most relevant page插件注册的web_search返回 Exa 的规范化搜索结果。它与内置的fetch_web_content是刻意分开的两个工具用web_search发现相关 URL需要深入某个具体页面时再用fetch_web_content。EXA_API_KEY只负责认证搜索后端CLI 本身仍需正常的模型 Provider Key 或已保存的 Provider 凭据来做推理。也可以在仓库中直接跑演示以sdk为工作目录ANTHROPIC_API_KEYsk-... bun run examples/plugins/weather-metrics.ts插件的解剖结构Anatomy一个最简插件长这样import type { AgentPlugin } from cline/core; import { createTool } from cline/core; const myPlugin: AgentPlugin { name: my-plugin, manifest: { capabilities: [tools, hooks], }, setup(api, ctx) { api.registerTool(createTool({ /* ... */ })); }, hooks: { beforeRun({ snapshot }) { /* ... */ }, afterRun({ result }) { /* ... */ }, }, }; export default myPlugin;结合 contribution-registry.ts 中的类型定义各部分的契约如下name扩展的唯一标识用于错误信息与钩子处理器命名manifest.capabilities必须是非空数组声明插件用到的能力注册表在setup()运行前会校验——能力名必须是合法值若插件定义了hooks却未声明hooks能力会直接抛出Invalid manifest ... runtime hooks require the hooks capability错误见源码 normalizeManifest 的校验逻辑manifest.providerIds/manifest.modelIds可选字符串数组用于把插件的作用限定到特定 Provider/模型PluginTargetingsetup(api, ctx)注册表初始化期间调用一次所有注册都会累积进ContributionRegistry在setup()完成后对宿主可用hooks运行时原生钩子直接被cline/agents的运行时消费。setup的第二个参数ctxPluginSetupContext可能包含session、client、user、workspaceInfo、automation、logger、telemetry等字段取决于宿主。源码注释特别强调这些值永远来自宿主会话配置而不是process.cwd()——需要 workspace 相对路径时应使用ctx.workspaceInfo?.rootPath而不是process.cwd()或import.meta.url的技巧。end-to-end 用法可参考 automation-events.ts。apiAgentExtensionApi的完整注册面每个方法都对应一个 capability方法所需 capability作用api.registerTool()tools注册 Agent 可调用工具api.registerCommand()commands注册连接聊天界面的斜杠命令api.registerRule()rules注册注入运行时 system prompt 的规则api.registerMessageBuilder()messageBuilders注册消息发送前的转换构建器api.registerProvider()providers注册自定义模型 Providerapi.registerAutomationEventType()automationEvents注册插件可发出的规范化自动化事件类型api.registerMcpServer()mcp注册以运行时工具形式暴露的 MCP 服务器从源码结构看合法 capability 全集定义为ExtensionCapabilityOptions [hooks, tools, commands, rules, skills, messageBuilders, providers, automationEvents, mcp]contribution-registry.ts#L204-L214其中skills不解锁api方法而是让插件包内捆绑的 skillsskills/目录被自动发现——目录型插件 agents-squad/ 就附带了 7 个 skill 文件。ctx.telemetry两种执行模式下的插件遥测ctx.telemetry在两种插件执行模式下都可用但拿到的是不同的东西进程内in-process插件直接拿到宿主遥测服务对象沙箱sandboxed插件拿到的是一个桥接器bridge它通过 IPC 把capture/captureRequired/recordCounter/recordHistogram/recordGauge调用转发给宿主只能传 JSON 可序列化的属性。宿主会为每个插件事件与指标统一加上plugin.命名空间前缀并打上plugin_name标记且当用户关闭了遥测时直接丢弃。使用规则telemetry.ts 把这些规则集中文档化始终特性检测——ctx.telemetry?.capture(...)宿主没有遥测服务时它就是undefined只传 JSON-only 数据沙箱注意项bridge 是无状态的isEnabled()恒报trueopt-out 的事件在宿主侧被丢弃——所以不要用isEnabled()门禁昂贵的属性计算保持遥测属性便宜易构造保持遥测低基数low-cardinality详细日志走ctx.logger身份设置器setDistinctId、setCommonProperties等属于宿主职责在沙箱内是 no-op。weather-metrics.ts 展示了典型用法setup中telemetry?.capture({ event: weather_plugin_setup, properties: { has_workspace, branch } })beforeTool中telemetry?.recordCounter(weather_plugin.tool_calls, 1, { tool_name })afterRun中带 status/iterations/tokens 的运行完成事件。沙箱插件的生命周期自动发现的插件运行在会话拥有的子进程中空闲子进程在无活动插件调用30 分钟后被回收下一次工具、钩子、命令、规则或消息构建器调用会透明地启动全新进程并重新执行插件 setup。宿主可用环境变量CLINE_PLUGIN_IDLE_TIMEOUT_MS毫秒调整空闲期活动调用active calls永远不会被驱逐。把模块级变量当作缓存而非持久存储它们会在空闲驱逐、hub 重启或沙箱崩溃后重置。必须跨这些边界存活的状态要落到磁盘或其他持久存储。插件的setup应保持同一会话内可安全重入。加载逻辑上plugin-config-loader.ts 中resolveAndLoadAgentPlugins()默认走loadSandboxedPlugins()仅当显式传入mode: in_process时才用loadAgentPluginsFromPathsWithDiagnostics()在宿主进程内加载options中还可配置importTimeoutMs、hookTimeoutMs、contributionTimeoutMs等超时。对于目录型插件插件入口的归属还与其package.json中cline.plugins声明联动——skill 根目录的解析会停在第一个声明了该入口的包边界避免把 monorepo 根目录里无关的skills/暴露进来见 collectPluginSkillRootCandidates。运行时钩子Runtime Hooks钩子是类型化的进程内回调与cline/agents位于同一钩子层在 Agent 循环内部执行且带完整类型信息钩子触发时机beforeRun运行时循环开始前afterRun运行时循环结束后beforeModel每次模型请求前afterModel每次模型响应后、工具执行前beforeTool每次工具执行前afterTool每次工具执行后onEvent运行时发出的每个AgentRuntimeEvent两个关键语义README 明确说明beforeRun/afterRun包裹一次run()/continue()调用——在交互会话中即一个用户回合afterRun是完成通知的合适位置但它也会在 aborted 与 failed 的运行上触发若只想处理成功情况需检查result.status completed。插件钩子 vs 文件钩子文件钩子是.cline/hooks中的外部脚本运行时用序列化 JSON payload 调用插件运行时钩子则是 Agent 循环内的类型化回调。Core 会把文件钩子适配到运行时钩子层两者映射关系如下文件钩子文件事件对应的运行时钩子TaskStartagent_startbeforeRunTaskResumeagent_resumebeforeRun带 resume 上下文UserPromptSubmitprompt_submitbeforeRun带 prompt 上下文PreToolUsetool_callbeforeToolPostToolUsetool_resultafterToolTaskCompleteagent_endafterRuncompletedTaskErroragent_errorafterRunfailedTaskCancelagent_abortafterRun或会话关闭SessionShutdownsession_shutdown会话清理选择原则用户或 workspace 配置的脚本用文件钩子行为属于可复用扩展、且需要类型化运行时访问时用插件运行时钩子。示例深读一weather-metrics.ts 的工具注册与 git push 拦截weather-metrics.ts 是官方推荐的最佳起点它把toolshooks两个能力放在同一个插件里。要点拆解workspace 感知的工具描述setup(api, ctx)中从ctx.workspaceInfo读取rootPath、latestGitBranchName、latestGitCommitHash、associatedRemoteUrls把它们拼进get_weather工具的 description让模型明确知道工具在哪个 workspace 上操作。注释特别解释ctx的 workspace 上下文直接来自会话配置因此即使用户向 CLI 传了--cwd而没有process.chdir()路径依然是正确的。beforeTool拦截受保护分支的git pushbeforeTool({ toolCall, input }) { toolCallCount 1; telemetry?.recordCounter(weather_plugin.tool_calls, 1, { tool_name: toolCall.toolName }); if (toolCall.toolName run_commands) { const { commands } input as { commands?: string[] }; const isProtected sessionBranch main || sessionBranch master; const hasPush commands?.some((c) c.trimStart().startsWith(git push)); if (isProtected hasPush) { return { stop: true, reason: Blocked git push on protected branch }; } } return undefined; }分支信息来自setup阶段缓存的ctx.workspaceInfo?.latestGitBranchName展示了「setup 时收集会话状态、钩子中消费」的典型模式。afterRun输出运行指标打印迭代次数、状态、输入/输出 token 与成本usage.totalCost并发出weather_plugin_run_completed遥测事件。示例深读二env-blocker.ts 的确定性密钥保护env-blocker.ts 展示了钩子作为硬保证hard guarantee的用法——「永远不要读 .env」写在 AGENTS.md 里只是模型可能忽略的建议而beforeTool钩子位于执行路径上工具调用根本不会运行const plugin: AgentPlugin { name: env-blocker, manifest: { capabilities: [hooks] }, hooks: { async beforeTool({ toolCall, input }) { let blocked: string | undefined; switch (toolCall.toolName) { case read_files: blocked extractFilePaths(input).find(isEnvFile); break; case run_commands: blocked extractShellCommands(input).find(commandReadsEnv); break; } if (!blocked) return undefined; return { skip: true, reason: Blocked ${toolCall.toolName}: reading environment secret files (${blocked}) is not permitted. ..., }; }, }, };实现细节值得注意isEnvFile用正则/^\.env(\.|$)/i匹配.env、.env.local、.env.production、path/to/.env等但放行.env.example/.env.sample/.env.template模板文件commandReadsEnv从 shell 命令 token 中扫描.env系文件从而封住cat .env、source ./.env这类旁路extractFilePaths/extractShellCommands则遍历工具输入的多种合法形状字符串、数组、{ command | commands | cmd }对象等以提取全部路径/命令。对比两个示例即可记住钩子的两种「否决」返回{ skip: true, reason }让工具结果记录策略错误而不执行env-blocker、gitignore 守卫的用法{ stop: true, reason }则用于中止运行weather-metrics 拦截git push的用法。自定义消息压缩message builder 还是 beforeModel当插件需要在模型调用前重写发往 Provider 的消息列表时扩展点是api.registerMessageBuilder()。构建器在运行时消息转换为 SDK 消息块之后、Core 内置安全构建器built-in safety pass之前运行——因此 provider-safe 规范化包括硬截断始终是最后把关者。多个构建器按注册顺序执行。custom-compaction.ts 的完整策略参数const MAX_INPUT_TOKENS 120_000; // 上下文上限 const COMPACT_AT_RATIO 0.75; // 达到上限 75% 触发压缩 const PRESERVE_RECENT_TOKENS 24_000; // 保留的近期上下文窗口其build(messages)流程用cline/shared的estimateTokens按字符数估算统计总 token低于MAX_INPUT_TOKENS * COMPACT_AT_RATIO时原样返回定位第一条用户消息findFirstUserIndex与近期窗口起点从尾向前累计到PRESERVE_RECENT_TOKENS将中间段messages.slice(firstUserIndex 1, recentStartIndex)替换为一条结构化「Context summary」消息——包含被压缩消息数、压缩前估算 token、角色统计、用过的工具列表collectToolNames、触及的文件collectTouchedFiles与最后 6 条高亮预览返回[...prefix(首条用户消息), summary, ...recent]。两种压缩路径的取舍README 给出的决策表示例扩展点适用场景custom-compaction.tsapi.registerMessageBuilder()可复用、插件自有的压缩策略常规压缩优先用这个custom-compaction-hook.example.tshooks.beforeModel运行时钩子需要运行时钩子上下文、或直接修改运行时请求对象的逻辑官方建议普通压缩用 message-builder 版本只有在需要运行时快照或想直接改运行时请求对象时才使用beforeModel。把插件传给 SDK插件也可以不经 CLI直接在 SDK 代码里作为扩展传入ClineCoreimport plugin from ./my-plugin; import { ClineCore } from cline/core; const host await ClineCore.create({ backendMode: local }); await host.start({ config: { providerId: anthropic, modelId: claude-sonnet-4-6, apiKey: process.env.ANTHROPIC_API_KEY ?? , cwd: process.cwd(), enableTools: true, systemPrompt: You are a helpful assistant., extensions: [plugin], // 插件作为扩展传入 }, prompt: Whats the weather like in Tokyo and Paris?, interactive: false, });后台终端插件的三个工具background-terminal.ts 为长时 Shell 作业注册了三个工具工具用途start_background_command启动分离detachedShell 命令立即返回 job idstdout/stderr 捕获到 Cline 数据目录下get_background_command读取作业状态与近期 stdout/stderr 尾部delete_background_command删除已保存的作业元数据可选删除捕获的日志当notifyParent为true默认值时插件在命令退出后通过宿主桥接发出steer_message把完成摘要推回活跃会话——Agent 因此可以响应长时命令而无需阻塞原始工具调用。小结选择哪种插件写法想让 Agent多一个能力查天气、搜网页、跳转定义、跑后台命令→ 声明tools能力在setup中api.registerTool(createTool({...}))参考 weather-metrics.ts、web-search.ts、typescript-lsp/想强制执行边界禁读.env、禁读 gitignore 文件、禁推受保护分支→ 声明hooks能力用beforeTool返回{ skip: true }/{ stop: true }参考 env-blocker.ts、gitignore-read-files-guard.ts想控制上下文压缩、脱敏→registerMessageBuilder参考 custom-compaction.ts想接入自有模型端点→registerProvider参考 openrouter-provider.ts想接入自动化/可观测→automationctx.telemetry/ctx.logger参考 automation-events.ts 与 telemetry.ts想构建多 Agent 协作→ 目录型插件 skills能力参考 agents-squad/。写插件时的三条纪律全部来自源码契约manifest.capabilities必须非空且与实际使用的 API 一致含hooks时必须有hooks能力workspace 路径一律取ctx.workspaceInfo而非process.cwd()模块级状态视为可被沙箱回收清空的缓存setup保持可重入。【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考