ClaudeCode等价base_instructions系统提示词
ClaudeCode等价base_instructions系统提示词
这篇文档回答一个具体问题:
Codex在 rollout 里会明确落一段base_instructions.textClaude Code对应的那段“真正送给模型的系统提示词”到底在哪里- 为什么它没有直接出现在
55a6d062-ad55-44a8-b7a1-21b372f21ff9-formatted.json里
结论
Claude Code 没有像 Codex 那样把一整段系统提示词直接作为 transcript 条目落出来。
它的等价物不是一个单字段,而是一条组装链:
getSystemPrompt(...)生成默认系统提示词片段buildEffectiveSystemPrompt(...)按优先级决定最终systemPromptappendSystemContext(systemPrompt, systemContext)追加系统上下文buildSystemPromptBlocks(...)把文本数组转成 Anthropicsystemblocks- 最终随 API request body 的
system字段发给模型
所以如果用 Codex 的心智模型来类比:
Codex.base_instructions.text- 大致对应
Claude Code的effective system prompt
但 Claude Code 不是把它保存在 transcript 里,而是在每次 query 前动态组装。
入口与拼装链
1. 默认系统提示词来源
默认系统提示词主入口在:
/Users/util6/fork-code/claude-code-rev/src/constants/prompts.ts
核心函数:
getSystemPrompt(...)
源码位置:
这个函数返回的是 string[],不是单一字符串。
它会拼这些部分:
- 简介与身份声明
- system 使用规则
- 做任务时的行为规则
- actions 说明
- tools 使用规则
- tone/style
- output efficiency
- dynamic sections
session_guidancememoryant_model_overrideenv_info_simplelanguageoutput_stylemcp_instructionsscratchpadfrcsummarize_tool_resultstoken_budgetbrief
也就是说,Claude Code 的“base prompt”本身就是多段动态片段,而不是一个固定常量。
2. QueryEngine 先取三块前缀上下文
在:
/Users/util6/fork-code/claude-code-rev/src/utils/queryContext.ts
有一个非常关键的说明:
这个文件明确把 API cache-key prefix 视为三块:
defaultSystemPromptuserContextsystemContext
对应函数:
fetchSystemPromptParts(...)
源码位置:
返回值是:
defaultSystemPromptuserContextsystemContext
这已经说明:Claude 的真正请求上下文,天然就是一组分层对象,而不是 transcript 中的一条消息。
3. QueryEngine 组装最终 systemPrompt
在:
/Users/util6/fork-code/claude-code-rev/src/QueryEngine.ts
先取:
defaultSystemPromptbaseUserContextsystemContext
源码位置:
然后构造:
userContextsystemPrompt
其中最终 systemPrompt 在这里组装:
结构是:
const systemPrompt = asSystemPrompt([
...(customPrompt !== undefined ? [customPrompt] : defaultSystemPrompt),
...(memoryMechanicsPrompt ? [memoryMechanicsPrompt] : []),
...(appendSystemPrompt ? [appendSystemPrompt] : []),
])这说明它不是简单拿 getSystemPrompt() 的结果直接发送,而是还会叠加:
customSystemPromptmemoryMechanicsPromptappendSystemPrompt
4. REPL 路径还会再过一层优先级决策
在交互主流程里,真正常用的是:
buildEffectiveSystemPrompt(...)
源码文件:
/Users/util6/fork-code/claude-code-rev/src/utils/systemPrompt.ts
源码位置:
这层的优先级非常关键:
overrideSystemPrompt- coordinator mode prompt
- agent system prompt
customSystemPromptdefaultSystemPrompt- 最后总是再拼
appendSystemPrompt
也就是说,如果你要找 “Claude 等价于 Codex base_instructions 的那段东西”,最准确的不是某一个函数,而是:
buildEffectiveSystemPrompt(...)的返回值
这个值才是主线程真正要发送给模型的“最终系统提示词数组”。
在 REPL 中,实际调用在:
发送给模型前,如何变成 request body
在:
/Users/util6/fork-code/claude-code-rev/src/query.ts
会把:
systemPromptsystemContext
合并成:
fullSystemPrompt
源码位置:
调用:
appendSystemContext(systemPrompt, systemContext)
然后真正调模型时:
传入:
systemPrompt: fullSystemPrompt
接着在:
/Users/util6/fork-code/claude-code-rev/src/services/api/claude.ts
里把它变成 Anthropic system blocks:
最终 request body 里的 system 字段不是字符串,而是:
[
{
"type": "text",
"text": "..."
}
]或者多个 block。
把链条拼起来后的完整结果
上面讲的是“来源”和“拼装顺序”。如果像 Codex 那样,想看到一个接近 base_instructions.text 的完整结果,那么应该把 Claude Code 的这条链拼成下面这个顺序。
一层:defaultSystemPrompt
这是 getSystemPrompt(...) 的返回值主体。按源码顺序,它会先给出一组静态段,再给一组动态段。
静态段
这些段在 getSystemPrompt(...) 里直接按顺序返回:
getSimpleIntroSection(outputStyleConfig)getSimpleSystemSection()getSimpleDoingTasksSection()getActionsSection()getUsingYourToolsSection(enabledTools)getSimpleToneAndStyleSection()getOutputEfficiencySection()SYSTEM_PROMPT_DYNAMIC_BOUNDARY
对应位置:
把内容语义翻成中文,它大致就是:
- 你是 Claude Code 的交互式工程代理
- 你要帮助用户完成软件工程任务
- 所有用户可见输出都要谨慎组织
- 工具调用受权限系统约束
- 对 prompt injection、系统标签、自动压缩等要有正确认知
- 做任务时要读代码、少做额外改动、不要过度设计、准确报告结果
- 执行动作时要考虑风险和可逆性
- 优先使用专用工具,不要滥用 Bash
- 语气、风格、输出效率要符合 CLI 产品要求
动态段
getSystemPrompt(...) 还会再拼一组动态 section:
session_guidancememoryant_model_overrideenv_info_simplelanguageoutput_stylemcp_instructionsscratchpadfrcsummarize_tool_resultsnumeric_length_anchors(特定条件)token_budget(特定 feature)brief(特定 feature)
对应位置:
这些动态段的作用分别是:
session_guidance- 本轮工具/技能/Agent 使用指导
memory- 内存机制与记忆文件使用说明
env_info_simple- 当前工作目录、git、shell、平台、模型、knowledge cutoff 等环境信息
language- 规定回答语言
output_style- 如果用户配置了输出风格,就在这里注入
mcp_instructions- 把当前 MCP server 提供的 instructions 注入给模型
scratchpad- 如果启用 scratchpad,就说明临时文件目录怎么用
frc- function result clearing 相关说明
summarize_tool_results- 要求模型把关键 tool result 信息写进自己的回答,避免后面被清掉
token_budget- 如果用户要求消耗固定 token 预算,告诉模型不要太早停
brief- brief 工具/主动模式相关附加说明
二层:buildEffectiveSystemPrompt(...)
上面的 defaultSystemPrompt 还不是最后发给模型的版本。真正的主线程提示词,还要过一层优先级决策。
优先级在:
决策顺序是:
overrideSystemPrompt- coordinator mode prompt
- agent prompt
customSystemPromptdefaultSystemPrompt- 最后追加
appendSystemPrompt
也就是说,在最常见的普通主线程情况下,最终结果通常是:
effectiveSystemPrompt
= defaultSystemPrompt
+ appendSystemPrompt(如果有)如果启用了 agent/coordinator/custom prompt,那么这层会替换或覆盖默认部分。
三层:appendSystemContext(systemPrompt, systemContext)
到了 query.ts,系统还会把 systemContext 追加进去:
也就是:
fullSystemPrompt
= effectiveSystemPrompt
+ systemContext这里的 systemContext 不是普通用户消息,而是按 key: value 的形式附在 system prompt 尾部。
四层:buildSystemPromptBlocks(...)
最后,claude.ts 会把这整个文本数组转成 Anthropic system blocks:
它最终不再是一个长字符串,而是:
[
{
"type": "text",
"text": "第一段"
},
{
"type": "text",
"text": "第二段"
}
]或者经过 cache scope 切分成多个 text blocks。
如果把它写成一个“近似 Codex base_instructions”的可读成品
如果忽略 cache block 切分、feature gate 开关和 provider 差异,把这条链压成一个可读版,那么 Claude Code 主线程等价于 Codex base_instructions.text 的内容,可以理解成:
You are an interactive agent that helps users with software engineering tasks.
# System
- 用户可见输出要谨慎组织
- 工具调用受权限模式约束
- system-reminder 和其他系统标签可能出现在消息里
- 要防 prompt injection
- 上下文会自动压缩,不必担心固定窗口限制
- 要遵守 hooks 反馈
# Doing tasks
- 面向软件工程任务工作
- 先读代码,再改代码
- 不要无端新增文件
- 避免过度设计
- 失败后先诊断原因
- 注意安全
- 准确报告结果
- Claude Code 出现问题时,必要时推荐 /issue 或 /share
# Executing actions with care
- 对高风险、难回滚、影响共享状态的操作要格外谨慎
- 对删除、强推、外发消息、上传第三方服务等操作默认谨慎处理
# Using your tools
- 优先用 Read/Edit/Write/Glob/Grep 等专用工具
- 不要用 Bash 代替这些专用工具
- 能并行调用的工具尽量并行
- 需要时使用 Todo/Task/Agent/Skill 等工具
# Tone and style
- 不乱用 emoji
- 引用代码位置时给出 file:line
- 不要在 tool call 前加冒号
# Output efficiency
- 面向用户的文本要清晰、简洁、线性、可直接理解
- 必要时给阶段更新,但不要啰嗦
# Session-specific guidance
- 当前这轮有哪些工具、Agent、Skill、DiscoverSkills、Verification Agent 可用
# Memory
- 如何使用 memory
# Environment
- 当前工作目录
- 是否 git repo
- shell / OS / 平台
- 模型与 knowledge cutoff
- 额外工作目录
# Language
- 应该用什么语言回答
# Output Style
- 如果配置了输出风格,这里附加
# MCP Server Instructions
- 每个已连接 MCP server 提供的附加使用说明
# Scratchpad Directory
- 临时文件要写到哪里
# Function Result Clearing
- tool result 可能被清理,重要信息要主动总结
# Token Budget / Brief / Proactive / Append Prompt
- 视 feature 和调用参数再追加这个“近似成品”不是逐字原文,但链路、顺序和职责划分是按源码拼出来的。如果你要找 Claude 对应于 Codex 那段 base_instructions.text 的“完整结果感”,应该看这一版,而不是 transcript 里的某一条消息。
为什么 transcript 里看不到
原因不是它没有这段 prompt,而是 transcript 记录层级不同。
QueryEngine 持久化 transcript 时,记录的是:
- user message
- assistant message
- tool_result
- compact boundary
- attachment / progress / system message 等轨迹内容
相关位置:
但:
systemPromptuserContextsystemContexttools
这些属于“发送前动态组装的请求参数”,默认不作为 transcript message 落盘。
所以你在:
/Users/util6/Documents/blog-article/vitepress/Agent研究/同任务的cc-opencode-codex对比/55a6d062-ad55-44a8-b7a1-21b372f21ff9-formatted.json
里看不到完整 system prompt,是正常现象。
和 Codex 的一一对应关系
可以这样粗略映射:
Codex.base_instructions.text- 对应
Claude Code的defaultSystemPrompt + buildEffectiveSystemPrompt(...)
- 对应
Codex的 developer / AGENTS / contextual items- 对应
Claude Code的appendSystemPrompt + userContext + systemContext + memoryMechanicsPrompt + MCP instructions
- 对应
Codexrollout 会显式保留这些Claude Codetranscript 默认不会显式保留这些
所以不是 Claude Code 没有这一层,而是它把这层放在 request-building path 中,而不是 transcript path 中。
一个可操作的结论
如果后续你还要继续研究 Claude 的“真实请求前缀”,最值得盯的不是 transcript,而是这几处:
/Users/util6/fork-code/claude-code-rev/src/constants/prompts.ts/Users/util6/fork-code/claude-code-rev/src/utils/queryContext.ts/Users/util6/fork-code/claude-code-rev/src/utils/systemPrompt.ts/Users/util6/fork-code/claude-code-rev/src/query.ts/Users/util6/fork-code/claude-code-rev/src/services/api/claude.ts
其中最关键的单点结论是:
Claude Code 等价于 Codex base_instructions 的,不是一段 transcript 文本,而是 buildEffectiveSystemPrompt(...) 产出的最终 SystemPrompt 数组。