当前位置: 首页 > news >正文

Claude Code 逆向工程分析,探索最新Agent设计

Claude Code 逆向工程分析

github上最近出现了一个Claude Code逆向工程研究仓库。虽然Claude Code没有开源代码,但是由于其是基于Node.JS开发就为后续进行逆向提供了可能。作者通过LLM+一套SOP逆向重建了整个Claude Code框架。虽然这种方式避免不了幻觉。但对于我们来探索Claude Code的设计,未来用在咱们自己项目设计上是绰绰有余的,好了回到正题,咱们按照这个项目提供的SOP一个一个问题的来拆解Claude Code的设计中我最关心的几个点。

github项目


Claude Code 的Agent Loop

在这里插入图片描述


Agent Loop的循环是如何进行?

大家注意这个agent loop,Claude Code的设计有很多,但是核心基本就是围绕上下文注入->决策->工具调用->状态更新->结果评估->是否回调这个循环来开展。

主循环采用动态继续机制没有固定的轮数,通过preventContinuation标志和递归调用实现智能循环控制。preventContinuation标志的改变不再继续循环大概有三种情况,

  • 1.用户主动中断的时候,多个位置插入了yield检查中断点,支持实时用户交互引导,链式传递中断信号。
  • 2.系统级别的错误,工具执行失败无法重试,模型调用失败无备用模型等。考虑到模型降级等因素,循环同时引入信号E采用默认false策略,只有在模型降级时才重新设为true进行对本轮循环进行重试。
  • 3.工具调用结束没有产生新的信息或者状态变换,任务模型明确判断任务完成,不需要调用新的工具。当然在Claude Code判断上任务完成上是工程上是多因素的,包含状态变化,所有工具调用完成,错误信息,重复内容去重,语义分析,上下文感知等因素。

源码位置:

  • 主循环: chunks.95.mjs:315-330 - nO函数
  • 中断检查: chunks.94.mjs:1595-1600 - yield中断点
  • 循环控制: chunks.95.mjs:810-850 - preventContinuation标志

核心源码实现:

// chunks.95.mjs:315-330 - nO主循环函数
async function* nO(J, B, Q, I, G, Z, F, Y, W) {let C = [];let E = false;while (E) {E = false;try {for await (let _ of wu(Ie1(J, Q), Qe1(B, I), Z.options.maxThinkingTokens, Z.options.tools, Z.abortController.signal, {getToolPermissionContext: Z.getToolPermissionContext,model: K,prependCLISysprompt: true,toolChoice: void 0,  // 自由选择工具isNonInteractiveSession: Z.options.isNonInteractiveSession,fallbackModel: Y})) {if (yield _, _.type === "assistant") C.push(_)}} catch (_) {if (_ instanceof wH1 && Y) {K = Y, E = true, C.length = 0, Z.options.mainLoopModel = Y;// 模型降级处理continue}throw _}}// 工具调用处理let N = C.flatMap((_) => _.message.content.filter((k) => k.type === "tool_use"));if (!N.length) return;let q = [], O = false;for await (let _ of hW5(N, C, G, Z)) {if (yield _, _ && _.type === "system" && _.preventContinuation) O = true;q.push(...JW([_]).filter((k) => k.type === "user"))}if (O) return;  // 循环终止条件// 递归调用继续循环yield* nO([...J, ...C, ...R], B, Q, I, G, L, F, Y, W)
}

意图识别是怎么实现的?

Claude Code的任务理解机制采用多层次语义分析架构,

  • 1.通过JN5函数对用户消息进行内容提取和格式标准化,
  • 2.由于Claude Code支持多种模式的输入,通过前缀识别模式(如"!“、”@“、”#“等特殊字符)和命令识别(如"exit”、“help”、"clear"等系统命令)进行快速指令解析和系统操作识别,
  • 3.然后通过系统提示词指导和工具描述,由LLM驱动的语义理解机制进行任务类型识别和分类(识别搜索、分析、创建、修改、调试等任务类型),
  • 4.同时结合对话历史进行上下文感知理解,识别任务的连续性和依赖关系,
  • 5.通过XN5函数进行任务复杂度评估,
    最终生成包含任务类型、意图、复杂度、推荐工具序列和执行策略的结构化理解结果,为后续的复杂度评估和工具选择决策提供准确的语义基础,实现了从原始用户输入到可执行任务计划的智能转换。

源码位置:

  • JN5函数: chunks.99.mjs:2750-2780 - 消息内容提取
  • 前缀识别: chunks.100.mjs:2030-2050 - 特殊字符处理
  • XN5函数: chunks.99.mjs:2780-2800 - 复杂度评估

核心源码实现:

// chunks.99.mjs:2750-2780 - 消息内容提取函数
function JN5(A) {if (typeof A.message.content === "string") return A.message.content;return A.message.content.map((B) => B.type === "text" ? B.text : "").join("")
}// chunks.99.mjs:2780-2800 - 复杂度分类函数
function FN5(A) {let B = [["HIGHEST", mw1.HIGHEST],    // 31999分["MIDDLE", mw1.MIDDLE],      // 10000分["BASIC", mw1.BASIC]         // 4000分];for (let [Q, I] of B)if (XN5(A, Q)) return I;return mw1.NONE  // 0分
}// chunks.99.mjs:2800-2820 - 模式匹配函数
function XN5(A, B) {for (let Q of Object.values(YN5)) {let I = Q[B];for (let {pattern: G,needsWordBoundary: Z}of I)if ((Z ? new RegExp(`\\b${G}\\b`) : new RegExp(G)).test(A)) return true}return false
}

上下文结构是什么样的?

Claude Code的上下文结构采用三层记忆架构设计,短期记忆(当前会话)+ 中期记忆(压缩历史)+ 长期记忆(文件系统)。通过Array和Map双模式存储消息(短期记忆),当Token使用率达到阈值时触发AU2函数的八段式智能压缩(中期记忆),将对话历史压缩为包含
用户的主要请求和意图、关键技术概念、相关的文件位置、出现的问题及其解决方案、问题解决的思路方法结果、所有用户消息的完整记录和时间线、 待完成的任务和当前工作及下一步的结构化摘要同时通过工具结果机制安全注入文件内容并附加恶意代码检测提醒,支持parentUuid的消息线程系统实现对话分支,采用60%/80%/92%的渐进式警告机制和文件恢复策略,最终实现了在有限上下文窗口中维持长时间对话的能力,确保信息完整性和安全性。如用户偏好等长期记忆会使用md文件记录下来。

源码位置:

  • AU2压缩函数: chunks.94.mjs:1780-1850 - 八段式压缩算法
  • 消息存储: chunks.94.mjs:1580-1620 - Array和Map双模式
  • 阈值检测: chunks.95.mjs:321-330 - 92%阈值触发

核心源码实现:

// chunks.94.mjs:1595-1600 - yield中断点实现
for await (let X1 of nO(O, _, R, T, G, {abortController: D,options: {isNonInteractiveSession: J ?? false,tools: C,commands: [],debug: Y,verbose: W,mainLoopModel: L,maxThinkingTokens: s$(O),mcpClients: [],mcpResources: {}},getToolPermissionContext: F,readFileState: X,getQueuedCommands: () => [],removeQueuedCommands: () => {},setInProgressToolUseIDs: V,agentId: q
})) {if (X1.type !== "assistant" && X1.type !== "user" && X1.type !== "progress") continue;if (k.push(X1), X1.type !== "assistant" && X1.type !== "user") continue;// 关键中断点:yield检查let v = AQ(k);for (let D1 of AQ([X1]))for (let N1 of D1.message.content) {if (N1.type !== "tool_use" && N1.type !== "tool_result") continue;// 实时中断检查yield {type: "progress",toolUseID: K ? `synthesis_${I.message.id}` : `agent_${B}_${I.message.id}`,data: {message: D1,normalizedMessages: v,type: "agent_progress"}}}
}

上下文感知是怎么做的?

Claude Code的上下文感知通过五个核心机制实现:

  • 识别任务连续性通过分析用户消息与历史对话的关键词重叠度、文件引用模式和当前任务状态来判断是否为同一任务的延续;
  • 维护对话结构通过parentUuid链式引用系统支持对话分支和复杂交互场景,每条消息都可以链接到父消息形成完整的对话树;
  • 智能上下文压缩通过AU2函数在92%阈值触发时将对话历史压缩为8个结构化部分(主要请求、技术概念、文件信息、错误修复、问题解决、用户消息、待办任务、当前工作),确保关键信息不丢失;
  • 动态相关性评估实时计算每条消息与当前上下文的相关性分数,通过关键词匹配、文件引用、时间距离和任务关联四个维度进行加权评估;
  • 依赖关系管理自动识别任务间的依赖关系,如编辑操作需要先读取文件、bash命令需要安全检查等,确保任务执行的正确顺序和安全性。

源码位置:

  • parentUuid系统: chunks.94.mjs:1595-1600 - 消息链式引用
  • 相关性评估: chunks.95.mjs:410-425 - 动态评分算法
  • 依赖管理: chunks.95.mjs:490-520 - 任务依赖检测

工具,agent Loop的核心?

通过前面主循环机制,我们能发现Claude Code实现Agent的核心就是这些工具,可以说工具即agent,Claude Code包含16个核心工具,分为文件操作、搜索发现、系统交互、专业格式、网络访问、项目管理、特殊功能七大类。具体包括:文件操作类(Read、Write、Edit、MultiEdit、LS)、搜索发现类(Glob、Grep、Task)、系统交互类(Bash)、专业格式类(NotebookRead、NotebookEdit)、网络访问类(WebFetch、WebSearch)、项目管理类(TodoRead、TodoWrite)、特殊功能类(exit_plan_mode),每个工具都有明确的职责分工和智能调度机制,通过LLM决策和系统优先级双重控制实现高效安全的工具执行

源码位置:

  • 工具定义: chunks.90.mjs:1720-1750 - 工具注册表
  • 工具调度: chunks.95.mjs:395-420 - 智能调度机制
  • 工具权限: cli.mjs:699-704 - 权限控制

核心源码实现:

// chunks.90.mjs:1720-1750 - 工具注册表定义
NR6 = n.object({name: n.string(),description: n.optional(n.string()),inputSchema: n.object({type: n.literal("object"),properties: n.optional(n.object({}).passthrough())}).passthrough(),annotations: n.optional(UR6)}).passthrough()// chunks.95.mjs:395-420 - 智能调度机制
async function* hW5(A, B, Q, I) {for (let {isConcurrencySafe: G,blocks: Z}of mW5(A, I))if (G) yield* uW5(Z, B, Q, I);  // 并发安全工具else yield* dW5(Z, B, Q, I)     // 顺序执行工具
}// chunks.95.mjs:410-425 - 工具安全性分析
function mW5(A, B) {return A.reduce((Q, I) => {let G = B.options.tools.find((Y) => Y.name === I.name),Z = G?.inputSchema.safeParse(I.input),D = Z?.success ? Boolean(G?.isConcurrencySafe(Z.data)) : false;if (D && Q[Q.length - 1]?.isConcurrencySafe) Q[Q.length - 1].blocks.push(I);else Q.push({isConcurrencySafe: D,blocks: [I]});return Q}, [])
}

工具的调用决策是怎么实现的?

  • Claude Code目前的路由决策:一种是特殊情况下的强制选择工具,比如用户输入以"#"开头的内容时,系统会识别为内存保存模式,强制LLM调用Edit工具保存用户内容。另一种是采用宏观提示词驱动的LLM智能决策+系统层面微观进行复杂度评估算法微调的自由选择工具。
  • 以Task工具为例,通过精心设计的提示词模板指导LLM根据任务特征自动判断是否使用Task工具:当用户请求涉及关键词搜索(如"config"、“logger”)、文件定位问题(如"哪个文件实现了X")或需要多轮globbing和grepping的复杂查询时,提示词会强烈推荐使用Task工具。
  • 同时,系统通过一套复杂度评估方法,通过WN5函数对用户消息进行文本提取和FN5函数进行复杂度分类,使用XN5函数通过正则表达式匹配预定义的复杂度模式库,根据复杂度高低,如用户输入"深入思考一下"这些关键词匹配到高复杂度自动触发多Agent并行处理模式,TodoWrite工具进行任务管理等。

源码位置:

  • 强制选择: chunks.95.mjs:822-825 - toolChoice强制模式
  • 自由选择: chunks.95.mjs:321 - toolChoice: void 0

核心源码实现:

// chunks.95.mjs:822-825 - 强制工具选择模式
toolChoice: {name: nJ.name,  // 指定工具名称type: "tool"    // 强制使用工具
}// chunks.95.mjs:321 - 自由工具选择模式
toolChoice: void 0,  // 允许AI自由选择工具// chunks.95.mjs:395-400 - 并发控制常量
const gW5 = 10;  // 最大并发工具数量限制// chunks.95.mjs:490-520 - 工具查找和执行
async function* MH1(A, B, Q, I) {let G = A.name,Z = I.options.tools.find((Y) => Y.name === G);// 工具权限检查if (I.setInProgressToolUseIDs((Y) => new Set([...Y, A.id])), !Z) {E1("tengu_tool_use_error", {error: `No such tool available: ${G}`,toolName: G,toolUseID: A.id,isMcp: false});yield K2({content: [{type: "tool_result",content: `Error: No such tool available: ${G}`,is_error: true,tool_use_id: A.id}],toolUseResult: `Error: No such tool available: ${G}`});Oe1(I, A.id);return}// 工具执行let D = A.input;try {if (I.abortController.signal.aborted) {E1("tengu_tool_use_cancelled", {toolName: Z.name,toolUseID: A.id,isMcp: Z.isMcp ?? false});let Y = kw2(A.id);yield K2({content: [Y],toolUseResult: Ju});Oe1(I, A.id);return}for await (let Y of pW5(Z, A.id, D, I, Q, B)) yield Y} catch (Y) {b1(Y instanceof Error ? Y : new Error(String(Y)));yield K2({content: [{type: "tool_result",content: "Error calling tool",is_error: true,tool_use_id: A.id}],toolUseResult: "Error calling tool"})}Oe1(I, A.id)
}
  • WN5函数: chunks.99.mjs:2736-2750 - 复杂度评估核心
  • 提示词模板: docs/code-prompts/main-system-prompt.txt

Claude Code的工具执行编排机制?

  • Claude Code的工具执行机制采用双层分工架构:LLM负责做出工具调用决策、调用顺序和参数设计;系统层面则负责微观优化,
  • 通过mW5函数进行工具安全性分析(将工具分为并发安全和顺序执行两类),通过calculatePriority函数计算根据工具优先级(如Plan工具优先级0最高,删除类工具优先级6最低),上下文相关性加分,用户偏好加分,在LLM决定的顺序基础上进行智能微调,确保安全工具(如Read、LS、Glob、Grep等只读操作)能够并发执行以提高效率,不安全工具(如Edit、Bash、Delete、Task等写操作)按优先级顺序执行以保证数据一致性,同时通过gW5=10的并发限制和实时中断检查机制确保系统稳定性和用户实时干预能力,实现了智能决策与系统优化的完美结合。

源码位置:

  • mW5函数: chunks.95.mjs:410-425 - 工具安全性分析
  • 并发控制: chunks.95.mjs:395-400 - gW5=10并发限制
  • 优先级计算: chunks.95.mjs:490-520 - calculatePriority函数

Task工具,无状态SubAgent机制?

  • 在这些工具中这里最重要的无疑就是Task工具,这是Claude Code最具创新性的组件,Task工具本质上就是实现了真正的无状态SubAgent系统。每次调用Task工具相当于"fork"出一个新的Agent实例,具有完整的工具访问权限但独立的执行上下文。
  • SubAgent采用无状态设计,每个调用完全独立,无法多轮交互,只能接收一次指令并返回最终报告,通过完全隔离的执行环境确保安全性和可靠性。
    通过I2A函数实现SubAgent实例化,每个SubAgent拥有独立的会话ID、执行上下文和工具权限,通过KN5函数进行结果聚合。
  • Task工具特别适用于复杂搜索任务、多文件分析和需要多工具协调的复杂任务,通过智能路由决策自动判断何时使用SubAgent而非直接工具调用,实现了复杂任务的分解和并行处理能力。

源码位置:

  • I2A函数: chunks.94.mjs:802-820 - SubAgent实例化
  • KN5函数: chunks.95.mjs:810-840 - 结果聚合
  • Task工具: chunks.90.mjs:1720-1750 - Task工具定义

核心源码实现:

// chunks.99.mjs:9980474-9983061 - SubAgent实例化函数
async function* I2A(A, B, Q, I, G, Z = {}) {let {abortController: D,options: {debug: Y,verbose: W,isNonInteractiveSession: J},getToolPermissionContext: F,readFileState: X,setInProgressToolUseIDs: V,tools: C} = Q, {isSynthesis: K = false,systemPrompt: E,model: N} = Z, q = VN5(), O = [K2({content: A})], [R, T, L] = await Promise.all([qW(), RE(), N ?? J7()]), _ = await (E ?? ma0(L, Array.from(Q.getToolPermissionContext().additionalWorkingDirectories))), k = [], i = 0, x = void 0;// SubAgent主循环for await (let X1 of nO(O, _, R, T, G, {abortController: D,options: {isNonInteractiveSession: J ?? false,tools: C,commands: [],debug: Y,verbose: W,mainLoopModel: L,maxThinkingTokens: s$(O),mcpClients: [],mcpResources: {}},getToolPermissionContext: F,readFileState: X,getQueuedCommands: () => [],removeQueuedCommands: () => {},setInProgressToolUseIDs: V,agentId: q})) {if (X1.type !== "assistant" && X1.type !== "user" && X1.type !== "progress") continue;if (k.push(X1), X1.type !== "assistant" && X1.type !== "user") continue;// 工具调用处理let v = AQ(k);for (let D1 of AQ([X1]))for (let N1 of D1.message.content) {if (N1.type !== "tool_use" && N1.type !== "tool_result") continue;if (N1.type === "tool_use") {if (i++, N1.name === "exit_plan_mode" && N1.input) {let u1 = hO.inputSchema.safeParse(N1.input);if (u1.success) x = {plan: u1.data.plan}}}yield {type: "progress",toolUseID: K ? `synthesis_${I.message.id}` : `agent_${B}_${I.message.id}`,data: {message: D1,normalizedMessages: v,type: "agent_progress"}}}}// 返回结果let s = UD(k);if (s && oK1(s)) throw new NG;if (s?.type !== "assistant") throw new Error(K ? "Synthesis: Last message was not an assistant message" : `Agent ${B+1}: Last message was not an assistant message`);let d = (s.message.usage.cache_creation_input_tokens ?? 0) + (s.message.usage.cache_read_input_tokens ?? 0) + s.message.usage.input_tokens + s.message.usage.output_tokens,F1 = s.message.content.filter((X1) => X1.type === "text");await CZ0([...O, ...k]), yield {type: "result",data: {agentIndex: B,content: F1,toolUseCount: i,tokens: d,usage: s.message.usage,exitPlanModeInput: x}}
}// chunks.99.mjs:9979615-9980473 - 结果聚合提示词生成
function KN5(A, B) {let Q = B.sort((I, G) => I.agentIndex - G.agentIndex).map((I, G) => {let Z = I.content.filter((D) => D.type === "text").map((D) => D.text).join(``);return `== AGENT ${G+1} RESPONSE ==
${Z}
`}).join(``);return `Original task: ${A}I've assigned multiple agents to tackle this task. Each agent has analyzed the problem and provided their findings.${Q}Based on all the information provided by these agents, synthesize a comprehensive and cohesive response that:
1. Combines the key insights from all agents
2. Resolves any contradictions between agent findings
3. Presents a unified solution that addresses the original task
4. Includes all important details and code examples from the individual responses
5. Is well-structured and completeYour synthesis should be thorough but focused on the original task.`
}

工具运行的内部流程,以Edit工具为例?

Claude Code的工具运行内部流程采用分层调度架构,以Edit工具为例:调用请求生成后,执行时通过MH1函数查找工具对象,使用Zod进行参数验证(验证file_path、edits等参数结构),调用validateInput进行输入验证,检查文件权限和前置条件(如必须先读取文件),然后执行核心逻辑(读取文件、应用字符串替换、写入文件),最后通过mapToolResultToToolResultBlockParam映射结果,记录事件日志,返回执行结果给LLM继续对话。整个流程包含完整的错误处理、权限验证、状态管理和事件记录机制,确保工具执行的安全性和可靠性。

源码位置:

  • MH1函数: chunks.95.mjs:490-520 - 工具查找
  • Zod验证: chunks.94.mjs:339-344 - Edit工具参数模式
  • 核心逻辑: chunks.91.mjs:1-50 - Edit工具实现

并发工具是怎么做结果聚合的?

Claude Code的多Agent并发执行结果智能合并和排序通过UH1并发调度器实现最大10个Agent的并发执行,通过Agent索引排序或者工具执行顺序确保结果按执行顺序排列,通过KN5函数生成提示词,然后由大模型进行智能处理,而不是通过传统的算法实现。部分提示词如下:
基于所有这些Agent提供的信息,合成一个全面且连贯的响应,要求:

  1. 整合所有Agent的关键见解
  2. 解决Agent发现之间的任何矛盾
  3. 提出一个统一的解决方案来应对原始任务
  4. 包含各个响应中的重要细节和代码示例
  5. 结构良好且完整
    你的合成应该全面但专注于原始任务。

源码位置:

  • UH1调度器: chunks.95.mjs:395-420 - 并发控制
  • KN5函数: chunks.95.mjs:810-840 - 结果聚合提示词生成

Claude Code的状态更新机制有哪些?

Claude Code的状态更新机制采用多级状态更新:

  • 全局状态管理:通过j0函数实现全局状态更新,支持状态合并和缓存失效
  • React状态管理:使用useState和useContext实现组件级状态管理
  • 异步状态更新:支持异步操作和防抖机制
  • 缓存优化:通过文件修改时间验证实现智能缓存
  • 事件记录:所有状态变更都会记录相应的事件日志
  • 批量更新:支持批量状态更新以提高性能

源码位置:

  • j0函数: chunks.88.mjs:366-372 - 全局状态更新
  • 缓存机制: chunks.88.mjs:3720-3750 - ZA函数智能缓存
  • 事件记录: cli.mjs:1684 - E1函数事件记录

核心源码实现:

// chunks.88.mjs:366-372 - 全局状态更新核心函数
function j0(A) {GD0(UX(), {...A,projects: $_(UX(), NX).projects}, NX), N_.config = null, N_.mtime = 0
}// chunks.88.mjs:3720-3750 - 智能缓存机制
function ZA() {try {let A = x1().existsSync(UX()) ? x1().statSync(UX()) : null;if (N_.config && A) {if (A.mtimeMs <= N_.mtime) return N_.config  // 缓存命中}let B = Qv1($_(UX(), NX));if (A) N_ = {config: B,mtime: A.mtimeMs};else N_ = {config: B,mtime: Date.now()};return Qv1(B)} catch {return Qv1($_(UX(), NX))}
}// chunks.88.mjs:435-442 - 智能差异写入
function GD0(A, B, Q) {let I = sf4(A),G = x1();if (!G.existsSync(I)) G.mkdirSync(I);let Z = Object.fromEntries(Object.entries(B).filter(([D, Y]) => JSON.stringify(Y) !== JSON.stringify(Q[D])));  // 只写入真正变更的配置项eM(A, JSON.stringify(Z, null, 2))
}

Claude Code的状态更新的核心是怎么运作的?

这其中,j0函数是Claude Code全局状态更新的核心函数,通过状态合并机制使用展开运算符将新状态与现有配置合并,同时保护关键配置项不被覆盖;通过GD0函数实现智能差异写入,只写入真正变更的配置项,避免不必要的文件操作;通过清除缓存对象和时间戳重置实现缓存失效机制,确保状态更新后立即生效;包含完整的文件系统错误处理和配置解析错误处理,提高系统稳定性;通过差异检测和智能缓存机制进行性能优化,最小化文件I/O操作。整个机制确保了状态更新的原子性、一致性和性能,是Claude Code配置管理的核心基础设施。

源码位置:

  • j0函数: chunks.88.mjs:366-372 - 核心状态更新
  • GD0函数: chunks.88.mjs:435-442 - 智能差异写入
  • 缓存失效: chunks.88.mjs:3720-3750 - 时间戳验证

ga0系统提示词?

ga0系统提示词生成机制是Claude Code的核心身份和行为指导系统,通过模块化设计将基础身份定义、安全策略、环境信息、工具指导等组件动态组装成完整的系统提示词。该机制采用ga0()函数定义产品身份,yj()函数生成主系统提示词,ha0()函数收集环境信息,通过常量注入安全策略和文档链接,并根据可用工具动态调整内容。整个系统强调简洁性(4行内响应)、安全性(防御性安全策略)、工具集成(任务管理和并行调用)和代码规范(遵循现有约定),确保Claude Code在CLI环境中提供安全、高效、用户友好的交互体验。

比如下面的安全策略提示词模板

安全策略模板

IMPORTANT: Assist with defensive security tasks only. Refuse to create, modify, or improve code that may be used maliciously. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation.

源码位置:

  • ga0函数: chunks.89.mjs:187-190 - 产品身份定义
  • yj函数: chunks.89.mjs:840-900 - 主系统提示词生成
  • ha0函数: chunks.89.mjs:370-390 - 环境信息收集
  • 提示词模板: docs/code-prompts/main-system-prompt.txt

核心源码实现:

// chunks.89.mjs:187-190 - 产品身份定义
function ga0() {return `You are ${m0}, Anthropic's official CLI for Claude.`
}// chunks.89.mjs:8987504-8987752 - 安全策略模板
va0 = "IMPORTANT: Assist with defensive security tasks only. Refuse to create, modify, or improve code that may be used maliciously. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation."// chunks.89.mjs:840-900 - 主系统提示词生成
async function yj(A, B, Q, I) {let G = new Set(A.map((D) => D.name)),Z = await xC("claude_code_docs_config", wL6);return [`
You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.${va0}
IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.# Tone and style
You should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, to make sure the user understands what you are doing (this is especially important when you are running a command that will make changes to the user's system).
Remember that your output will be displayed on a command line interface. Your responses can use Github-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.
Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like ${ZK} or code comments as means to communicate with the user during the session.
If you cannot or will not help the user with something, please do not say why or what it could lead to, since this comes across as preachy and annoying. Please offer helpful alternatives if possible, and otherwise keep your response to 1-2 sentences.
Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.
IMPORTANT: You should minimize output tokens as much as possible while maintaining helpfulness, quality, and accuracy. Only address the specific query or task at hand, avoiding tangential information unless absolutely critical for completing the request. If you can answer in 1-3 sentences or a short paragraph, please do.
IMPORTANT: You should NOT answer with unnecessary preamble or postamble (such as explaining your code or summarizing your action), unless the user asks you to.
IMPORTANT: Keep your responses short, since they will be displayed on a command line interface. You MUST answer concisely with fewer than 4 lines (not including tool use or code generation), unless user asks for detail. Answer the user's question directly, without elaboration, explanation, or details. One word answers are best. Avoid introductions, conclusions, and explanations. You MUST avoid text before/after your response, such as "The answer is <answer>.", "Here is the content of the file..." or "Based on the information provided, the answer is..." or "Here is what I will do next...". Here are some examples to demonstrate appropriate verbosity:
<example>
user: 2 + 2
assistant: 4
</example><example>
user: what is 2+2?
assistant: 4
</example><example>
user: is 11 a prime number?
assistant: Yes
</example><example>
user: what command should I run to list files in the current directory?
assistant: ls
</example><example>
user: what command should I run to watch files in the current directory?
assistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]
npm run dev
</example><example>
user: How many golf balls fit inside a jetta?
assistant: 150000
</example><example>
user: what files are in the directory src/?
assistant: [runs ls and sees foo.c, bar.c, baz.c]
user: which file contains the implementation of foo?
assistant: src/foo.c
</example><example>
user: write tests for new feature
assistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]
</example># Proactiveness
You are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:
1. Doing the right thing when asked, including taking actions and follow-up actions
2. Not surprising the user with actions you take without asking
For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.
3. Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.# Following conventions
When making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.
- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).
- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.
- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.
- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.# Code style
- IMPORTANT: DO NOT ADD ***ANY*** COMMENTS unless asked${G.has(yG.name)||G.has(oN.name)?`# Task Management
You have access to the ${yG.name} and ${oN.name} tools to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving the user visibility into your progress.
These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps. If you do not use this tool when planning, you may forget to do important tasks - and that is unacceptable.It is critical that you mark todos as completed as soon as you are done with a task. Do not batch up multiple tasks before marking them as completed.Examples:<example>
user: Run the build and fix any type errors
assistant: I'm going to use the ${yG.name} tool to write the following items to the todo list: 
- Run the build
- Fix any type errorsI'm now going to run the build using ${ZK}.Looks like I found 10 type errors. I'm going to use the ${yG.name} tool to write 10 items to the todo list.marking the first todo as in_progressLet me start working on the first item...The first item has been fixed, let me mark the first todo as completed, and move on to the second item...
..
..
</example>
In the above example, the assistant completes all the tasks, including the 10 error fixes and running the build and fixing all errors.<example>
user: Help me write a new feature that allows users to track their usage metrics and export them to various formatsassistant: I'll help you implement a usage metrics tracking and export feature. Let me first use the ${yG.name} tool to plan this task.
Adding the following todos to the todo list:
1. Research existing metrics tracking in the codebase
2. Design the metrics collection system
3. Implement core metrics tracking functionality
4. Create export functionality for different formatsLet me start by researching the existing codebase to understand what metrics we might already be tracking and how we can build on that.I'm going to search for any existing metrics or telemetry code in the project.I've found some existing telemetry code. Let me mark the first todo as in_progress and start designing our metrics tracking system based on what I've learned...[Assistant continues implementing the feature step by step, marking todos as in_progress and completed as they go]
</example>
`:""}false# Doing tasks
The user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:
- ${G.has(yG.name)||G.has(oN.name)?`Use the ${yG.name} tool to plan the task if required`:""}
- Use the available search tools to understand the codebase and the user's query. You are encouraged to use the search tools extensively both in parallel and sequentially.
- Implement the solution using all tools available to you
- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.
- VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) with ${ZK} if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CLAUDE.md so that you will know to run it next time.
NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.- Tool results and user messages may include <system-reminder> tags. <system-reminder> tags contain useful information and reminders. They are NOT part of the user's provided input or the tool result.${Um()?fa0():""}# Tool usage policy${G.has(cX)?`
- When doing file search, prefer to use the ${cX} tool in order to reduce context usage.`:""}
- You have the capability to call multiple tools in a single response. When multiple independent pieces of information are requested, batch your tool calls together for optimal performance. When making multiple bash tool calls, you MUST send a single message with multiple tools calls to run the calls in parallel. For example, if you need to run "git status" and "git diff", send a single message with two tool calls to run the calls in parallel.You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail.
`, `
${await ha0(B,I)}`, `
${va0}
`, G.has(yG.name) || G.has(oN.name) ? `
IMPORTANT: Always use the ${yG.name} tool to plan and track tasks throughout the conversation.` : "", (Q && Q.length > 0, ""), `
# Code ReferencesWhen referencing specific functions or pieces of code include the pattern \`file_path:line_number\` to allow the user to easily navigate to the source code location.<example>
user: Where are errors from the client handled?
assistant: Clients are marked as failed in the \`connectToServer\` function in src/services/process.ts:712.
</example>
`]
}// chunks.89.mjs:370-390 - 环境信息收集
async function ha0(A, B) {let [Q, I] = await Promise.all([jz(), EL6()]), G = NdA(A), Z = G ? `You are powered by the model named ${G}. The exact model ID is ${A}.` : `You are powered by the model ${A}.`, D = B && B.length > 0 ? `Additional working directories: ${B.join(", ")}
` : "";return `Here is useful information about the environment you are running in:
<env>
Working directory: ${dA()}
Is directory a git repo: ${Q?"Yes":"No"}
${D}Platform: ${mA.platform}
OS Version: ${I}
Today's date: ${new Date().toISOString().split("T")[0]}
</env>
${Z}
`
}

复杂度评估是怎么做的?

Claude Code的复杂度评估采用基于关键词模式匹配的实时评估机制,通过WN5函数对用户消息进行文本提取和FN5函数进行复杂度分类,使用XN5函数通过正则表达式匹配预定义的复杂度模式库(YN5),将任务分为四个等级:HIGHEST(31999分,如"think harder"、“think intensely”)、MIDDLE(10000分,如"analyze"、“examine”)、BASIC(4000分,如"search"、“find”)和NONE(0分)。复杂度判断的维度主要包括任务指令强度(通过关键词强度识别用户对思考深度的要求),判断方法采用优先级匹配策略(从高到低依次匹配,匹配到即返回对应分数)、词边界控制(通过needsWordBoundary参数控制是否要求完整词匹配)和综合评分机制(将各维度评分加权计算得出最终复杂度等级)。

源码位置:

  • WN5函数: chunks.99.mjs:2736-2750 - 复杂度评估核心
  • FN5函数: chunks.99.mjs:2780-2800 - 复杂度分类
  • XN5函数: chunks.99.mjs:2800-2820 - 模式匹配
  • YN5模式库: chunks.99.mjs:2498-2710 - 关键词模式定义
  • 复杂度常量: cli.mjs:2393 - mw1复杂度分数定义

核心源码实现:

// chunks.99.mjs:2498-2710 - 多语言关键词模式库
YN5 = {english: {HIGHEST: [{pattern: "think harder",needsWordBoundary: true}, {pattern: "think intensely",needsWordBoundary: true}, {pattern: "think longer",needsWordBoundary: true}, {pattern: "think really hard",needsWordBoundary: true}, {pattern: "think super hard",needsWordBoundary: true}, {pattern: "think very hard",needsWordBoundary: true}, {pattern: "ultrathink",needsWordBoundary: true}],MIDDLE: [{pattern: "think about it",needsWordBoundary: true}, {pattern: "think a lot",needsWordBoundary: true}, {pattern: "think deeply",needsWordBoundary: true}, {pattern: "think hard",needsWordBoundary: true}, {pattern: "think more",needsWordBoundary: true}, {pattern: "megathink",needsWordBoundary: true}],BASIC: [{pattern: "think",needsWordBoundary: true}],NONE: []},chinese: {HIGHEST: [{pattern: "多想一会"}, {pattern: "深思"}, {pattern: "仔细思考"}],MIDDLE: [{pattern: "多想想"}, {pattern: "好好想"}],BASIC: [{pattern: "想"}, {pattern: "思考"}],NONE: []},japanese: {HIGHEST: [{pattern: "熟考"}, {pattern: "深く考えて"}, {pattern: "しっかり考えて"}],MIDDLE: [{pattern: "もっと考えて"}, {pattern: "たくさん考えて"}, {pattern: "よく考えて"}, {pattern: "長考"}],BASIC: [{pattern: "考えて"}],NONE: []}// ... 其他语言模式
}// cli.mjs:2393 - 复杂度分数常量定义
const mw1 = {HIGHEST: 31999,  // 最高复杂度分数MIDDLE: 10000,   // 中等复杂度分数  BASIC: 4000,     // 基础复杂度分数NONE: 0          // 无复杂度分数
}

核心源码实现:

// chunks.99.mjs:2736-2750 - 复杂度评估核心函数
function WN5(A) {if (A.isMeta) return 0;let B = JN5(A).toLowerCase(),  // 消息内容提取Q = FN5(B);                   // 复杂度分类if (Q > 0) E1("tengu_thinking", {provider: Wz(),tokenCount: Q});return Q
}// chunks.99.mjs:2750-2780 - 消息内容提取
function JN5(A) {if (typeof A.message.content === "string") return A.message.content;return A.message.content.map((B) => B.type === "text" ? B.text : "").join("")
}// chunks.99.mjs:2780-2800 - 复杂度分类
function FN5(A) {let B = [["HIGHEST", mw1.HIGHEST],    // 31999分["MIDDLE", mw1.MIDDLE],      // 10000分["BASIC", mw1.BASIC]         // 4000分];for (let [Q, I] of B)if (XN5(A, Q)) return I;return mw1.NONE  // 0分
}// chunks.99.mjs:2800-2820 - 模式匹配
function XN5(A, B) {for (let Q of Object.values(YN5)) {let I = Q[B];for (let {pattern: G,needsWordBoundary: Z}of I)if ((Z ? new RegExp(`\\b${G}\\b`) : new RegExp(G)).test(A)) return true}return false
}

h2A消息队列,架构上突破

h2A消息队列通过Je1异步迭代器包装器、nE2核心异步生成器和多个关键中断点,实现了真正的非阻塞异步处理。系统采用直接委托机制实现零延迟消息传递,通过智能背压控制防止内存溢出,支持>10,000消息/秒的高吞吐量,并在AI处理前、响应后、工具执行前、递归回调等关键位置插入yield点。h2A消息队列的核心作用是实现真正的非阻塞异步处理和实时用户交互引导,让Claude Code能够:

  • 非阻塞处理:避免界面冻结,保持系统响应性
  • 实时交互:用户可以在任何节点干预AI行为
  • 内存安全:防止内存溢出,支持大文件处理
  • 透明协作:用户和AI的协作过程完全可见和可控

源码位置:

  • Je1函数: chunks.94.mjs:895-897 - 异步迭代器包装器
  • nE2函数: chunks.94.mjs:1595-1780 - 核心异步生成器
  • yield中断点: chunks.94.mjs:1595-1600 - 关键中断位置

核心源码实现:

// chunks.94.mjs:895-897 - 异步迭代器包装器
async function* Je1(A, B) {return yield* B()
}// chunks.94.mjs:1595-1780 - 核心异步生成器
async function* nE2(A, B, Q, I, G, Z) {// 消息预处理let D = AQ(A);// 上下文注入let Y = await SE2(D, {getToolPermissionContext: Z.getToolPermissionContext,tools: I});// 对话管道处理let W = aE2(B);let J = zy() && Y.length > 0;let F = Z.temperature ?? bY5;let X = JW(A);// 实时中断检查点for await (let d of E) {if (d.type === "message_start") {// 消息开始处理yield {type: "progress",data: {type: "message_start",message: d.message}};}// 关键中断点:yield检查if (d.type === "content_block_delta") {yield {type: "progress", data: {type: "content_delta",delta: d.delta}};}// 工具调用中断点if (d.type === "content_block_stop" && d.content_block.type === "tool_use") {yield {type: "tool_use",data: d.content_block};}}
}

Claude Code安全机制总结

Claude Code采用多层次安全机制保护系统安全,

  • 1.配置访问控制机制,初始化时,根据配置,防止未授权访问;
  • 2.配置键验证机制,使用白名单验证和强制退出,确保只有预定义配置键可被修改;
  • 3.文件系统安全机制,通过权限设置和目录创建保护配置文件安全;
  • 4.凭证存储安全机制,优先使用系统密钥链并实现安全回退;
  • 5.输入验证和清理机制,通过安全的JSON解析和环境变量验证防止注入攻击;
  • 6.工具权限控制机制,通过工具验证和路径验证防止恶意操作;
  • 7.网络请求安全机制,通过API密钥验证和错误处理保护数据传输安全。
    整个安全体系确保了配置管理、文件操作、凭证存储和网络通信的安全性,为用户提供安全可靠的开发环境。

源码位置:

  • 配置访问控制: chunks.88.mjs:790-796 - ZD0函数权限检查
  • 配置键验证: chunks.88.mjs:2087-2095 - JD0函数白名单验证
  • 工具权限控制: cli.mjs:699-704 - 工具权限管理
  • 输入验证: chunks.94.mjs:339-344 - Zod参数验证

核心源码实现:

// chunks.88.mjs:790-796 - 配置访问控制
function ZD0() {if (Gv1) return;Gv1 = true, $_(UX(), NX, true)  // 权限检查
}// chunks.88.mjs:2087-2095 - 配置键白名单验证
function JD0(A) {let B = ZA();if (B.customApiKeyResponses?.approved?.includes(A)) return "approved";if (B.customApiKeyResponses?.rejected?.includes(A)) return "rejected";return "new"
}// chunks.88.mjs:7968-8451 - 安全配置访问
function $_(A, B, Q) {if (!Gv1) throw new Error("Config accessed before allowed.");  // 权限检查if (!x1().existsSync(A)) return Ec(B);try {let I = x1().readFileSync(A, {encoding: "utf-8"});try {let G = JSON.parse(I);return {...Ec(B),...G}} catch (G) {let Z = G instanceof Error ? G.message : String(G);throw new Vv(Z, A, B)}} catch (I) {if (I instanceof Vv && Q) throw I;return Ec(B)}
}// chunks.94.mjs:339-344 - Zod参数验证
let D = A.inputSchema.safeParse(Q);
if (!D.success) {let R = MU2(A.name, D.error);E1("tengu_tool_use_error", {error: "InputValidationError",messageID: Z.message.id,toolName: A.name});yield K2({content: [{type: "tool_result",content: `InputValidationError: ${R}`,is_error: true,tool_use_id: B}],toolUseResult: `InputValidationError: ${D.error.message}`});return
}
http://www.lryc.cn/news/594460.html

相关文章:

  • JavaScript 中Object、Array 和 String的常用方法
  • 金融工程、金融与经济学知识点
  • 数据结构与算法汇总
  • 连接语言大模型(LLM)服务进行对话
  • GaussDB select into和insert into的用法
  • 机器学习基础:从数据到智能的入门指南
  • python生成密钥
  • Self-Consistency:跨学科一致性的理论与AI推理的可靠性基石
  • An End-to-End Attention-Based Approach for Learning on Graphs NC 2025
  • JAVA面试宝典 -《API设计:RESTful 与 GraphQL 对比实践》
  • 《通信原理》学习笔记——第五章
  • 【1】YOLOv13 AI大模型-可视化图形用户(GUI)界面系统开发
  • Openlayers 面试题及答案180道(121-140)
  • 让不符合要求的任何电脑升级Windows11
  • 【LeetCode数据结构】单链表的应用——环形链表问题详解
  • WireShark抓包分析TCP数据传输过程与内容详解
  • 使用Qt6 QML/C++ 和CMake构建海康威视摄像头应用(代码开源)
  • 【GameMaker】GML v3 的现行提案
  • FreeRTOS任务创建与删除
  • Python 图片爬取入门:从手动下载到自动批量获取
  • Selenium 处理动态网页与等待机制详解
  • 复杂度优先:基于推理链复杂性的提示工程新范式
  • AUTOSAR进阶图解==>AUTOSAR_SWS_CryptoInterface
  • 【Java学习|黑马笔记|Day18】Stream流|获取、中间方法、终结方法、收集方法及其练习
  • 扩散模型与强化学习(12):RLHF中的Reward hacking现象
  • 深入解析Ext2文件系统架构
  • 【RK3576】【Android14】ADB工具说明与使用
  • 【Linux性能优化】常用工具和实战指令
  • 软件测试-Bug
  • 【软件测试】从软件测试到Bug评审:生命周期与管理技巧