转载声明:本文翻译转载自 Affaan Mustafa(@affaanmustafa)的文章《The Longform Guide to Everything Claude Code》。
原文链接:https://x.com/affaanmustafa/article/2014040193557471352
在《Claude Code 速查指南》中,我涵盖了基础设置:技能与命令、钩子、子代理、MCP、插件,以及构成高效 Claude Code 工作流骨干的配置模式。那是一份设置指南和基础设施说明。
这篇长篇指南则深入探讨那些将高效会话与浪费时间的会话区分开来的技巧。如果你还没读过速查指南,请先回去配置好你的设置。以下内容假设你已经配置好了技能、代理、钩子和 MCP,并且它们正常工作。
本文的主题包括:Token 经济学、记忆持久化、验证模式、并行化策略,以及构建可复用工作流的复合效应。这些是我经过 10 多个月的日常使用提炼出来的模式,它们决定了你是在第一个小时内就被上下文腐化困扰,还是能维持数小时的高效会话。
速查指南和长篇指南中涵盖的所有内容都可以在 GitHub 上找到。
对于跨会话共享记忆,最好的方法是使用一个技能或命令来总结和检查进度,然后保存到 .claude 文件夹中的 .tmp 文件,并在会话结束前持续追加内容。第二天它可以以此为上下文,从上次停下的地方继续。为每个会话创建一个新文件,这样就不会将旧上下文污染到新工作中。最终你会积累一大堆会话日志——定期备份或清理不需要的会话对话。
Claude 创建一个总结当前状态的文件。检查它,如果需要可以要求修改,然后重新开始。对于新对话,只需提供文件路径。这在碰到上下文限制需要继续复杂工作时特别有用。这些文件应包含:
一旦计划确定并清除了上下文(现在是 Claude Code 计划模式的默认选项),你就可以基于计划工作。这在积累了大量探索性上下文但已不再与执行相关时非常有用。对于战略性压缩,禁用自动压缩。在逻辑间隔点手动压缩,或创建一个技能来为你执行或根据定义的条件建议压缩。
将它挂载到 Edit/Write 操作的 PreToolUse 上——当你积累了足够的上下文需要压缩时,它会提醒你。
我采纳并正在试用的一种模式是:不仅仅将所有内容放在 CLAUDE.md(用户范围)或 .claude/rules/(项目范围,每次会话都加载),而是使用 CLI 标志动态注入上下文。
这让你能更精确地控制何时加载什么上下文。你可以根据正在做的工作在每个会话中注入不同的上下文。
为什么这比 @ file 引用更重要:
当你使用 @ file.md 或将内容放在 .claude/rules/ 中时,Claude 在对话过程中通过 Read 工具读取——它作为工具输出进入。当你使用 --system-prompt 时,内容在对话开始前被注入到实际的系统提示中。
区别在于指令层级。系统提示内容的权威性高于用户消息,用户消息的权威性高于工具结果。对于大多数日常工作来说,这个差异是微小的。但对于严格的行为规则、项目特定约束或你绝对需要 Claude 优先处理的上下文——系统提示注入确保了它被适当地加权。
一种有效的做法是利用 .claude/rules/ 作为基线项目规则,然后为特定场景创建 CLI 别名:
dev.md 专注于实现review.md 专注于代码质量/安全research.md 专注于行动前的探索同样,对于大多数情况,使用 .claude/rules/context1.md 和直接将内容追加到系统提示之间的差异是微小的。CLI 方法更快(无需工具调用)、更可靠(系统级权威)、且稍微更节省 token。但这是一个小优化,对很多人来说可能得不偿失。
有一些大多数人不知道或知道但没有真正利用的钩子可以帮助记忆:
钩子配置:
这些脚本的功能:
将这些链接在一起实现无需手动干预的跨会话持续记忆。这建立在第一篇文章中的钩子类型(PreToolUse、PostToolUse、Stop)之上,但专门针对会话生命周期。
我们讨论过以更新代码地图的形式进行持续记忆更新,但这同样适用于其他方面,比如从错误中学习。如果你不得不多次重复一个提示,而 Claude 遇到相同的问题或给了你之前听过的回答,这就适用于你。
最可能你需要发出第二个提示来"重新引导"并校准 Claude 的方向。这适用于任何此类场景——那些模式必须被追加到技能中。
你可以通过简单地告诉 Claude 记住它或将其添加到你的规则中来自动完成这个操作,或者你可以有一个专门做这件事的技能。
问题:浪费 token、浪费上下文、浪费时间,你的皮质醇水平飙升,因为你沮丧地对 Claude 大喊不要做你已经在之前会话中告诉它不要做的事情。
解决方案:当 Claude Code 发现非琐碎的东西——一种调试技术、一个变通方案、某个项目特定的模式——它将该知识保存为新技能。下次类似问题出现时,技能会被自动加载。
为什么用 Stop 钩子而不是 UserPromptSubmit? UserPromptSubmit 在你发送的每条消息上运行——这开销很大,给每个提示增加延迟,坦率地说对此目的是杀鸡用牛刀。Stop 在会话结束时运行一次——轻量级,不会在会话中拖慢你,并且评估完整会话而非零散片段。
安装方法:
Stop 钩子在你的会话结束时触发——脚本分析会话中值得提取的模式(错误解决方案、调试技术、变通方案、项目特定模式等),并将它们保存为可复用技能到 ~/.claude/skills/learned/。
/learn 手动提取你不必等到会话结束。该仓库还包括一个 /learn 命令,你可以在会话中刚解决了非琐碎问题时运行。它会提示你立即提取模式,起草技能文件,并在保存前要求确认。
该技能期望 .tmp 文件中的会话日志。模式是:~/.claude/sessions/YYYY-MM-DD-topic.tmp——每个会话一个文件,包含当前状态、已完成项目、阻塞项、关键决策和下次会话的上下文。
一种方法涉及对会话日志进行反思,提炼用户偏好——本质上是建立一本关于什么有效什么无效的"日记"。每次会话后,反思代理提取什么顺利、什么失败、你做了什么纠正。这些学习成果更新一个在后续会话中加载的记忆文件。
另一种方法让系统每 15 分钟主动建议改进,而不是等你发现模式。代理审查最近的交互,提出记忆更新建议,你批准或拒绝。随着时间推移,它从你的批准模式中学习。
我从价格敏感的用户或作为高级用户经常遇到限制问题的人那里收到了很多问题。在 token 优化方面有几个技巧。
主要优化你使用的工具和设计为将最便宜的足够完成任务的模型分配工作的子代理架构来减少浪费。你有几个选择——你可以尝试试错法并随着时间适应。一旦你了解了什么是什么,你可以委托给 Haiku 而不是 Sonnet,委托给 Sonnet 而不是 Opus。
另一种更复杂的方法是让 Claude 设置一个基准测试,你有一个定义明确的目标和任务的仓库,以及一个定义明确的计划。在每个 git worktree 中,让所有子代理都使用同一个模型。在完成任务时记录日志——理想情况下在你的计划和任务中。你至少需要使用每个子代理一次。
完成一整轮并从 Claude 计划中勾选任务后,停止并审计进度。你可以通过比较 diff、创建在所有 worktree 中统一的对单元、集成和 E2E 测试来实现。这将根据通过的用例与失败的用例给你一个数字基准。如果所有测试在所有 worktree 上都通过,你需要添加更多测试边缘情况或增加测试的复杂性。这是否值得取决于这对你的真正重要性。
默认使用 Sonnet 完成 90% 的编码任务。在以下情况升级到 Opus:首次尝试失败、任务跨越 5 个以上文件、架构决策或安全关键代码。在以下情况降级到 Haiku:任务重复、指令非常清晰,或在多代理设置中用作"工作者"。
坦率地说,Sonnet 4.5 目前处于一个奇怪的位置,每百万输入 token 3 美元,每百万输出 token 15 美元,与 Opus 相比节省约 66.7%,绝对来说这是一个不错的节省,但相对而言对大多数人来说微不足道。Haiku 和 Opus 的组合最有意义,因为 Haiku 与 Opus 相比有 5 倍的成本差异,而与 Sonnet 相比只有 1.67 倍的价格差异。
在你的代理定义中,指定模型:
考虑 Claude 最频繁调用的工具。例如,用 mgrep 替换 grep——在各种任务中,与传统 grep 或 ripgrep(Claude 默认使用的)相比,平均 token 减少约一半。
在适用时,如果你不需要 Claude 处理整个输出并实时流式传输,可以在 Claude 之外运行后台进程。这可以通过 tmux 轻松实现。获取终端输出然后仅总结或复制你需要的部分。这将节省大量输入 token——Opus 4.5 每百万 token 5 美元(输入),输出每百万 token 25 美元。
拥有更模块化的代码库,具有可复用的工具、函数、钩子等——主文件在数百行而不是数千行——既有助于 token 优化成本,又有助于第一次就正确完成任务,两者是相关的。如果你不得不多次提示 Claude,你就在消耗 token,特别是当它在很长的文件上反复阅读时。你会注意到它需要做很多工具调用来完成文件读取。在中间过程中,它让你知道文件很长并会继续读取。在这个过程中的某个环节,Claude 可能会丢失一些信息。而且停止并重新读取会消耗额外的 token。这可以通过拥有更模块化的代码库来避免。
这可能是显而易见的,但你的代码库越精简,token 成本就越低。使用技能持续清理代码库、通过重构来识别死代码至关重要。在某些时候,我喜欢通览整个代码库,寻找突出或看起来重复的内容,手动拼凑那个上下文,然后连同重构技能和死代码技能一起喂给 Claude。
对于真正关注成本的人:Claude Code 的系统提示占用约 18k token(200k 上下文的约 9%)。这可以通过补丁减少到约 10k token,节省约 7,300 token(静态开销的 41%)。如果你想走这条路,参见 YK 的指南。个人我不做这个。
根据项目,你会想要使用某种形式的可观测性和标准化。
一种方法是将 tmux 进程挂接到跟踪思维流并在技能触发时输出。另一种方法是使用 PostToolUse 钩子记录 Claude 具体执行了什么以及确切的更改和输出。
与在没有技能的情况下要求同样的事情并检查输出差异来基准测试相对性能:
分叉对话,在其中一个中启动一个没有技能的新 worktree,最后拉出 diff,看看记录了什么。这与持续学习和记忆部分相关联。
更高级的评估和循环协议在此进入。分为基于检查点的评估和基于 RL 任务的持续评估。
基于检查点的评估:
持续评估:
决定因素是你工作的性质。基于检查点适用于有清晰阶段的功能实现。持续适用于探索性重构或没有清晰里程碑的维护。
我想说通过一些干预,验证方法足以避免大多数技术债。让 Claude 在完成任务后通过运行技能和 PostToolUse 钩子来验证有助于此。持续的代码地图更新也有帮助,因为它保留了变更日志以及代码地图如何随时间演变,作为仓库本身之外的真相来源。通过严格的规则,Claude 会避免创建随意的 .md 文件弄得一团糟,以及相似代码的重复文件和留下死代码的荒原。
pass@k:k 次尝试中至少有一次成功
| k 值 | 通过率 |
|---|---|
| k=1 | 70% |
| k=3 | 91% |
| k=5 | 97% |
k 越高 = 成功概率越高
pass^k:k 次尝试必须全部成功
| k 值 | 通过率 |
|---|---|
| k=1 | 70% |
| k=3 | 34% |
| k=5 | 17% |
k 越高 = 越难(一致性)
当你只需要它工作且任何验证反馈就够时使用 pass@k。当一致性至关重要且你需要近乎确定性的输出一致性(在结果/质量/风格方面)时使用 pass^k。
在多 Claude 终端设置中分叉对话时,确保分叉和原始对话中的操作范围定义明确。在代码更改方面争取最小重叠。选择彼此正交的任务以防止干扰的可能性。
个人而言,我更喜欢让主聊天处理代码更改,而我做的分叉用于我对代码库及其当前状态的问题,或研究外部服务(如拉取文档、搜索 GitHub 寻找有帮助的开源仓库),或其他有帮助的通用研究。
Boris(Claude Code 的创建者,传奇人物)有一些关于并行化的建议,我有些同意有些不同意。他建议过像本地运行 5 个 Claude 实例和 5 个上游实例这样的事情。我建议不要设置像这样的任意终端数量。添加终端和添加实例应该是出于真正的必要性和目的。如果你能用脚本完成任务,就用脚本。如果你能在主聊天中让 Claude 在 tmux 中启动一个实例并在单独的终端中流式传输,就那样做。
你的目标应该是:用最少的可行并行化完成最多的事情。
对于大多数新手,我甚至建议远离并行化,直到你掌握了只运行单个实例并在其中管理一切的技巧。我不是在提倡限制自己——我是在说要小心。大多数时候,甚至我也总共只使用 4 个终端左右。我发现通常用 2 或 3 个 Claude 实例就能完成大部分事情。
如果你确实要开始扩展实例并且有多个 Claude 实例处理彼此重叠的代码,使用 git worktree 并为每个实例制定非常明确的计划是必须的。此外,为了避免在恢复会话时对哪个 git worktree 用于什么感到困惑(除了树的名称),使用 /rename <name> 命名为你的所有聊天命名。
好处:
运行多个 Claude Code 实例时,用"级联"模式组织:
从头开始时,实际的基础很重要。这应该是显而易见的,但随着代码库复杂度和规模增加,技术债也会增加。管理它非常重要,如果你遵循一些规则并不那么困难。
对于我自己的工作流管理(不是必须的但有帮助),我喜欢用 2 个打开的 Claude 实例启动一个空仓库。
实例 1:脚手架代理
CLAUDE.md、规则、代理——速查指南中的所有内容)实例 2:深度研究代理
启动设置:左终端用于编码,右终端用于提问——使用 /rename 和 /fork。
你最初需要的最低限度就够了——这比每次都使用 Context7 或喂入链接让它抓取或使用 Firecrawl MCP 站点更快。当你在某事中已经深陷其中,Claude 明显在语法上出错或使用过时的函数或端点时,所有这些方法都有效。
如果可用,你可以在许多文档参考上找到 llms.txt,方法是到达它们的文档页面后加上 /llms.txt。这会给你一个干净的、LLM 优化的文档版本,你可以直接喂给 Claude。
我完全认同的一个洞察:"早期,我花时间构建可复用工作流/模式。构建很繁琐,但随着模型和代理 harness 改进,这产生了疯狂的复合效应。"
值得投资的:
为什么它会复合:"最好的部分是所有这些工作流都可以转移到 Codex 等其他代理。" 一旦构建,它们跨模型升级工作。对模式的投资 > 对特定模型技巧的投资。
子代理的存在是为了通过返回摘要而不是转储所有内容来节省上下文。但编排器拥有子代理缺少的语义上下文。子代理只知道字面查询,不知道请求背后的目的/推理。摘要经常遗漏关键细节。
比喻:"你的老板派你去开会并要求一份摘要。你回来给了他一个概要。十有八九,他会有后续问题。你的摘要不会包含他需要的一切,因为你没有他拥有的隐式上下文。"
修复方法是让编排器:
传递目标上下文,而不仅仅是查询。分派子代理时,包含特定查询和更广泛的目标。这有助于子代理在摘要中优先包含什么。
关键规则:
/clear 保持上下文新鲜第一层:直接增益(易于使用)
第二层:高技能门槛(更难用好)
要点:从第一层模式开始。只有在掌握了基础并有真正需求时才晋升到第二层。
一些 MCP 是可替代的,会释放你的上下文窗口。方法如下。
对于版本控制(GitHub)、数据库(Supabase)、部署(Vercel、Railway)等 MCP——这些平台大多数已经有强大的 CLI,MCP 本质上只是在包装它们。MCP 是一个不错的包装器,但需要付出代价。
要让 CLI 像 MCP 一样运行而不实际使用 MCP(以及随之而来的减少上下文窗口),考虑将功能打包到技能和命令中。将 MCP 暴露的工具剥离出来,把它们变成命令。
例如:与其一直加载 GitHub MCP,不如创建一个包装 gh pr create 的 /gh-pr 命令,加上你偏好的选项。与其让 Supabase MCP 消耗上下文,不如创建直接使用 Supabase CLI 的技能。功能相同,便利性类似,但你的上下文窗口被释放用于实际工作。
自从我发布原文以来的过去几天,Boris 和 Claude Code 团队在记忆管理和优化方面取得了很多进展,主要是 MCP 的延迟加载,这样它们不再从一开始就消耗你的窗口。之前我会建议尽可能将 MCP 转换为技能,通过以下两种方式卸载执行 MCP 的功能:在当时启用它(不太理想,因为需要离开并恢复会话)或拥有使用 MCP 的 CLI 类似物的技能(如果存在)并让技能成为它的包装器——本质上是让它充当伪 MCP。
有了延迟加载,上下文窗口问题基本解决了。但 token 使用和成本并没有以同样的方式解决。CLI + 技能方法仍然是一种 token 优化方法,效果可能与使用 MCP 相当或接近。此外,你可以通过 CLI 而不是在上下文中运行 MCP 操作,这显著减少了 token 使用,特别适用于重型 MCP 操作如数据库查询或部署。