今天这篇文章源于最近半年深度使用 Claude Code、两个账号每月 40 刀氪金换来的一些踩坑经验,希望能给大伙一些输入。
刚开始我也把它当 ChatBot 用,后来很快发现不对劲:上下文越来越乱、工具越来越多但效果越来越差、规则越写越长却越不遵守,折腾了一段时间,研究了 Claude Code 本身之后才意识到,这不是 Prompt 问题,而是这套系统的设计就是这样的。
这篇文章想和大伙聊聊这几个事:Claude Code 底层怎么运作、上下文为什么会乱以及怎么治理、Skills 和 Hooks 应该怎么设计、Subagents 的正确用法、Prompt Caching 的架构影响,以及怎么写一个真正有用的 CLAUDE.md。
我觉得最直接的理解方式,是把 Claude Code 拆成六层来看:
claude code 教程
只强化其中一层,系统就会失衡,CLAUDE.md 写太长,上下文先污染自己了;工具堆太多了,选择就搞不清楚了;subagents 开得到处都是,状态就漂移了;验证这步跳过了,出了问题根本不知道是哪里挂的。

Claude Code 的核心不是”回答”,而是一个反复循环的代理过程:
用了一段时间才意识到,卡住的地方几乎从来不是模型不够聪明,更多时候是给了它错误的上下文,或者写出来了但根本没法判断对不对,也没法撤回。
对着这几个面看,很多问题就好排查了。结果不稳定,查上下文加载顺序,不是模型的事;自动化失控,看控制层有没有设计,不是 agent 太主动;长会话质量下降,中间产物把上下文污染了,换个新会话比反复调 prompt 有用得多。
简单记:给 Claude 新动作能力用 Tool/MCP,给它一套工作方法用 Skill,需要隔离执行环境用 Subagent,要强制约束和审计用 Hook,跨项目分发用 Plugin。
很多人把上下文当”容量问题”,但卡住的地方通常不是不够长,而是太吵了,有用的信息被大量无关内容淹没了。

Claude Code 的 200K 上下文并非全部可用:

一个典型 MCP Server(如 GitHub)包含 20-30 个工具定义,每个约 200 tokens,合计 4,000-6,000 tokens。接 5 个 Server,光这部分固定开销就到了 25,000 tokens(12.5%)。我第一次算出这个数字的时候,真没想到有这么多,在要读大量代码的场景,这 12.5% 真的很关键。
说白了,偶尔用的东西就不要每次都加载进来。
- 保持 短、硬、可执行,优先写命令、约束、架构边界。Anthropic 官方自己的 CLAUDE.md 大约只有 2.5K tokens,可以参考
- 把大型参考文档拆到 Skills 的 supporting files,不要塞进 SKILL.md 正文
- 使用 做路径/语言规则,不让根 承担所有差异
- 长会话主动用 观察消耗,不要等系统自动压缩后再补救

- 任务切换优先 ,同一任务进入新阶段用
- 把 Compact Instructions 写进 CLAUDE.md,压缩后必须保留什么由你控制,不由算法猜

默认压缩算法按”可重新读取”判断,早期的 Tool Output 和文件内容会被优先删掉,顺带把架构决策和约束理由也一起扔了。两小时后再改,可能根本不记得两小时前定了什么,莫名其妙的 Bug 就是这么来的。
解决方案就是在 CLAUDE.md 里写明:
除了写 Compact Instructions,还有一种更主动的方案:在开新会话前,先让 Claude 写一份 HANDOFF.md,把当前进度、尝试过什么、哪些走通了、哪些是死路、下一步该做什么写清楚。下一个 Claude 实例只读这个文件就能接着做,不依赖压缩算法的摘要质量:
在 HANDOFF.md 里写清楚现在的进展。解释你试了什么、什么有效、什么没用,让下一个拿到新鲜上下文的 agent 只看这个文件就能继续完成任务。
写完后快速扫一眼,有缺漏直接让它补,然后开新会话,把 HANDOFF.md 的路径发过去就行。

Plan Mode 的核心是把探索和执行拆开,探索阶段不动文件,确认方案后再执行:
- 探索阶段以只读操作为主
- Claude 可以先澄清目标和边界,再提交具体方案
- 执行成本在计划确认之后才发生

对于复杂重构、迁移、跨模块改动,这样做比”急着出代码”有用多了,它能显著降低在错误假设上持续修改的概率。按两下 进入 Plan Mode,进阶玩法是开一个 Claude 写计划,再开一个 Codex 以”高级工程师”身份审这个计划,让 AI 审 AI,效果很好。
Skill 官方描述是”按需加载的知识与工作流”,描述符常驻上下文,完整内容按需加载,用起来和”保存的 Prompt”差别挺大的。
- 描述要让模型知道”何时该用我”,而不是”我是干什么的”,这两个差很多
- 有完整步骤、输入、输出和停止条件,别写了个开头没有结尾
- 正文只放导航和核心约束,大资料拆到 supporting files 里
- 有副作用的 Skill 要显式设置 ,不然 Claude 会自己决定要不要跑
Claude Code 团队在内部设计中反复强调 “progressive disclosure”,意思不是让模型一次性看到所有信息,而是先获得索引和导航,再按需拉取细节:
- 负责定义任务语义、边界和执行骨架
- supporting files 负责提供领域细节
- 脚本负责确定性收集上下文或证据
一个比较稳定的结构长这样:
下面几个例子都来自我在开源 terminal 项目 Kaku 里的实际 Skill,比较直观。
类型一:检查清单型(质量门禁)
发布前跑一遍,确保不漏项:
类型二:工作流型(标准化操作)
配置迁移高风险,显式调用 + 内置回滚步骤:
类型三:领域专家型(封装决策框架)
运行时出问题时让 Claude 按固定路径收集证据,不要瞎猜:
每个启用的 Skill,描述符常驻上下文。优化前后差距很大:
还有一个很重要的 使用策略:
- 高频(>1 次/会话)→ 保持 auto-invoke,优化描述符
- 低频(<1 次/会话)→ disable-auto-invoke,手动触发,描述符完全脱离上下文
- 极低频(<1 次/月)→ 移除 Skill,改为 AGENTS.md 中的文档
- 描述过短:(任何后端工作都能触发,哈哈)
- 正文过长:几百行工作手册全塞进 SKILL.md 正文
- 一个 Skill 覆盖 review、deploy、debug、docs、incident 五件事
- 有副作用的 Skill 允许模型自动调用
我后面越用越觉得,给 Claude 的工具和给人写的 API 不是一回事。给人用的 API 往往会追求功能齐全,但给 agent 用,重点不是功能堆得多完整,而是让它更容易用对。
几个实用设计原则:
- 名称前缀按系统或资源分层:、
- 对大响应支持
- 错误响应要教模型如何修正,不要只抛 opaque error code
- 能合并成高层任务工具时,不要暴露过多底层碎片工具,避免 让模型自行筛选

我看到 Claude Code 团队内部工具的这段演进时,感觉还挺有意思。像这种需要在任务中途停下来问用户的场景,他们前后试了三种做法:
- 第一版:给已有工具(如 Bash)加一个 参数,让 Claude 在调用工具时顺带提问。结果 Claude 大多数时候直接忽略这个参数,继续往下跑,根本不停下来问。
- 第二版:要求 Claude 在输出里写特定 markdown 格式,外层解析到这个格式就暂停。问题是没有强制约束,Claude 经常”忘了”按格式写,提问逻辑非常脆弱。
- 第三版:做成独立的 工具。Claude 想提问就必须显式调用它,调用即暂停,没有歧义。效果显著好于前两版。
下面这张图刚好能解释,为什么第三版明显更稳:

左边(markdown 自由输出)太松,模型格式随意、外层解析脆弱;右边(ExitPlanTool 参数)太死,等到退出计划阶段提问已经太晚; 独立工具落在中间,结构化且随时可调用,是这三者里最稳定的设计。
说白了,既然你就是要 Claude 停下来问一句,那就直接给它一个专门的工具。加个 flag 或者约定一段输出格式,很多时候它一顺手就略过去了。
Todo 工具的演进:

早期用 TodoWrite 工具 + 每 5 轮插入提醒让 Claude 记住任务。随着模型变强,这个工具反而成了限制,Todo 提醒让 Claude 认为必须严格遵循,无法灵活修改计划。挺有意思的教训:当初加这个工具是因为模型不够强,模型变强之后它反而变成了枷锁。值得过段时间回来检查一下,当初加的限制还成不成立。
搜索工具的演进:最初用 RAG 向量数据库,虽然快但需要索引、不同环境脆弱,最重要的是 Claude 不喜欢用。改成 Grep 工具让 Claude 自己搜索后,效果显著提升。后来又发现一个顺带的好处:Claude 读 Skill 文件,Skill 文件又引用其他文件,模型会递归读取,按需发现信息,不需要提前塞进去,这个模式后来被叫做”渐进式披露”。
- 本地 shell 可以可靠完成的事情
- 模型只需要静态知识,不需要真正与外部交互
- 需求更适合 Skill 的工作流约束,而不是 Tool 的动作能力
- 还没验证过工具描述、schema 和返回格式能被模型稳定使用
Hooks 很容易被当成”自动运行的脚本”,但我自己用下来,觉得它更像是把一些不能交给 Claude 临场发挥的事情,重新收回到确定性的流程里。
比如格式化要不要跑、保护文件能不能改、任务完成后要不要通知,这些事真不要指望 Claude 每次都自己记得。

适合:阻断修改受保护文件、Edit 后自动格式化/lint/轻量校验、SessionStart 后注入动态上下文(Git 分支、环境变量)、任务完成后推送通知。
不适合:需要读大量上下文的复杂语义判断、长时间运行的业务流程、需要多步推理和权衡的决策,这些该在 Skill 或 Subagent 里。

在 100 次编辑的会话中,每次节省 30-60 秒,累积节省 1-2 小时,还挺可观的。注意限制输出长度(),避免 Hook 输出反而污染上下文。
- :声明”提交前必须通过测试和 lint”
- :告诉 Claude 在什么顺序下运行测试、如何看失败、如何修复
- :对关键路径执行硬性校验,必要时阻断
用下来感觉,三样少任何一层都会有漏洞。只写 CLAUDE.md 规则,Claude 经常当没看见;只靠 Hooks,细节判断又做不了,放在一起才比较稳。
Subagent 就是从主对话派出去的一个独立 Claude 实例,有自己的上下文窗口、只用你指定的工具、干完汇报结果。核心价值不是”并行”,而是隔离,扫代码库、跑测试、做审查这类会产生大量输出的事,交给 Subagent 做,主线程只拿摘要,不会被中间过程污染。Claude Code 内置了 Explore(只读扫库,跑 Haiku 省成本)、Plan(规划调研)、General-purpose(通用),也可以自定义。
- / :限定能用什么工具,别给和主线程一样宽的权限
- :探索任务用 Haiku/Sonnet,重要审查用 Opus
- :防止跑飞
- :需要动文件时隔离文件系统
另一个实用细节:长时间运行的 bash 命令可以按 移到后台,Claude 之后会用 BashOutput 工具查看结果,不会阻塞主线程继续工作。subagent 同理,直接告诉它「在后台跑」就行。
- 子代理权限和主线程一样宽,隔离没有意义
- 输出格式不固定,主线程拿到没法用
- 子任务之间强依赖,频繁要共享中间状态,这种情况用 Subagent 不合适
这块我之前在很多教程里都没怎么看到有人展开讲,但它其实很影响 Claude Code 的成本结构和很多设计取舍。
工程界有句话 “Cache Rules Everything Around Me”,对 agent 同样如此,Claude Code 的整个架构都是围绕 Prompt 缓存构建的,高缓存命中率不只降低成本,也帮助创造更宽松的速率限制,Anthropic 甚至会对命中率运行告警,太低直接宣布 SEV。

Prompt 缓存是按前缀匹配工作的,从请求开头到每个 断点之前的内容都会被缓存。所以这里的顺序很重要:
破坏缓存的常见陷阱:
- 在静态系统 Prompt 中放入带时间戳的内容(让它每次都变)
- 非确定性地打乱工具定义顺序
- 会话中途增删工具
那像当前时间这种动态信息怎么办?别去动系统 Prompt,放到下一条消息里传进去就行。Claude Code 自己也是这么做的,用户消息里加 标签,系统 Prompt 不动,缓存也就不会被打坏。
Prompt 缓存是模型唯一的。假如你已经和 Opus 对话了 100K tokens,想问个简单问题,切换到 Haiku 实际上比继续用 Opus 更贵,因为要为 Haiku 重建整个缓存。确实需要切换的话,用 Subagent 交接:Opus 准备一条”交接消息”给另一个模型,说明需要完成的任务就行。

上图是 Compaction(上下文压缩)的执行流程:左边是上下文快满时的状态,中间是 Claude Code 开一个 fork 调用,把完整对话历史喂给模型,加一句”Summarize this conversation”,这一步命中缓存所以只需 1/10 的价格,右边是压缩完之后,原来几十轮对话被替换成一段 ~20k tokens 的摘要,System + Tools 还在,再挂上之前用到的文件引用,腾出空间继续新的轮次。
直觉上 Plan Mode 应该切换成只读工具集,但这会破坏缓存。实际实现是: 是模型可以自己调用的工具,检测到复杂问题时自主进入 plan mode,工具集不变,缓存不受影响。
Claude Code 有数十个 MCP 工具,每次请求全量包含会很贵,但中途移除会破坏缓存。解决方案是发送轻量级 stub,只有工具名,标记 。模型通过 ToolSearch 工具”发现”它们,完整的工具 schema 只在模型选择后才加载,这样缓存前缀保持稳定。
「Claude 说完成了」其实没啥用,你得能知道它做没做对、出了问题能退回来、过程还能查,这才算数。
- 最低层:命令退出码、lint、typecheck、unit test
- 中间层:集成测试、截图对比、contract test、smoke test
- 更高层:生产日志验证、监控指标、人工审查清单
写任务 Prompt 或 Skill 的时候,最好把验收标准提前说清楚。哪些命令跑完算完成,失败了先查什么,截图和日志看到什么才算过,这些越早讲明白,后面越省事。
我自己有个很简单的判断:假如一个任务你都说不清楚「Claude 怎么才算做对了」,那它大概率也不适合直接丢给 Claude 自动完成。
这些命令说白了就干一件事:主动管理上下文,别等系统自己处理。

:对刚改完的代码做三维检查,代码复用、质量和效率,发现问题直接修掉。特别适合改完一段逻辑后立刻跑一遍,代替手动 review。
:不是”撤销”,而是回到某个会话 checkpoint 重新总结。适合:Claude 已沿错误路径探索太久;想保留前半段共识但丢掉后半段失败。
:在不打断主任务的前提下快速问一个侧问题,适合”两个命令有什么区别”这类单轮旁路问答,不适合需要读仓库或调用工具的问题。
:实时 JSON 事件流,适合长任务监控、增量处理、流式集成到自己的工具。
:让 Claude 分析当前会话,提炼出哪些内容值得沉淀到 CLAUDE.md。用法是会话做了一段之后跑一次,它会指出”这个约定你们反复提到,但没有写进契约”之类的盲点,是迭代优化 CLAUDE.md 的好手段。
双击 ESC 回溯:按两次 ESC 可以回到上一条输入重新编辑,不用重新手打。Claude 走偏了、或者上一句话没说清楚,双击 ESC 修改后重发,比重新开会话省事得多。
对话历史都在本地:所有会话记录存放在 下,文件夹名按项目路径命名(斜杠变横杠),每个会话是一个 文件。想找某个话题的历史,直接 就能定位,或者直接告诉 Claude「帮我搜一下之前关于 X 的讨论」,它会自己去翻。
在我看来更像是你和 Claude 之间的协作契约,不是团队文档,也不是知识库,里面只放那些每次会话都得成立的事。
我自己的建议其实很简单,一开始甚至可以什么都不写。先用起来,等你发现自己老是在重复同一件事,再把它补进去。加法也不复杂,输入 可以把当前对话里的内容直接追加进 CLAUDE.md,或者直接告诉 Claude「把这条加到项目的 CLAUDE.md 里」,它会知道该改哪个文件。

- 怎么 build、怎么 test、怎么跑(最核心)
- 关键目录结构与模块边界
- 代码风格和命名约束
- 那些不明显的环境坑
- 绝对不能干的事(NEVER 列表)
- 压缩时必须保留的信息(Compact Instructions)
- 大段背景介绍
- 完整 API 文档
- 空泛原则,如”写高质量代码”
- Claude 通过读仓库即可推断的显然信息
- 大量背景资料和低频任务知识(这些放到 Skills)
用起来其实不复杂:每次都要知道的放 CLAUDE.md,只对部分文件生效的放 rules,只在某类任务中需要的放 Skills。
我最喜欢的一个技巧:每次纠正 Claude 的错误后,让它自己更新 CLAUDE.md:
“Update your CLAUDE.md so you don’t make that mistake again.”
Claude 在给自己补这类规则时其实还挺好用,用久了确实越来越少犯同样的错。不过也要定期 review,时间一长总会有些条目慢慢过时,当初有用的限制现在未必还适合,这件事后面第 14 节有个更系统的做法。
春节放假时,我用 Claude Code 做了一个开源 terminal 项目 Kaku,底层是 Rust + Lua,也带了一些 AI 能力。混合语言加上自定义配置系统,实际折腾下来反而暴露出不少典型的 agent 协作问题,顺手聊几个对我帮助比较大的经验。
Claude Code 调用的都是真实的 shell、git、package manager 和本地配置。这里面只要有一层不透明,它就只能开始猜;一旦走到猜环境这一步,可靠性通常就会掉得很快。这其实也不只是 Claude Code 的问题,很多 agent 都一样。
所以我后来很快就在 terminal 里加了个 命令,把环境状态、依赖和配置情况先统一收上来,输出一份结构化的健康报告。Claude Code 开始做事前先跑一次 doctor,确实能省掉很多”环境没搞清楚就开干”的问题。
另外我还发现,假如 CLI 本身就有 、、 这类语义清楚的子命令,Claude Code 用起来会稳不少,比让它自己去猜配置文件怎么摆要靠谱。先把状态收敛住,再暴露编辑入口,顺序一反过来就很容易乱。
两套语言、两套检查,其实挺适合用 Hooks 按文件类型分别触发:
每次编辑完立刻知道有没有编译错误,比”跑了一堆才发现最开始就挂了”舒服得多。
假如有同学想给自己项目配一套比较完整的 Claude Code 工程布局,可以参考这个结构,不用全做,按需裁剪:
全局约束()、路径约束()、工作流()和架构细节完全解耦,Claude Code 的执行稳定性会显著上升。假如你同时维护多个项目,可以把稳定的个人基线放在 ,各项目的差异放在项目级 ,通过同步脚本分发,不同项目之间就不会互相污染了。
基于文章里的六层框架,我把这套检查整理成了一个开源 Skill 项目 ,可以一键检查你的 Claude Code 配置现在处于什么状态。
装好之后在任意会话里跑 ,它会自动识别项目复杂度,对 、、、、 和实际行为模式各跑一遍检查,输出一份优先级报告:需要立刻修 / 结构性问题 / 可以慢慢做。
如果你读完这篇文章想知道自己的配置离这些原则差多远,跑一次 是最快的方式。
用 Claude Code 大概会经历三个阶段:
到了第三阶段,关注点会悄悄变掉,从「这个功能怎么用」变成「怎么让 agent 在约束下自己跑起来」,两件事感觉差很多。
有一个问题挺值得想的:假如一个任务你说不清楚「什么叫做完」,那大概率也不适合直接扔给 Claude 自主完成,验证标准本身都没有,Claude 再聪明也跑不出正确答案。
这些是半年折腾下来的一些总结,肯定还有很多没有挖掘到的地方,如果大伙有用得更 6 的技巧,欢迎告诉我。
发布者:Ai探索者,转载请注明出处:https://javaforall.net/274583.html原文链接:https://javaforall.net
