
1. 先搞懂 AI token 到底在消耗什么很多人一提到 AI token第一反应就是“按量计费的那个东西”然后就开始算钱。但如果你只是把 token 当成账单单位那基本等于把一辆车的油表当成装饰——你永远不知道油是怎么没的。我在过去大半年里重度使用 Claude Code 做日常开发从最开始每个月额度用不到一半到后来三天就见底中间踩过的坑和总结出来的经验足够写一篇完整的实战复盘。先把概念理清楚。AI token 是模型处理文本的最小单位一个英文单词大约对应 1 到 1.5 个 token中文一个字大约 1 到 2 个 token。但真正决定你消耗速度的不是单次对话的长度而是整个上下文窗口里累积的所有内容。这就像你去餐厅吃饭不是按你吃了几口菜收费而是按桌上摆了多大的盘子、盘子里装了多少东西来收费。每轮对话模型都要把之前所有的历史记录重新“看”一遍这些历史记录全部计入 token 消耗。Claude Code 这类工具的特殊之处在于它不是一个简单的聊天窗口。它会读取你的项目文件、执行命令、分析目录结构、维护对话历史、调用子任务。每一个动作都在往上下文窗口里塞东西。你以为你只是问了一个问题实际上模型可能已经读了十几个文件、跑了三四条命令、生成了几百行中间输出。这些全部是 token。所以“最大化利用 AI token”这个命题核心不是省着不用而是让每一个 token 都花在刀刃上。省 token 不是目的用同样的 token 完成更多有效工作才是。我见过太多人要么完全不在意消耗月底看着账单发呆要么过度节省该让模型读的文件不读结果生成的代码全是幻觉返工消耗的 token 反而更多。这篇文章适合所有在使用 Claude Code 或其他 AI 编程工具的开发者不管你是刚安装好还在摸索阶段还是已经用了一段时间但总觉得额度不够用。我会从上下文窗口的管理、prompt cache 的利用、Subagent 的拆分策略、以及日常操作习惯四个维度把 token 消耗这件事拆开讲透。2. 上下文窗口管理别让垃圾信息占着位置2.1 上下文窗口到底是怎么被填满的Claude Code 的上下文窗口是有限的目前主流模型大概在 20 万 token 左右。听起来很多但实际用起来消耗速度远超想象。我做过一个粗略统计在一个中等规模的 TypeScript 项目里如果让 Claude Code 完整读取src目录下的所有文件光是文件内容就能吃掉 3 到 5 万 token。再加上package.json、tsconfig.json、.eslintrc这些配置文件以及之前的对话历史一轮下来轻松突破 8 万 token。更隐蔽的消耗来自工具调用。每次 Claude Code 执行一个 bash 命令命令的输出会完整进入上下文。你跑一次npm install输出可能有几百行跑一次测试失败日志可能上千行。这些内容一旦进入上下文后续每一轮对话都会重新计算。我遇到过最夸张的情况是一个同事让 Claude Code 跑了一次完整的构建构建日志有 2000 多行直接导致上下文爆满后续对话全部失败。还有一个容易被忽略的点Claude Code 在启动时会自动读取项目根目录下的CLAUDE.md文件如果存在以及一些默认的配置文件。这些内容也会占用上下文。如果你在CLAUDE.md里写了几千字的项目说明那每次启动都会消耗这部分 token。2.2 精准投喂只给模型看它需要的东西我的核心原则是永远不要让模型主动去“探索”你的项目。很多人习惯性地说“帮我看看这个项目有什么问题”然后 Claude Code 就开始遍历目录、读取文件、分析结构。这个过程消耗的 token 可能比你真正要解决的问题本身多十倍。正确的做法是你作为开发者先定位到具体问题然后只把相关的文件路径告诉模型。比如你要修一个登录模块的 bug不要说“帮我看看登录为什么有问题”而是说“检查src/auth/login.ts和src/auth/session.ts登录时 session 没有正确写入”。这样模型只需要读两个文件而不是整个src目录。我自己的习惯是在让 Claude Code 处理任务之前先在脑子里过一遍这个任务最少需要哪些文件然后把文件路径明确列出来。如果任务涉及的文件超过五个我会考虑拆分成多个小任务而不是一次性全部丢进去。还有一个技巧是使用符号引用文件。Claude Code 支持在对话中用filename的方式指定文件这样模型只会读取你指定的文件不会自作主张去扩展。比如src/utils/date.ts 这个文件里的 formatDate 函数在处理时区时有问题帮我修复这比“帮我看看日期格式化哪里有问题”要高效得多。2.3 及时清理别让历史对话拖后腿Claude Code 的对话历史是累积的。你聊了十轮之后第一轮的内容还在上下文里占着位置。如果前面的对话已经解决了问题后面的对话跟前面无关那前面的内容就是纯粹的浪费。我的做法是每完成一个独立任务就开新对话。不要在一个对话里连续处理多个不相关的问题。比如你先修了一个 bug然后又想加一个新功能这两个任务之间没有依赖关系就应该分开。开新对话的成本几乎为零但节省的 token 可能非常可观。Claude Code 本身也提供了一些清理上下文的命令。比如/clear可以清空当前对话历史/compact可以压缩历史记录保留摘要丢弃细节。我通常在完成一个阶段性任务后如果还需要继续在同一个对话里工作会先用/compact压缩一下把之前的详细内容变成简短摘要释放出大量空间。但要注意/compact不是万能的。它压缩后的摘要可能丢失一些关键细节如果后续任务需要引用之前的细节压缩后模型可能就“记不清”了。所以我的建议是如果后续任务跟前面强相关就不要压缩如果只是弱相关压缩是划算的。2.4 控制工具输出别让日志淹没上下文前面提到过bash 命令的输出会完整进入上下文。这是 token 消耗的大头也是最容易控制的。我的经验是永远不要让 Claude Code 执行会产生大量输出的命令。比如跑测试的时候不要直接npm test而是加上过滤条件只输出失败的用例npm test -- --reporterdot 21 | tail -50这样即使有几百个测试进入上下文的也只有最后 50 行。再比如查看 git 日志不要git log直接输出全部而是git log --oneline -10只看最近十条。还有一个更激进的做法如果某个命令的输出你确定不需要让模型看到可以重定向到文件然后只告诉模型“命令执行成功”或“命令执行失败错误码是 X”。比如npm run build /tmp/build.log 21 echo BUILD_OK || echo BUILD_FAILED这样进入上下文的只有一行BUILD_OK或BUILD_FAILED而不是几百行构建日志。如果构建失败需要排查再单独让模型读取日志文件的相关部分。注意控制工具输出的时候要确保你保留了足够的信息来判断命令是否成功。如果只输出BUILD_FAILED而不给任何错误信息模型也没法帮你排查问题。我的做法是失败时输出最后 20 行日志成功时只输出一行状态。3. Prompt Cache被大多数人忽略的省钱利器3.1 Prompt Cache 的工作原理Prompt cache 是 Anthropic API 提供的一个特性Claude Code 在底层会自动使用它。简单来说如果你连续多次请求中前面的内容是完全相同的那么这部分内容会被缓存后续请求只需要为缓存部分支付很低的费用通常是正常价格的 10%甚至在某些情况下完全免费。这个机制对 Claude Code 特别有用因为 Claude Code 每次请求都会带上系统提示词、工具定义、项目配置等固定内容。这些内容在同一个会话中是不变的所以可以被缓存。如果没有 prompt cache每次请求都要为这些固定内容全额付费消耗会非常夸张。但 prompt cache 有一个关键限制缓存有有效期通常是 5 分钟。如果两次请求之间间隔超过 5 分钟缓存就失效了下次请求又要重新计算。这意味着如果你在 Claude Code 里问一个问题然后去喝了杯咖啡回来再问下一个问题缓存可能已经过期了两次请求都要全额计费。3.2 怎么利用 Prompt Cache 省 token基于这个机制我的策略是集中时间处理任务避免碎片化使用。如果你今天有几个任务要处理尽量连续做完不要做一会儿停一会儿。这样缓存一直有效后续请求的成本会大幅降低。具体来说我会把需要 Claude Code 处理的任务攒在一起比如上午集中处理代码审查和 bug 修复下午集中处理新功能开发。在每个时间段内保持对话的连续性不要频繁开关。另一个技巧是在同一个会话中尽量保持前缀内容不变。Claude Code 的请求结构是系统提示词 工具定义 对话历史 当前问题。系统提示词和工具定义是固定的对话历史是累积的。如果你在对话中间修改了CLAUDE.md或者切换了工作目录前缀内容就变了缓存失效。所以我在一个会话中不会去改配置文件也不会频繁切换目录。还有一点Claude Code 在启动时会读取CLAUDE.md。如果你把这个文件写得很长虽然它会被缓存但第一次请求还是要全额计算。而且如果缓存过期了下次又要重新计算。所以CLAUDE.md的内容要精炼只写真正必要的项目说明不要把它当成文档仓库。3.3 实测数据缓存到底能省多少我做过一个对比测试。同一个任务修复一个 TypeScript 类型错误分两种方式执行第一种方式一次性完成。启动 Claude Code读取相关文件定位问题修改代码验证。整个过程大约消耗 12000 token其中缓存部分占 8000 token实际计费按 8000×0.1 4000 4800 token 计算。第二种方式分三次完成。第一次启动读取文件消耗 5000 token间隔 10 分钟后第二次启动定位问题消耗 6000 token再间隔 10 分钟后第三次启动修改代码消耗 4000 token。由于每次间隔都超过 5 分钟缓存全部失效三次都是全额计费总共消耗 15000 token。差距是 3 倍多。这还只是一个小任务如果任务更复杂涉及更多文件读取和工具调用差距会更大。提示如果你用的是按量计费的 APIprompt cache 的节省会直接体现在账单上。如果你用的是订阅制比如 Claude Pro虽然不直接按 token 计费但额度消耗速度会明显不同。订阅制通常有每 5 小时或每天的额度限制省 token 意味着你能在同样的额度内做更多事。4. Subagent 拆分让每个 token 都花在专业的事上4.1 什么是 Subagent为什么要用它Subagent 是 Claude Code 的一个高级特性允许你把一个复杂任务拆分成多个子任务每个子任务由一个独立的 agent 处理。每个 subagent 有自己的上下文窗口不会互相干扰。这个机制对 token 优化的意义在于每个 subagent 只需要加载跟自己相关的上下文。比如你有一个任务需要同时修改前端和后端代码如果用一个 agent 处理它需要同时加载前端和后端的文件上下文里混杂着两种技术栈的内容。但如果拆成两个 subagent前端 agent 只加载前端文件后端 agent 只加载后端文件各自的上下文都更干净token 利用效率更高。更重要的是subagent 之间可以并行执行。Claude Code 支持同时启动多个 subagent它们各自独立工作最后汇总结果。这不仅节省时间也节省 token因为每个 subagent 不需要等待其他 subagent 完成也不需要把其他 subagent 的中间过程加载到自己的上下文里。4.2 怎么拆分任务才合理拆分任务的核心原则是按关注点拆分而不是按文件数量拆分。我见过有人把任务拆成“读取文件 A”“读取文件 B”“修改文件 C”这种粒度这完全是错误的。每个 subagent 启动都有固定开销系统提示词、工具定义等拆得太细反而浪费。合理的拆分方式是按照功能模块或技术层次来分。比如一个 subagent 负责数据库 schema 变更和 migration 脚本一个 subagent 负责后端 API 接口的实现一个 subagent 负责前端组件的修改一个 subagent 负责测试用例的编写每个 subagent 的上下文里只有自己相关的文件和技术栈互不干扰。而且这些任务之间如果有依赖关系可以通过文件系统来传递结果而不是通过上下文传递。我自己的经验是一个 subagent 处理的任务最好控制在 3 到 5 个文件以内。如果超过这个数量要么是任务拆分不够细要么是这个任务本身太复杂需要进一步分解。4.3 Subagent 的上下文隔离优势Subagent 最大的优势是上下文隔离。举个例子你让一个 agent 去排查一个内存泄漏问题它可能需要跑很多诊断命令输出大量日志。这些日志如果进入主对话的上下文会严重挤占空间。但如果放在 subagent 里这些日志只在 subagent 的上下文里存在主对话不受影响。Claude Code 在实现 subagent 时会给每个 subagent 分配独立的上下文窗口。subagent 完成任务后只把最终结果返回给主对话中间过程全部丢弃。这就像你派了一个助手去调查一件事助手回来只给你一份总结报告而不是把调查过程中的所有笔记都堆在你桌上。我通常会在以下场景使用 subagent需要大量试错的任务比如调试一个难以复现的 bug需要读取大量文件但只需要少量输出的任务比如代码审查可以并行执行的独立任务比如同时修改多个不相关的模块注意Subagent 虽然好但也不是越多越好。每个 subagent 启动都需要时间而且如果任务之间有强依赖关系拆成 subagent 反而会增加协调成本。我的经验是只有当任务确实可以独立执行或者中间过程会产生大量噪音时才值得拆成 subagent。5. 日常操作习惯那些不起眼但影响巨大的细节5.1 提问方式决定 token 消耗同样一个问题不同的问法会导致完全不同的 token 消耗。我总结了几条原则第一给上下文但只给必要的上下文。不要说“我的代码有问题”而要说“src/api/user.ts第 45 行的fetchUser函数在用户不存在时返回了 undefined应该返回 null”。前者会让模型去猜、去搜索、去读取大量文件后者模型直接定位到具体位置只需要读一个文件。第二明确输出格式。如果你只需要模型改代码就说“只输出修改后的代码不要解释”。如果你需要解释就说“用三句话解释修改原因”。不指定输出格式模型可能会生成一大段分析这些分析也会消耗 token。第三避免开放式问题。“这个项目有什么可以优化的地方”这种问题模型可能会列出几十条建议每一条都需要读取相关文件来验证。不如直接说“src/utils/目录下的工具函数有没有重复实现的如果有合并它们”。5.2 文件读取的策略Claude Code 读取文件时默认会读取整个文件。如果文件很大比如一个 2000 行的组件文件读取一次就消耗大量 token。我的做法是尽量让模型读取文件的特定部分。Claude Code 支持指定行号范围。比如读取 src/components/Dashboard.tsx 的第 100 到 200 行这样只读取 100 行而不是整个 2000 行。当然这需要你对代码结构比较熟悉知道问题大概在哪个位置。如果你不确定可以先让模型读取文件的前 50 行通常是 import 和类型定义了解文件结构后再定位到具体部分。另一个技巧是使用grep或rg来定位关键代码而不是让模型通读文件。比如rg function handleSubmit src/ -n这样只输出匹配的行号和行内容token 消耗极小。模型根据这些信息就能定位到具体文件的具体行然后再读取那附近的内容。5.3 模型选择与 token 消耗的关系Claude Code 支持切换不同的模型。不同模型的 token 计费标准不同能力也不同。我的策略是按任务难度选择模型。对于简单的任务比如格式化代码、重命名变量、写简单的单元测试用轻量级模型就够了。这些任务不需要复杂的推理能力用大模型是浪费。对于复杂的任务比如架构设计、疑难 bug 排查、性能优化才需要用大模型。Claude Code 允许在对话中切换模型。我通常会在开始一个任务前评估一下难度然后选择合适的模型。如果任务执行到一半发现模型能力不够再切换到更强的模型。这样比一开始就用最强模型要节省很多。5.4 定期审查 token 消耗Claude Code 提供了查看 token 使用情况的命令。我建议养成定期查看的习惯了解自己的 token 都花在哪里了。是文件读取占大头还是工具输出占大头还是对话历史占大头找到最大的消耗源然后针对性地优化。我自己的统计是在优化之前我的 token 消耗分布大概是文件读取 40%工具输出 30%对话历史 20%其他 10%。优化之后文件读取降到 25%工具输出降到 15%对话历史降到 10%整体消耗下降了近一半。6. 常见问题与排查技巧实录6.1 Token 消耗异常快的排查思路如果你发现 token 消耗速度远超预期可以按照以下顺序排查排查项检查方法常见问题文件读取范围查看对话中读取了哪些文件模型自动遍历了整个目录工具输出查看 bash 命令的输出行数构建/测试日志未过滤对话历史查看当前对话轮数在一个对话里处理了多个不相关任务缓存命中查看请求间隔时间频繁间隔超过 5 分钟模型选择查看当前使用的模型简单任务用了大模型我遇到最多的情况是第一条和第二条。很多人没有意识到Claude Code 在收到模糊指令时会主动去“探索”项目这个探索过程消耗的 token 可能比实际任务还多。6.2 上下文爆满后的恢复方法如果上下文已经爆满Claude Code 会提示上下文不足。这时候有几个选择第一用/compact压缩历史。这会把之前的详细对话压缩成摘要释放大量空间。但要注意压缩后一些细节会丢失如果后续任务需要这些细节可能会出问题。第二开新对话。如果当前任务已经完成直接开新对话是最干净的方案。新对话的上下文是空的所有空间都可用。第三手动清理。Claude Code 允许你删除对话中的特定消息。如果你知道哪部分内容占用了大量空间且不再需要可以手动删除。我的建议是预防胜于治疗。与其等上下文爆满后再想办法恢复不如从一开始就控制上下文的使用。每完成一个阶段性任务就检查一下上下文占用如果超过 70%就考虑压缩或开新对话。6.3 那些我踩过的坑坑一让 Claude Code 自动修复 lint 错误。我曾经让 Claude Code 跑eslint --fix结果它读取了整个项目的所有文件消耗了大量 token。后来我改成只对修改过的文件跑 lint消耗降低了 80%。坑二在对话中粘贴大段代码。有时候为了说明问题我会把一段代码直接粘贴到对话里。但如果这段代码有几百行消耗的 token 非常可观。更好的做法是把代码保存到文件然后让模型读取文件。坑三忽略CLAUDE.md的体积。我一开始在CLAUDE.md里写了详细的项目说明后来发现每次启动都要消耗这部分 token。精简之后只保留最必要的构建命令和代码规范启动消耗降低了 60%。坑四在高峰期使用。虽然这不直接影响 token 消耗但高峰期 API 响应慢对话间隔容易超过 5 分钟导致缓存失效。我后来尽量避开高峰期使用缓存命中率明显提升。6.4 一个完整的优化案例最后分享一个我实际优化过的案例。有一个任务是在一个 React 项目中添加一个新的页面涉及路由配置、页面组件、API 调用、状态管理四个部分。优化前一个对话搞定让 Claude Code 自动探索项目结构读取了 30 多个文件跑了 5 次构建消耗约 45000 token。优化后拆成四个 subagent。第一个 subagent 只处理路由配置读取src/router/index.ts和src/router/routes.ts两个文件。第二个 subagent 只处理页面组件读取src/pages/下的相关模板文件。第三个 subagent 只处理 API 调用读取src/api/下的相关文件。第四个 subagent 只处理状态管理读取src/store/下的相关文件。每个 subagent 的上下文都控制在 5000 token 以内总共消耗约 18000 token。而且优化后的方案还有一个额外好处四个 subagent 可以并行执行总耗时从原来的 15 分钟缩短到 5 分钟。这个案例让我深刻体会到token 优化不是抠门而是让工作流更高效。你省下来的 token 可以用于更有价值的任务你节省的时间可以用于更有创造性的工作。AI 工具的价值在于放大你的能力而不是让你把时间花在等待和调试上。我个人在实际操作中的体会是token 管理本质上是一种资源管理思维。就像你管理内存、管理带宽、管理团队时间一样你需要知道资源花在哪里了哪些是必要的哪些是浪费的。一旦你建立了这种意识优化就会变成一种习惯而不是额外的负担。