上周我写完一个 Claude Code Skill,满心欢喜地让它跑一个多文件重构。结果它像失忆了一样,明明 CLAUDE.md 里写了「不要动依赖版本」,它还是 bump 了 package.json;明明强调了「先 ask 再 write」,它直接覆盖了三个文件。
我盯着终端发呆,心想,这玩意是不是根本不看我的提示词。
直到 Claude Code 那 515 条系统提示词被泄露,我才反应过来,不是它不看,是我写的地方不对。Claude Code 的真实偏好,藏在 Anthropic 给它写的那套全局指令里,而不是你项目根目录的 CLAUDE.md。
一句话摘要 Claude Code 的系统提示词不是项目上下文,Skill/MCP 作者真正该对齐的是底层 tool descriptions 和 agent delegation 的隐含假设。
为什么要搞清楚这件事
很多 Skill 作者(包括三个月前的我)有个默认假设,提示词写得越长越细,模型就越听话。于是我们在 CLAUDE.md 里堆约束、在 skill prompt 里加规则、在每次请求里反复强调。
结果往往是下面这样。
- 模型照样跳过步骤
- MCP 工具被误调用
- subagent 返回的结果和主会话对不上
- 文件改到一半,突然开始格式化不相关的代码
这些问题不是 Claude Code 变笨了,而是你自己的提示词和它底层的 515 条系统提示词在打架。Anthropic 每个版本都在迭代这套全局指令,CHANGELOG 已经追到 237 个版本,v2.1.211 单版本就新增了 +3890 tokens。你写的 Skill 如果和这些底层假设冲突,越用力越跑偏。
搞清楚这件事,不是为了吃瓜。而是当你再遇到 Skill 不听话、MCP 乱调用、subagent 上下文对不上时,知道该去哪一层找原因。而不是像三个月前的我一样,只会不断地往 CLAUDE.md 里加更多约束。
越用力,越跑偏。
它不是你以为的那一层提示词
很多人把 system prompt 和 CLAUDE.md 混为一谈。其实它们的层级完全不同。
- System Prompt,Claude Code 启动时注入给模型的全局指令,约 515 条,覆盖工具调用格式、subagent 委派、MCP 工具刷新、文件修改策略等。模型每次交互都带在身上。
- CLAUDE.md,项目级上下文,放在仓库根目录,Claude Code 自动读取后追加到上下文里。它影响的是「这个项目的背景和约定」,不是「你怎么用工具」。
- Skill prompt ,只在调用
/skill-name时加载,解决特定任务该怎么做。 - 当前对话上下文,你一句一句聊出来的临时状态。
四层从上到下,作用域越来越小,但优先级不是简单的谁大谁小。system prompt 决定 Claude Code 怎么用工具,CLAUDE.md 和 Skill prompt 决定它怎么理解你的项目,对话上下文决定当前任务的目标。
打个比方,system prompt 是操作系统的内核调度策略,CLAUDE.md 是某个应用的配置文件,Skill prompt 是应用里的某个功能开关。你在配置文件里写「CPU 优先级最高」,但内核根本不认这个字段;你在功能开关里写「全局禁止弹窗」,但弹窗策略还是内核说了算。
所以,当你发现 Skill 不听话时,别急着加更多约束到 CLAUDE.md。先想清楚,这条约束到底该放在哪一层。
| 维度 | System Prompt | CLAUDE.md |
|---|---|---|
| 层级 | 全局 | 项目级 |
| 谁写 | Anthropic | 你 |
| 生效时机 | 每次 Claude Code 启动 | 读取到项目时 |
| 主要内容 | 工具描述、agent 策略、安全边界 | 项目约定、目录结构、命名规范 |
| 可修改性 | CLI 可覆盖或追加 | 直接编辑文件 |
层级错了,规则再细也白搭。
5 个 Skill/MCP 作者最容易踩的坑
坑 1:把 CLAUDE.md 当 system prompt 写
这是最常见的错误。我看到很多项目把「每次修改前先 git diff」「禁止修改 lock 文件」「必须使用 TypeScript」这种全局性行为约束写进 CLAUDE.md,期待它像系统提示词一样被严格执行。
但 CLAUDE.md 的优先级低于 system prompt。当 system prompt 里对工具调用、文件修改、subagent 委派有明确偏好时,CLAUDE.md 里的宽泛约束很容易被覆盖。
我们生产环境遇到过类似情况。一个内部 Skill 在 CLAUDE.md 里反复强调「不要自动执行测试」,结果 Claude Code 还是触发了 npm test。后来排查发现,system prompt 里对 Bash 工具的默认描述更强调「验证改动」,我们的 CLAUDE.md 措辞又太弱,直接被忽略。
怎么改 ,把全局性行为约束放进 --system-prompt 或 --append-system-prompt,CLAUDE.md 只保留项目专属上下文(目录结构、技术栈、命名约定)。
坑 2:忽略 tool descriptions 的隐性偏好
泄露的 515 条提示词里,有很大一部分是工具描述。Claude Code 怎么调用 Bash、怎么使用 Read/Write、什么时候启动 subagent,都藏在这些描述里。
比如最新 v2.1.211 新增了对 RefreshMcpTools 和 SendFile 的工具描述,还拆分了 background、foreground、fresh 三种 subagent delegation examples。单版本就多了 +3890 tokens。
如果你写了一个 MCP server,但没有在 tool description 里明确告诉 Claude Code「这个工具应该什么时候被调用」「输入参数的真实语义是什么」,它就可能按 system prompt 里的默认假设去猜。猜错了,就是误调用。
怎么改,给每个 MCP tool 写清晰的 description,包含使用场景、参数语义、返回格式。不要假设模型懂你函数名的缩写。
坑 3:subagent 提示词和主会话断层
Claude Code 的 system prompt 里有大量关于 subagent 的 delegation examples。v2.1.211 甚至把 delegation 拆成了 background、foreground、fresh 三种模式。
很多 Skill 作者写 subagent 时,只关注 prompt 内容,没关注上下文继承。结果是,主会话明明已经确认了方案,subagent 进去后又从头分析一遍;或者 subagent 返回的结构和主会话的预期不一致,导致后续工具链崩掉。
我们生产环境遇到过这样的情况。一个批量重构任务让 subagent 处理单个文件,但 subagent 的 prompt 里没有明确「只改这个文件、不要改依赖、不要跑测试」。结果它返回了一份洋洋洒洒的全局重构计划,主会话误以为任务完成,直接退出了。
怎么改,subagent prompt 必须包含当前任务的边界、已确认的上下文、返回格式。不要让它自己猜。
坑 4:假设 system prompt 是静态的
Piebald 仓库收录的 515 条提示词对应 Claude Code v2.1.211,而 CHANGELOG 已经追到 237 个版本。2026-06-12 那波更新,一次性从 350 条扩展到 515 条(+165 条)。
你今天测试通过的 Skill 写法,下个版本可能就失效。
我在一个长期维护的 Skill 里吃过这个亏。之前它稳定运行的「强制先 ask 后 write」逻辑,在某次 Claude Code 更新后突然失效。排查了很久才发现,system prompt 里关于 Write 工具的默认描述改了,模型对「必要时才询问」的理解和我不一样。
怎么改 ,把 Skill 的关键行为约束显式写进 --system-prompt 或 --append-system-prompt,不要依赖某个版本的默认 system prompt。同时给 Skill 加回归测试,每次 Claude Code 更新后跑一遍。
坑 5:直接照搬泄露的提示词
Reddit 上有个高赞帖叫「Don't use Claude Code's Default System Prompt」,434 upvotes,145 comments。帖子的核心观点是,默认 system prompt 试图取悦所有人,结果在特定场景下表现平庸,建议自己定制。
但很多人读完后的第一反应是,我去 GitHub 把那 515 条 prompt 复制下来,放到自己项目里用。
这很危险。Claude Code 的 system prompt 是为它的完整工具链、权限模型、运行环境设计的。你脱离这些上下文,直接照搬到自己项目或其他 LLM 上,大概率水土不服。
怎么改,把泄露的提示词当作「参考手册」,理解 Anthropic 的设计偏好,然后提炼出适合自己 Skill 或项目的最小约束集。不要整段搬运。
这 5 条,建议逐条自查。
来投个票,这 5 个坑,你踩过哪个?
- 把 CLAUDE.md 当 system prompt 写
- MCP tool description 写得太泛,导致误调用
- subagent 和主会话上下文断层
- 以为 system prompt 不会变,没做回归测试
- 照搬过泄露的 515 条提示词
动手接入,用 --system-prompt 锁定 Skill 行为
Claude Code CLI 支持 --system-prompt <prompt> 和 --append-system-prompt <prompt>。前者覆盖默认系统提示词,后者在默认提示词后追加你的约束。
直接上手试。
本文环境 macOS / Claude Code v2.1.211 / 已安装 Claude Code CLI
第一步:准备自定义提示词文件
创建一个 skill-system-prompt.md,内容聚焦于你的 Skill 必须遵守的全局行为。
markdown
你是 <Skill 名称> 的专属助手。
核心约束:
1. 每次 Write 前,必须先 Read 目标文件,确认当前内容。
2. 修改 package.json 前,必须征得用户明确同意。
3. 不要自动运行测试、构建或部署命令。
4. 使用 subagent 时,必须在 prompt 中重复当前任务的边界和返回格式。
5. 如果用户没有指定输出路径,默认写到当前目录的 output/ 下。
返回格式:
- 每个文件修改后,给出一句变更摘要。
- 遇到不确定的依赖版本问题,直接询问用户,不要猜测。
注意,这个文件不要塞进 CLAUDE.md,它属于 system prompt 层。
第二步:用 --append-system-prompt 启动 Claude Code
bash
claude --append-system-prompt "$(cat skill-system-prompt.md)"
✅ 验证,启动后,在对话里问它「你现在的核心约束是什么」,它应该能复述出你文件里的 1-5 条。
第三步:实测一个真实场景
让 Claude Code 执行一个会触发默认行为的操作,比如,
bash
/你的-skill 帮我给 package.json 加一个 lodash 依赖
在不加 --append-system-prompt 时,Claude Code 可能会直接修改 package.json 并尝试安装。加了之后,它应该先 Read 文件,然后询问你是否要加、加什么版本。
✅ 验证,终端输出应包含类似「我需要先确认 package.json 的当前内容,可以吗」的询问,而不是直接执行 npm install lodash。
常见报错与解决
问题 1 提示词太长,启动报错
自定义 system prompt 加上默认的 515 条,可能超出模型的上下文窗口。解决方法是,只覆盖或追加你最关心的约束,不要复制整份泄露 prompt。
bash
claude --append-system-prompt "核心约束:1. Write 前必须 Read;2. 修改 package.json 前必须询问。"
问题 2 追加后模型反而更不主动了
过度约束会让 Claude Code 变得保守,每件事都问。解决方法是,把「必须」改成「除非...否则」,给模型留出判断空间。
比如,
- 差,「每次修改前都必须询问用户」
- 好,「只有当修改会影响项目依赖或公共 API 时,才需要询问用户」
性能表现与真实局限
用了 --append-system-prompt 之后,Claude Code 的行为确实更可控了。但也带来新的成本。
有利必有弊。
- 上下文占用,追加的提示词会消耗 token。如果你的自定义 prompt 有 800 tokens,对话轮次一多,留给实际代码和返回结果的上下文空间就少了。长任务时可能更早触发上下文截断。
- 响应变慢,约束越多,模型每一步的决策越谨慎。原本一次性能完成的判断,可能被拆成两次确认,交互轮次增加 20% 到 50% 是常见现象。
- 版本依赖,system prompt 的追加效果会随 Claude Code 版本变化。某版本里有效的约束,下个版本可能被新的默认描述覆盖,需要定期回归。
- 迁移成本,同一个 Skill 在不同项目里可能需要不同的 system prompt 后缀。A 项目允许自动改配置,B 项目必须人工确认,你就得维护两份后缀。
我目前的做法是,把「绝对不能错」的规则放进 `--append-system-prompt」,把「项目偏好」放进 CLAUDE.md,把「临时任务边界」放进当前对话。三层各司其职,冲突最少。同时我会给关键 Skill 写一组回归用例,每次 Claude Code 大版本更新后跑一遍。加了回归用例后,这种问题能在 5 分钟内发现,而不是等生产环境踩坑后再救火。
什么时候用,什么时候别用
适合追加 system prompt 的场景
- Skill 需要稳定的全局行为约束,比如「任何情况下都不允许自动执行 deploy 脚本」。
- 多文件重构、批量生成等高风险任务,约束能减少误改范围。
- 团队内统一 Claude Code 行为,避免每个人结果不一样。尤其是新人加入时,自定义 system prompt 能把团队红线显性化。
- 默认 system prompt 在某版本更新后导致 Skill 行为变化,需要快速兜底。
一个判断经验,如果你的 Skill 在没有大改的情况下突然「变笨」,大概率不是模型能力问题,而是底层 system prompt 的默认偏好变了。
不建议的场景
- 一次性简单问答(用对话上下文就够了,别折腾)。
- 想完全替代 CLAUDE.md(它们层级不同,不是二选一)。
- 直接搬运泄露的 515 条提示词(水土不服,维护成本还高)。
- prompt 写得比项目代码还长(约束太多,模型反而束手束脚)。
坦白讲,追加 system prompt 不是万能药。它适合解决「行为不稳定」的问题,不适合解决「模型理解不了需求」的问题。需求本身没写清楚,加再多约束也没用。
system prompt 是缰绳,不是方向盘。它能限制马不要乱跑,但不能替马决定要去哪。
常见问题
Q1 Claude Code 的 system prompt 和 CLAUDE.md 到底是不是一回事?
不是。system prompt 是全局指令,决定 Claude Code 怎么用工具、怎么拆任务、怎么调 MCP。CLAUDE.md 是项目上下文,决定「这个项目是什么」。前者是 Anthropic 写的,每次启动注入;后者是你写的,读取到项目时追加。层级不同,生效时机也不同。
Q2 普通开发者能不能改系统提示词?
能。Claude Code CLI 提供 --system-prompt 和 --append-system-prompt。前者覆盖默认系统提示词,后者在默认后追加。但改之前要清楚,你是在和 Anthropic 的默认策略博弈,不是简单加几条规则。追加的约束要精准,否则模型会变保守,甚至直接忽略弱约束。
Q3 为什么有人说「别用默认 system prompt」?
因为默认 prompt 试图覆盖所有场景,对特定 Skill 来说可能太宽泛。Reddit 上的高赞讨论认为,自定义 system prompt 能让 Claude Code 在特定任务上更聚焦。但这不是说默认 prompt 一无是处,而是说如果你的任务有明确边界,定制后的表现通常更稳定。
Q4 作为 Skill/MCP 作者,我应该立刻调整哪些写法?
- 把全局行为约束从 CLAUDE.md 移到
--append-system-prompt; - 给 MCP tool 写更清晰的 description,说明调用时机和参数语义;
- 在 subagent prompt 中明确边界、已确认上下文和返回格式;
- 不要把泄露 prompt 整段搬运,只提炼适合自己场景的最小约束集;
- 给关键 Skill 加回归用例,每次 Claude Code 大版本更新后跑一遍。
Q5 泄露的提示词会过时吗?
会。CHANGELOG 已有 237 个版本,v2.1.211 相对之前又有大量变化,单版本新增 +3890 tokens。把它当参考,不要当圣经。真正值得关注的是 tool descriptions 和 agent delegation 的变化趋势,而不是某条具体 prompt 的字面内容。
我的判断
Claude Code 的 system prompt 泄露,最大的价值不是让我们去复制那 515 条提示词,而是让我们第一次看清楚,一个生产级 AI Coding Agent 的全局指令长什么样。
Skill/MCP 作者真正该学的,不是 prompt 的字面内容,而是 Anthropic 对「工具怎么用、任务怎么拆、上下文怎么传」的设计偏好。理解了这些,你写的 Skill 才不会和底层假设打架。也不会再出现「明明写了不要改依赖,它偏要改」的无力感。
我还是始终相信,提示词工程不是堆字数,而是减少歧义。你写的每一条约束,都要明确回答「在什么场景下、针对什么行为、期望什么结果」。
515 条提示词是 Anthropic 给 Claude Code 写的全局策略。你的 Skill 只需要写清楚自己的局部策略。两者不冲突,才能发挥出 Claude Code 真正的生产力。
写技术文章是真累,如果你觉得这篇对你有用,给个星标不过分吧。下篇打算聊聊「怎么给 Claude Code Skill 写回归测试」,把「system prompt 更新后 Skill 行为变化」这件事自动化掉,感兴趣的可以关注一下。你身边如果有朋友正在写 Claude Code Skill 或 MCP server,这篇可以直接甩给他。
