Claude Code 的工程化落地:省 Token 篇

6 阅读7分钟

用 Claude Code 干活,最直观的成本就是 token。跑一个复杂的代码审查 skill,上下文里塞满了各种规范文件,一轮对话下来几千 token 就没了——其中大半可能根本没用上。

这篇聊的就是一件事:怎么让每个 token 都花在刀刃上。

Token(词元)是 LLM 处理的最小文本单位。不同模型的分词算法不一样,同一段文字切出来的 token 数也不同。你可以把 token 理解成各模型的"内部货币",没有统一汇率,也没有锚定物——只有各家"央行"的定价。

Token 花在哪了?

Token 的消耗主要分散在三个阶段:

  1. 知识库创建 — AI 启动时加载的"底子"
  2. 上下文构建 — 任务执行过程中携带的信息
  3. 执行操作 — 实际的工具调用和推理

搞清楚钱花在哪,才能知道往哪省。

知识库创建:AI 的"开机自检"

这个阶段是 AI 工作的必经之路,每次对话都会发生。三个地方在烧 token:

Skill 扫描 — Claude Code 启动时会扫描所有已安装的 skill,但只读取每个 skill 的 description 字段,相当于只看"目录"不翻书。所以 description 写得精炼很重要,啰嗦的描述会在每一次对话里重复占位。

CLAUDE.md 加载 — 项目的 CLAUDE.md 会被完整加载,它是 AI 理解项目的"参考手册"。写多了浪费,写少了 AI 两眼一抹黑到处乱找文件——这个平衡后面细说。

权限模型 — 给 AI 该有的权限,不给无关的。代码审查的 skill 不需要执行命令的权限,发布流程的 skill 不需要读写文件的权限。权限越少,AI 的决策路径越短,token 消耗越低。

上下文:越精炼越好

人类大脑处理信息块的平均数量是 7 个,超过这个数人就开始犯糊涂。AI 也一样——上下文越长,"注意力"越分散,处理效率越低,消耗的 token 越多。

在执行过程中,AI 需要不断回顾上下文来做决策。如果上下文里塞了一堆跟当前任务无关的信息,AI 就像在一屋子杂物里找钥匙,翻得越多消耗越大。

保持上下文的精炼和相关性,是省 token 最直接的手段。

执行:全量加载 vs 渐进式加载

知识怎么喂给 AI,直接决定了 token 的消耗量。两种策略,各有适用场景。

全量加载

把所有知识、规范、上下文一次性写进 instructions,AI 从第一步就拥有完整信息。

启动 Skill
  → 加载 SKILL.md(含全部知识内容)
  → 所有规范、规则、示例已在上下文中
  → 开始执行任务
  → 每一步都携带全部知识(无论是否用到)
  → 任务完成

简单粗暴,好处是 AI 不需要中途去读文件,执行链路干净。坏处也明显:上下文从一开始就很"重",随着对话轮次增加,那些根本没用上的知识一直在重复消耗 token。

什么时候适合全量加载?

场景原因
知识总量 < 1000 tokens太小不值得拆,拆了反而增加管理成本
每次都要用到全部知识比如 lint 规则,每个文件都要对照全部规则
单轮对话、一次性任务不存在多轮累积的浪费
知识之间高度耦合拆开后缺少上下文,AI 容易判断失误

渐进式加载

只在 instructions 里写"索引"——去哪找、什么时候找。具体知识存放在外部文件,AI 在执行过程中按需读取。 image.png

启动 Skill
  → 加载目录页: SKILL.md(仅含流程 + 知识索引)
  → 开始执行任务,执行章节,激活skill。
  → 读取附录按需加载: 
  → 遇到 TypeScript 文件? → 读取 typescript-rules.md
  → 遇到 CSS 文件? → 读取 style-guide.md
  → 遇到 API 接口? → 读取 api-conventions.md
  → 查看接口返回数据? → 读取 api-response-guidelines.json
  → 没遇到的类型? → 对应知识文件从未加载,0 token 消耗
  → 任务完成

上下文初始很"轻",按需逐步增重。没触发的知识路径完全不消耗 token。代价是每次读文件有少量额外开销,但跟省下的 token 比,九牛一毛。

什么时候适合渐进式加载?

场景原因
知识总量 > 2000 tokens全量加载太重,拆分收益明显
知识可按类型/场景分组按文件类型、按业务模块、按阶段都能拆
多轮对话、复杂任务避免每轮都重复携带不相关的知识
知识模块相互独立审查 CSS 不需要知道 TypeScript 规则

怎么选?

知识总量 < 1k tokens?
  └─ 是 → 全量加载(不值得拆)
  └─ 否 → 每次都用到全部知识?
              └─ 是 → 全量加载(拆了也省不了)
              └─ 否 → 知识能按场景分组?
                          └─ 是 → 渐进式加载
                          └─ 否 → 全量加载(耦合太强拆不动)

不是"能不能拆",而是"拆了能不能少加载"。 拆完每次还是全部加载,那就是白拆。

Token ROI:让每个 token 都有回报

理解了加载策略之后,回到具体实践。三个维度提升知识回报率:

Skill description 要精炼 — 这行字会常驻在每次对话的上下文里。写成"审查代码变更,检查规范和潜在问题"就够了,别写成一段小作文。

CLAUDE.md 要写成架构地图 — 不需要事无巨细,只需要告诉 AI 项目的核心结构和边界。目的是减少 AI 到处 findgrep 找文件的 token 消耗。给一张地图,比让它自己探索便宜得多。

本地知识库用渐进式加载 — 当 skill 需要对接领域知识时,把知识文件放在 skill 自己的目录下,instructions 里只写加载条件。知识文件可以是 .md.json.txt 等任何文本格式。

实战例子:代码审查 Skill

一个审查 skill,知识库按需加载而非全量注入上下文。所有辅助文件都在 skill 自己的目录内,保持模块化和清晰的边界:

# .github/skills/code-review/SKILL.md
name: code-review
description: "审查代码变更,检查规范和潜在问题"  # 精炼!这行会常驻上下文

instructions: |
  ## 审查流程
  1. 读取变更文件列表
  2. 按文件类型加载对应规范(见下方知识库)
  3. 逐文件审查并输出建议

  ## 本地知识库(渐进式加载)
  # ❌ 反模式:把所有规范一次性塞进 instructions
  # ✅ 正确做法:引用外部文件,需要时再读取

  当审查 TypeScript 文件时,读取:
    .github/skills/code-review/knowledge/typescript-rules.md

  当审查 CSS/样式文件时,读取:
    .github/skills/code-review/knowledge/style-guide.md

  当审查 API 接口时,读取:
    .github/skills/code-review/knowledge/api-conventions.md

  当查看接口返回数据时,用返回的 key 查找读取:
    .github/skills/code-review/knowledge/api-response-guidelines.json

  不要提前加载所有知识文件,只在遇到对应文件类型时才读取。

目录结构长这样:

.github/skills/code-review/
├── SKILL.md                          # 入口,常驻上下文(控制在精炼范围)
└── knowledge/                        # 按需加载,不占初始 token
    ├── typescript-rules.md           # ~200 行规范
    ├── style-guide.md                # ~150 行规范
    ├── api-conventions.md            # ~180 行规范
    └── api-response-guidelines.json  # 数据结构规范,key-value 形式

算一笔账:

  • 全量加载:4 个知识文件全部塞进去 ≈ ~4000 tokens 常驻上下文
  • 渐进式加载:每次只加载相关的 1-2 个文件,节省 50%-70% 的知识库 token

一个 skill 省 2000 token 看着不多,但项目里有 5 个 skill、每天跑 20 轮对话,一个月下来就是实打实的成本差距。

省 token 这件事没有什么银弹,就是在每个环节抠细节:description 少写一句废话,知识库多拆一个文件,权限少给一项。积少成多,效果比你想象的明显。