连载03-commands ---一起吃透 Claude Code,告别 AI coding 迷茫

20 阅读17分钟

为什么 Claude Code 要有指令(Commands):本质是上下文管理

AI Coding 系列第 03 篇 · 上下文与 Commands


这篇想回答三个问题:

  1. 为什么一开始很好用的 Claude Code,会在长会话里越来越"跑偏"?
  2. 为什么有些纠正你明明说过很多次,它还是会回退?
  3. 为什么 Claude Code 要用 /clear/compact/memory 这种命令,而不是全做成按钮?

如果你已经是高频用户,这篇不会提供很多新奇技巧,但会把这些现象背后的机制串成一套可操作的框架。对刚进入稳定开发阶段的用户,这比记住几个命令更重要。


先给结论

Claude Code 里的很多命令,看起来像快捷操作,实际上是在帮你管理三个东西:

  1. Claude 现在看到了什么
  2. Claude 接下来应该忘掉什么
  3. 哪些规则不应该继续留在“会衰减的对话历史”里

如果只把 /clear/compact/memory 当成“方便一点的小功能”,你会低估它们的价值。它们真正解决的,是长会话里最常见、也最让人误判的协作问题:Claude 不是突然变差了,而是上下文开始劣化了。


你大概遇到过这种情况

开始一个新任务,头几轮对话质量很高——Claude 理解你的意图,给出准确的方案,代码风格和项目一致。

但聊着聊着,情况变了:它开始重提已经否掉的方案,重复犯你纠正过的错误,或者在一个局部问题上越绕越深,忘了你们最初要解决什么。

这不是 Claude 变笨了,也不是你的 Prompt 写差了。这是上下文劣化——一个有规律、可以预测、也可以干预的现象。


一个贯穿全文的真实场景

假设你在做一个登录模块,从头到尾大概会经历这样一条线:

  1. 前期你和 Claude 一起讨论技术方案,聊过 Session、JWT、Redis、PostgreSQL,最后决定先用 PostgreSQL + JWT,把主流程跑通。
  2. 接着你开始写代码,发现 Claude 老是顺手加 console.log,你纠正了它两次。
  3. 做到一半你又决定把 ORM 从 Sequelize 换成 Prisma,因为前者在这个项目里太重。
  4. 再往后,对话已经很长了,你只是问一个事务边界问题,Claude 却开始同时聊缓存、日志、前端错误提示和部署建议。

如果你不理解上下文管理,这整条链看起来像是:“Claude 前面挺聪明,后面越来越不靠谱。”

但如果从上下文角度看,这其实是四类不同问题叠在一起:

  • 前面讨论过但已经否掉的方案,还残留在历史里
  • 你纠正过的规则,还停留在会衰减的对话层
  • 已经废弃的 Sequelize 路线,还在干扰后续回答
  • 对话长度过大以后,Claude 的注意力开始发散

也正因为它们是四类不同问题,所以不能指望一个万能 Prompt 解决。你需要的不是“再说清楚一点”,而是把正确的动作放在正确的层级上:该 /compact 的时候压缩,该 /clear 的时候重开,该进 CLAUDE.md 的规则就不要继续留在聊天记录里。


为什么 Claude Code 用命令,而不是全做成按钮

刚接触 Claude Code 的人常问:为什么不把这些能力做成 GUI?为什么要用 /clear/compact 这种命令?

因为 Claude Code 管理的不是"功能开关",而是 Claude 此刻正在处理的内容。

举个对比:你在 VS Code 里点"开启 dark mode",改的是软件的配置文件,和编辑器当前打开了什么文件没关系。但你在 Claude Code 里输入 /clear,清掉的是 Claude 脑子里正在处理的所有东西——之前讨论过的方案、做过的决策、来来覆去的对话,全部抹掉,让它重新认识你。这不是改配置,是在决定 Claude 此刻"知道什么、记得什么"。

命令形式在这里有几个优势:它可重复,你可以稳定复现同一种操作;它可传达,你可以直接告诉同事"先 /clear 再开始";它也更容易固化成工作流,比如"任务切换先 /clear,长会话中途 /compact,提交前 /review"。对还在快速迭代的 AI 工具来说,命令也比 GUI 更容易快速交付新能力。

所以 Claude Code 的命令系统,本质上是一套让你主动管理 AI 工作现场的操控面板


四种上下文劣化模式

Claude Code 的 4 种上下文劣化转存失败,建议直接上传图片文件

模式一:早期探索污染后期决策

任务开始时,你和 Claude 在讨论方案,思路是发散的。"要不要用 Redis?""用 JWT 还是 Session?""这个表要不要拆?"——这些都是探索性的讨论,很多想法最终被否决了。

问题是:这些被否决的想法还留在上下文里,和最终确定的方案并排存在。Claude 看到的是一串讨论记录,它会对"用 Redis"和"不用 Redis"这两种可能性都保持某种权重。对话越长,早期探索的内容就越像已确认的决策。

例如:

你:认证这块先别上 Redis,先用 PostgreSQL 把主流程跑通。
Claude:好,先按 PostgreSQL 方案实现。
...
(十几轮后)
Claude:为了提高性能,建议把 session 放到 Redis。

你明明在第 5 轮确认了用 PostgreSQL,第 25 轮它开始建议你考虑一下 Redis 的方案。

模式二:纠正回退

你发现 Claude 用错了某个写法,纠正了它。它承认了,改对了。五轮之后,它犯了同样的错误。

这是因为"纠正"发生在对话的第 8 轮,而你现在在第 15 轮。纠正的内容在上下文里的位置越来越靠后,在 lost-in-the-middle 的注意力分布下,它的权重持续降低,直到 Claude 实际上已经"忘了"那次纠正,重新回到了训练数据里的默认行为。

例如:

你:不要用 console.log,用 logger.info。
Claude:好的,我改成 logger.info。
...
(五轮后)
Claude:这里我先加一个 console.log 方便排查。

你已经说了三次"不要用 console.log,用 logger.info",但它还是偶尔会写 console.log

模式三:废弃方案的幽灵

你尝试了一种实现方式,做到一半发现不对,放弃了,换了另一种方式。旧的代码删掉了,但关于旧方案的讨论还留在上下文里。

这段"废弃的历史"会持续影响 Claude 的输出——它可能在新方案里混入旧方案的逻辑,或者在你遇到问题时建议你回到旧方案,因为旧方案在它的上下文里看起来也是一个"被讨论过的合理选项"。

例如:

你:Sequelize 这条路不走了,切到 Prisma。
Claude:明白,后续都按 Prisma 来。
...
(后来你问一个查询问题)
Claude:你可以在 Sequelize 的 include 里这样写...

你已经换掉了 ORM,但 Claude 还在参考旧 ORM 的写法给你示例。

模式四:注意力发散

随着上下文增长,Claude 需要处理的信息量越来越大。注意力是有限的——分给了 A 就少给了 B。越是长对话,Claude 越难在某一个具体问题上保持高度聚焦。它的回答开始变得面面俱到但不够深入,或者在你问一个具体问题时夹带了很多你没问的背景讨论。

例如:

你:只看这个接口的事务边界,哪里可能有问题?
Claude:这个接口本身有事务问题。另外认证模块、日志方案、缓存策略、
      前端错误提示也建议一起调整...

任务越来越复杂,但 Claude 的回答越来越泛,不够犀利。


理解了劣化,命令就有了意义

这四种模式,对应的干预手段是不同的:

劣化模式干预手段原因
早期探索污染/compact 明确声明保留哪些决策压缩时主动过滤探索内容,只留结论
纠正回退把纠正写进 CLAUDE.md从"对话历史"变成"系统注入",每轮强制生效
废弃方案幽灵/clear 重开一个干净会话彻底清除废弃历史,而不是试图覆盖它
注意力发散拆任务 + 每个任务独立会话每个会话只有一个聚焦点

但这些命令本质上是不同类型的东西,可靠性和适用场景差别很大——这是大多数人没意识到的。


5 条最实用的决策规则

如果你只想带走最实用的部分,可以先记这 5 条:

  1. 任务已经切换,就先 /clear。不要让上一个任务的残留背景继续污染当前任务。
  2. 任务没切,但会话已经很长,就 /compact。而且最好写清楚“只保留哪些已确认决策”。
  3. 同一条规则纠正两次以上,就别再聊了,直接写进 CLAUDE.md
  4. 你要复用的是“提示词流程”,就做成自定义 command;你要复用的是“带权限约束的能力”,就做成 skill。
  5. 当 Claude 开始“什么都懂一点但什么都答不深”时,优先怀疑上下文过载,而不是先怀疑模型突然变差。

这 5 条的价值,在于它们能把“模糊感觉”迅速翻译成明确动作。真正影响协作质量的,不是你知不知道这些概念,而是你能不能在出现问题的当下做对动作。


Claude Code 命令的三种类型

Claude Code 的 3 类指令 / Commands转存失败,建议直接上传图片文件

第一类:CLI 状态操作命令

这些命令直接操作 Claude Code 进程的内部状态,不经过 AI 模型,执行的是确定性的代码逻辑。

/clear    → 直接清空内存里的对话历史数组
/cost     → 读取 token 计数器,格式化输出
/model    → 修改当前会话的模型配置
/memory   → 读取和展示 Memory 目录下的文件内容
/help     → 输出命令列表

关键特性:结果确定,不依赖 Claude 的理解。 /clear 必然清空,/cost 必然显示费用,不会因为你的 Prompt 写得好不好而有差异。这类命令是系统层面的操作,不是 AI 行为。

第二类:自定义 Slash Command(提示词模板)

这类命令存放在 .claude/commands/ 目录下,每个命令是一个 .md 文件。文件名就是命令名,文件内容就是命令触发时注入给 Claude 的提示词。

.claude/
  commands/
    review.md      → /review 命令
    pr-desc.md     → /pr-desc 命令
    standup.md     → /standup 命令

可以用 $ARGUMENTS 接收参数:

<!-- .claude/commands/review.md -->
对以下代码做专项 review,聚焦:$ARGUMENTS

检查顺序:
1. 安全漏洞(SQL 注入、权限校验缺失)
2. 边界条件和错误处理
3. 项目规范符合性(参考 CLAUDE.md)

每个问题标注严重等级:blocking / warning / suggestion

关键特性:本质上是一次对话,经过 AI 模型处理,结果有随机性。 你写的是提示词,不是程序——好的自定义命令写法和好的 Prompt 写法是一回事:具体、有约束、有明确的输出格式。

第三类:Skills(能力包触发)

Skills 比自定义命令更重,有完整的元数据配置:限制工具权限(allowed-tools)、指定触发条件(when_to_use)、选择模型(model)、设置上下文隔离(context: fork)。

---
name: security-audit
description: 安全审查
when_to_use: 审查代码安全漏洞时
allowed-tools:
  - Read
  - Grep
  - Glob
model: claude-opus-4-5
context: fork
---
 ${target} 执行安全审查...

Skills 触发时,会在隔离的子上下文里运行,工具权限是物理隔离的(不是靠 Claude 自律),结束后把结果返回主会话。

关键特性:比自定义命令更结构化,工具权限有硬约束,可以和主会话隔离运行。 适合封装有副作用、需要权限控制的操作。第 05 篇会专门讲 Skills 的设计。


三类命令的选用原则

需要确定性结果,不想靠 Claude 判断 → 第一类 CLI 命令。清空上下文、查费用、切模型,这些操作不该有歧义。

想复用一套工作流程,不需要特殊权限控制 → 第二类自定义命令。把反复用到的提示词结构固化下来,/standup/pr-desc/review 这类日常命令都适合。注意:它还是提示词,不是代码。

封装有风险的操作,或者需要隔离运行 → 第三类 Skills。权限隔离只有 Skills 能做到。


两个值得停下来想的洞见

什么时候该 /clear、/compact、改 CLAUDE.md转存失败,建议直接上传图片文件

把命令类型和劣化模式放在一起,有两个反直觉的结论。

洞见一:在对话里纠正 Claude 是徒劳的——这是机制决定的,不是你说得不够清楚

模式二"纠正回退"的根本原因不是 Claude 不配合,而是你在用错误的工具纠正它。

在对话里说"不要用 console.log",这条纠正被写进了"会随时间衰减的历史"——位置越来越靠后,注意力权重持续降低,最终必然回退。这不是偶然的,是 lost-in-the-middle 的机制决定的。

更重要的是,这件事其实很容易自己验证。你可以做一个小实验:

  1. 在纯对话里告诉 Claude:"不要用 console.log,用 logger.info。"
  2. 继续推进几轮任务,再让它生成新代码。
  3. 然后把同一条规则写进 CLAUDE.md,再重复一次类似流程。

大多数时候你会发现,两种方式的持久性差别非常明显。前者更容易回退,后者更稳定。这比单纯讲原理更有说服力,因为你能亲手看到规则所在层级不同,稳定性就不同。

真正有效的纠正只有一种:把规则从对话历史移进系统注入层。

# CLAUDE.md
- 日志统一用 logger.info/warn/error,禁止 console.log
- 所有异步函数必须有 try-catch,不依赖外层中间件捕获
- 禁止使用 any,类型必须明确

写进 CLAUDE.md 的规则,在每次对话开始时被系统自动注入,优先级高于对话历史,不会随对话长度衰减。这是 CLAUDE.md 存在的真实原因——不是"项目文档",是绕过对话历史衰减的唯一可靠手段

判断标准很简单:如果你对同一件事纠正了两次以上,就不该继续在对话里纠正,而应该把它写进 CLAUDE.md。

洞见二:/compact 不是无损压缩,它本身就是一次 AI 调用

很多人以为 /compact 是把历史"存档"了,实际上 Claude Code 在压缩时会调用模型生成摘要——这意味着压缩结果的质量,取决于 Claude 怎么理解这段历史。

这里不需要依赖源码猜。单从行为上你就能判断出来:/compact 不是简单的机械压缩,而是在"理解历史之后生成摘要"。

为什么这么说?因为如果它只是确定性的算法压缩,那么你补不补"保留说明",结果应该差异很小;但实际使用中,空着用和带明确保留说明用,摘要质量往往差很多。这更像是模型在根据你的提示重新组织历史,而不是程序在做无损归档。

你在 /compact 后面附加的保留说明,本质上就是在告诉 Claude:哪些内容应该成为压缩后的锚点。有没有写、写了什么,会直接影响压缩后的摘要长什么样。

这有两个实际含义:

第一,/compact 不在第一类"确定性命令"里——尽管它看起来是内置命令,但压缩结果是 AI 行为,不是代码行为,存在质量差异。

第二,空着用和带保留说明用,结果可以差很多:

❌ /compact
   → Claude 自己判断什么重要,探索性讨论和已确认决策同等对待

✅ /compact 只保留已确认的决策:JWT 方案、Prisma 数据库表结构、
            错误处理用 AppError 类。探索阶段被否决的方案不需要保留。
   → Claude 围绕这些锚点生成摘要,后续对话里这些决策记得最清楚

如果你一直在空着用 /compact,本质上是在让 Claude 替你决定什么值得记住。


两个可以立刻自己验证的小实验

如果你想判断这篇文章讲的是不是“经验之谈”,最好的办法不是相信我,而是自己试一下。

实验一:同一条规则,留在对话里 vs 写进 CLAUDE.md

找一条你平时经常纠正的规则,比如:

不要用 console.log,用 logger.info

先只在对话里说这条规则,继续推进几轮任务,再让 Claude 生成新代码。然后把同一条规则写进 CLAUDE.md,重新开始一个类似任务,再观察它的稳定性。

你大概率会看到一个很明显的差别:
留在对话里的规则更容易回退;写进 CLAUDE.md 的规则更稳定。

这个实验最重要的启发不是“CLAUDE.md 很有用”,而是:规则所在的层级不同,稳定性就不同。

实验二:空着 /compact vs 带保留说明 /compact

找一段讨论过很多方案的长会话。先在类似场景里直接执行:

/compact

再换一次,在压缩时明确写:

/compact 只保留已确认的决策:JWT 方案、Prisma 表结构、错误处理规范。
探索阶段被否掉的方案不保留。

然后比较压缩后的后续表现。你通常会发现,后者更不容易把探索阶段的噪音继续带下去。

这个实验说明的不是“提示词可以调得更好”,而是:/compact 本身就在重新组织历史,所以你不该把它当成无脑归档。


完整视图:五类控制机制

把命令扩展到所有控制机制,共五类:

类型触发方式经过 AI可靠性
CLI 状态命令(/clear/cost 等)手动输入确定性
自定义 Slash Command手动输入依赖提示词质量
Skills命令或自然语言触发工具权限有硬约束
Hooks(PreToolUse 等)工具执行事件自动触发确定性
键盘快捷键(Plan Mode 等)键盘操作确定性

不经过 AI 的机制(CLI 命令、Hooks、快捷键)是确定性的,适合做强约束;经过 AI 的机制(自定义命令、Skills)有随机性,需要好的提示词设计,但表达能力更强。


这篇文章的边界

这里讲的现象,并不是 Claude Code 独有的怪癖,而是长上下文 AI 协作的一类共性问题。不同模型、不同客户端、不同版本,细节会有差别,但下面这几个事实不会变:

  • 对话历史不是长期稳定记忆
  • 早期探索内容会污染后续判断
  • 留在对话层的规则会衰减
  • 当上下文过长时,注意力一定会分散

所以这篇文章真正想讲的,不是“背命令表”,而是一个更底层的判断:

Claude Code 的核心问题,不是你会不会再写一个更长的 Prompt,而是你有没有把信息放在正确的层级上。

项目背景、长期规则、任务上下文、阶段性探索,这四种东西不应该混在一起管理。Claude Code 之所以有这些 Commands,本质上就是为了让你把它们拆开。


本篇实践任务

任务一: 找你最近一次“感觉 Claude 越来越糊涂”的会话,对照四种劣化模式,判断到底是哪一种在起作用,不要再笼统地归因于“模型变差”。

任务二: 检查你现在的 CLAUDE.md,有没有把“曾经在对话里纠正过不止一次”的规则写进去?把它们补进去,下次对话观察差异。

任务三: 做一次对照实验:一段长任务会话里分别试试“空着 /compact”和“带保留说明 /compact”,比较后续回答质量。

任务四:.claude/commands/ 里创建一个你最常用操作的自定义 command,比如 /pr-desc/standup,感受一下它和直接输提示词的区别。


下篇预告

第 04 篇:CLAUDE.md 完整指南——让 Claude 真正理解你的项目

你已经知道 CLAUDE.md 是"系统注入的长期记忆",优先级高于对话历史,是纠正回退的唯一可靠手段。但写什么进去、怎么写才能真正影响 Claude 的行为而不只是让它"读到",是另一个问题。下一篇专门讲这个。


AI Coding 系列持续更新。上下文劣化有规律,干预就有方法。