深入解构Claude Code - 第 8 篇 · 数据放哪、钱怎么算

本篇回答四个问题:程序里变化的数据怎么管理?关掉程序对话怎么找回?AI 改坏了文件怎么退回?花了多少钱是怎么记的?


8.1 程序里有两个"记事本":一个给机器看、一个给界面看

一个运行中的助手,内部有大量不断变化的数据:当前工作目录、累计花费、当前模型、聊天消息、你在输入框打了一半的字、界面主题、弹窗状态......这些数据放哪、怎么管,直接决定程序好不好维护。

项目的做法是两个记事本分开,这一点第 2 篇埋过伏笔,这里讲透。

记事本一:全局档案(给整个程序用)

就是第 2 篇讲的"全局小本本"。它记的是低频变化、和界面无关、到处都要用的数据:

  • 工作目录、项目根目录;
  • 累计花费、网络请求总耗时、工具执行总耗时、增删行数;
  • 当前模型、会话编号;
  • 是否交互模式、各种模式开关。

它的特点:变化慢(很多数据一场对话才变几次)、要给核心循环/工具/对接层等各处读取、不涉及界面渲染。读写必须通过专门的函数(不能谁都直接改),而且项目严格控制往里加东西。

记事本二:界面状态(给 React 用)

界面相关的数据放在另一个地方(用 Zustand 这类界面状态库管理,你只需要知道它是"给 React 用的集中状态"):

  • 聊天消息列表(界面要渲染);
  • 输入框当前内容(敲一个字变一次);
  • 是否正在思考(转圈要不要显示);
  • 主题、弹窗、待办面板、权限请求队列;
  • 界面开关(显不显示花费、显不显示提示)。

它的特点:变化极快(输入框一秒变十次)、只有界面关心、驱动着第 6 篇讲的 React 重绘。

为什么必须分开

如果混在一起,会两头受罪:

  • 界面卡顿:React 是"数据一变就重绘相关部分"。如果把"输入框内容"和"累计花费"放一起,你每敲一个字,订阅了"累计花费"的组件也可能被牵连重算;
  • 全局污染:界面状态变化极频繁且随意(输入框草稿这种东西毫无重要性),如果和"当前模型""累计花费"这种关键数据混在一个全局对象里,关键数据会被高频、无序的界面更新淹没,出问题极难追查。

打个比方:记事本一像公司档案室 (人事档案、财务总账,一天不变一次,谁都能查但只有专人能改);记事本二像员工桌面上的便利贴和白板(今天的草稿、便签,随便涂随便擦)。你不会把财务总账写在可擦白板上,也不会把电话留言登记进人事档案。

两者怎么联动

数据流动是单向的:核心循环干活时产生的结果(新消息、花费增长),由调度员写进全局档案,同时通知界面状态更新("有新消息了"),React 收到后重绘。反过来,界面不会直接改全局档案------用户的操作(切换模型、发消息)走的是"调用调度员的功能"这条路,由调度员统一改档案。这样"数据从哪改的"永远只有一个方向,不会两个记事本互相打架。


8.2 关掉程序再打开,上次的对话怎么找回来

第 3 篇讲过聊天记录逐条落盘,这一章讲清楚这套机制。

每一场对话都是一个"会话档案"

你启动一次助手、聊一段内容,这叫一个会话(session)。每个会话在磁盘上对应一个文件,里面按时间顺序记录每一条消息(用户说的、助手说的、工具调用和结果、系统通知),每行一条,格式是结构化的(JSON,一种"标签: 值"的通用数据格式)。

这种"一行一条记录、不断往后追加"的文件格式有个专门的叫法(JSONL,JSON Lines)。好处是:

  • 追加写入:新消息往文件末尾加一行就行,不用重写整个文件,快且不容易坏;
  • 天然有序:行的顺序就是时间顺序;
  • 崩了损失小:即使程序中途崩溃,已经写入的行都还在,最多丢最后没写完的一点点;
  • 好读好查:想找某条消息,按行扫描即可。

消息里存的不只是文字

为了能完整恢复,每条消息存的信息很全:消息类型、内容(包括图片引用、文件路径)、工具调用的名字和参数、工具结果、当时的模型、时间戳、这条消息在界面上怎么显示的信息等。目标是:把这个文件读回来,就能把当时的对话现场一模一样地重建出来

恢复会话

启动时你可以选择"继续上次的对话"或从历史列表里挑一个。程序读出对应文件,把消息逐行还原成内部的聊天记录,界面重新渲染出当时的内容,就能接着聊。

会话分叉

还有个进阶能力:你可以在历史对话的某一条消息处"岔开"------回到那个时间点,然后朝另一个方向重新聊(类似代码里的分支概念)。因为每条消息都有完整记录,程序可以从任意一条消息处截断、开新会话,老会话不受影响。

和记忆的区别

注意区分:会话档案是"这场对话完整发生了什么 "(流水账,全量、详细);第 5 篇讲的记忆是"跨会话提炼出的长期规矩"(精炼、少量)。一个是完整录像,一个是总结笔记。恢复会话靠录像,长期记住你的偏好靠笔记。


8.3 "后悔药"机制:它改坏了文件怎么退回去

AI 会改文件,改坏了怎么办?项目有一套文件历史机制,让你能"读档"回到改动前。

改文件前先拍快照

关键策略:任何会修改文件的工具,在动手前先给文件拍一张"快照"

  • 快照保存文件在被改之前的完整内容;
  • 快照和会话关联,存在项目的一个隐藏目录里;
  • 每次修改都拍,于是一个文件在一场对话里可能有一串快照(改之前 → 改一次 → 再改一次......)。

这和第 4 篇讲的"只读工具不用拍快照、会写的工具才拍"对应上了------读文件不改变任何东西,没有后悔的必要。

回退(rewind)

当你说"退回到改这个文件之前",程序做两件事:

  1. 文件回退:把文件内容恢复成当时那个快照的样子;
  2. 对话回退:把聊天记录也退回到那个时间点(8.2 的会话档案让这成为可能)。

于是整个现场------文件和对话------一起回到过去,就像游戏读档。你可以退回几步、换个说法重新让它试。

快照成本的控制

每次改文件都存一份完整内容,会不会很占空间?几个缓解措施:

  • 只对"会修改文件"的动作拍,只读操作不拍;
  • 快照可以做去重(内容没变就不重复存);
  • 旧会话的快照可以定期清理。

和 git 的关系

你可能会问:这不就是 git 干的事吗?思路类似(都是"保存历史版本、可回退"),但定位不同:

  • git 是你主动提交的版本管理,粒度粗(一个功能提交一次),而且 AI 改了一半的中间状态通常不会提交;
  • 快照是每次工具修改自动拍的,粒度细,覆盖"AI 正在改、还没改好"的中间状态------正是你最可能想后悔的时刻。

实践中两者配合:git 管正式版本,快照管"AI 动手过程中的反悔"。快照机制也不碰你的 git 历史,它是独立的一层安全网。

工作区(worktree)隔离

更进一步,有些模式下 AI 干活时会用 git 的 worktree 功能开一个"平行工作区":在一个独立的目录副本里改,你的主工作目录完全不受影响,改好了再合并,改砸了直接扔掉副本。这是比"事后回退"更主动的隔离思路。


8.4 花了多少钱、用了多少电量:账是怎么记的

用模型是按用量付费的(按处理的字数计价),所以程序必须精确记账。这一章讲账单怎么算。

用量数据从哪来

模型每次回复,都会在流式事件的末尾(第 3 篇讲的 message_delta 事件)附带这次的用量:

  • 输入了多少字(你发给它的所有内容,包括手册、聊天记录);
  • 输出了多少字(它生成的内容);
  • 缓存命中了多少字(第 5 篇讲的省钱缓存,这部分单价低);
  • 缓存新建了多少字。

程序每收到一次用量就累加起来。

累计记哪些账

记账分几个维度:

  • 按模型分:这次用了哪个模型、各用了多少字------因为不同模型单价不同;
  • 按时段/会话分:这场对话花了多少、今天花了多少、总共花了多少;
  • 换算成钱:用字数 × 对应单价,折算成金额;
  • 时间账:网络请求累计耗时、工具执行累计耗时(不直接花钱,但反映效率);
  • 改动量:加了多少行代码、删了多少行。

这些数据就是存在 8.1 说的"全局档案"里的累计数字。

为什么输入字数是大头

一个反直觉的点:输入比输出贵得多 。因为每次提问都要把系统提示手册(几万字)+ 全部聊天记录重新发一遍。这正是第 5 篇那套机制(提示缓存、上下文压缩、工具结果截断、记忆按需取)的意义所在------它们本质上都是在压低输入字数

  • 缓存让重复的手册部分按低价计费;
  • 压缩把聊天记录变短;
  • 截断防止工具结果把输入撑爆;
  • 记忆按需取而不是全塞。

所以"上下文工程"(第 5 篇)和"省钱"是同一件事的两面。记账数据反过来也能帮你发现问题:如果某次对话输入字数异常高,可能是缓存没命中、或者某个工具返回了过多内容。

钱花哪了能看到

界面上可以随时查看当前会话的花费明细(/cost/usage 这类命令):各模型用了多少字、缓存省了多少、折算多少钱。这让成本对用户透明,也帮助判断"这个任务用更贵的模型值不值"。

未知价格的处理

有些模型(比如用户自己接的小众模型)程序不知道确切单价,这种情况下金额算不准,程序会明确标记"这个模型的花费是估算/未知",而不是给你一个看似精确实则错误的数字------账可以不全,但不能假。


本篇小结

  • 数据分两个记事本:全局档案(低频、关键、全程序用,通过专门函数读写)和界面状态(高频、只给 React 用);数据单向流动,避免互相污染。
  • 每场对话是一个会话档案,消息逐行追加落盘(崩了损失小),读回来能完整重建现场,支持恢复和分叉。
  • 后悔药靠"改文件前自动拍快照 + 对话记录回退",文件和对话一起读档;git 管正式版本,快照管 AI 改动的中间状态;worktree 提供更主动的隔离。
  • 记账靠模型每次回复附带的用量数据逐次累加,按模型/会话统计、折算金额;输入是成本大头,所以第 5 篇的缓存、压缩、截断本质都是省钱;未知单价的模型如实标记为估算。

下一篇讲扩展:斜杠命令、钩子、插件、子助手------怎么给这个助手加新能力。

相关推荐
plainGeekDev2 小时前
Agent 技术调研自动化
agent·ai编程·claude
kyriewen2 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
魔术师Grace2 小时前
模型查资料、会做事、还省成本,分别靠什么?
aigc·agent·ai编程
默_笙4 小时前
🔥 让 AI 帮我写完整个 Next.js 博客:框架就是 AI 的"上下文 buff"
前端·javascript
AI编程实验室4 小时前
Agent Handoff v0.6.0 跨电脑同步:Git、EVENTS.jsonl、CONTEXT.md 使用方法
ai编程
殷紫川4 小时前
Hy4 Preview 与 Hy3:从 295B 到 770B,腾讯混元的架构跃迁与生产力落地
ai编程
ServBay4 小时前
Claude Code 插件别瞎装,这 9 款才是 2026 年的真生产力工具
aigc·ai编程·claude
zhangfeng11334 小时前
CodeBuddy‑CLI:启动自动授权 + 继续上次对话 codebuddy -c --permission-mode acceptEdits
ai编程
plainGeekDev5 小时前
Agent调试、错误处理与成本优化
agent·ai编程·claude