
Cline Hooks 系统实战指南文件钩子与运行时钩子拦截 Agent 全生命周期【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/clineCline 的钩子Hooks系统是拦截和增强自主编码代理行为的两大扩展点文件钩子File Hooks通过.cline/hooks/目录下的外部脚本Bash/Python/TypeScript以 JSON 负载通信运行时钩子Runtime Hooks则以类型化的进程内回调beforeRun、beforeModel、afterTool等供插件直接操作运行时状态。读完本文你将能够按事件命名放置钩子脚本实现工具调用审计、破坏性操作拦截、上下文注入与参数改写读懂钩子的 stdin/stdout JSON 协议并理解文件钩子如何在源码层映射到运行时钩子回调以及何时该改用beforeModel或registerMessageBuilder()插件方案。术语定义先分清三种Hook参考文档 sdk/examples/hooks/README.md 要求在整个生态中统一使用以下术语运行时钩子Runtime hooks类型化的进程内插件/代理生命周期回调如beforeRun、beforeModel、afterTool文件钩子File hooks从钩子配置目录中被发现、以序列化 JSON 负载运行的外部脚本钩子事件Hook events文件钩子使用的序列化负载名称如agent_end、tool_call、prompt_submit。从源码结构看文件钩子本质上是运行时钩子层之上的适配器核心运行时发现钩子文件、把事件名映射到运行时钩子回调然后把匹配的脚本当作子进程执行并向其 stdin 写入 JSON 负载。这一关系由 hook-file-hooks.ts 中的createHookConfigFileHooks()实现——它返回一个标准的AgentHooks对象含beforeRun/beforeTool/afterTool/afterRun/onEvent再通过createHookConfigFileExtension()注册为名为core.hook_config_files的运行时扩展从而与插件钩子共用同一套合并逻辑mergeAgentHooks。选型建议原文档明确想要工作区或用户级配置的 shell/Python 脚本 →用文件钩子编写插件、需要类型化地访问运行时状态或影响模型/工具执行 →用运行时钩子。另外注意执行粒度beforeRun与afterRun包裹一次运行时run()或continue()调用在交互式会话中即一次提交的用户轮次。afterRun对 completed、aborted、failed 三种结果都会触发如果你只关心成功完成请检查result.status。文件钩子侧成功完成对应agent_end事件插件侧则使用afterRun并判断result.status completed。文件钩子事件与运行时钩子的映射表完整继承原文档的映射关系与 hook-file-config.ts 中HOOK_CONFIG_FILE_EVENT_MAP常量一致文件钩子文件名文件钩子事件背后的运行时钩子TaskStartagent_startbeforeRunTaskResumeagent_resumebeforeRun带 resume 上下文UserPromptSubmitprompt_submitbeforeRun加提交的 prompt 上下文PreToolUsetool_callbeforeToolPostToolUsetool_resultafterToolTaskCompleteagent_end完成时的afterRunTaskErroragent_error失败时的afterRunTaskCancelagent_abort带取消/中止原因的afterRun或会话关闭SessionShutdownsession_shutdown会话清理/运行时关闭PreCompact当前未为文件钩子接线无PreCompact在映射表中被显式置为undefined见 hook-file-config.ts#L41即该文件会被识别但不会触发任何事件——压缩场景请走运行时钩子或插件方案。源码中几个值得注意的行为细节agent_resume的判定beforeRun触发时检查环境变量CLINE_HOOK_AGENT_RESUME 1是则派发agent_resume负载否则派发agent_starthook-file-hooks.ts#L927-L934agent_end仅在result.status completed时派发hook-file-hooks.ts#L962-L976abort错误消息含 cancel/abort/interrupt 字样走agent_abort其余错误走agent_error工具类钩子tool_call/tool_result是阻塞执行超时默认 120 秒toolCallTimeoutMs ?? 120000而生命周期类钩子agent_start、prompt_submit、agent_end等以 detached 方式异步派发不阻塞主流程多个同事件钩子的输出会合并mergeHookControlscancel/review任一为true即生效context以换行拼接overrideInput后写的优先。钩子发现机制目录、命名与解释器推断搜索目录paths.ts#L487-L501 中resolveHooksConfigSearchPaths()定义了钩子目录的发现顺序去重后用户级Documents下的 Cline/Hooks 目录resolveDocumentsExtensionPath(Hooks)用户级~/.cline/hooks工作区级旧路径标记 deprecatedworkspace/.config/cline/hooks工作区级当前路径workspace/.cline/hooks。此外CLI 还提供--hooks-dir path选项用于从其他目录加载钩子program.ts#L72-L75默认~/.cline/hooks例如 CI 场景可用cline --hooks-dir ./ci/hooks -i test prompt。文件命名与扩展名钩子文件必须按所处理的事件命名文件名匹配不区分大小写支持的扩展名在 hook-file-config.ts#L49-L62 中枚举无扩展名legacy、.sh、.bash、.zsh、.js、.mjs、.cjs、.ts、.mts、.cts、.py、.ps1。合法的事件基名即上表中的TaskStart、PreToolUse等十个名字。解释器推断inferHookCommand()hook-file-hooks.ts#L327-L370负责为每个钩子文件构造执行命令优先级为Shebang 优先解析首行#!并归一化解释器如python3在 Windows 上改写为py -3且当py命令缺失时会回退到python见getWindowsPythonFallbackCommand按扩展名回退.sh/.bash/.zsh→bash.js/.mjs/.cjs→node.ts/.mts/.cts→bun run.py→python3Windows 为py -3.ps1→pwsh/powershell -File无扩展名默认bash。也就是说文档示例中chmod x与 shebang 主要服务于可移植性即使脚本不可执行核心也会用推断出的解释器命令数组来 spawn。若确实遇到EACCESsubprocess-runner.ts#L60-L76 会给出明确的错误提示。钩子输入负载stdin 上的 JSON所有钩子都会从 stdin 收到一份详细 JSON 事件核心字段由basePayload()/createPayloadBase()构造subprocess.ts#L251-L280clineVersion、hookName、timestamp、taskId、workspaceRoots、userId以及从源码可确认的额外字段sessionContext含rootSessionId、workspaceInfo会话启动时生成的结构化 git/路径元数据让钩子不必自己跑git命令、agent_id、parent_agent_id。PreToolUsetool_call事件{ hookName: tool_call, clineVersion: 1.0.0, timestamp: 2026-01-15T10:30:00Z, taskId: conv-123, workspaceRoots: [/path/to/repo], userId: user, iteration: 1, tool_call: { id: call-456, name: read_files, input: {filePath: /path/to/file.ts} } }除tool_call嵌套字段外负载还带有兼容性的preToolUse段toolName 字符串化的parameters见 hook-file-hooks.ts#L787-L801。PostToolUsetool_result事件{ hookName: tool_result, clineVersion: 1.0.0, timestamp: 2026-01-15T10:30:00Z, tool_result: { id: call-456, name: read_files, input: {filePath: /path/to/file.ts}, output: file contents here, error: null, durationMs: 45 } }TaskStart 等其他生命周期事件{ hookName: agent_start, clineVersion: 1.0.0, timestamp: 2026-01-15T10:30:00Z, taskId: conv-123, workspaceRoots: [/path/to/repo], userId: user }agent_end负载会额外包含iteration计数与turnoutputText、statusagent_error包含errorname/message/stackagent_abort与session_shutdown携带reasonprompt_submit携带userPromptSubmit.prompt。这些字段结构均可在 hook-file-hooks.ts 的各runXxx函数中对照核实。钩子输出stdout 上的控制 JSON钩子必须在 stdout 返回 JSON 对象空{}表示什么都不做。可用控制字段字段类型效果生效事件cancelboolean取消待执行的工具调用PreToolUsereviewboolean暂停并请求用户审查PreToolUsecontextstring向 Agent 下一轮注入上下文PreToolUse、PostToolUseerrorMessagestring向 Agent 暴露一条错误PreToolUseoverrideInputobject执行前替换工具输入PreToolUse这些字段的解析逻辑值得展开subprocess.ts#L74-L83 的HookOutputSchema与toHookControlcontext兼容旧字段contextModification两者都是字符串时优先取contextcontext有 50,000 字符上限MAX_HOOK_CONTEXT_SIZE超长会被截断并附加[hook context truncated]标记防止钩子撑爆 promptsubprocess.ts#L52-L65cancel: true时消息不会被注入为对话上下文errorMessage或兜底的context会作为取消原因cancelReason单独传递避免一个钩子的注入上下文泄漏进另一个钩子的取消原因stdout 解析容错runner 会先查找HOOK_CONTROL\t前缀的行取最后一条作为控制 JSON否则把整个 trim 后的 stdout 当 JSON 解析解析失败会记录parseError并告警但不会让 Agent 崩溃subprocess-runner.ts#L29-L58。这也是日志请走 stderr、stdout 只放 JSON这一约束的底层原因。tool_call/tool_result钩子默认120 秒超时超时进程被SIGKILL并记录hook command timed outDEFAULT_TOOL_HOOK_TIMEOUT_MSsubprocess.ts#L128-L131。cancel/context/overrideInput最终如何影响运行时可在 hook-file-hooks.ts#L536-L584 的beforeToolResultFromControl/afterToolResultFromControl中对照cancel→stopreasoncontext→appendContextoverrideInput→input。官方示例清单Bash / Python / TypeScriptsdk/examples/hooks/ 目录提供了覆盖各场景的可运行示例。文档中的复制命令以sdk/为基准目录从仓库根目录执行时需把路径写成sdk/examples/hooks/...。Bash 示例PreToolUse.sh—— 记录每次工具调用及其输入适合审计 Agent 将要做什么参考实现见 PreToolUse.sh读 stdin、jq提取tool_call.name与参数写 stderr返回{}mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse.sh .cline/hooks/ chmod x .cline/hooks/PreToolUse.sh cline -i do something # 在 stderr 中看到工具调用日志PostToolUse.sh—— 检查工具结果并追加补充上下文mkdir -p .cline/hooks cp sdk/examples/hooks/PostToolUse.sh .cline/hooks/ chmod x .cline/hooks/PostToolUse.sh cline -i do something # 看到工具结果被记录并增强PreToolUse_BlockDestructive.sh—— 拦截 force push、批量删除等破坏性操作mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse_BlockDestructive.sh .cline/hooks/PreToolUse.sh chmod x .cline/hooks/PreToolUse.sh cline -i clean up the repo # 破坏性操作将被拦截PreToolUse_RequireReview.sh—— 对关键文件的写入强制人工审查mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse_RequireReview.sh .cline/hooks/PreToolUse.sh chmod x .cline/hooks/PreToolUse.sh cline -i update dependencies # 关键文件写入会暂停等待审查PreToolUse_InjectFileContext.sh—— 在执行前抽取并注入文件上下文相关测试文件、lock 文件、环境信息mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse_InjectFileContext.sh .cline/hooks/PreToolUse.sh chmod x .cline/hooks/PreToolUse.sh cline -i review the configuration # 相关文件会被自动提及TaskStart.sh/TaskComplete.sh/SessionShutdown.sh—— 跟踪 Agent 会话生命周期开始、结束、关闭mkdir -p .cline/hooks cp sdk/examples/hooks/TaskStart.sh .cline/hooks/ cp sdk/examples/hooks/TaskComplete.sh .cline/hooks/ cp sdk/examples/hooks/SessionShutdown.sh .cline/hooks/ chmod x .cline/hooks/Task*.sh .cline/hooks/SessionShutdown.sh cline -i do something # 会话生命周期被记录Python 示例PreToolUse.py—— Python 版工具调用日志与过滤mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse.py .cline/hooks/ chmod x .cline/hooks/PreToolUse.py cline -i do something # Python 钩子记录工具调用PostToolUse.py—— Python 版后置结果增强mkdir -p .cline/hooks cp sdk/examples/hooks/PostToolUse.py .cline/hooks/ chmod x .cline/hooks/PostToolUse.py cline -i do something # Python 钩子增强工具结果PreToolUse_InjectContext.py—— Python 版上下文注入含文件分析测试文件、配置文件、lock 文件、Node.js 版本、git 分支mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse_InjectContext.py .cline/hooks/PreToolUse.py chmod x .cline/hooks/PreToolUse.py cline -i add a new feature # 相关文件与环境信息被注入TypeScript 示例PreToolUse.ts—— TypeScript 钩子用于进阶的工具调用过滤与日志mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse.ts .cline/hooks/ chmod x .cline/hooks/PreToolUse.ts cline -i do something # TypeScript 钩子通过 bun 执行PostToolUse.ts—— TypeScript 后置执行钩子mkdir -p .cline/hooks cp sdk/examples/hooks/PostToolUse.ts .cline/hooks/ chmod x .cline/hooks/PostToolUse.ts cline -i do something # TypeScript 钩子通过 bun 执行PreToolUse_ModifyInput.ts—— 执行前改写工具输入路径归一化、补默认值、清洗mkdir -p .cline/hooks cp sdk/examples/hooks/PreToolUse_ModifyInput.ts .cline/hooks/PreToolUse.ts chmod x .cline/hooks/PreToolUse.ts cline -i install dependencies # npm install 自动加上 --save-exact快速上手三步把钩子拷到项目文件钩子放入.cline/hooks/或~/.cline/hooks、--hooks-dir指定目录且文件名必须等于事件名赋予执行权限chmod x .cline/hooks/PreToolUse.*测试cline -i test prompt或指定目录cline --hooks-dir ./my-hooks -i test prompt。常见钩子模式可直接复制以下模式完整继承自原文档均只依赖jq/标准库与上文协议一一对应。1. 记录并放行Bash#!/usr/bin/env bash input$(cat) tool$(echo $input | jq -r .tool_call.name) echo Action: $tool 2 echo {}2. 向下一轮注入上下文#!/usr/bin/env bash input$(cat) tool$(echo $input | jq -r .tool_call.name) if [ $tool run_commands ]; then branch$(git branch --show-current 2/dev/null) echo {\context\: \Current branch: $branch\} else echo {} fi3. 执行前修改工具输入#!/usr/bin/env bash input$(cat) tool$(echo $input | jq -r .tool_call.name) file$(echo $input | jq -r .tool_call.input.filePath) if [ $tool read_files ] [[ $file ~/* ]]; then normalized${file/#\~/$HOME} echo {\overrideInput\: {\filePath\: \$normalized\}} else echo {} fi4. 拦截特定工具或命令#!/usr/bin/env bash input$(cat) tool$(echo $input | jq -r .tool_call.name) cmd$(echo $input | jq -r .tool_call.input.command // empty) if [ $tool run_commands ] [[ $cmd ~ git\ push\ --force ]]; then echo {cancel: true, errorMessage: Force push is blocked.} else echo {} fi5. 对敏感文件要求审查#!/usr/bin/env bash input$(cat) tool$(echo $input | jq -r .tool_call.name) file$(echo $input | jq -r .tool_call.input.filePath // empty) if ([ $tool editor ] || [ $tool write_file ]) \ [[ $file ~ (package\.json|\.env|secrets|tsconfig) ]]; then echo {review: true, context: This will modify a critical file} else echo {} fi6. Python解析并操作 JSON#!/usr/bin/env python3 import sys import json event json.load(sys.stdin) tool_name event.get(tool_call, {}).get(name, ) tool_input event.get(tool_call, {}).get(input, {}) if tool_name read_files: file_path tool_input.get(filePath, ) if file_path.endswith(.test.ts): print(json.dumps({context: This is a test file})) else: print(json.dumps({})) else: print(json.dumps({}))7. TypeScript类型安全 异步操作#!/usr/bin/env bun interface HookEvent { tool_call: { name: string; input: Recordstring, unknown }; } const event: HookEvent JSON.parse(await Bun.stdin.text()); const toolName event.tool_call.name; if (toolName run_commands) { const branch await getGitBranch(); console.log(JSON.stringify({ context: Branch: ${branch} })); } else { console.log(JSON.stringify({})); } async function getGitBranch(): Promisestring { return main; }运行时钩子进阶自定义压缩Custom Compaction文件钩子只能观察生命周期事件对消息压缩这类需要直接改写请求的高级场景应使用 TypeScript运行时钩子插件。仓库提供了完整示例 custom-compaction-hook.example.ts它通过hooks.beforeModel估算请求体积并在向模型供应商发起请求前把较旧的中间历史替换为一条摘要消息。原文档的安装与验证流程为cline plugin install 示例文件位置 --cwd . cline -i Search the codebase for dispatcher usage, then summarize it原文档以仓库 URL 安装该示例本地开发时对应文件即sdk/examples/hooks/custom-compaction-hook.example.ts。两种压缩方案的取舍示例扩展点消息形态适用场景custom-compaction-hook.example.ts位于.cline/plugins/hooks.beforeModel运行时钩子Agent 运行时请求消息含tool-call、tool-result、reasoning、image、file等运行时 part需要运行时钩子上下文、当前运行时快照或直接改写请求对象的场景plugins/custom-compaction.ts参考 sdk/examples/plugins/ 下的custom-compaction.tsapi.registerMessageBuilder()运行时消息转换为 SDK/供应商绑定Message[]之后的形态大多数可复用的、插件自有的消息改写与压缩策略原文档的结论普通插件自有的供应商消息改写优先用registerMessageBuilder()——它在核心消息管线中运行、且先于内置的 provider-safety builder只有当压缩逻辑需要运行时钩子上下文、或必须检查精确的运行时请求对象时才使用beforeModel。调试钩子的三种手段1. 打印钩子调用轨迹cline --verbose your prompt2. 手动喂 JSON 测试单个钩子无需启动 Agentecho {tool_call: {name: read_files, input: {filePath: test.ts}}} | .cline/hooks/PreToolUse.sh3. 检查钩子输出的 JSON 结构.cline/hooks/PreToolUse.sh input.json | jq .从源码看手动测试之所以可行是因为钩子子进程的全部契约就是stdin 收 JSON、stdout 回 JSONsubprocess-runner.ts#L126-L220。另外核心还会把审计负载以 JSONL 追加写入钩子日志CLINE_HOOKS_LOG_PATH或~/.cline数据目录下的hooks.jsonl见 hook-file-hooks.ts#L598-L607可用它回溯每一次事件的完整负载。实战注意事项原文档 Tips 全量整理--yolo模式下钩子被禁用——需使用--act或--plan模式启用钩子日志一律写 stderr——stdout 被控制 JSON 独占保持钩子快——它们在任何一次工具调用前后都会执行性能直接影响 Agent 吞吐且工具钩子有 120 秒硬超时用jq做 JSON 提取——JSON 解析容易出错jq是最安全的提取方式允许多钩子共存——不同事件文件可同时放在.cline/hooks/同一事件的多个文件其输出按上文合并规则叠加自定义目录加载——--hooks-dir ./ci/hooks可把钩子集中放在仓库内的 CI 专用目录便于团队统一审计策略。小结Cline 钩子系统的设计可以概括为一句话用统一的运行时钩子回调beforeRun/beforeTool/afterTool/afterRun/onEvent作为单一扩展内核文件钩子只是把其中五个回调桥接成按事件命名的外部脚本 stdin/stdout JSON的适配层。掌握 sdk/examples/hooks/README.md 中的事件映射表与输入输出协议配合 sdk/packages/core/src/hooks/ 下的hook-file-config.ts发现与命名、hook-file-hooks.ts事件桥接与控制合并、subprocess.ts负载与控制字段、subprocess-runner.ts子进程执行与容错四个文件你就能从照着示例拷脚本进阶到按团队审计规范定制拦截策略并在需要改写模型请求时平滑切换到beforeModel/registerMessageBuilder()插件方案。【免费下载链接】clineAutonomous coding agent as an SDK, IDE extension, or CLI assistant.项目地址: https://gitcode.com/GitHub_Trending/cl/cline创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考