如果你已经用 Claude Code 工作过一段时间,大概遇到过这样的情况:一开始对答如流,越到后面回答越奇怪,开始忘记之前说好的规范,反复犯同样的错误,甚至把你刚改完的代码又改回去,甚至只说不做了。这不是 Claude 变笨了,是上下文窗口快满了。
一、理解上下文:你真正的稀缺资源
Claude Code 的上下文窗口是 200,000 tokens。听起来很多,但在实际工作中消耗惊人:
| 内容 | 约占 tokens |
|---|---|
| 500 行 TypeScript 文件 | ~4,000 |
| 一次详细的 Claude 回复 | |
| 一次复杂的 bash 命令输出 | |
| 完整交互轮次(粗估) | ~50 轮 |
核心认知转变: 上下文管理不是"让 Claude 记住更多",而是精简噪音,保留信号。
满载上下文的典型症状:
- 回答开始跑偏,无视之前设定的规范
- 重复询问已经告知的信息
- 对同一问题给出不同答案
- 代码修改后又悄悄改回去
这些症状出现时,通常不是继续填充上下文的好时机。
二、监控先行:知道自己在哪里
无法管理你无法度量的事物。Claude Code 状态栏实时显示上下文使用量:
Context: 67% (134k/200k tokens)
颜色会直观告警:
- 绿色 (0~60%):工作区间,正常操作
- 黄色 (60~80%):开始考虑压缩策略
- 红色 (80~100%):主动干预,或等待自动压缩
行动阈值建议:
- 60%:评估当前任务是否值得继续,或做一次有针对性的
/compact - 80%:强制介入,选择
/compact精简或/clear重置 - 超过 85%:自动压缩会触发,但要警惕"摘要的摘要"问题(后文详述)
三、核心命令:三板斧用对才有效
/clear —— 激进但彻底
/clear
本质:清空所有对话历史,只保留 CLAUDE.md 中的持久化内容。
很多人舍不得用 /clear,觉得会丢失"上下文"。但这恰恰是一个思维误区——任务边界处的清空,往往比带着脏上下文继续更高效。
适用场景:
- 切换到完全不相关的任务
- 调试陷入混乱,想从干净状态重新来过
- 上下文已经被无关信息严重污染
实践建议:将 /clear 作为任务切换的固定仪式,就像关闭一个浏览器标签再打开新的。
/compact —— 外科手术式压缩
# 基础用法:通用压缩
/compact
# 进阶用法:带指令的定向压缩
/compact Focus on the authentication flow changes
/compact Preserve: architecture decisions, API contracts. Discard: debug output, failed attempts
/compact Keep: modified file list and current task status
本质:让 Claude 将整段对话历史蒸馏为结构化摘要,以此作为新的上下文起点。典型压缩率 60~70%。
关键技巧在于带指令。通用 /compact 会按 Claude 的判断保留内容,而指定指令后,Claude 知道你接下来要继续做什么,摘要的信噪比会高得多。
局部压缩(进阶):
- 按
Esc+Esc或使用/rewind选择历史检查点 - 选择 "Summarize from here"
- 仅压缩该节点之后的消息,保留早期的完整上下文
这个方法特别适合:前半段是关键架构讨论,后半段是冗长的调试过程。
自动压缩的隐患:摘要的摘要
当你不主动干预,Claude Code 会在接近上下文上限时自动触发压缩。问题在于:
对话 → 自动压缩 → 继续对话 → 再次自动压缩 → ...
每次压缩都会有信息损失,多次叠加后,早期的关键决策可能已经被高度抽象,细节全无。如果你发现 Claude 对项目背景的理解越来越模糊,通常是多次自动压缩的后果。
判断原则:一旦出现第二次自动压缩,优先考虑 /clear 而不是继续在压缩后的基础上工作。
四、CLAUDE.md:建立持久记忆层
上下文窗口是短期记忆,CLAUDE.md 是长期记忆。把"永远需要知道"的信息从会话历史迁移到 CLAUDE.md,是最高效的上下文优化。
一个实用的 CLAUDE.md 结构:
# 项目架构
- 后端:FastAPI + PostgreSQL(pg 15)
- 前端:React 18 + TypeScript strict
- 部署:Docker + K8s,CI/CD 用 GitHub Actions
# 常用命令
- 启动开发环境:`make dev`
- 运行测试:`pytest tests/ -v --tb=short`
- 数据库迁移:`alembic upgrade head`
- 代码格式化:`ruff format . && ruff check --fix .`
# 代码规范
- Python:强制 type hints,禁止 Any,函数名用动词开头
- TypeScript:strict 模式,禁止 as any,组件用函数式
- API 响应统一格式:`{"data": ..., "error": null}`
# 当前迭代重点
- 正在迁移认证方案:Session Cookie → JWT
- API v2 路由前缀:/api/v2/
几个实践细节:
- 目录作用域:根目录的 CLAUDE.md 全局生效,子目录的 CLAUDE.md 仅在该目录下生效。可以为不同模块设置专属上下文
- 动态更新:对话中输入
#可以快速向 CLAUDE.md 追加内容,无需手动编辑文件 - 精简是美德:CLAUDE.md 本身也占上下文,建议控制在 150~200 行内。过长的 CLAUDE.md 反而是上下文负担
黄金原则:稳定信息(架构、规范、命令)放 CLAUDE.md;临时信息(当前 bug 的错误信息、某次调试的中间结果)留在对话中,不要混用。
五、精确文件引用:减少无关 token
一个常见的上下文浪费源:让 Claude 读整个文件,但实际只需要其中一小部分。
# 低效做法:读取整个 800 行文件
Read src/api/user_service.py
# 高效做法:精确定位到需要的部分
Read src/api/user_service.py:120-180
@src/api/user_service.py # 用 @ 引用,Claude 会按需读取
一个 800 行的 Python 文件大约消耗 6,400 tokens,精确读取 60 行则只消耗约 500 tokens。在需要参考多个文件时,这个差距会成倍放大。
实践建议:
- 告诉 Claude 具体要找什么,让它自己决定读哪部分,而不是直接丢整个文件
- 用
@文件路径语法引用文件时,配合具体问题使用效果更好 - 避免让 Claude 扫描整个目录,除非真的需要全局视图
六、会话管理:像 Git 分支一样思考
Claude Code 的会话可以命名、保存、恢复。把这套机制用起来,能显著改善多任务工作流。
# 为当前会话起个有意义的名字
/rename feature/auth-jwt-migration
# 意外关闭终端后,接续上次会话
claude --continue
# 选择历史会话恢复(会显示会话列表)
claude --resume
多任务工作流实践:为不同功能模块创建独立的命名会话。比如同时在推进两个 feature:
会话 A:feature/user-profile-redesign
会话 B:bugfix/payment-timeout-issue
两个会话各自维护独立的上下文,互不干扰。在 A 中累积的 payment 相关上下文不会污染 B 的会话。
断点续作:claude --continue 比重新向 Claude 描述"之前我们在做什么"要快得多,特别是在复杂任务的中途。
七、多会话并行:突破单窗口上限
这是很多人没有充分利用的策略:同时开多个 Claude Code 终端,每个会话有独立的 200k token 窗口。
领域隔离策略
Terminal 1: claude → 后端 API 开发(专注 services/、models/)
Terminal 2: claude → 前端组件开发(专注 src/components/、pages/)
Terminal 3: claude → 测试与 CI(专注 tests/、.github/workflows/)
每个会话只加载与自己领域相关的文件和上下文,互不污染。在 5 万行级别的项目中,单个会话很难同时维持全局视图,但 3 个专域会话可以无压力覆盖整个项目。
跨会话状态同步
并行会话最大的挑战是同步。建议维护一个 .claude/shared-context.md:
# 跨会话共享上下文
更新时间:2025-03-04 15:30
## 今日架构决策
- 认证方案已确认:从 Session Cookie 迁移到 JWT
- access token 有效期:15min
- refresh token 有效期:7天,存 Redis
- API 路由统一加 /api/v2/ 前缀,v1 保持兼容到 Q2
## 当前 schema 变更
- users 表新增:last_login_at (timestamp), jwt_jti (varchar 36)
- sessions 表标记废弃,Q2 后删除
## 待协调问题
- [ ] 前端 token 刷新逻辑需要与后端对齐(@前端会话处理)
每个并行会话开始时读取此文件,做出重大决策后更新。这样 3 个会话虽然独立,但能保持架构层面的一致性。
八、子 Agent 隔离:深度任务的上下文保护
Claude Code 的子 Agent 机制让你可以把任务委托给独立的 Claude 实例处理,主会话上下文完全不受影响。
Task 工具 vs 自定义 Subagent
这是两种不同的使用方式,适用场景有别:
Task 工具(临时 Worker)
通过自然语言描述触发,Claude 自动创建一个临时 Claude 实例执行任务,任务完成后实例销毁。适合一次性的、自包含的任务:
主会话(上下文:整体架构 + 任务协调)
├── Task Worker 1(上下文:安全审计,独立 200k 窗口)
├── Task Worker 2(上下文:性能分析,独立 200k 窗口)
└── Task Worker 3(上下文:测试覆盖检查,独立 200k 窗口)
子 Agent 完成后,只有结果摘要返回主会话,整个探索过程消耗的 token 不进入主上下文。
自定义 Subagent(可复用专家)
在 ~/.claude/agents/ 目录下创建 .md 配置文件,定义有预设系统提示和工具权限限制的专项 Agent,可在任何会话中复用:
# ~/.claude/agents/code-reviewer.md
---
name: code-reviewer
description: 专项代码审查,检查安全漏洞、性能问题和代码规范
tools: Read, Grep, Glob
---
你是一位专业的代码审查员。重点检查:
1. 安全漏洞(SQL注入、XSS、敏感信息泄露)
2. 性能问题(N+1查询、不必要的循环)
3. 代码规范(命名、注释、类型安全)
输出格式:按严重程度分级列出问题,每条附上文件路径和行号。
这类 Subagent 限制了可用工具(只有 Read、Grep、Glob),避免它意外修改文件,同时让每次代码审查都有一致的评判标准。
解决 Handoff Problem
子 Agent 从近乎空白的上下文开始(默认会继承部分父会话上下文,但不依赖于此)。这意味着你描述给 Task 工具的 prompt 必须自包含:
# 低效 prompt(依赖子 Agent 自己发现背景)
"帮我检查认证模块的安全问题"
# 高效 prompt(自包含)
"检查 src/api/auth.py 的安全漏洞。
背景:这是一个 FastAPI 应用,使用 JWT 认证,PostgreSQL 数据库。
重点检查:SQL 注入、token 验证逻辑、密钥管理。
输出格式:按严重程度(Critical/High/Medium)列出,每条附文件路径和行号。"
使用限制与成本警告
子 Agent 有几个重要限制需要了解:
- 并行上限:约 10 个 Task 并行(Claude Code 等待整批完成后再启动下一批)
- Token 成本:子 Agent 可能消耗大量 token,某些深度分析任务单个 Agent 就能消耗 160k tokens,需要权衡收益
- 不支持嵌套:子 Agent 无法再启动子 Agent,如需多级委托只能在主会话中链式调用
- 非完全隔离:默认子 Agent 会继承部分父上下文,真正的完全隔离(对代码审查等场景很有用)目前尚在实验中
适用场景:
- 专项代码审查(让审查者不受编写者思路影响)
- 大型重构前的现状调查(探索代码不污染主对话)
- 需要限制工具权限的敏感操作
- 多个相互独立的分析任务并行执行
九、Skills:按需加载的专项知识包
Skills 是 Claude Code 的知识模块化机制——把特定领域的规范、工作流、最佳实践打包成独立的知识单元,按需调用而非全量加载。
Skills 的本质:渐进式上下文注入
与 CLAUDE.md 每次会话必然全量加载不同,Skills 采用两阶段加载:
- Session 启动时:仅加载每个 Skill 的名称和描述(约 30~50 tokens/个)
- 任务触发时:Claude 判断当前任务与某 Skill 相关时,才加载该 Skill 的完整内容
这个设计让你可以维护十几个专项 Skill,而常规会话只消耗几百 tokens 用于索引,真正需要的 Skill 才按需展开。
Skills vs CLAUDE.md:选择哪个?
| CLAUDE.md | Skills | |
|---|---|---|
| 加载时机 | 每次会话必加载 | 按需加载 |
| 适合内容 | 项目核心信息 | 专项工作流知识 |
| Token 消耗 | 固定(每次会话) | 渐进式(按需) |
| 作用范围 | 全局背景 | 特定任务增强 |
判断规则:如果某段知识"每次对话都用得上",放 CLAUDE.md;如果"偶尔才需要,但需要时很重要",做成 Skill。
配置 Skills
在 .claude/skills/ 目录下创建 Markdown 文件(全局 Skills 放 ~/.claude/skills/):
# .claude/skills/api-design.md
---
name: api-design
description: FastAPI RESTful API 设计规范,包括路由命名、响应格式、错误处理
---
# API 设计规范
## 路由命名
- 资源用复数名词:/users, /orders, /products
- 操作通过 HTTP 方法区分,不用动词路由
- 正确:DELETE /users/{id}
- 错误:POST /delete-user
## 响应格式
统一使用:
{"data": <payload>, "error": null}
{"data": null, "error": {"code": "NOT_FOUND", "message": "..."}}
## 错误处理
- 4xx:客户端错误,附上 message 说明原因
- 5xx:服务端错误,不暴露内部细节,记录到日志
# .claude/skills/git-workflow.md
---
name: git-workflow
description: 团队 Git 工作流规范,包括分支命名、commit 格式、PR 描述模板
---
# Git 工作流
## 分支命名
- feature/描述-JIRA编号
- bugfix/描述-JIRA编号
- hotfix/描述
## Commit 格式
type(scope): description
type: feat | fix | refactor | docs | test | chore
...
触发方式
自动触发:Claude 根据任务内容判断,在你讨论 API 设计时自动加载 api-design Skill,在你提交代码时自动参考 git-workflow Skill。
手动触发:通过斜杠命令显式调用:
/api-design ← 立即加载该 Skill 的完整内容
Token 预算与管理
所有 Skill 描述的总预算 = 上下文窗口的 2%(约 4,000 tokens)。当 Skill 数量多或描述较长时,可能超出预算导致部分 Skill 描述被截断。
# 检查是否有 Skill 因超出预算被排除
/context
# 如需突破预算限制
export SLASH_COMMAND_TOOL_CHAR_BUDGET=8000
最佳实践:每个 Skill 的 description 字段控制在 80 字以内(用于索引),详细规范放在正文中。
Skills 适合包装什么
- 技术栈规范:FastAPI 最佳实践、React 组件设计、数据库 schema 规范
- 团队工作流:PR 描述模板、code review 标准、部署清单
- 调试流程:生产问题排查步骤、性能分析流程
- 领域知识:业务术语表、外部 API 使用说明
不适合放进 Skills 的内容:项目架构、常用命令、当前迭代重点——这些属于 CLAUDE.md 的领域。
十、Plan Mode:预防性上下文控制
Plan Mode(规划模式)经常被当作"减少错误"的工具,但它同时也是重要的上下文节约策略。
在 Plan Mode 下,Claude 只执行只读操作(Glob、Grep、Read),不写文件、不运行命令。这个探索阶段不会产生"操作 → 错误 → 修复 → 再次错误"这类反复循环,而这种循环是上下文的主要消耗源之一。
一次复杂任务的上下文消耗对比:
没有 Plan Mode:
探索(1k) → 尝试(2k) → 出错(3k) → 修复(4k) → 再出错(5k) → ... 总计 20k+
使用 Plan Mode:
规划探索(3k) → 确认方案 → 执行(5k) → 完成 总计 8k
规划越充分,执行阶段的上下文消耗越少。对于多文件变更的复杂任务,Plan Mode 几乎是必选项。
十一、Markdown 清单:任务状态外置
对于多步骤的长任务(数据库迁移、大批量重构、多阶段 feature 开发),在上下文中追踪任务进度会持续消耗 token。更好的做法是把任务状态外置到文件。
让 Claude 维护一个 Markdown 清单:
# 认证迁移任务清单
更新:Claude Code session #3
## 已完成
- [x] 分析现有 Session 认证代码
- [x] 设计 JWT 方案(access + refresh token)
- [x] 实现 JWT 工具类(src/utils/jwt.py)
- [x] 更新 users 表 schema
## 进行中
- [ ] 迁移登录接口(src/api/auth.py:login)
- 当前问题:refresh token 的 Redis key 格式待确认
## 待处理
- [ ] 迁移注销接口
- [ ] 更新前端 token 存储逻辑
- [ ] 编写迁移测试
- [ ] 验证旧 session 的向后兼容
## 决策记录
- JWT secret 从环境变量读取,key: JWT_SECRET_KEY
- refresh token 用 jti 字段标识,支持单点吊销
这个文件充当了"外部工作记忆"——进度状态、中间结论、待解决问题都在文件里,对话中只需要引用这个文件,而不是在每轮对话中反复陈述当前进度。
十二、踩坑总结
这些是实际使用中总结的反直觉经验:
1. "舍不得 /clear" 综合征
上下文越接近满,Claude 的表现越差。很多人在性能开始下降时还在坚持,期望通过更好的提示词来弥补。这是在和物理限制较劲。任务边界处主动 /clear,加载 CLAUDE.md,重新开始,往往比在满载上下文里挣扎快得多。
2. CLAUDE.md 膨胀
CLAUDE.md 本身也占上下文。把所有文档、注释、历史记录都塞进去的 CLAUDE.md 可能消耗 10,000+ tokens,这是每次会话的固定成本。保持 CLAUDE.md 精简(150~200 行),只放真正每次都需要的核心信息。
3. 多次压缩后的信息失真
/compact 一次是好事,三次就可能是问题。每次压缩都是有损压缩,多次叠加会丢失大量细节。一旦出现两次自动压缩,果断 /clear 比继续在失真的摘要上工作要好。
4. 并行会话不同步
开了 3 个并行会话,但没有维护 shared-context.md,3 个会话很快就会在架构理解上产生分歧。我曾经遇到前端会话和后端会话对同一接口的字段名有不同假设,最后合并时一团糟。共享状态文件是并行会话的前提,不是可选项。
5. 把 Plan Mode 只当防错工具
很多人只在"这个任务比较复杂"时才用 Plan Mode。但其实上下文节约才是更重要的理由——Plan Mode 把无效探索拦在执行阶段之外,是最便宜的上下文优化。
6. Skills description 太长导致被截断
Skills 的描述字段(description)用于生成索引,受 2% 上下文预算限制。把详细内容都写进 description 会导致超出预算后被截断,Claude 看不到这个 Skill 的存在。正确做法:description 写摘要(80 字以内),详细规范写在正文。
7. 子 Agent 的 Handoff Problem
子 Agent 从近乎空白的上下文启动。很多人给 Task 工具的 prompt 过于简短,结果子 Agent 花了大量 token 去"自己发现"背景信息,最终结果质量也差。高质量的子 Agent prompt 应该自包含:任务目标 + 相关文件路径 + 约束条件 + 期望输出格式,缺一不可。
速查表
| 场景 | 推荐策略 |
|---|---|
| 任务切换 | /clear,用 CLAUDE.md 维持项目知识 |
| 长会话继续 | /compact "保留架构决策和当前任务,丢弃调试日志" |
| 第二次自动压缩出现 | /clear,重新开始 |
| 大型项目 | 多会话并行 + .claude/shared-context.md |
| 专项深度分析 | 子 Agent 隔离,结果摘要返回主会话 |
| 一次性调查任务 | Task 工具,自包含 prompt |
| 复用的专项审查 | 自定义 Subagent(~/.claude/agents/) |
| 偶尔需要的领域规范 | Skills(按需加载,不占常驻上下文) |
| 项目核心信息 | CLAUDE.md(固定加载) |
| 复杂多步骤任务 | Plan Mode + Markdown 外部清单 |
| 精确引用代码 | Read file.py:50-120 或 @file.py |
| 意外中断续作 | claude --continue |
| 多任务并行 | 按功能域命名会话 /rename,claude --resume 切换 |
结语
上下文管理的本质是信噪比管理:把真正有用的信息压缩到尽可能少的 token,把噪音驱逐出去。
CLAUDE.md 是结构化的信号注入,/compact 是噪音过滤,/clear 是彻底的重置,多会话并行是通过隔离来提升信噪比,Plan Mode 是防止噪音的源头产生,Skills 是按需召唤的专项知识,子 Agent 是把复杂任务外包给独立实例以保护主上下文。
这些工具单独使用都有效,组合使用才能发挥最大价值。一旦建立起这套工作习惯,会发现 Claude Code 的有效工作时长和可靠性都会有显著提升。