【免费下载链接】codeburn
Free, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn
导读
Kimi Code 是 MoonshotAI(月之暗面)推出的 AI 编码助手,本地运行时会将会话数据写入磁盘。CodeBurn 内置的kimicodeProvider 会主动扫描这些本地运行时存储(eager 加载),解析会话事件流,还原每一次调用的真实模型、四类 token 消耗、工具活动与项目归属,并依据官方定价计算估算成本。本文基于仓库文档 docs/providers/kimicode.md 与核心实现 src/providers/kimicode.ts 展开,读完你将掌握:Kimi Code 的本地数据布局、wire.jsonl 的事件格式、token 字段映射、别名到真实模型的解析链路、去重与缓存指纹机制,以及主代理与子代理的记账边界。
一、Provider 定位:本地文件扫描的 eager 加载器
CodeBurn 是一个免费、本地的 AI 编程 Token 用量与成本追踪工具,覆盖 37 个工具与 Agent。kimicode是 src/providers/index.ts 中coreProviders注册的内置 Provider 之一,其定义位于 src/providers/kimicode.ts,对应的测试套件为 tests/providers/kimicode.test.ts。
与其他 Provider 相比,Kimi Code 有两点关键定位:
- eager 加载:与按需拉取的网络型 Provider(
network?: true,见 src/providers/types.ts)不同,Kimi Code 的数据全部来自本地方言存储(Kimi 桌面端 / IDE 嵌入运行时写入的会话文件),因此每次扫描都会主动遍历磁盘目录,而不是等待某个 API 回调。 - 本地解析、无官方账单:Kimi Code 的会话记录中不包含费用字段(
usage.record只记 token 不记成本),因此 CodeBurn 依据模型定价表自行计算成本,并将每条调用标记为“估算成本”(costIsEstimated: true)。
二、数据来源:扫描哪些目录,如何定位会话
2.1 默认扫描两个运行时存储
kimicodeHomes()(src/providers/kimicode.ts)在未设置环境变量时返回两个默认 home:
~/.kimi-code ~/Library/Application Support/kimi-desktop/daimon-share/daimon/runtime/kimi-code/home第二个路径对应 Kimi 桌面端 / IDE 嵌入运行时,其内部使用与 CLI 相同的 wire 布局。两个 home 都会被扫描,从而保证“嵌入式 Agent”的用量不会在报表中缺失。路径解析后会经过resolve归一化并用Set去重。
2.2 用 KIMI_CODE_HOME 收窄扫描范围
设置环境变量KIMI_CODE_HOME(或在构造 Provider 时传入 home 覆盖参数homeOverride)会收窄扫描范围到该单一 home。这与kimicodeHomes的实现直接对应:
const explicit = override || process.env['KIMI_CODE_HOME'] if (explicit) return [resolve(explicit)]在测试中,这一行为被显式验证:设置KIMI_CODE_HOME后,probeRoots()返回唯一的该路径并标注为Kimi Code home(见 tests/providers/kimicode.test.ts)。该环境变量同时被注册进 Provider 的环境指纹(见下文缓存章节)。
2.3 目录结构与会话门控
在每个 home 内部,扫描器按如下结构逐层遍历(对应discoverSources,src/providers/kimicode.ts):
$HOME/sessions/wd_*/<session-dir>/ ├── state.json └── agents/<agent-id>/wire.jsonl- 第一层
wd_*:工作目录目录。名称形如wd_<project>_<12位十六进制>。 - 第二层会话目录:命名随宿主产品不同而不同——CLI 使用
session_*,桌面端 / IDE 嵌入运行时使用conv-*/ctitle-*。扫描器接受任意目录名,真正的“会话门控”是agents/*/wire.jsonl文件是否存在:只有存在该文件(isFile探测通过)的目录才被识别为会话源(SessionSource)。测试中专门构造了conv-abc123def456与ctitle-019f8f78-db81两种目录名验证嵌入式运行时会话也能被发现和计价(tests/providers/kimicode.test.ts)。 state.json:会话元数据。解析器读取其中的workDir作为项目路径(sourcePath),并用projectFromWorkDir(src/providers/kimicode.ts)推导项目名:优先取workDir的 basename,缺失时回退到解析wd_<name>_<hash>中的项目段。
discoverSources采用“每层扇出 + 并发 map”(mapWithConcurrency配合FS_SCAN_CONCURRENCY)而不是串行嵌套循环——因为一个会话语料可能包含成千上万个state.json读取与wire.jsonlstat,串行会让整个扫描卡在内核 I/O 上;最终结果按路径排序,保证顺序与完成时序无关。
2.4 probeRoots 与 codeburn doctor
probeRoots()返回所有解析后的 Kimi Code home 路径(带Kimi Code home标签)。这意味着即使当前没有任何会话,codeburn doctor也能展示并检查这些被探测路径的存在性(见 src/providers/types.ts 对ProbeRoot的注释)——从而区分“工具未安装”与“覆盖变量配置错误”两种故障场景。
三、存储格式与事件解析:wire.jsonl 的事件流
3.1 每行一个事件
wire.jsonl是每个 Agent 一条的事件流文件,一行一个 JSON 事件。解析器(createParser,src/providers/kimicode.ts)按行读取,逐行JSON.parse,解析失败的行独立跳过,不影响后续有效事件——测试专门用混入{not valid json、null、截断 JSON 的 fixture 验证了这一容错行为(tests/providers/kimicode.test.ts)。
3.2 四类关键事件
解析器关注的事件类型与用途如下:
| 事件类型 | 用途 |
|---|---|
turn.prompt | 取input作为当前用户消息;input可能是字符串或[{type:'text',text}]结构(inputText负责归一化) |
llm.request | 提供真实模型 ID(model)、配置别名(modelAlias)与轮次前缀(turnStep);同时记录时间戳 |
context.append_loop_event | 当event.type === 'tool.call'时,取event.name进入工具分解(tool breakdown) |
usage.record | 提供计费 token(usage对象)与模型别名(model) |
3.3 Token 字段映射表
usage.record.usage中的 token 字段按如下方式映射到 CodeBurn 的调用结构(ParsedProviderCall,见 src/providers/types.ts):
| Kimi Code | CodeBurn |
|---|---|
inputOther | inputTokens(输入) |
output | outputTokens(输出) |
inputCacheRead | cacheReadInputTokens与cachedInputTokens(缓存读取) |
inputCacheCreation | cacheCreationInputTokens(缓存写入) |
此外reasoningTokens、webSearchRequests固定为 0,speed固定为'standard'。所有 token 数值经nonNegativeNumber清洗(负数与 NaN 归 0,且取整),避免脏数据污染聚合总额。
四、模型解析与成本计算:别名到真实模型的链路
4.1 为什么不能直接用 usage.record.model
usage.record.model记录的只是配置别名(alias),而非计费用模型。解析器通过观测到的llm.request事件建立aliasModels映射:每当一个llm.request同时携带model与modelAlias,就把alias -> 真实model写入映射。随后处理usage.record时:
const realModel = aliasModels.get(usageAlias) ?? (currentRequest?.model || 'kimicode-unknown')即:优先用别名反查映射;别名缺失或未知时,回退到最近一次llm.request的真实模型;仍为空则标记为kimicode-unknown。测试中两个不同请求(kimi-k3与glm-5.2)先后使用各自别名,随后的usage.record能精确命中第一条请求的模型kimi-k3(tests/providers/kimicode.test.ts)。
4.2 估算成本与 calculateCost
Kimi Code 自身不记录成本,因此 CodeBurn 用真实模型 ID 在定价表(getModelCosts)中查价并计算:
- 成本计算入口为 src/models.ts 的
calculateCost(model, input, output, cacheCreation, cacheRead, webSearch, speed, oneHourCacheCreation),按输入、输出、缓存写入、缓存读取四类 token 分别乘以对应单价(含 tiered pricing 与 fast 倍率)。 - 每条调用设置
costIsEstimated: true,并在报表中带有-est-cost语义标记。 - 若真实模型没有定价数据,
calculateCost返回 0 并(仅在CODEBURN_VERBOSE=1时)打印no pricing data for model ...提示(见 src/models.ts)。测试断言kimi-k3会通过 kimi-k3 别名定价且costUSD > 0,绝不会是 0(tests/providers/kimicode.test.ts)。
五、工具活动归因:tool.call 如何进入工具分解
5.1 工具名归一化
context.append_loop_event.event为tool.call时,toolDetails取出name,并通过toolNameMap(src/providers/kimicode.ts)归一化为统一名称:
const toolNameMap: Record<string, string> = { Bash: 'Bash', Shell: 'Bash', bash: 'Bash', shell: 'Bash', Read: 'Read', ReadFile: 'Read', read_file: 'Read', Write: 'Write', WriteFile: 'Write', write_file: 'Write', Edit: 'Edit', EditFile: 'Edit', edit_file: 'Edit', Grep: 'Grep', grep: 'Grep', Glob: 'Glob', glob: 'Glob', Agent: 'Agent', Task: 'Agent', }未出现在映射表中的原始名称原样保留(toolNameMap[rawName] ?? rawName)。当工具是 Bash 且args.command存在时,还会调用extractBashCommands提取其中的命令词(测试中断言npm test && git status被提取为['npm', 'git'])。
5.2 工具附加到下一次计费记录
工具的归属规则是:工具挂载到同一 wire 中紧随其后的下一个usage.record,随后被清空,从而保证每个tool.call只贡献一次。若一个轮次发起请求后工具调用失败、没有产生usage.record,那么turn.prompt会重置待处理工具列表,失败的轮次工具不会泄漏到下一轮计费——failed-turn-tools测试专门覆盖了这一场景(tests/providers/kimicode.test.ts)。多工具场景中,Write/Read/Bash/Grep四个工具调用全部附着在下一个计费步骤上(tests/providers/kimicode.test.ts)。
六、去重机制:agent 与行号双重作用域
6.1 去重键结构
每次usage.record生成的去重键为:
kimicode:<session-id>:<agent-id>:<line-number>:<usage-ordinal>其中:
session-id来自session_*目录名(剥去session_前缀,见sessionIdForWire);agent-id来自agents/<agent-id>目录名(sourceId或agentIdForWire);line-number是 wire 文件中的稳定行号;usage-ordinal是同一条 wire 中 usage 记录的序号。
包含 agent ID使得主代理与子代理的事件保持相互独立;稳定的行位置保证同一条 wire 在多次解析间不会被重复计数。测试验证:主代理与子代理在共享seenKeys集合下各计一次、去重键集合大小为 2(tests/providers/kimicode.test.ts)。
6.2 前提与未来风险
该键依赖一个存储不变式:每个 Agent 的usage.record只出现在它自己的wire.jsonl中,而这一点由state.json的agents映射(agent 名 → 描述符)来识别。若未来 Kimi Code 版本将子代理用量镜像写入主 wire,去重键就必须改为内容作用域(content-scoped)——文档明确指出了这一演进约束。
七、会话缓存与指纹:eager 与增量读取
Kimi Code 属于“eager provider,使用共享会话缓存”,其缓存行为体现在 src/session-cache.ts 两处:
- 环境指纹:
PROVIDER_ENV_VARS中注册kimicode: ['KIMI_CODE_HOME'](src/session-cache.ts)。KIMI_CODE_HOME的任何变化都会改变 Provider 的环境指纹(env fingerprint),进而使缓存段整体失效重解析——避免换目录后仍读到旧 home 的用量。 - 解析版本:
PROVIDER_PARSE_VERSIONS中注册kimicode: 'wire-usage-v1-est-cost-session-lineage-capture-v1'(src/session-cache.ts)。该解析版本号与 Kimi Code parser 版本共同参与指纹;版本升级会强制已经缓存的会话重新解析一次,以落地新字段。
文件层面的缓存按每个 Agent 的wire.jsonl分别做指纹(fingerprint):文件未变化时直接命中缓存,不重复解析。
八、Subagent 记账:血缘归因与不重复计数
8.1 子代理用量只存在于自己的 wire
Kimi Code 的子代理 token 用量只记录在子代理自己的wire.jsonl中。当子代理完成时,父代理的 wire 只会收到一条subagent.completed摘要事件(该事件仅具信息性,解析器忽略),而不会收到镜像子代理 token 的usage.record(参见 MoonshotAI/kimi-code 的packages/agent-core/src/session/subagent-host.ts)。因此,对所有 agent wire 的usage.record求和不会出现双重计数。
8.2 state.json 血缘与 CB-1 归因
state.json的agents映射携带parentAgentId字段:main代理为null(自身无父),其他代理记录其父代理名。解析器通过kimicodeLineageForSource(src/providers/kimicode.ts)将这一 Provider 记录的血缘转换为 CodeBurn 的SessionLineage:
- 非
main代理且parentAgentId === 'main'→ 作为该会话根的子代理(role:child); main代理且存在其他以它为父的代理 → 作为会话根(role:root);- 无
agents映射时返回undefined(不生成默认值,避免误导)。
该血缘在解析阶段由 src/parser.ts 接入,供 CB-1(会话血缘)归因使用。
九、边界行为与 Quirks 汇总
结合文档与源码,以下边界行为值得关注:
- 多轮续聊:多轮延续会追加到同一条 wire。
llm.request.turnStep的数字前缀(如0.1、1.1)用于把同一轮内的多个模型步骤归组到正确的轮次(turnIdFromStep取turnStep.split('.')[0])。测试验证多轮会话产出两条调用,turnId分别为0与1,各自关联正确的 prompt 与模型(tests/providers/kimicode.test.ts)。 - 失败重试不产生用量:包含重试
llm.request事件但没有usage.record的失败会话,解析结果为零调用、零用量;attempt重试序号不被解释。对应failed-retry测试(tests/providers/kimicode.test.ts)。 - kimi-cli 的继任者:Kimi Code 是旧版
kimi-cli的继任者,会把自己的前代配置与会话迁移进新存储;本 Provider刻意不解析旧版~/.kimi布局(旧版相关文档见 docs/providers/kimi.md)。 - 时间戳兜底:
usage.record无时间戳时回退到currentRequest时间,再回退到state.json的updatedAt/createdAt;全部缺失时该记录被跳过(不产出调用)。 - 畸形行独立容错:单行 JSON 解析失败不影响其他行。
十、在此修复 Bug 时的开发规范
文档为后续维护者列出了四条纪律,均可在源码与测试中找到对应实现:
- 真实模型归因不可动摇:始终基于
llm.request.model解析真实模型,绝不用usage.record.model的别名上报(对应 4.1 节链路)。 - 主/子代理成对测试:主代理与子代理 wire 必须放入同一个去重集合(shared
seenKeys)一起测试(对应subagent测试)。 - 保留容错覆盖:新增事件变体时,必须保留畸形行与纯重试会话的既有覆盖(对应
malformed-lines与failed-retry测试)。 - fixture 卫生:测试 fixture 保持脱敏,且必须放在临时
KIMI_CODE_HOME内(测试的beforeEach用mkdtemp创建、afterEach删除,见 tests/providers/kimicode.test.ts)。
十一、实操速查
# 安装 CodeBurn npx codeburn # 默认扫描 ~/.kimi-code 与 Kimi 桌面端嵌入 home npx codeburn # 只扫描指定 Kimi Code home(收窄扫描范围) KIMI_CODE_HOME=/path/to/custom/kimi-home npx codeburn # 通过 codeburn doctor 检查探测路径是否存在(即使无会话也能自检) npx codeburn doctor常见的排查路径:
- 报表缺失 Kimi Code 用量:先确认
codeburn doctor中 Kimi Code home 探测路径是否正确,再检查~/.kimi-code/sessions下是否有含agents/*/wire.jsonl的会话目录(conv-*/ctitle-*亦被接受)。 - 成本显示为 0:确认真实模型 ID 是否在定价表中;未知模型在
CODEBURN_VERBOSE=1下会输出no pricing data for model ...提示。 - 更改 KIMI_CODE_HOME 后仍读到旧数据:环境变量已纳入缓存指纹,正常情况下换目录会触发缓存段失效;若怀疑缓存陈旧,可关注解析版本
wire-usage-v1-est-cost-session-lineage-capture-v1的升级路径。
总结
Kimi Code Provider 是 CodeBurn 对“本地优先、无官方账单”类 AI 编码工具的一种完整解法:通过扫描 CLI 与桌面端/IDE 嵌入运行时的双 home 布局,逐行解析wire.jsonl事件流,完成 token 字段映射、别名到真实模型的解析、工具活动归因、成本估算与 agent 级去重,并通过环境变量指纹与解析版本号保证缓存一致。其“子代理用量只存在于自己的 wire”的记账模型,加上state.json提供的血缘信息,使得主代理与子代理的用量可以精确分摊而不重复。对希望理解 CodeBurn Provider 架构、或计划为类似本地运行时接入用量追踪的开发者,src/providers/kimicode.ts 与 tests/providers/kimicode.test.ts 是一份可以直接照抄的最小完整范例。
【免费下载链接】codeburn
Free, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn
相关推荐
CodeBurn 的 Kimi Code 会话解析指南:wire.jsonl 存储格式、Token 计量与去重原理
CodeBurn 的 Kimi Code 会话解析指南:wire.jsonl 存储格式、Token 计量与去重原理 本指南以 CodeBurn 仓库 https
ccusage 的 Kimi 数据源(Experimental):从 wire.jsonl 日志解析 Kimi CLI 用量与成本
ccusage 的 Kimi 数据源(Experimental):从 wire.jsonl 日志解析 Kimi CLI 用量与成本 Kimi 数据源目前处于实验
AI 应用CLI开发工具codeburn 源码级解析:Codebuff(Manicode)CLI Agent 本地会话的用量与成本追踪实现
codeburn 源码级解析:Codebuff(Manicode)CLI Agent 本地会话的用量与成本追踪实现 本篇技术指南围绕 codeburn 开源仓库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考