犀牛鸟 2026 研究笔记 estelledc.github.io

Claude Code System Prompt 分层:组装、缓存、Skills、泄露对照

一句话定位:Claude Code 的 System Prompt 是一个由 110+ 动态片段组装的模块化架构,通过静态/动态分界线实现 API 级 prompt cache 优化,每次 API 调用节省约 3000 token 的重复计费。

调研时间:2026-06-22
依据版本:泄露源码包(2026-03-31)+ system_prompts_leaks 仓库 + Piebald-AI/claude-code-system-prompts(v2.1.185)
核心文件src/constants/prompts.tssrc/utils/systemPrompt.tssrc/constants/systemPromptSections.tssrc/constants/system.ts


证据等级汇总

结论 来源
buildEffectiveSystemPrompt 5 级优先级 [源码] systemPrompt.ts
静态/动态分界线 + global cache scope [源码] prompts.ts
systemPromptSection 缓存机制 [源码] systemPromptSections.ts
7 个静态段落 + 12+ 动态段落 [源码] prompts.ts
15 类提示词内容分类 [社区] Piebald-AI 跟踪
安全监控独立并行运行 [社区] system_prompts_leaks
CLAUDE.md 作为 userContext 注入 [源码] context.ts
Skills 通过 SkillTool 展开而非直接注入 [源码] skills/
跨 215 版本的 prompt 变更追踪 [社区] Piebald-AI

日常类比

把 System Prompt 想象成餐厅的员工手册

类比边界:真实系统中”手册正文”被 API 缓存后,后续请求只需传”白板通知”部分,大幅降低 token 成本。


组装全链路

graph TB
    subgraph "Phase 1: 收集素材"
        Prompts[prompts.ts<br>getSystemPrompt] --> Static[7 个静态段落]
        Prompts --> Dynamic[12+ 动态段落]
        Context[context.ts] --> UserCtx[CLAUDE.md + 日期]
        Context --> SysCtx[Git status + 分支]
    end

    subgraph "Phase 2: 优先级决策"
        BSP[buildEffectiveSystemPrompt]
        Override[overrideSystemPrompt] -->|"P0 完全替换"| BSP
        Coord[Coordinator prompt] -->|"P1 替换"| BSP
        Agent[Agent definition] -->|"P2 替换/追加"| BSP
        Custom[--system-prompt] -->|"P3 替换"| BSP
        Default[defaultSystemPrompt] -->|"P4 兜底"| BSP
        Append[appendSystemPrompt] -->|"始终追加"| BSP
    end

    subgraph "Phase 3: API 发送"
        BSP --> Split[splitSysPromptPrefix]
        Split --> StaticBlock["静态块<br>cache_control: global"]
        Split --> DynamicBlock["动态块<br>cache_control: ephemeral"]
        UserCtx --> Prepend[prependUserContext]
        SysCtx --> AppendCtx[appendSystemContext]
    end

优先级逻辑:buildEffectiveSystemPrompt

src/utils/systemPrompt.ts 定义了 5 级优先级 [源码]

优先级 条件 行为
P0 overrideSystemPrompt 存在 完全替换所有其他 prompt
P1 Coordinator Mode 激活 使用协调器专用 prompt
P2 mainThreadAgentDefinition 存在 Proactive 模式:追加到 default;普通模式:替换 default
P3 customSystemPrompt 存在 替换 default
P4 以上都不满足 使用 defaultSystemPrompt
+∞ appendSystemPrompt 存在 始终追加在末尾

关键设计:Agent 在 Proactive/KAIROS 模式下是追加而非替换——因为自主 agent 需要保留基础行为规范,domain-specific 指令叠加在上面。


静态/动态分界线

┌─────────────────────────────────────────────────┐
│  STATIC ZONE (globally cacheable)                │
│  ≈ 3000 tokens, scope: 'global'                 │
│                                                  │
│  1. Intro + Identity                             │
│  2. System Rules                                 │
│  3. Doing Tasks (coding guidelines)              │
│  4. Executing Actions with Care                  │
│  5. Using Your Tools                             │
│  6. Tone & Style                                 │
│  7. Output Efficiency                            │
│                                                  │
├─────── __SYSTEM_PROMPT_DYNAMIC_BOUNDARY__ ───────┤
│                                                  │
│  DYNAMIC ZONE (session-specific)                 │
│  scope: 'ephemeral' (5min or 1h TTL)            │
│                                                  │
│  - Session Guidance (agents, skills, verify)     │
│  - Memory prompt                                 │
│  - Environment info (cwd, platform, shell)       │
│  - Language preference                           │
│  - Output style                                  │
│  - MCP instructions (volatile, 每轮重算)         │
│  - Scratchpad directory                          │
│  - Function Result Clearing                      │
│  - Token budget / Brief mode                     │
│                                                  │
└─────────────────────────────────────────────────┘

缓存工程 [源码]

// systemPromptSections.ts
systemPromptSection(name, compute)
  // 计算一次,缓存到 /clear 或 /compact

DANGEROUS_uncachedSystemPromptSection(name, compute, reason)
  // 每轮重算,会破坏 prompt cache
  // 命名中的 DANGEROUS 是对开发者的警告

为什么这么设计:Anthropic 的 Prompt Cache 按前缀匹配。静态部分标记 scope: 'global' 可跨用户/跨组织缓存,只计费一次。动态内容推到分界线之后,变化时不会 bust 前缀缓存。

1h TTL 优化:对 Anthropic 内部用户和付费订阅者,prompt cache TTL 从默认 5 分钟提升到 1 小时,进一步降低成本。


七个静态段落详解

1. Identity(身份定义)[源码][社区]

三种身份字符串根据运行模式切换:

包含硬约束:网络安全指令(CYBER_RISK_INSTRUCTION)、禁止生成 URL。

2. System Rules(系统规则)[源码][社区]

6 条运行时规则:

3. Doing Tasks(任务执行)[源码][社区]

核心哲学:”做被要求的事,不做额外的事”。

反过度工程三原则

4. Executing Actions with Care(谨慎执行)[源码][社区]

操作前评估可逆性和影响范围。高风险操作(删文件/force push/创建 PR)需用户确认。核心格言:”measure twice, cut once”。

5. Using Your Tools(工具使用)[源码][社区]

最复杂的段落,核心规则:

6. Tone & Style(语气风格)[源码][社区]

不用 emoji、代码引用用 file:line 格式、工具调用前用句号不用冒号。

7. Output Efficiency(输出效率)[源码][社区]

极简输出、倒金字塔结构。外部版强调”一句话能说清的不用三句”。


动态段落机制

段落名 缓存 内容
session_guidance Agent 工具说明、Explore agent、Skill 工具、验证 agent
memory loadMemoryPrompt() — MEMORY.md + 相关记忆
env_info_simple 工作目录、平台、Shell、模型名、知识截止日期
language 语言偏好(跟随用户)
output_style 输出风格配置
mcp_instructions MCP 服务器使用说明(volatile,每轮重算)
scratchpad 临时文件目录路径
frc Function Result Clearing 说明
summarize_tool_results “记下重要信息因为工具结果可能被清除”
token_budget Token 预算说明
brief Brief 模式说明

mcp_instructions 是唯一使用 DANGEROUS_uncachedSystemPromptSection 的段落——因为 MCP 服务器可能在会话中途连接/断开。


CLAUDE.md 注入机制

CLAUDE.md 不是 system prompt 的一部分,而是作为 userContext 注入 [源码]

// context.ts
getUserContext():
  claudeMd:  .claude/ 目录层级加载所有 CLAUDE.md
  currentDate: 当前日期

// 注入方式 (api.ts)
prependUserContext(messages, userContext)
  // 作为第一条 user message 的前缀注入

层级加载

  1. ~/.claude/CLAUDE.md — 全局规则
  2. <project>/.claude/CLAUDE.md — 项目规则
  3. <project>/.claude/settings.json 中的 claudeMdFiles — 额外规则文件

Skills 系统

Skills 不直接进入 system prompt 正文 [源码]

Skills 来源:
  1. Bundled skills (src/skills/bundled/) — 编译进二进制
  2. File-based skills (.claude/skills/) — 从磁盘加载 SKILL.md
  3. MCP skills — 通过 MCP 服务器动态发现
  4. Conditional skills — 带 paths frontmatter,仅匹配文件时激活

注入方式:
  system prompt 中只包含 "use SkillTool to execute them" 的指引
  模型调用 SkillTool 时才展开具体 skill 内容
  
优化:
  EXPERIMENTAL_SKILL_SEARCH flag 启用时
  使用 Sonnet 侧查询预取相关 skills
  避免将所有 skill 内容塞入 context

泄露对照:源码 vs system_prompts_leaks

维度 源码(prompts.ts) 泄露合集(Piebald-AI)
版本 2026-03-31 持续更新至 v2.1.185
格式 TypeScript 函数 纯文本 markdown
完整度 有条件编译(ant-only 段落不可见) 运行时提取,更完整
动态段落 能看到 compute 逻辑 只能看到某次运行的快照
缓存标记 能看到 global/ephemeral 策略 不可见
安全监控 源码中未找到独立文件 泄露合集有完整 9 步分类流程

交叉验证结论


与开源框架对比

维度 Claude Code LangGraph tRPC-Agent
Prompt 管理 模块化 110+ 片段 + 缓存工程 用户自定义字符串 无内置
缓存优化 静态/动态分离 + global scope
规则注入 CLAUDE.md 层级加载 无标准方案
技能系统 SkillTool 按需展开
安全监控 独立并行分类器
版本管理 编译时 + 运行时 flag 用户代码管理 用户代码管理

关键设计决策

为什么 CLAUDE.md 是 userContext 而非 systemPrompt?

[源码] 因为 system prompt 有 global cache scope——如果项目规则进入 system prompt,每个项目都会 bust 全局缓存。放在 userContext 中,全局缓存不受影响。

为什么 Skills 不直接注入?

[源码] 一个项目可能有几十个 skills,全部注入会消耗大量 token。通过 SkillTool 按需展开 + skill search 预取,只在需要时加载相关 skill。

为什么有 DANGEROUS_ 前缀?

[源码] 这是对开发者的代码级警告:任何使用 DANGEROUS_uncachedSystemPromptSection 的段落都会在每轮破坏 prompt cache,增加约 3000 token 的重复计费。命名约定强制开发者思考是否真的需要每轮重算。


局限性


下一步