在本章中,我们将从“如何开始使用 Claude Code”进一步过渡到“如何把它配置成一个适合日常使用的工具”。目标是帮助你真正熟悉 Claude Code 在实际工作中的行为方式、你如何在会话中控制它,以及如何对它进行配置,从而让它在不同项目之间保持一致性。
我们会先简要介绍定价与认证方式,帮助你在开始之前选择合适的接入方案。之后,我们会聚焦于你最常用的部分:用于管理会话和上下文的斜杠命令、用户级与项目级配置,以及如何在 Cursor 这样的 IDE 中直接运行 Claude Code。然后,我们会在这些基础之上继续展开,介绍那些能让长工作流更安全、更可靠的能力,包括用于自动化的 hooks、通过 CLAUDE.md 文件实现的 memory、通过 checkpointing 实现的 rewind,以及可用于构建可复用、作用域清晰工作流的自定义斜杠命令(skills)。
Skills 可以通过 /skill-name 这样的语法手动调用,这也是为什么旧文档里有时会把它们称为 skills。就内部实现而言,它们现在已经统一归入 Skills 系统之下。
本章将涵盖以下主题:
- Claude Code 的定价与方案
- 使用斜杠命令控制 Claude Code
- 在 Claude Code 中使用 hooks
- 理解 Claude Code 中的 memory
- Claude Code 中的 rewind 功能
- Claude Code 中的 skills
Claude Code 的定价与方案
在这一节中,我们将讨论使用和消费 Claude Code 时可选的定价方式,以及不同的套餐方案。我们会先从认证方式讲起,因为你如何认证,实际上也决定了你的 token 使用会如何计费。
本节提到的定价与套餐细节,在写作本书时是准确的。由于订阅层级、使用限制与计费策略都可能变化,请始终以 Claude 官方定价页面为准,获取最新信息:
https://claude.com/pricing
图 3.1 —— Claude Code 的认证方式选择界面
Claude Code 提供了三种主要的认证与 token 付费方式。
图 3.2 —— Claude Code 的订阅与 API 计费登录方式
方案 1:使用 Anthropic API Key
一种方式是通过 Anthropic API Key 进行认证。这采用的是**按量付费(pay-as-you-go)**模式,使用量会在 Anthropic 控制台中进行追踪。对于偏好按使用量计费的用户,或者希望在决定订阅之前先评估 Claude Code 的用户来说,这种方式很有用。
如果你在阅读本书时采用 Anthropic API Key 这种方式,那么实际使用量会取决于 Claude Code 被调用的频率,以及所使用的模型。
如果你选择这条路径,就在认证时选择 API Key 认证方式,并通过你的 Anthropic 组织授权 Claude Code。之后,Claude Code 会自动生成一个 API Key,并在终端中完成配置。配置完成后,Claude Code 就会以按量付费模式运行。
使用 Anthropic API 时需要注意的点
使用 API Key 时,一个很重要的点是:你需要监控 token 消耗情况。你可以直接在 Claude Code 中通过 /cost 命令来完成这件事。这个命令只有在 Claude Code 通过 Anthropic API Key 认证时才可用。它会显示已消耗的 token 数量以及它们的分布情况。
图 3.3 —— 使用 /cost 命令监控 Token 使用情况
同样的信息,在 Anthropic 控制台里也能看到。当前成本之所以是 0,是因为还没有消耗任何 token。你只需要先随便输入一点内容,等 Claude 返回结果之后,再输入一次 /cost 即可。
图 3.4 —— 运行一个 Prompt 之后更新的 Token 使用情况
请记住,不同模型的价格并不相同。比如,使用 Opus 的 token 成本通常会明显高于其他模型。
使用 API Key 时的重要考量
使用 API Key 需要格外谨慎。因为一旦 Key 被意外泄露,别人就可能用你的 Key 去消耗 token,而费用由你承担。极端情况下,这甚至可能导致非常高的意外账单。
另外,本书中会涉及智能体、子智能体以及编排模式等内容,而这些都会消耗大量 token。如果某些配置出错,就有可能一次性触发大量智能体并发运行,从而显著推高成本。
降低这种风险的一种办法,是在 Anthropic 控制台中设置消费上限(spending limits) 。Anthropic 允许你为账号设置使用上限,一旦达到限制,后续请求将不再被服务。关于如何配置这些限制,请参考 Anthropic 的设置页面:
https://platform.claude.com/settings/limits
方案 2:使用 Claude 订阅
如果你是按照第 2 章里的配置走下来的,那么你现在使用的就是方案 2,也就是通过 Claude 订阅进行认证。在本书中,我们全程都会使用这种方式。具体来说,就是把你现有的 Claude 订阅直接连接到 Claude Code。这样可以获得更顺畅的集成体验,以及可预测的按月计费模式。
Claude 当前提供以下订阅层级:
- Free ——
$0/月(不包含 Claude Code 访问权限) - Pro ——
$20/月 - Max 5x ——
$100/月 - Max 20x ——
$200/月
Claude Code 从 Pro 及以上套餐开始提供访问权限。
在本书中,我使用的是 Max 5x 套餐。它比 Pro 提供更高的使用上限,同时对于日常开发工作流来说,仍然具有较好的性价比。
与前一种方式不同的是,在订阅模式下,成本监控的逻辑会有所不同。由于 Claude Code 的使用已经包含在订阅中,所以你不需要再通过 /cost 去追踪 token 级别的费用。价格是固定的,不过不同套餐依然有对应的使用上限。
图 3.5 —— 使用 /usage 命令查看订阅使用情况
这种方式下可用的模型
通过 /models 命令,你可以看到当前有哪些模型可用。Claude Code 目前支持 Opus、Sonnet 和 Haiku:
- Claude Opus:这是能力最强的模型,非常适合复杂任务和深度推理。它拥有 200K token 的上下文窗口,通常用于深度规划或研究类任务。由于成本较高,Opus 一般不会被拿来大量写代码。
- Claude Sonnet:Sonnet 在智能、速度与成本之间提供了较好的平衡。它同样拥有 200K token 上下文窗口,并且会是本课程中用于代码生成的主力模型。由于这种平衡性,绝大多数代码编写与修改任务都由 Sonnet 承担。
- Claude Haiku:这是速度最快、最轻量的模型。它适合简单任务、快速迭代,以及那些对低延迟要求更高、但不需要深度推理的工作流。
这些模型本身都由 Anthropic 托管并提供服务。在企业环境中,它们也可以通过支持的第三方云平台来接入,例如 AWS Bedrock、Google Cloud Vertex AI 或 Microsoft Azure。这种方式通常用于那些需要集中式计费、云平台合规控制、区域部署能力,或希望通过现有云基础设施进行治理的组织。
订阅套餐与定价
Claude 提供多个订阅层级:
- Free 计划
- Pro 计划
- Max 5x 计划
- Max 20x 计划
为了防止滥用,例如共享账号或不当使用系统,官方引入了速率限制(rate limits) 。这些限制适用于 Pro 和 Max 套餐。
对于大多数用户,尤其是业余开发者来说,推荐从 Pro 套餐开始。只有当你确实需要更高的使用额度时,再升级到 Max 套餐才更合理。
精确的使用上限其实很难被量化,而这并不只是 Claude Code 面临的问题。AI 编码智能体的定价,本身就是整个行业尚未完全解决的一个难题。定价模型的变化也已经在开发者社区中引发了不少挫败感,而这依然是一个持续演化中的问题。
本节的目的,是帮助你理清可选的定价方式,并理解使用 Claude Code 时计费是如何发生的,从而选择最适合自己的方案。
方案 3:使用第三方云服务商
Claude Code 还可以通过受支持的第三方云平台进行认证,例如 Amazon Bedrock、Microsoft Azure AI 或 Google Cloud Vertex AI。在这种情况下,计费与使用量将由所选云服务商管理,而不是通过 Claude 订阅或 Anthropic API Key 来处理。关于支持的第三方集成详情,请参考官方文档:
https://code.claude.com/docs/en/third-party-integrations
使用斜杠命令控制 Claude Code
斜杠命令(slash commands)是在 Claude Code 聊天界面中控制其功能与设置的主要方式。当我们输入 / 时,Claude Code 会展示一份可用命令列表,如下所示:
图 3.6 —— 在 Claude Code 中列出可用斜杠命令
当我们和 Claude Code 聊得很多时,会话会变得非常长,这会导致系统变慢,并且带来所谓的 context rot(上下文腐化) ,这一点我们会在后面的章节里讨论。长会话还会增加成本,甚至因为 Claude 需要记住太多内容而让它变得混乱。
为了解决这个问题,Claude Code 提供了两个命令:
/clear:清空所有内容,从头开始,就像一张白纸/compact:生成一个简短摘要,保留重要信息,同时去掉冗余细节
使用 /clear 和 /compact 可以帮助 Claude 持续保持聚焦,并随着时间推移维持更好的工作状态。这其实就是上下文工程在实践中的体现(见第 1 章)。
让我们先从一个全新的会话开始。为此,我们需要运行 /clear。
另一个值得注意的命令是 /agents,它用于管理专门化的子智能体。你可以把子智能体理解为为特定任务创建的专家助手,比如代码审查器、调试器或架构师。
它们运行在自己的上下文和工具集合之上,并作为多智能体工作流的一部分被使用。关于子智能体和这些工作流,后面会有专门的实操章节展开。
接下来是 /config 命令。/config 会打开 Claude Code 的配置面板,在那里你可以看到各种设置项与偏好选项。运行这个命令后,你会看到如下所示的设置界面:
图 3.7 —— Claude Code 配置面板与设置选项
例如,我们可以看到 Auto-compact 已经开启。这意味着,当 Claude 检测到会话即将逼近 token 上限,或者判断当前是一个适合压缩上下文的时机时,它会自动运行 /compact。此外,这里还会看到诸如使用待办事项列表(to-do lists)、checkpointing,以及其他选项。我们不会在这里逐项讲解所有配置;最完整、最新的设置清单,可以在 Claude Code 官方文档中查看:
https://code.claude.com/docs/en/settings
除了每个单独的选项本身,更重要的是这些设置是如何组织和生效的。Claude Code 提供了一套细粒度配置系统:
- 用户级设置:存放在主目录下的
.claude/settings中,对每一个 Claude Code 实例全局生效 - 项目级设置:存放在项目目录中的
.claude/settings.json中,仅对该项目生效,并且可以和团队共享 - 本地设置:允许你做个人化微调,而不会影响共享的项目设置
这种结构使你可以同时拥有全局默认配置、项目级规范,以及个人偏好。贯穿本书中展示的设置,都可以通过这些 settings 文件,按照个人与团队需求来完成配置。
最后,我们再看一下 /cost。由于这里使用的是 Claude Pro 订阅,所以不会在这里展示成本监控,因为订阅本身已经包含 Claude Code 的使用。/cost 这个命令在你通过 Anthropic API Key 使用 Claude Code 时会更有意义。
将 Claude Code 集成进 IDE
在结束这一节之前,我们再来看一下如何把 Claude Code 集成到 IDE 中。这个例子里,我们会把它集成到 Cursor IDE。打开斜杠菜单,选择 IDE,就可以把 Claude Code 集成进 Cursor。这样会直接在 IDE 中安装 Claude Code 扩展。
安装完成后,我们就可以在 Cursor 中看到 Claude Code 扩展。
图 3.8 —— Cursor 编辑器中的 Claude Code 扩展
你会注意到右上角会出现一个 Claude Code 图标。这其实就是大多数开发者在实践中使用 Claude Code 的方式。Claude Code 通常通过 Cursor 扩展打开,从而直接运行在 IDE 内部。这样我们就能在编辑器里工作、更清晰地查看 diff,并且把一切都保留在同一个界面里。本书后续也会一直采用这种使用方式。
我们还会用到 /mcp 命令,它用于管理 MCP Server。借助这个命令,我们可以添加、删除以及列出所有已配置的 MCP Server。
在这一刻,可能还没有配置任何 MCP Server。MCP Server 会为 Claude Code 提供额外功能。它们可能来自已验证的厂商,也可能是开源项目;本质上,它们就是在为 Claude Code 扩展新的工具和能力。
MCP 本身是一个很深的话题。在本书后续内容里,我们会把 MCP Server 真正集成进工作流中并实际使用它们。此处暂时默认你对 MCP Server 的基本概念已经有所了解。
在 Claude Code 中使用 Hooks
Hooks 是 Claude Code 中一项非常强大的能力。它们是在 Claude Code 工作流中的特定节点上自动执行的逻辑。
图 3.9 —— Claude Code 中的 Hook 配置与安全警告
例如,Hook 可以在某个工具被使用之前或之后运行,也可以在 Claude 完成工作时运行。它们可以帮助自动完成诸如格式化代码、运行测试、阻止不安全编辑等任务。通过这种方式,Hooks 能确保这些动作在没有人工干预的情况下,依然稳定、一致地执行。
Hooks 是构建可靠工作流的关键组成部分,后面书里我们会花大量时间动手实践它们。先做一个简短预告:Hooks 还可以被用来触发 Claude 的子智能体。每个子智能体都有自己的上下文和工具集,这就为更复杂、更强大的工作流打开了空间。
创建一个通知 Hook
现在我们来配置第一个 Hook。在这一节中,我们会构建一个简单的通知 Hook:每当 Claude 完成输出时,就播放一段声音。
所有相关代码都可以在仓库中的 project/hooks-notification 分支下找到。在继续之前,请先 clone 这个仓库,并切换到 project/hooks-notification 分支。
初始化环境
请按以下步骤进行:
- 确保仓库中已经包含所有所需文件,包括声音文件。为了从零开始搭建环境,可以删除除音频录音之外的所有内容。
- 为这个 Hook 初始化 Python 环境。由于 Hook 是一个 Python 脚本,所以需要先创建 Python 环境并安装依赖。这里我们使用
uv来初始化环境。运行以下命令:
uv init
这个示例使用的是 uv,它是 Astral 提供的一个快速 Python 包与环境管理工具。如果你还没有安装 uv,请参考官方文档中的安装说明:
https://docs.astral.sh/uv/
执行后,它会创建一个虚拟环境以及一个主文件。
- 重命名并运行主文件。把主文件重命名为
play_sound.py,然后运行:
uv run play_sound.py
这样可以确认环境已经正确配置完成。
- 重新打开 Claude Code,并确认这个 Hook 还不存在。你可以先运行一个 Prompt,确认 Claude 正常返回结果,但并不会播放声音。
- 然后让 Claude Code 帮你编写这个 Hook 脚本。使用下面这条 Prompt:
I want you to please write a python script that is going to play the sound @ulala.wav, every time the script runs.
也就是说,请 Claude 写一个 Python 脚本,每次运行时都播放录制好的声音文件。
自定义通知音效
这个 Hook 并不依赖某个特定的声音文件。它只是播放脚本中指向的那个文件而已。本节的示例使用的是 @ulala.wav,但你完全可以替换成任何你喜欢的音频文件。
如果你选择不同的文件,就把它放到项目中(例如放在 hooks/ 或 assets/ 目录下),并修改脚本,让它使用新的文件名或路径。
接着,审查 Claude 提出的修改。
图 3.10 —— 在 Diff 视图中审查并批准 Hook 文件修改
Claude 会显示一个 diff 视图,标出新增和删除的代码行,并请求你批准对 play_sound.py 的编辑。此时批准这次文件修改:
你可以选择以下某一种批准方式:
- 本次批准
- 本会话内持续批准
- 拒绝并给出不同指示
如果你选择本会话内持续批准,Claude 会把这个决定写入本地设置,使它在这个会话里不再针对这个文件重复询问。这个权限步骤是一项安全机制,因为 Claude Code 是在直接修改文件。
接下来安装所需依赖。由于这个脚本使用 pygame 来播放音频,所以运行以下命令安装:
uv add pygame
然后测试这个脚本。再次运行它,确认声音能够正确播放:
Uv run play_sound.py
接着,打开 hooks 配置界面,把这个脚本注册成一个自动化动作。打开斜杠菜单,输入 /hooks,然后从列表中添加一个新 Hook。
可选事件包括:
- PreToolUse —— 工具执行前
- PostToolUse —— 工具执行后
- Notification —— 通知被发送时
- UserPromptSubmit —— 用户提交 Prompt 时
- Stop —— Claude 即将结束响应之前
这一步是必须的,因为 Claude Code 需要知道:应该在什么时机、以什么方式自动运行这个脚本,而不是每次都要求你手工执行。
选择 Hook 事件。这里选 Stop 事件,也就是在 Claude 即将完成响应时触发。这样可以保证脚本会在输出生成后立即执行,因此非常适合通知类 Hook。虽然还有其他事件可以选,但对于当前需求来说,这个事件最匹配。
然后配置 Hook 命令,把命令设置为:
uv run play_sound.py
如果脚本位于某个文件夹,比如 hooks/ 中,那么就写成对应路径,例如:
your/path/to/play_sound.py
这样可以确保脚本是在虚拟环境中运行的。作用域请选择 project scope,这样这个 Hook 只会对当前项目生效。
审查生成出的配置
完成后,会创建一个 .claude 目录,其中包含一个 settings 文件,Hook 配置会以 JSON 形式保存在里面:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "uv run
/Users/edenmarco/GithubProjects/
claude-code-crash-course/play_sound.py"
}
]
}
]
}
}
这里空的 "matcher": "" 表示:这个 Hook 会作用于该类型事件下的所有匹配情况。也就是说,在这个例子里,它会对每一个 Stop 事件都触发,而不会做额外过滤。
这个配置明确指定了:事件类型、可选的 matcher,以及在 Claude 输出结束时要执行的命令。
接着,重新加载 Claude Code。退出 Claude Code,再重新打开它,这样新设置才能被加载进来。
最后验证这个 Hook。输入任意一个 Prompt,并确认 Claude 每次完成响应时,都会播放那段声音。这样就说明这个 Hook 已经正常工作了。
到这里,这个 Hook 就算完成配置了。现在,在 Cursor 中打开 Claude Code,随便输入一个 Prompt:
hello how are you?
当 Claude 响应结束后,通知音效应该会自动播放。
这就证明了:
- Python 环境已经正确初始化
- 脚本可以成功执行
- Hook 已经注册,并且会在
Stop事件上被触发
如果没有声音,请重新检查 Hook 配置,并确认命令路径是否正确。
关于 Hooks 与可扩展性的说明
这个 Hook 不接收任何参数,但 Hook 其实也可以被配置为接收上下文信息。这些信息可能包括用户输入、工具调用或其他运行时细节。最佳实践是把 Hooks 统一组织在专门的 hooks 目录中,因为它们本质上就像一组可复用的小工具。
Hooks 还可以输出内容,以进一步影响 Claude Code 接下来的行为。它们可以阻止某些动作、修改行为,甚至触发子智能体。更高级的 Hook 用法,后面章节里会继续讲。本例只是一个入门示范。
Skills 依然按前文所述方式工作。只是在内部实现上,命令已经统一到 skills 这个概念之下。已有的 .claude/commands/ 文件仍然完全兼容,而定义在 .claude/skills/ 下的等价 skill 也会以相同方式工作。Skills 增加了可选结构、支持文件,以及对 Claude 何时、如何被调用的更强控制。关于 skills 的更多内容,会在第 9 章继续讲。
在继续之前,还值得说明一点:Hooks 只是 Claude Code 用来扩展行为的几种机制之一。Hooks 作用于特定执行节点,而其他一些特性则聚焦于上下文与持久化控制。接下来,我们会通过 memory 系统来讨论这些内容。
另外,在生产环境里请尽量保持 Hook 轻量。因为 Hook 是自动运行且可能触发得非常频繁的,过重的脚本会引入不必要的延迟。对于简单通知来说,一个极简的系统命令,比如 macOS 上的 afplay sound.wav 或 Linux 上的 aplay sound.wav,通常都比启动完整 Python 运行时并加载外部依赖更快。因此,只要可行,针对高频 Hook 优先使用轻量命令。
理解 Claude Code 中的 Memory
在 Claude Code 中,memory 指的是一套允许 AI 在不同编码会话之间保留并复用重要信息的机制,例如设置、规则和上下文细节。memory 的目的,是提升工作流效率,并在长期使用中保持一致性。
Memory 主要通过一类特殊文件来管理,也就是 CLAUDE.md 文件。这些文件中存放的是 Claude Code 在每次会话开始时会加载的指令和偏好设置,它们会在整个交互过程中持续影响 Claude 的行为。
Memory 的类型
Claude Code 中的 memory 具有细粒度结构,可以在不同层级定义:
- 用户级 memory(User memory) :存放在用户主目录的
~/.claude/CLAUDE.md中。这个文件通常保存会跨所有项目生效的个人偏好,例如代码风格偏好、常用工作流、快捷习惯,以及其他希望无论在哪个项目中都保持一致的做法。 - 项目级 memory(Project memory) :以
./CLAUDE.md的形式存放在项目目录中。它通常包含团队共享规则和项目特定上下文,例如编码规范、架构决策,以及只适用于该项目的通用工作流。 - 托管策略(Managed policy,组织级 memory) :这是由 IT 或 DevOps 团队统一管理的组织级指令。它们存放在系统级路径中(例如 macOS 上的
/Library/Application Support/ClaudeCode/CLAUDE.md、Linux/WSL 上的/etc/claude-code/CLAUDE.md,或 Windows 上的C:\Program Files\ClaudeCode\CLAUDE.md)。这类 memory 用于公司范围内的编码标准、安全策略和合规要求,并且会对组织内所有用户生效。
Claude Code 如何读取 Memory?
Claude Code 采用一种分层、层级化的方式来加载 memory。它会从当前工作目录开始,递归向上搜索父目录,查找相关的 memory 文件。所有找到且适用的 memory 文件,都会被加载到当前会话中,并组合成最终的工作上下文。
这种设计使得 Claude Code 能够支持分层配置。全局偏好可以与项目级规则共存,而当出现冲突时,更具体的指令会覆盖更宽泛的默认设置。
Claude Code 的 Memory 层级结构
Claude Code 将 memory 分成多个层级,每一层都有不同用途。优先级高的层级不能被低层级覆盖:
-
Level 1 —— Managed Policy(最高优先级)
- 组织范围规则,由 IT 或 DevOps 团队管理
- 路径:系统托管路径(例如 macOS 上的
/Library/Application Support/ClaudeCode/CLAUDE.md) - 作用域:整个组织
- 覆盖行为:不可被下层覆盖
-
Level 2 —— User Memory
- 保存跨所有项目生效的个人偏好
- 路径:
~/.claude/CLAUDE.md - 作用域:仅个人
-
Level 3 —— Project Memory
- 定义某个项目的共享规则与约定
- 路径:
./CLAUDE.md或./.claude/CLAUDE.md - 作用域:团队共享,并提交到版本控制
-
Level 4 —— Project Rules
- 对于较大项目,可以把 memory 拆分成按主题组织的规则文件
- 路径:
./.claude/rules/*.md - 作用域:团队共享,并提交到版本控制
-
Level 5 —— Project Local Memory
- 允许你在某个具体项目中定义仅自己使用的个性化覆盖项
- 路径:
./CLAUDE.local.md - 作用域:仅个人,并自动被 Git 忽略
如果同一层级内出现冲突,那么离当前工作目录更近的、更具体的文件会优先生效。
向上发现(upward discovery)是如何工作的
当 Claude Code 启动时,它会从当前工作目录开始搜索 memory 文件,并一路向上,直到文件系统根目录。
例如,假设有下面这样一个目录结构:
/Users/edenmarco/
├── .claude/
│ └── CLAUDE.md
└── Desktop/
└── my-company/
├── CLAUDE.md
└── frontend/
└── CLAUDE.md
如果 Claude Code 是从下面这个目录启动的:
/Users/edenmarco/Desktop/my-company/frontend/
那么会被加载进当前会话的 memory 文件包括:
frontend/CLAUDE.md(当前目录)my-company/CLAUDE.md(父目录)~/.claude/CLAUDE.md(用户级 memory)
这三个文件会被组合起来,共同形成最终生效的上下文。
嵌套 Memory 文件的惰性加载(lazy loading)
位于当前工作目录下方的 memory 文件,并不会在一开始立即加载。它们只会在 Claude Code 真正访问到那些子目录中的文件时,才被惰性加载。
例如,如果 Claude Code 是从项目根目录启动的,那么某个 backend/ 子目录中的 memory 文件,不会立即加载;只有当 Claude Code 开始处理这个目录中的文件时,它才会被加载进来。
在 Claude Code 中添加与编辑 Memory
添加 memory 可以通过输入 # 字符来完成,这会触发 Claude Code 把相关信息保存到合适的 memory 文件中。对于更大规模的修改,则可以使用 /memory 命令,直接在代码编辑器中打开 memory 文件进行编辑。
一个推荐的最佳实践是:保持 memory 文件简洁而具体。如果往 memory 里塞入含糊不清或过量的信息,不仅会浪费 token,还会引入混乱,并降低结果质量。
使用 memory 的好处,是可以减少重复指令,并帮助 Claude 在不同会话之间维持一致输出。它让交互更高效、更聚焦,同时保留那些重要上下文。
如果你以前用过 Cursor,那么这个概念和 Cursor rules 是比较类似的。
使用 /init 初始化 Memory
Claude Code 还提供了 /init 命令,它会基于现有代码库初始化一个新的 CLAUDE.md 文件。运行后,Claude 会审查项目中的文件,并生成一个 CLAUDE.md,其中包含有助于后续交互的相关上下文信息。
虽然这一节主要讲概念,而不是实操细节,但很快后面就会进入实际示范。接下来的部分会把这些概念真正用起来,让你更容易理解 memory 如何在真实工作流中生效。
实战示例:在现有项目中使用 Memory
为了更具体地展示 memory 在实践中的工作方式,我这里使用了一个现成仓库,它来自一个 LangChain 项目。这个项目被创建出来,用于抓取 LinkedIn 和 X 平台上的信息,并据此生成一个 icebreaker。关于 icebreaker 的更多细节,可以参考:
https://github.com/emarco177/IceBreaker
它是一个用 LangChain agents 构建的实用示例,非常适合用来演示 Claude Code 的能力。
我们先把这个仓库 clone 到一个新目录中,并在 Cursor 里打开它。在这个例子里,我把目录命名为 tmp3。打开后,我们就能看到完整的项目结构。这个项目是一个基于 LangChain 技术栈构建的 Python 项目。
图 3.11 —— 在 Cursor 中打开已克隆的 IceBreaker 仓库
然后我们打开 Claude Code,并把它固定在界面中。当 Claude Code 请求访问并分析项目文件时,我们批准它。
第一步,是通过运行 /init 命令为该项目创建一个 CLAUDE.md 文件。初始化过程会让 Claude 扫描仓库中的所有文件。它会识别技术栈、已安装依赖、所需环境变量以及整体结构。在此基础上,Claude 会生成一个 CLAUDE.md 文件,并把这些信息作为项目 memory 保存下来。
图 3.12 —— Claude 扫描仓库文件以生成 CLAUDE.md
在这个过程中,Claude 会列出目录、搜索文件,并通过模式匹配和内容检查做快速分析。读取完成后,它会生成一个建议版 CLAUDE.md 文件。
图 3.13 —— 自动生成的 CLAUDE.md,包含项目概览与架构细节
这个生成文件会包含诸如:如何通过 pip 安装依赖、如何运行项目,以及主要组件概览——例如抓取、摘要生成和智能体逻辑等内容。你批准后,这个文件就会成为项目 memory 的一部分。
从这一刻起,你后续发给 Claude 的每一个 Prompt,都会自动把这个 CLAUDE.md 文件的内容带入上下文。
验证项目 Memory
为了确认 memory 真的在生效,我们先重置会话,消除之前聊天历史的影响。运行 /clear,然后重新提问。比如,我问 Claude:
What stack am I using for this project?
你应当能看到类似下面这样的回答:
Based on the codebase analysis, your project uses this tech stack:
Backend Framework: Flask (Python web framework)
AI/LLM Framework: LangChain with OpenAI GPT models (GPT-4o-mini for agents, GPT-3.5-turbo for content generation)
Data Sources: Scraping (LinkedIn), Twitter API, Tavily (web search)
Package Management: Pipenv
Code Quality: Black (formatting), isort (import sorting), pylint (linting)
Testing: pytest
Output Parsing: Pydantic models
Frontend: HTML templates with Flask templating
Environment: Python 3.10+The core architecture is a LangChain-powered AI pipeline that combines social media data scraping with LLM-based content generation.
Claude 给出了一个准确答案,而且没有调用任何工具。这些信息是在初始化时分析代码库后就已经推断出来并写入 memory 的。
这说明 Claude 确实是在依赖存储下来的 memory,而不是当前聊天历史。
添加并使用 Memory 条目
接下来我们看看如何添加新的 memory 条目。此时,如果我们问:
What do I like to eat?
Claude 会给出类似下面的回答:
what do i like to eat?
I don't have any information about what you like to eat. I can only see your codebase files and project structure, but there's no personal information about your food preferences in this ice breaker application repository.
If you'd like to share what you like to eat, I'd be happy to help with any related coding tasks!
如果想让 Claude 能回答这个问题,我们就需要通过 # 语法添加一条 memory。比如,我们告诉它:我喜欢吃 pizza,并把它存储到项目级 memory 中:
# I like to eat pizza
加入这条信息之后,清空会话,再问同样的问题,Claude 就可以利用存储好的 memory 正确回答:
what do i like to eat?
Pizza
如果我们还想再添加一条 memory,可以重复同样的过程,加入另一条偏好,比如喜欢吃 hamburgers。这一次,把它存到用户级 memory,也就是 ~/.claude/CLAUDE.md 中。然后再次清空会话,再问一遍相同问题。Claude 就会正确回忆出两条偏好:
what do i like to eat?
Based on your CLAUDE.md files, you like to eat both Hamburger (from your global preferences) and Pizza (from your project-specific memory).
同样的方式也可以用于其他长期有效的信息,例如偏好的编码风格、常用工具,或那些希望 Claude 在不同项目和会话之间持续记住的工作约定。
在多个 Memory 文件之间协同工作
随着项目规模扩大,单个 CLAUDE.md 文件很容易变得庞大且难以维护。Claude Code 支持在整个仓库中分布多个 CLAUDE.md 文件。Claude 会递归遍历目录结构,并把所有相关 memory 文件加载进上下文。
这让 memory 可以用一种更有结构的方式组织起来。比如,你可以把服务端相关上下文放在一个区域,把前端上下文放在另一个区域,再把 DevOps 或 Claude 专属规则放在别处。这样做能让 memory 更易维护,也更具针对性。
当它和 hooks 结合使用时,就能产生更高级的行为。例如,根据当前工作类型加载不同的 memory 文件:当处理数据库代码时,附加数据库相关 memory;当处理 UI 组件时,附加前端上下文;当处理后端逻辑时,附加 API 相关上下文。
这种控制粒度,使得 memory 可以根据用户输入和工作流需求进行动态定制,为更高级、更灵活的上下文管理模式打开了空间。
Claude Code 中的 Rewind 功能
在这一节中,我们将探讨 Claude Code 的 checkpointing 与 rewind 功能。它允许你在编码会话中安全地撤销变更。Claude Code 会自动追踪每一次 Prompt 导致的文件修改,因此在需要时,你就可以回滚那些不想要的编辑。
要触发 rewind,可以按两次 Esc,或者直接使用 /rewind 命令。
Rewind 的价值与意义
这个功能的价值非常直接:
- 当你尝试较大或更激进的改动时,它提供了一个安全网
- 它允许你探索替代实现方案,而不会丢失已有的可用代码
- 它让你能更快、更可预测地从错误中恢复
- 它降低了修复 AI 生成错误的成本,因为撤销操作变得很容易
- 它增强了用户在使用 AI 辅助编码时的信心
- 它通过降低用户感知到的风险,促进了这类工具的更广泛采用
- 它与 CAIR(Cost of AI Recovery) 指标密切相关,这个指标用于衡量用户从 AI 错误中恢复的难易程度,后续课程里还会再次讨论它:
https://www.blog.langchain.com/the-hidden-metric-that-determines-ai-product-success/
Rewind 功能是在 Claude Code 最初发布几个月后才加入的。
图 3.14 —— Claude Code 发布时间线与 Rewind 功能引入时点
这个功能曾被社区强烈呼吁,甚至在它成为原生能力之前,已经有若干开源工具尝试提供类似功能。如今,rewind 已经是 Claude Code 内建的一部分,而且它足够直观,以至于几乎不需要太多解释。为了理解它在实践中的界面和使用方式,我们先快速看一下它所处的交互环境。
在实践中使用 Rewind
在写作本书时,Claude Code 运行的是 2.1 版本。界面已经包含多项近期更新,包括视觉样式改进,以及使用 Sonnet 4.5——这是 Anthropic 当前为编码任务优化的最新模型。你还会注意到界面底部有一个自定义状态栏,这是用户自己定制的内容,后面书里会讲。
为了演示 rewind,我们先从一个简单的 Next.js 示例开始:
先向 Claude Code 提一个问题,例如:
How do I bootstrap a Next.js project?
这个 Prompt 会在本地执行。搭建完成后,运行 npm run dev,并在浏览器中打开应用。你会像预期那样看到标准的 Next.js 样板应用。
接下来,我们故意对代码库做一小串渐进式修改。这里的重点不是评价 UI 做得好不好,而是模拟一个真实开发工作流:有些改动后面可能需要撤回。在我的例子里,我会依次做这些事:
- 首先,让 Claude Code 为 HooksHub 创建一个风格鲜明的 landing page
- 接着,让 Claude Code 添加一个 FAQ 区域
- 最后,再让 Claude Code 添加一个 footer 区域
图 3.15 —— 使用 Claude Code 生成的 HooksHub landing page
每一次 Prompt 都会产生文件修改,这些修改在 diff 视图中都能看到,并且会立即反映到运行中的应用里。
当 footer 被加进去之后,我们会发现:虽然功能确实实现了,但结果显得过重、视觉占比过高,并不是我们真正想要的样子。这正是一个非常自然的撤销点——与其手工改代码,或者继续发修正 Prompt,不如直接回退。
要撤销这些改动,运行 /rewind。这会打开当前会话的时间线,展示到目前为止你发过的所有 Prompt,并标记出哪些 Prompt 产生了文件修改。
图 3.16 —— 使用 /rewind 查看会话历史与文件改动
那些只生成解释、不涉及改文件的 Prompt,在时间线上不会显示关联的文件变化;而那些真正修改了文件的 Prompt,则会明确列出受影响的文件和行数。
选择你最后添加的那个 Prompt。在这个例子里,就是添加 footer 的那条 Prompt。随后系统会给你三个选项:
- Restore code and conversation:同时把文件和聊天上下文都恢复到那个时间点
- Restore conversation:只恢复会话上下文,保留文件改动
- Restore code:只恢复文件,不改变会话历史
在实践中,最常见的选择通常是同时恢复代码和会话,因为这能把项目带回一个干净且一致的状态。只恢复代码则适合这样一种情况:你想保留已有的对话上下文,但想重做某部分实现。
为了说明这一点,这里只恢复与 footer 相关的代码改动。恢复后,footer 会立刻从应用中消失。这之所以能做到,是因为 Claude Code 会在应用任何文件修改之前,自动创建一个 checkpoint。
每一个导致代码改动的 Prompt,都会创建一个新的 checkpoint。这些 checkpoint 会跨会话保留,并且最长保存 30 天,从而为实验与迭代提供一个安全网。
由于聊天历史还在,你接着就可以发一条后续 Prompt,例如:
create a footer, make it minimalistic
Claude Code 会基于现有上下文正确理解这句话,并生成一个更轻量的实现。刷新应用后,你会看到新的 footer 确实更符合预期设计。
虽然 rewind 很强大,但它也有局限:
- Claude Code 执行过的 Bash 命令不会被追踪,因此也无法通过 rewind 撤销
- 在 Claude Code 之外手工做的编辑不会被 checkpoint 捕获
- Rewind 不能替代 Git 这样的版本控制系统
- Checkpoint 更应该被理解为一种本地、短期的撤销机制,而不是永久历史记录
如果用得好,rewind 会显著降低实验成本。它鼓励探索,降低修改风险,并让基于 Claude Code 的迭代式开发变得更安全、更高效。
Claude Code 中的自定义斜杠命令(由 Skills 驱动)
在这一节里,我们会看看如何在 Claude Code 中创建自定义斜杠命令。这个能力非常强大,因为它给了开发者极大的灵活性,可以按自己的方式定制和扩展 Claude Code。这里我们会通过定义一个用于创建 Git commit message 的 skill,来构建一个自定义斜杠命令。更高级的 skill 内容,会在第 7 章继续展开。
创建一个 Skill
我们先从一个干净项目开始,并切换到 custom-commands 分支。要创建一个 skill,先在项目里创建一个 .claude 目录(如果还不存在的话),然后在里面创建一个 skills 目录。
每一个 skill 都应该有自己的独立目录,例如:
.claude/skills/commit-code/
在这个目录中,创建一个必需文件,文件名为:
SKILL.md
Skill 采用 Markdown 文件进行定义。元数据通过顶部的 YAML frontmatter 来声明,并用 --- 分隔包裹起来;文件主体则是实际 Prompt 内容,同样写在 Markdown 中。
先给文件加上一个标题。这个标题会出现在斜杠菜单中。
然后编写命令 Prompt:
Review the files that have changed, and create a commit with a commit message summarizing the changes made. Always try to give short and concise messages that convey the business logic.
我在这里告诉 Claude Code:去检查已经发生变化的文件,然后创建一个 commit,并生成一条简洁的 commit message,用来概括这些改动所表达的业务逻辑。
虽然这个 Prompt 本身很短,但 Claude Code 其实能够推断并完成一系列操作。它可以通过 Git 命令检查变更文件、审查 diff,并最终创建一个 commit。这说明:一个单独 skill 就能够封装一整串动作。
执行这个 Skill
为了测试这个命令,打开 Claude Code,然后输入 /。你应该会在列表中看到新的 commit-code 命令。执行它之后,Claude Code 就会运行写在 SKILL.md 中的 Prompt。
Claude Code 还会检测到 .claude 目录下存在未跟踪文件,并询问是否应该把它们也加进去。你做出的批准决定会被写入 settings.local。之后,Claude 会基于检测到的变更,提出一个 commit message,并展示相应的 Git 命令。
但如果它生成的 commit message 不够具体怎么办?这时候,我们先不要继续,而是停下来改进这个 skill。
使用 $ARGUMENTS 改进 Skill
回到最初写的那个 Prompt,并更新它。在我的例子里,我通过加入一个 $ARGUMENTS 占位符,让 Claude Code 可以接受用户提供的提示信息。
调用 skill 时,我们可以给它传参,这些参数会通过 $ARGUMENTS 占位符传入。
也就是说,$ARGUMENTS 会被替换成 skill 名称后面紧跟着的内容。关于这一点,第 9 章还会进一步讲。
更新后的 Prompt 如下:
Review the files that have changed, and create a commit with a commit message summarizing the changes made. Always try to give short and concise messages that convey the business logic.
Use user hints to be the message main subject $ARGUMENTS
完成这个修改后,再次执行 /commit-code,并提供一个与 skill 相关的主题提示:
/commit-code custom code
这时,Claude Code 生成的 commit message 就应当会更具描述性,并且反映出你提供的变更主题。
一旦你批准,这个 commit 就会被真正创建,而且 commit 里还会以 Claude 共同作者(co-authored by Claude) 的形式记录下来。然后我们通过运行 git push 把改动推送到远程仓库,并在项目的 custom-commands 分支中验证这个 commit。
你也可以用同样的方式继续创建和执行其他 skill,只需要:
- 创建一个带有适当标题的新命令文件
- 定义一个能根据用户输入生成输出的 Prompt
- 给它挂上参数,让命令在运行时能接受动态值
重新启动 Claude Code 后,这个新命令就会出现在列表中,并能带着用户提供的输入运行。由此你可以看到,skills 能够支持非常灵活、动态的行为。
通过上下文工程改进自动生成的 Commit Message
前面我们已经讨论过上下文工程。为了让这个概念更具体一些,我们来看一个直接摘自 Claude Code 官方文档的实际示例:
---
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
description: Create a git commit
---
## Context
- Current git status: !`git status`
- Current git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
- Recent commits: !`git log --oneline -10`
## Your task
Based on the above changes, create a single git commit.
这个例子所完成的任务,与前面生成 commit message 的 skill 本质上是一样的,但它实现得更稳健、更安全、功能也更丰富。理解为什么这种方式更好,有助于你真正看清上下文工程、工具控制与智能体设计,是如何在实践中汇合到一起的。
在 skills 中,我们可以运行 shell 和 Bash 脚本。这意味着:我们可以把任意代码作为命令的一部分去执行。结果就是,我们可以发 HTTP 请求、运行容器,或者做任何可以用代码表达出来的事情。换句话说,这几乎消除了 skill 在能力上的大部分限制。
在这个具体的斜杠命令示例中,配置的开头先定义了一组允许使用的工具(allowed tools) 。这样就通过限制智能体可用的工具,把它的作用域收窄了。
如果你做过智能体实现,这其实非常符合最小权限原则(principle of least privilege) 。这个原则的核心思想是:只给智能体完成任务所必需的最小能力集合。在“生成 commit message”这个场景里,它真正需要的操作其实只限于 git add、git status 和 git commit 这几个命令。
像这样限制工具集合,会显著提升安全性。相比之下,前面那个更简单的 commit-message 命令,并没有做任何工具限制,这意味着智能体实际上可以访问 Claude Code 中所有可用工具。在那种情况下,如果上下文被污染(例如混入恶意输入),智能体就可能在系统上执行一些本不该做的动作。这也是为什么文档中的这个版本是一个更强、更安全的设计。
这个例子也很好地展示了有意识的 Prompt Engineering。其中的上下文是显式定义、并且经过精心构造的。在真正生成 commit message 之前,这个命令先执行了一系列 Git 命令,例如 git status、git branch 和 git log。这些命令为当前仓库状态以及待提交变更提供了非常精准的上下文。
如果从这个角度去看,这个工作流其实很像 RAG(retrieval-augmented generation,检索增强生成) 。第一步,系统通过执行 Git 命令来“检索”相关上下文;第二步,在上下文准备好之后,再进行“生成”,输出 commit message。
这说明:检索和生成可以在一个定义清晰、作用域受控的命令里被组合起来。同时它也展示了前面讨论过的多个概念——包括上下文工程、工具限制和智能体设计——是如何在一个实际、可扩展的用例中汇聚到一起的。
总体来看,这种方式为在 Claude Code 中借助 skills 构建更安全、更强大的工作流打开了很大空间。
这里用 --- 分隔包裹起来的部分,叫做 frontmatter,它会在 Prompt 主体执行之前先被解析和处理。
总结
在本章中,你学会了如何在基础操作之外,进一步配置和使用 Claude Code。我们从高层次上讨论了认证与定价,介绍了如何使用斜杠命令控制 Claude Code,以及如何把它直接集成进 IDE 里,从而获得更顺滑的工作流。你还了解了配置选项、用于自动化的 hooks、通过 CLAUDE.md 文件实现的 memory,以及上下文如何在不同会话之间被加载和复用。
我们还进一步考察了 checkpointing 和 rewind,看看如何安全地撤销修改;同时也讨论了 skills,了解如何把那些可重复的工作流封装起来,并通过恰当的工具作用域控制来提升安全性。到这个阶段,你应该已经理解了 Claude Code 在实践中是如何运作的,如何让它保持安全、可预测,以及如何按你的需要塑造它的行为,以支持更高级、持续时间更长的开发工作流。
在下一章中,我们将讨论 Model Context Protocol(MCP) ,以及它如何为 AI 应用与外部工具之间的集成提供标准化接口。