作者解析 Claude Code、Cursor 与 Codex 的不同 JSONL 日志格式,将 token 用量统一为按模型、日期和代理统计的成本报告。工具还设置80%预警和100%超限标记,便于实施预算控制。
AI 编程 Agent 确实令人惊叹——直到你收到费用账单。而且账单会同时来自三个地方:一个目录里的 Claude Code、另一个目录里的 Cursor,以及第三个目录里的 Codex。它们各自使用不同的 JSONL 格式记录用量,字段名和计价模型也各不相同。
所以,我开发了一个小型本地工具,用来读取这三种日志,将其标准化,并生成统一的费用报告——可以按模型、日期和 Agent 查看费用,还提供预算防护机制:达到预算的 80% 时发出警告,达到 100% 时进行标记。下面是实现它的过程。
每个 Agent 记录用量的方式都不一样:
// Claude Code — usage nested under message, with cache fields
{"type":"assistant","message":{"model":"claude-sonnet-4-20250514",
"usage":{"input_tokens":523,"output_tokens":187,"cache_read_input_tokens":1200}},
"timestamp":"2026-08-01T10:00:00.000Z"}
// Codex CLI — usage nested under payload
{"type":"response_item","payload":{"type":"message","model":"gpt-5-codex",
"usage":{"input_tokens":2000,"output_tokens":800}}}
// Cursor — different field names entirely
{"type":"assistant","message":{"model":"gpt-4o",
"usage":{"prompt_tokens":800,"completion_tokens":300}}}
解析器不能预设固定的数据结构。与其分别手写三个解析器,我选择编写一个递归提取器:遍历对象树,找到所有 usage 对象,再通过一系列回退字段提取 token 数据:
function extractUsage(obj, out, parentTs) {
if (!obj || typeof obj !== 'object') return;
if (obj.usage) {
out.push({
model: obj.model || obj.message?.model || '',
inputTokens: obj.usage.input_tokens ?? obj.usage.prompt_tokens ?? 0,
outputTokens: obj.usage.output_tokens ?? obj.usage.completion_tokens ?? 0,
cachedReadTokens: obj.usage.cache_read_input_tokens ?? 0,
ts: parentTs || obj.timestamp || ''
});
return;
}
for (const k of Object.keys(obj)) {
if (['usage','message','payload','request'].includes(k)) {
extractUsage(obj[k], out, obj.timestamp);
}
}
}
这样只用一条代码路径,就能处理全部三种格式,以及未来可能出现的新格式。
真正关键的洞察是:工具要做到实用,并不需要针对每个模型都计算得分毫不差——只要足够准确,能识别失控的费用增长即可。我复用了一份包含 23 家提供商的价格表,涵盖 Anthropic、OpenAI、DeepSeek、Google 等。匹配时先检查完整名称或名称前缀;对于未知模型,则根据提供商名称推测价格:
function estimateCost({ model, inputTokens, outputTokens, cachedReadTokens = 0 }) {
const price = lookupModel(model); // $/1K tokens
const cached = Number(cachedReadTokens) || 0;
// cache reads are ~10x cheaper than fresh input
const cost = (inputTokens * price.input
+ cached * price.input * 0.1
+ outputTokens * price.output) / 1000;
return { cost, estimated: !!price.estimated };
}
未知模型会采用估算费率,并在报告中明确标记,因此不会有任何费用悄无声息地从总额中消失。
真正的杀手级功能不是报告,而是限额。设置每月预算后,工具会告诉你当前的预算使用情况:
≥ 80%——WARN(照这个速度下去,你将会超支)
Guardrail: $0.0698 / $50 (0%) → OK
开发者生活在终端里,但 Agent 活跃在 MCP 生态中。因此,这个工具同时提供两种使用方式:
CLI:agentcost scan ~/.claude/projects 50 → 输出终端报告
MCP server:暴露 scan_cost、get_budget 和 set_budget tools——这样,你的编程 Agent 就能自行回答“我这个月已经花了多少钱?”
字段名漂移才是真正的成本——input_tokens、prompt_tokens 和 inputTokens 表达的是同一类数据。一个递归提取器胜过三个解析器。
缓存计费不容忽视——Claude 的缓存读取成本大约低 10 倍;如果忽略这一点,在长时间会话中就会严重高估费用。
估算胜过沉默——如果未知模型显示为“$0”,用户只会逐渐无视这个工具。更好的做法是给出估算值,并明确标记。
本地优先本身就是一项功能——“任何数据都不会离开你的机器”是用户真正关心的隐私保障,尤其是在处理费用数据时。
该项目目前处于早期发布阶段(v0.1,22/22 项测试全部通过),已在 npm 上发布:agentcost-cli。这是 SellerTools 系列中的第一个开源工具。我希望听到 Claude Code、Cursor 和 Codex 重度用户的反馈:你的工作流还缺少什么?按项目设置预算?团队费用汇总?异常告警?欢迎在评论区告诉我。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。