我如何使用 Claude Code 的每一个功能
2025年11月4日
我是 Claude Code 的重度用户。
作为业余开发者,我每周会在虚拟机里运行它好几次来做个人项目,经常加上 --dangerously-skip-permissions 参数,想到什么就直接让它写代码。在工作中,我们团队负责为工程团队构建 AI-IDE 的规则和工具,光是代码生成这块,每个月就要消耗几十亿个 token。
现在 CLI 智能体领域竞争很激烈,Claude Code、Gemini CLI、Cursor 和 Codex CLI 都在争夺市场,感觉真正的较量还是在 Anthropic 和 OpenAI 之间。但说实话,我和其他开发者聊天时发现,大家选择工具往往看的是表面因素——某个"恰好好用"的功能实现,或者就是喜欢某个系统提示词的"感觉"。
到了这个阶段,这些工具其实都挺不错的。我还觉得很多人过于在意输出风格或用户界面。比如那种"你说得太对了!"的谄媚语气,在我看来根本不是什么大问题,这只是说明你介入得太深了。
我的目标一般是"发射后不管"——把任务委派出去,设定好上下文,让它自己干活。评判工具好坏要看最终的 PR,而不是看它怎么完成的。
这几个月我一直在用 Claude Code,这篇文章记录了我对 Claude Code 整个生态的思考。我会讲到几乎所有常用的功能(同样重要的是,我不用的那些),从基础的 CLAUDE.md 文件、自定义斜杠命令,到强大的子智能体、钩子和 GitHub Actions。
这篇文章写得有点长,建议作为参考资料来查阅,不必从头读到尾。
CLAUDE.md
要用好 Claude Code,代码库中最重要的文件就是根目录的 CLAUDE.md。这个文件相当于智能体的"宪法",是它了解你的代码仓库运作方式的首要信息来源。
怎么对待这个文件要看具体情况。对于我的个人项目,我让 Claude 想往里面写什么就写什么。
在工作中,我们 monorepo 的 CLAUDE.md 维护得很严格,目前有 13KB(我觉得很容易就能涨到 25KB)。
- 只记录 30%(这个比例是随意定的)以上工程师会用到的工具和 API(其他工具的文档会放在产品或库的专门 markdown 文件里)
- 我们甚至开始为每个内部工具的文档分配最大 token 数,就像卖"广告位"一样。如果你没法简洁地解释你的工具,那它还不适合放进
CLAUDE.md。
技巧和常见反模式
长期下来,我们形成了一套关于如何写好 CLAUDE.md 的强烈主张。
- 从护栏开始,不是从手册开始。 你的
CLAUDE.md应该从小做起,根据 Claude 犯的错误来写文档。 - 不要用
@引用文件文档。 如果你在别处有大量文档,很容易想在CLAUDE.md里@引用这些文件。这会让整个文件在每次运行时都嵌入进来,撑爆上下文窗口。但如果你只是_提到_路径,Claude 往往会忽略它。你必须向智能体_推销_为什么以及什么时候去读那个文件。"遇到复杂的……用法或者碰到FooBarError时,请查看path/to/docs.md了解高级排查步骤。" - 不要只说"不要"。 避免只有否定的约束,比如"永远不要使用
--foo-bar标志"。当智能体觉得它_必须_使用那个标志时就会卡住。永远提供替代方案。 - 把
CLAUDE.md当作倒逼机制。 如果你的 CLI 命令又复杂又冗长,不要写好几段文档去解释它们。那是在给人类的问题打补丁。正确做法是写一个简单的 bash 封装脚本,提供清晰直观的 API,然后记录_那个_脚本。尽可能缩短CLAUDE.md是简化代码库和内部工具的绝佳倒逼手段。
这是一个简化的示例:
# Monorepo
## Python
- 始终…
- 测试使用<command>
…还有 10 条…
## <内部 CLI 工具>
…10 个要点,聚焦 80% 的用例…
- <使用示例>
- 始终…
- 永远不要<x>,建议使用<Y>
对于<复杂用法>或<错误>,参见 path/to/<tool>_docs.md …
</Y></x></错误></复杂用法></使用示例></内部></command>
最后,我们会让这个文件和 AGENTS.md 保持同步,以便兼容工程师可能使用的其他 AI IDE。
如果你想了解更多为编码智能体写 markdown 的技巧,可以看看"AI Can't Read Your Docs"、"AI-powered Software Engineering" 和 "How Cursor (AI IDE) Works"。
要点:把 CLAUDE.md 当作高层次、精心筛选的护栏和指引。用它来指导哪里需要投入更多对 AI(和人类)友好的工具,而不是试图把它写成全面的手册。
精简、上下文与清晰
我建议在编码过程中至少运行一次 /context 命令,了解你的 20 万 token 上下文窗口使用情况(即使有了 Sonnet-1M,我也不相信整个上下文窗口真的能被有效利用)。
对我们来说,在 monorepo 里开一个新会话,基线成本就是约 2 万 token(10%),剩下的 18 万用来做修改——这个空间很快就会用完。
[图片:一个侧边项目中 /context 的截图。你可以把这想象成磁盘空间,随着你开发功能会逐渐占满。几分钟或几小时后,你需要清除消息(紫色部分)来腾出空间继续工作。]
我有三种主要工作流:
/compact(尽量避免): 我尽可能避免用这个。自动压缩不透明、容易出错,而且优化得不好。/clear+/catchup(简单重启): 这是我的默认重启方式。我用/clear清除状态,然后运行自定义的/catchup命令,让 Claude 读取我 git 分支中所有修改过的文件。- "记录并清除"(复杂重启): 用于大型任务。我让 Claude 把它的计划和进度写入一个
.md文件,/clear清除状态,然后开启新会话,告诉它读取那个.md文件并继续。
要点:不要相信自动压缩。简单重启用 /clear,复杂任务用"记录并清除"方法创建持久的外部"记忆"。
自定义斜杠命令
我把斜杠命令看作常用提示词的简单快捷方式,仅此而已。我的设置很简洁:
/catchup:前面提到的命令。它只是提示 Claude 读取我当前 git 分支中所有修改过的文件。/pr:一个简单的辅助命令,用来清理代码、暂存并准备 pull request。
在我看来,如果你有一长串复杂的自定义斜杠命令,那就是反模式。对我来说,像 Claude 这样的智能体,整个意义就在于你可以输入_几乎_任何内容,都能得到有用的、可合并的结果。一旦你强迫工程师(或非工程师)去学习一堆记录在某处的必备魔法命令才能完成工作,那就失败了。
要点:把斜杠命令当作简单的个人快捷方式,而不是用来替代构建更直观的 CLAUDE.md 和更好的智能体工具。
自定义子智能体
理论上,自定义子智能体是 Claude Code 在上下文管理方面最强大的功能。设计思路很简单:一个复杂任务需要 X 个 token 的输入上下文(比如如何运行测试),累积 Y 个 token 的工作上下文,产生 Z 个 token 的答案。运行 N 个任务意味着主窗口要消耗 (X + Y + Z) * N 个 token。
子智能体的方案是把 (X + Y) * N 的工作外包给专门的智能体,它们只返回最终的 Z 个 token 答案,保持你的主上下文清爽。
我觉得这个想法很强大,但实际上,_自定义_子智能体会带来两个新问题:
- 它们封锁了上下文: 如果我创建一个
PythonTests子智能体,我就把所有测试上下文从_主_智能体那里隐藏了。它现在无法整体推理一个改动。它现在被迫调用子智能体才能知道如何验证自己的代码。 - 它们强加了人类工作流: 更糟的是,它们把 Claude 困在一个僵化的、人类定义的工作流里。我现在在指示它_如何_委派工作,但这正是我想让智能体帮我解决的问题。
我更喜欢的替代方案是使用 Claude 内置的 Task(...) 功能来生成_通用_智能体的克隆。
我把所有关键上下文都放进 CLAUDE.md。然后,我让_主智能体_决定何时以及如何把工作委派给自己的副本。这样我既能获得子智能体节省上下文的好处,又没有那些缺点。
智能体动态管理自己的编排。
在我的"构建多智能体系统(第 2 部分)"文章中,我把这叫做"主从克隆"架构,我强烈偏好这种方式,而不是自定义子智能体鼓励的"领导-专家"模式。
要点:自定义子智能体是个脆弱的方案。给你的主智能体提供上下文(放在 CLAUDE.md 里),让它使用自己的 Task/Explore(...) 功能来管理委派。
恢复、继续与历史记录
简单来说,我经常用 claude --resume 和 claude --continue。它们很适合重启出错的终端或快速恢复旧会话。我常常 claude --resume 几天前的会话,只是为了让智能体总结它当时是如何克服某个特定错误的,然后用这些信息来改进我们的 CLAUDE.md 和内部工具。
更深入一点,Claude Code 把所有会话历史都存储在 ~/.claude/projects/ 里,可以直接访问原始的历史会话数据。我有脚本对这些日志做元分析,寻找常见的异常、权限请求和错误模式,帮助改进面向智能体的上下文。
要点:使用 claude --resume 和 claude --continue 重启会话,挖掘埋藏的历史上下文。
钩子
钩子非常重要。我在个人项目里不用它们,但在复杂的企业代码库中,它们对引导 Claude 至关重要。
它们是确定性的"必须做"规则,补充了 CLAUDE.md 中"应该做"的建议。
我们使用两种类型:
- 提交时阻断钩子: 这是我们的主要策略。我们有一个
PreToolUse钩子,包装任何Bash(git commit)命令。它检查/tmp/agent-pre-commit-pass文件是否存在,只有所有测试通过时,我们的测试脚本才会创建这个文件。如果文件不存在,钩子会阻止提交,强制 Claude 进入"测试-修复"循环,直到构建成功。 - 提示钩子: 这些是简单的、非阻塞钩子,如果智能体在做不太好的事情,它们会提供"发后不管"的反馈。
我们特意不使用"写入时阻断"钩子(比如在 Edit 或 Write 时)。在智能体计划进行到一半时阻断它会让它困惑甚至"沮丧"。更有效的做法是让它完成工作,然后在提交阶段检查最终完成的结果。
要点:使用钩子在提交时强制状态验证(提交时阻断)。避免在写入时阻断——让智能体完成它的计划,然后检查最终结果。
规划模式
对于用 AI IDE 进行任何"大型"功能变更,规划都是必不可少的。
对于我的个人项目,我只用内置的规划模式。这是一种在 Claude 开始工作前与它对齐的方式,既定义_如何_构建某个东西,也定义需要在哪些"检查点"停下来展示工作成果。经常使用这个功能能培养出很好的直觉,知道需要提供哪些最少的上下文才能得到好的计划而不会让 Claude 搞砸实现。
在我们工作的 monorepo 中,我们开始推出一个基于 Claude Code SDK 构建的自定义规划工具。它类似于原生规划模式,但经过大量提示调整,让输出符合我们现有的技术设计格式。它还内置了我们的内部最佳实践——从代码结构到数据隐私和安全。这让我们的工程师能够像资深架构师一样"随意规划"新功能(至少这是我们的宣传语)。
要点:对于复杂变更,始终使用内置规划模式,在智能体开始工作前对齐计划。
技能
我同意 Simon Willison 的观点:技能(可能)比 MCP 更重要。
如果你一直在关注我的文章,就会知道我在大多数开发工作流中已经不太用 MCP 了,更喜欢构建简单的 CLI(正如我在"AI Can't Read Your Docs"中论述的)。我对智能体自主性的理解模型已经演变成三个阶段:
- 单次提示:在一个超大提示中给智能体提供所有上下文。(脆弱,不可扩展)。
- 工具调用: "经典"智能体模型。我们精心制作工具,为智能体抽象掉现实。(更好,但创造了新的抽象和上下文瓶颈)。
- 脚本编程: 我们让智能体访问原始环境——二进制文件、脚本和文档——它_即时_编写代码来与它们交互。
有了这个模型,智能体技能就是显而易见的下一个功能。它们是"脚本编程"层的正式产品化。
如果你和我一样,已经在偏好 CLI 而不是 MCP,那你一直以来就在享受技能的好处。SKILL.md 文件只是一种更有组织、可分享、可发现的方式来记录这些 CLI 和脚本,并把它们暴露给智能体。
要点:技能是正确的抽象。它们正式化了基于"脚本编程"的智能体模型,这比 MCP 代表的僵化的、类似 API 的模型更强大、更灵活。
MCP(模型上下文协议)
技能不意味着 MCP 已死(另见"MCP 的所有问题")。以前,很多人构建了糟糕的、上下文沉重的 MCP,包含几十个工具,只是镜像了一个 REST API(read_thing_a()、read_thing_b()、update_thing_c())。
"脚本编程"模型(现在通过技能正式化)更好,但它需要一种安全的方式来访问环境。在我看来,这就是 MCP 新的、更聚焦的角色。
MCP 不应该是臃肿的 API,而应该是一个简单、安全的网关,提供几个强大的高级工具:
download_raw_data(filters…)take_sensitive_gated_action(args…)execute_code_in_environment_with_state(code…)
在这个模型中,MCP 的工作不是为智能体抽象现实;它的工作是管理认证、网络和安全边界,然后让开。它为智能体提供_入口点_,然后智能体使用它的脚本编程和 markdown 上下文来完成实际工作。
我现在唯一还在用的 MCP 是 Playwright,这说得通——它是一个复杂的、有状态的环境。我所有的无状态工具(如 Jira、AWS、GitHub)都已经迁移到简单的 CLI。
要点:使用充当数据网关的 MCP。给智能体一两个高级工具(比如原始数据转储 API),然后它可以针对这些数据编写脚本。
Claude Code SDK
Claude Code 不只是一个交互式 CLI;它还是一个强大的 SDK,可以用来构建全新的智能体——既可以用于编码任务,也可以用于非编码任务。
在大多数新的个人项目中,我已经开始用它作为我的默认智能体框架,取代了 LangChain/CrewAI 这类工具。
我主要通过三种方式使用它:
- 大规模并行脚本: 对于大规模重构、bug 修复或迁移,我不用交互式聊天。我编写简单的 bash 脚本,并行调用
claude -p "在 /pathA 中把所有 foo 的引用改成 bar"。这比试图让主智能体管理几十个子智能体任务要可扩展和可控得多。 - 构建内部聊天工具: SDK 非常适合为非技术用户把复杂流程包装成简单的聊天界面。比如一个安装器,出错时就回退到 Claude Code SDK,直接为用户_修复_问题。或者一个内部的"v0-at-home"工具,让我们的设计团队在我们的内部 UI 框架中随意编码模拟前端,确保他们的想法高保真度,代码更能直接用于前端生产代码。
- 快速智能体原型开发: 这是我最常用的方式。不仅仅是用于编码。如果我有任何智能体任务的想法(比如一个使用自定义 CLI 或 MCP 的"威胁调查智能体"),我会用 Claude Code SDK 快速构建和测试原型,然后再投入到完整的、部署好的脚手架中。
要点:Claude Code SDK 是一个强大的通用智能体框架。
用它来批量处理代码、构建内部工具,以及在使用更复杂的框架_之前_快速为新智能体制作原型。
Claude Code GHA
Claude Code GitHub Action(GHA)可能是我最喜欢也是最被低估的功能。概念很简单:就是在 GHA 中运行 Claude Code。但这种简单性正是它如此强大的原因。
它类似于 Cursor 的后台智能体或 Codex 管理的网页 UI,但可定制性要强得多。你可以完全控制容器和环境,让你能访问更多数据,而且关键是,比任何其他产品都能提供更强的沙箱和审计控制。
此外,它支持所有高级功能,比如钩子和 MCP。
我们用它构建了自定义的"任意来源 PR"工具。用户可以从 Slack、Jira 甚至 CloudWatch 告警触发 PR,GHA 会修复 bug 或添加功能,返回一个经过充分测试的 PR。
由于 GHA 日志就是完整的智能体日志,我们有一个运维流程定期在公司层面审查这些日志,查找常见错误、bash 错误或不符合工程实践的地方。
这创造了一个数据驱动的飞轮:Bug → 改进 CLAUDE.md / CLI → 更好的智能体。
$ query-claude-gha-logs --since 5d | claude -p "看看其他 claude 在哪里卡住了,修复它,然后提交一个 PR"
要点:GHA 是让 Claude Code 投入运营的终极方式。它把 Claude Code 从个人工具变成了你工程系统中可审计、能自我改进的核心部分。
settings.json
最后,我有几个特定的 settings.json 配置,对个人和工作项目都很重要。
-
HTTPS_PROXY/HTTP_PROXY:这对调试很有用。我会用它来检查原始流量,准确看到 Claude 发送的是什么提示。对于后台智能体,这也是细粒度网络沙箱的强大工具。 -
MCP_TOOL_TIMEOUT/BASH_MAX_TIMEOUT_MS:我会调高这些值。我喜欢运行长时间、复杂的命令,默认超时往往太保守。说实话我不确定现在 bash 后台任务功能出来后是否还需要这样,但我还是保留着以防万一。 -
ANTHROPIC_API_KEY:在工作中,我们使用企业 API 密钥(通过 apiKeyHelper)。这让我们从"按席位"许可转向"按使用量"定价,这对我们的工作方式是更好的模式。- 它考虑到了不同开发者使用量的_巨大_差异(我们见过工程师之间有 1:100 倍的差异)。
- 它让工程师可以尝试非 Claude-Code 的 LLM 脚本,全都在我们单一的企业账户下。
-
"permissions":我会偶尔自查一下我允许 Claude 自动运行的命令列表。
要点:你的 settings.json 是进行高级定制的强大位置。
结语
内容很多,但希望对你有用。如果你还没有使用像 Claude Code 或 Codex CLI 这样的基于 CLI 的智能体,你可能应该试试。
这些高级功能很少有好的指南,学习的唯一方法就是亲自实践。
关于一个挺有意思的哲学问题:对于直接从客户请求生成的 PR(没有内部人工提示者),应该有多少审核者?我们目前决定任何 AI 发起的 PR 都需要 2 个人类审批,但当不再是一个人为另一个人审核而创作内容时,这确实是一种奇怪的范式转变(至少对我来说是这样)。