配置 Claude Code 一段时间后,很多中重度用户会碰到同一个困惑:明明没做几次大改,令牌却消耗得比预期快。问题往往不在某一次会话,而在于配置和上下文管理。Claude Code 按输入、输出、缓存三类令牌计费,配置不当会让输入令牌成倍放大。本文会从令牌消耗路径讲起,给出审计基线,拆解七个容易忽视的消耗点,并提供可执行的修复和排错方法。
1. 先理解 Claude Code 的令牌消耗路径
1.1 令牌在 Claude Code 中消耗在哪里
Claude Code 是 Anthropic 推出的命令行 AI 编程助手,它通过 API 与模型交互,按令牌计费。对最终用户而言,令牌大致分三类:
- 输入令牌:包括系统提示词、CLAUDE.md 注入内容、历史消息、工具调用结果、原始请求。模型每次回答前都需要处理这些内容。
- 输出令牌:模型生成的回复正文、代码 diff、计划文本等。
- 缓存令牌:上下文缓存命中或写入时产生的计量。缓存写入通常比完整重新处理便宜,但读取缓存也会有成本。
容易忽略的一点是,工具调用结果并不会“免费”。当 Claude Code 执行了 Bash、Read、Grep 或 Edit 后,工具返回的内容会作为新的输入消息继续参与下一轮请求。换句话说,一个tail -n 2000的输出,可能会被完整送进上下文。
1.2 单次请求看起来不贵,会话生命周期才是关键
单次小任务的令牌消耗并不多,但 Claude Code 的交互模式是“多轮 + 工具调用链”。每一轮新的请求,模型都要看到此前的消息和工具结果。于是:
- 会话越长,每轮请求的输入令牌越多。
- 单个工具输出越大,后续每一轮都会携带这部分内容。
- 请求失败后重试,历史上下文被重新加载或从缓存重新计算。
- 切换模型或清空会话后,上下文缓存失效,重新处理完整输入的成本会集中出现一次。
这也是为什么排查令牌问题时,不能只看“我让模型写了多少次代码”,而要看“这轮会话的上下文里堆积了多少内容”。
1.3 审计前的观测入口
在动手修配置之前,先确认下面几个观测点是否可用,后续所有判断都依赖它们:
- Anthropic Console 的 Usage 页面,可以查看账号级别的用量趋势和请求统计。
- 本地日志目录:Claude Code 会在用户目录下保存运行日志,例如
~/.claude/下的日志文件。日志是排查 401、529 以及重试行为的第一手资料。 - 会话内命令:
/status可以查看会话状态,/context可以查看上下文占用情况,/cost可以查看会话费用估算。不同版本命令名可能不同,以当前安装版本实际支持为准。 - 环境变量:
ANTHROPIC_API_KEY、ANTHROPIC_MODEL、ANTHROPIC_BASE_URL等。它们能影响请求去向、模型选型和鉴权方式。
2. 环境准备与审计基线
2.1 确认版本和安装方式
审计前先确认 Claude Code 版本,因为配置字段、命令行为和模型支持列表在不同版本间有差异。常见安装方式有两种:
- npm 全局安装:
npm install -g @anthropic-ai/claude-code - 原生安装:官方安装包或 Homebrew 等包管理方式
检查版本:
claude --version claude doctorclaude doctor会检查环境变量、认证状态和常见配置问题。如果返回异常,说明环境本身就有隐患,先修复环境再谈令牌优化。
2.2 记录一份可对比的基线
不要凭感觉判断“令牌为什么多了”。先记录一组基线数据,修复后再跑同一个任务对比:
- 当前模型配置:
ANTHROPIC_MODEL或 settings 中的model字段。 - API key 的创建时间和启用状态。
- CLAUDE.md 大小:
wc -l CLAUDE.md、wc -c CLAUDE.md。 - MCP 服务器数量:
claude mcp list。 - hooks 数量:查看
~/.claude/settings.json和项目级.claude/settings.json。 - 一个标准任务的令牌消耗:例如固定模型后,让 Claude Code 给某个函数补充单元测试,记录任务前后 Usage 页面的差值。
2.3 设置日志和预算告警
审计期间可以把日志级别调高,观察每次请求的实际输入输出量:
export ANTHROPIC_LOG_LEVEL=debug claude --debug注意:debug 日志会产生大量文件内容,只用于定位问题时开启,修复后要恢复。
同时在 Anthropic Console 配置支出限制和用量告警。没有预算边界时,配置错误会一直累计成本。下面是一个审计基线记录表,可以直接复制使用:
| 审计项 | 记录值 | 备注 |
|---|---|---|
| Claude Code 版本 | 通过claude --version获取 | 不同版本配置差异明显 |
| 模型配置 | 记录ANTHROPIC_MODEL | 要区分默认模型和显式配置 |
| CLAUDE.md 字符数 | 记录wc -c结果 | 大于若干 KB 时重点关注 |
| MCP 服务器数量 | 每个服务器的名称 | 停用不常用服务 |
| hooks 数量 | 记录触发点和输出 | 注意输出文本大小 |
| 标准任务令牌差 | 记录 Usage 页面差值 | 每次配置变更后重跑 |
3. 七个隐藏消耗点的定位与修复
3.1 消耗点一:CLAUDE.md 过大,系统提示词被反复放大
现象:会话刚开始时上下文占用就比较明显,每轮请求都带着大量项目说明。
原因:CLAUDE.md 是 Claude Code 的项目记忆文件,会作为系统提示词的一部分注入上下文。很多项目用久了,CLAUDE.md 越攒越长,里面混入了代码片段、历史决策、过时命令、甚至大段 URL 和排错日志。模型每一轮都要处理这些内容,即使它们与当前任务无关。
检查方式:
wc -l CLAUDE.md wc -c CLAUDE.md head -50 CLAUDE.md修复思路:
- 只保留高频信息:技术栈、启动命令、测试命令、目录约定。
- 低频内容拆分到独立文档,如
docs/ARCHITECTURE.md、docs/CODING_GUIDE.md,让模型按需读取。 - 不要在 CLAUDE.md 里贴完整代码或超长链接。
- 项目和全局两个层级都要检查:项目
.claude/CLAUDE.md或./CLAUDE.md,以及用户级~/.claude/CLAUDE.md。
精简前:
# 项目说明 本仓库用于订单系统的开发。 包含 3 个微服务,具体路径如下: - order-service - payment-service - user-service 历史上有一次因为 Feign 超时导致联调失败,当时的排查记录: < 一大段排错日志 >精简后:
# 项目说明 - 技术栈:Java 17、Spring Boot 3、MySQL 8 - 服务目录:order-service、payment-service、user-service - 启动方式:见 docs/RUNBOOK.md - 编码规范:见 docs/CODING_GUIDE.md3.2 消耗点二:工具输出未裁剪,长日志全文进入上下文
现象:一次简单的“帮我看下这个接口”操作,输入令牌突然涨了几千甚至几万。
原因:Claude Code 需要读取文件内容来回答问题。如果直接请求“读取整个文件”或“看完整日志”,工具返回的大段文本会被当作后续请求的输入消息。文件越大,后续每一轮都在为这同一份文本支付输入令牌。
检查方式:开启 debug 日志后,观察单次请求中输入内容的大小。也可以在会话里用/context查看上下文占比,如果某次命令后占用明显跳升,多半是工具输出过大。
修复思路:
- 面试式引导:让模型先用
grep、sed、head、tail定位关键片段,再决定是否读取全文。 - 阅读大文件时要求输出摘要,而不是原样粘贴。
- 如果某次工具结果确实没用,用
/compact压缩会话或/clear清理后重开。 - 确认是否有针对工具结果最大长度的配置项,按需限制。
错误示范:
读取
/var/log/app.log全文,然后分析所有 ERROR。
推荐方式:
先执行
grep -n "ERROR" /var/log/app.log | tail -50,再分析摘要。
3.3 消耗点三:MCP 服务器配置过多,元数据请求频繁
现象:会话刚启动,上下文里就出现了大量工具名称和工具描述。
原因:MCP 服务器会向 Claude Code 注册工具,每个工具的描述和参数 schema 会进入请求。服务器越多,工具列表越长,固定开销越大。某些 MCP 服务器返回的数据也容易“一查一大片”,例如数据库查询返回整个表,或搜索引擎返回大量网页摘要。
检查方式:
claude mcp list统计未使用但一直启用的服务器。
修复思路:
- 只保留高频使用的 MCP 服务器,低频服务器配置后不自动启用。
- 优先选择返回结构化小数据的 MCP 工具。
- 对返回体过大的 MCP,尽量在 Prompt 中限制字段和行数,例如“只返回前 20 行,每行包含 id 和 name”。
MCP 配置示例:
{ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }这样一个额外 MCP 服务器会为请求增加一批工具定义。如果同时开启多个,固定开销会叠加。
3.4 消耗点四:模型配置错误导致失败-重试循环
现象:请求直接报错,常见的有:
unexpected status 401 unauthorized: 未提供令牌 (request id: 20260825104057560686022r5wsty4ffkmuu)或:
"deepseek-v4-pro" is not a model this version of claude code recognizes原因:环境变量ANTHROPIC_MODEL或 settings 里的model字段写成了不存在的模型名,或 API key 未设置、已过期、base URL 指向了错误环境。失败请求本身不一定消耗大量令牌,但工作流中断后,用户反复重发,历史上下文被反复加载,间接放大了消耗。还有一个隐藏问题:错误配置会让用户误判为“令牌用尽”,在错误方向浪费大量时间。
修复思路:
- 先看模型名:使用官方当前支持的模型标识,确认版本兼容性。
- 再看鉴权:重新设置
ANTHROPIC_API_KEY。 - 最后看地址:如果设置了
ANTHROPIC_BASE_URL,确认它指向的 API 网关兼容 Claude Code。不要随意填写自定义地址。
检查配置:
echo $ANTHROPIC_MODEL echo $ANTHROPIC_API_KEY claude config list401 报错里的 request id 是定位问题的重要线索,提交支持或群组排查时带上它。
3.5 消耗点五:529 与自动重试的重复计费风险
现象:高峰期使用 Claude Code 时频繁遇到529 Overloaded,任务进度丢失,重试多次后令牌消耗明显上升。
原因:529 代表模型服务过载,API 暂时无法处理请求。Claude Code 通常会有重试机制,但如果同时有多个会话并发跑,或者用户手动连续重发,同一段上下文会被重复提交多次。模型未完成响应时,下一次请求要重新携带上下文,成本高于正常连续对话。
修复思路:
- 减少并发会话数量,高峰时段不要同时开多个任务。
- 遇到 529 时不要连续重发,等待一段时间再重试。
- 长任务拆成多个小步骤,避免一次失败导致全量重跑。
- 如果 529 持续出现,换非高峰时段或更换可用模型。
针对不同模型的兼容性,建议固定模型名,避免自动 fallback 到不同上下文窗口的模型,导致缓存失效后产生额外输入开销。
3.6 消耗点六:会话不清理,上下文无限膨胀
现象:一个会话用了一整天甚至跨周,后期一段简单对话都会消耗大量输入令牌。
原因:多轮对话的输入令牌随历史消息增长。即便模型只输出一句话,模型也要处理全部历史消息,包括大量已完成的旧任务和工具输出。
修复思路:
- 任务结束后按主题重新开会话。
- 大型重构拆成阶段,每阶段结束时
/clear。 - 不确会话历史是否继续有用时,用
/compact压缩历史上下文。 - 定期检查
/context占用比例,超过告警水位就该清理。
这里的核心原则是:不要把一个会话当作长期工作区。Claude Code 不是像编辑器那样“保持打开就行”,而是每轮请求都在为历史消息付费。
3.7 消耗点七:hooks 与 skills 的隐式开销
现象:明明没有主动向模型提问,配置了多个 hooks 后,每次工具调用前后都会附加额外上下文。
原因:hooks 可以在特定事件触发脚本,并把输出注入工作流。如果某个 hook 的脚本输出很大,例如打印环境变量、读取配置文件全文、拉取 git 状态,这些内容会在事件发生时进入模型处理链路。skills 同理,技能描述过长或数量过多时,模型每次都需要读取相关说明。
检查方式:查看~/.claude/settings.json和项目.claude/settings.json,统计 hooks 配置。
修复思路:
- 只保留必要 hooks,尤其是让脚本输出尽量简短。
- hook 命令用
echo输出关键摘要,不要直接cat大文件。 - skill 描述写短,具体内容在 skill 内部按需加载。
hooks 配置示例:
{ "hooks": { "PostToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "echo \"tool completed with exit code $?\"" } ] } ] } }这个例子里输出只有一行文字,不会给上下文带来明显压力。如果把echo换成env或cat some-large-file,每次工具调用都会产生额外的输入成本。
4. 配置审计实操:从命令到文件
4.1 查看当前生效配置
Claude Code 配置有多个层级:用户级、项目级、环境变量、会话内指令。高优先级配置容易覆盖低层级配置,所以审计时必须看“最终生效值”。
常用检查命令:
# 查看版本 claude --version # 查看环境诊断 claude doctor # 查看 MCP 服务器列表 claude mcp list # 查看配置(如果当前版本支持) claude config list配置文件通常分布在以下位置:
- 用户级:
~/.claude/settings.json - 项目级:
.claude/settings.json - 项目记忆:
./CLAUDE.md或.claude/CLAUDE.md - MCP 配置:
~/.claude.json或项目.mcp.json
查看大文件时注意裁剪输出:
wc -l ~/.claude/settings.json cat ~/.claude/settings.json | head -1004.2 统计一次会话的令牌差
推荐做法是固定模型,记录任务前后账号用量差值。这样可以知道一次标准任务的真实成本。
如果会话内支持/cost,也可以直接用:
/cost它会显示当前会话的费用估算。再配合/context查看上下文占用。如果一个任务累计成本远超预期,说明隐藏消耗点正在起作用。
下面是一次模拟统计过程:
- 记录 Usage 页面当前已用令牌数。
- 固定模型,运行一次标准重构任务。
- 任务结束后记录新的令牌数。
- 对差值做初步分类,区分输入、输出、缓存。
如果只有总令牌数,也能通过下面特征判断问题方向:
- 总令牌数高但任务简单:多半是上下文膨胀或工具输出过大。
- 请求次数异常多:注意重试循环或 hooks 触发。
- 缓存命中率低:会话不连续、模型切换频繁、上下文被清空后重新处理。
4.3 异常模式速查表
| 异常特征 | 可能原因 | 优先检查 |
|---|---|---|
| 单次请求输入令牌突增 | 工具输出过大、文件全文读取 | grep定位关键内容,而非全文读取 |
| 上下文占用持续上涨 | 会话历史过长 | /compact、/clear、按主题拆分会话 |
| 请求数量异常多 | 401/529 重试、hooks 触发频繁 | 查看日志中的错误码,限制并发 |
| 缓存命中率低 | 模型配置切换、会话频繁清理 | 固定模型名,必要时保留长会话 |
| 刚启动就有上下文压力 | CLAUDE.md 过大、MCP 工具列表过长 | 精简 CLAUDE.md,裁剪 MCP 数量 |
5. 常见问题排查:现象到根因
5.1 按链路排查的顺序
遇到令牌相关报错,不要先怀疑“令牌用完了”。优先按下面顺序检查:
- 输入是否正确:API key 是否设置、是否过期。
- 文件路径和命名:settings 文件是否加载了预期文件。
- 模型名是否兼容:
ANTHROPIC_MODEL是否写成已下线或不存在的模型。 - 配置是否生效:环境变量和 settings 是否存在覆盖。
- 网络地址是否正确:base URL 是否指向了错误网关。
- 日志中的异常:查看本地日志关键字,如 401、529、timeout。
- 工具或框架限制:当前 Claude Code 版本是否支持所用配置字段。
5.2 典型错误与处理方案
| 错误现象 | 常见根因 | 检查方式 | 处理建议 |
|---|---|---|---|
unexpected status 401 unauthorized: 未提供令牌 | API key 未设置、已撤销或 base URL 错误 | 打印环境变量,检查请求日志中的 request id | 重新配置ANTHROPIC_API_KEY,确认 base URL 兼容性 |
"xxx" is not a model this version of claude code recognizes | 模型名写错或版本过旧 | 查看ANTHROPIC_MODEL、settings 中的 model 字段 | 使用官方当前支持的模型名,升级 Claude Code |
529 Overloaded | 服务过载,并发过高 | 查看日志中 529 出现频率 | 退避重试,减少并发,避开高峰 |
| 令牌消耗比预期快但任务简单 | 上下文膨胀、MCP 过多、hooks 输出过大 | 检查/context占用,统计输入输出 | 按七个消耗点逐项核对修复 |
| 撤销 API key 后请求仍成功 | 配置残留了旧 key | 全局搜索环境变量、CI 配置、.env文件 | 轮换所有环境中的 key,清理残留 |
5.3 令牌泄露后的撤销难题
热词里提到的“令牌撤销难题”在实际项目中很常见:API key 一旦泄露,单纯在代码里改字符串不够,因为 key 可能已经进入 Git 历史、CI 日志、截图、错误上报系统或同事的本地环境。
处理步骤:
- 立即在 Anthropic Console 撤销该 key。
- 创建新 key,并更新所有独立环境的配置。
- 检查用量明细,判断是否有异常请求来自陌生 IP 或陌生 model。
- 搜索泄露渠道:
git log -p查看历史提交、CI 平台的输出日志、团队共享文档。 - 对不再使用的 key 保留一段观察期,确认无新增消耗后再归档。
这里还涉及一个安全原则:不要把 key 硬编码到仓库中。配置要么写入本地未提交文件,要么通过环境的密钥管理机制注入。
6. 最佳实践与扩展方向
6.1 发布前配置检查清单
每次调整 Claude Code 配置后,建议对照下面的清单确认:
- 固定模型名,不依赖默认值。
- CLAUDE.md 体积控制在合理范围,并做了按需拆分。
- MCP 服务器只保留常用项。
- hooks 输出短小,skill 描述精简。
- debug 日志已经关闭。
- 会话内上下文占用已被定期查看。
- Usage 页面已开启用量告警。
- API key 的轮换周期有明确计划。
- 项目配置已纳入版本管理,敏感字段单独处理。
6.2 区分学习环境与生产环境
| 维度 | 学习环境 | 生产环境/团队项目 |
|---|---|---|
| 模型选择 | 便宜模型优先 | 固定模型,考虑稳定性和上下文窗口 |
| 日志级别 | 可开启 debug 便于学习 | 默认关闭,避免日志膨胀 |
| 会话管理 | 随意测试,频繁清理 | 按任务开会话,定期/compact |
| 密钥管理 | 本地环境变量即可 | 用环境的密钥管理机制,禁止入库 |
| 审计 | 偶尔查看用量 | 每周查看用量,保留审计底稿 |
| 告警 | 不必须 | 必须开启预算限制和异常告警 |
6.3 把日志纳入内部审计体系
Claude Code 的本地日志通常按时间追加写入,会话清理不影响历史日志保留。对团队而言,可以把这些日志纳入已有的日志审计系统,定期做以下检查:
- 是否有人把模型配置锚到了非预期环境。
- 是否存在反复重试仍失败的请求。
- 是否有 API key 在多个环境中被复用。
日志只要进入审计链路,令牌消耗问题就能从“被动看账单”变成“主动发现”。在日志系统中做分类归档时,可以采用 append-only 方式保存原始日志,避免后期被覆盖或误删。
6.4 下一步扩展方向
如果七个消耗点都排查完毕,令牌消耗仍然很高,可以继续做三件事:
- 建立更精细的基线:不同任务类型分别统计数据,例如重构、测试、排错、文档生成各占多少。
- 关注模型和版本更新:新版本可能带来更优的上下文处理策略或更便宜的模型。
- 优化团队工作流:把公共配置沉淀到项目模板中,让每个开发者初始配置一致,避免个人环境差异导致消耗差异。
对新手来说,最有价值的练习不是把所有高级功能都配齐,而是从最小配置开始:一个精简的 CLAUDE.md、一个固定模型、一个标准任务。每增加一个 MCP、一个 hook、一段系统提示词,就重跑同一个任务,观察令牌消耗变化。这样能直观感受到每个配置项的边际成本,也就能在真正消耗失控前及时收手。
真正控制令牌消耗的关键,不是找到某个“隐藏开关”,而是建立上下文管理意识:保持描述精简、控制工具输出、限制插件数量、及时清理会话。把这些习惯固化到日常开发里,比等到账单报警后再来审计有效得多。