乐于分享
好东西不私藏

挖掘Claude源码: Claude.md竟然每次User prompt都会被注入

挖掘Claude源码: Claude.md竟然每次User prompt都会被注入

Claude源码泄露了,咱们得好好吃这口瓜,今天先从源码分析一下为什么Claude.md要简洁、明了

TL,DR;

  • Claude.md 在每一次用户提交Prompt都会被注入;
  • claude.md(包括.claude/rules) 在Claude的系统提示词中是被作为最高的排他准则,要求模型严格遵守的,IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.

难怪Claude 的创始人Boris 的Claude.md 只有两行!!

Claude.md是如何加载到Prompt里的

prompt = system prompt + user prompt

Claude的system prompt是动态拼装出来的

Claude的 system prompt 是由一个叫 getSystemPrompt() 的函数动态拼装出来的,包括静态部分和动态部分,

export async function getSystemPrompt(	...return [    // --- Static content (cacheable) ---    getSimpleIntroSection(outputStyleConfig),    getSimpleSystemSection(),    outputStyleConfig === null ||    outputStyleConfig.keepCodingInstructions === true      ? getSimpleDoingTasksSection()      : null,    getActionsSection(),    getUsingYourToolsSection(enabledTools),    getSimpleToneAndStyleSection(),    getOutputEfficiencySection(),    // === BOUNDARY MARKER - DO NOT MOVE OR REMOVE ===    ...(shouldUseGlobalCacheScope() ? [SYSTEM_PROMPT_DYNAMIC_BOUNDARY] : []),    // --- Dynamic content (registry-managed) ---    ...resolvedDynamicSections,  ].filter(s => s !== null))

静态部分包括:

  • 身份定位(getSimpleIntroSection)、
  • 系统规范(getSimpleSystemSection)、
  • 做任务的哲学(getSimpleDoingTasksSection)、
  • 风险动作规范(getActionsSection)、
  • 工具使用规范(getUsingYourToolsSection)、
  • 语气风格(getSimpleToneAndStyleSection)、
  • 输出效率(getOutputEfficiencySection)。

动态部分包括:

  • session guidance、
  • memory、
  • 环境信息、
  • 语言设置、
  • 输出风格、
  • MCP instructions、
等等
Claude.md是如何被加载到Prompt中的

再看看claudemd.ts中的定义,从claudemd.ts可以看到,claude.md(包括.claude/rules) 在Claude的系统提示词中是被作为最高的排他准则,要求模型严格遵守的,IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.

任何不是你的项目中要求严格遵守规则,都不要写到CLAUDE.md和RULES中

const MEMORY_INSTRUCTION_PROMPT =  'Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANTThese instructions OVERRIDE any default behavior and you MUST follow them exactly as written.'
这里的Memory指的就是 各个层级的Claude.md和 .claude/rules 下的定义,如下为 claudemd.ts的注释
 * Files are loaded in the following order: * * 1. Managed memory (eg. /etc/claude-code/CLAUDE.md) - Global instructions for all users * 2. User memory (~/.claude/CLAUDE.md) - Private global instructions for all projects * 3. Project memory (CLAUDE.md, .claude/CLAUDE.md, and .claude/rules/*.md in project roots) - Instructions checked into the codebase * 4. Local memory (CLAUDE.local.md in project roots) - Private project-specific instructions * * Files are loaded in reverse order of priority, i.e. the latest files are highest priority * with the model paying more attention to them. * * File discovery: * - User memory is loaded from the user's home directory * - Project and Local files are discovered by traversing from the current directory up to root * - Files closer to the current directory have higher priority (loaded later) * - CLAUDE.md, .claude/CLAUDE.md, and all .md files in .claude/rules/ are checked in each directory for Project memory

各个层级的CLAUDE.md和rules,都会被默认加载到系统上下文中,平常咱们使用得最多的还是项目层级的CLAUDE.md

重点来了,每一次提交给LLM的User Prompt,都被注入了Claude.MD

每一次提交给LLM的User Prompt,都被注入了Claude.MD

// query.ts:659-661for await (const message of deps.callModel({  messages: prependUserContext(messagesForQuery, userContext),  // ← 每次调用  systemPrompt: fullSystemPrompt,  ...}))
// api.ts:449-479export function prependUserContext(  messagesMessage[],  context: { [k: string]: string },): Message[] {  // context = { claudeMd: "...", currentDate: "..." }  return [    createUserMessage({      content`<system-reminder>        As you answer the user's questions, you can use the following context:        # claudeMd        ${context.claudeMd}        # currentDate        ${context.currentDate}        IMPORTANT: this context may or may not be relevant...      </system-reminder>`,      isMetatrue,  // 标记为元消息,不显示在 UI    }),    ...messages,  // 原有对话历史  ]}

保持你的CLAUDE.MD简洁

最佳实践:将 CLAUDE.md 控制在 200 行以内,约 5,000-8,000 字符,把详细规则拆分到 .claude/rules/ 目录下按需加载。

Claude.md是地图而非百科全书,一定要保持简洁,

Boris Cherny (Claude创始人)的Claude.md只有两行 !!

auto-merge PRpost to Slack

业界的最佳实际是,尽量维持在200行以内,约简洁约好,按如下方式写

  • 项目how to build , how to test , how to run
  • 项目结构目录,模块边界
  • Never ,绝对杜绝的事情
  • 上下文压缩规则,可以压缩的信息,不可以压缩的信息
  • 项目里的特殊环境变量! (如果有的话)
  • 只讲规则,不讲细节,严格要求AI不能做哪些事

作为在每次提交Prompt都默认加载的信息,对于Claude.md中的每一行内容,都要问自己:“删除这个会导致 Claude 犯错吗?” 如果不会,删除它。膨胀的 CLAUDE.md 文件会导致 Claude 忽略你的实际指令!

更会浪费你的TOKEN!!