news 2026/9/12 12:23:33

Codex Token统计Skill实战:一句话打开每日用量看板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Codex Token统计Skill实战:一句话打开每日用量看板

我用 Codex 快一年了,重度使用的情况下,每个月花在 Token 上的钱不比一杯咖啡便宜。真正让人焦虑的不是花多少,而是你根本不知道它怎么花掉的——每次对话结束,Codex 只会告诉你这轮用了多少 token,但你要看今天、这个月、哪个项目烧得最狠,基本靠猜。后来我写了一个 Skill,让 Codex 用一句话就能打开每日用量看板,彻底解决了这个黑箱问题。

这篇文章把整个升级过程拆开讲清楚:从为什么用 Skill 而不是外部脚本,到 SKILL.md 怎么设计、统计脚本怎么写、部署时踩了哪些坑,全部记录下来。适合两类人看:一类是天天用 Codex 写代码但没仔细算过成本的人,另一类是打算给 Codex 集成自定义 Skill、想找个完整案例参考的开发者。

1. 为什么你急需一个 Token 统计 Skill

1.1 用量焦虑:看不见的 token 在烧钱

大多数人用 Codex 的方式是“有问题就问”,一条任务可能来回跑几十轮,每轮都会把上下文重新拼进模型里。你以为自己只写了一百行代码,实际上模型把整个项目的目录结构、过往对话、工具输出全部读了一遍——这些都要算 token。Codex 的计费逻辑是按“输入 + 输出”总量走的,上下文越长,单轮成本越高。

更麻烦的是,Codex 的会话记录分散在本地目录里,官方界面只管展示“本次会话用了多少 token”,没有给你一个“今天总共花了多少”的汇总视角。你一个月结束看到账单才发现:咦,怎么超了这么多?那时候已经来不及省了。

我个人的经验是:用量统计必须每天都看,就像记账一样,一旦变成月末回头看,就等着被数字吓一跳。

1.2 为什么选择 Skill 而不是外部脚本

有人可能会说,想统计 token,写个 Python 脚本不就行了?为什么非要绕一圈做成 Skill?

区别在于使用场景。外部脚本你得在终端里手动跑到文件夹、找到正确的文件、执行命令,然后盯着输出看。对技术人来说,这一套不算难,但问题是——你总是会忘记跑。人会偷懒,这是常态。

做成 Skill 之后就不一样了。Skill 的本质是给 Codex 注入一套“行为预设”,让它在特定触发条件下自动执行一组操作。你不需要记住脚本路径,不需要翻历史命令,只要在对话里说一句“打开每日用量看板”,剩下的全部交给 Codex。

还有一个更重要的点:直接让 Codex 读取本地文件、计算数据,往往会出现格式不稳定的问题。用 Skill 把统计逻辑固化下来,每次得到的结果都是同一套口径,不会这次按 session 算、下次按 usage 字段算。对于做记录、做对比来说,口径一致比什么都重要。

1.3 升级前的老方案痛点

我在做这个 Skill 之前,用的是最原始的方式:手动打开 Codex 的会话目录,用jqawk现场拼命令,把 JSONL 里的 usage 字段捞出来求和。

这套做法有几个明显的问题。首先是麻烦,每次都要回忆一遍 JSONL 的结构,时间一长根本不记得哪个字段代表输入 token、哪个代表输出 token。其次是容易出错,Codex 的会话文件偶尔会写入不完整的 JSON 行,jq一碰到解析失败就整个挂掉,你还得单独处理容错。

最关键的是,手动命令只能告诉你“总数”,给不了“每天的趋势”。而用量管理最需要的就是趋势:周一为什么爆了?是不是那天跑了几个超大任务?这些信息一旦变成历史,再去查就很费劲。

所以升级的方向很清楚:把统计逻辑固化成 Skill,用自然语言触发,输出结构化的每日用量看板。

2. 升级设计:一句话触发的用量看板

2.1 核心思路与交互设计

整个 Skill 的设计目标,我定成了三条硬性要求:

  • 只用一句话触发,不需要额外参数
  • 统计结果必须按“日期”分组,而不是按会话
  • 输出必须直接可读,不能再套一层工具去解析

交互上,我参考了 Claude Code 的 Skill 机制——一个 Skill 对应一个文件夹,里面必须有SKILL.md作为说明书,其他辅助脚本放在同目录下。Codex 读到这里有 Skill 定义,会把这套能力注册进上下文,用户只要提到“用量”“token 统计”这类关键词,就会自动触发。

为什么强调“一句话”?因为使用频率越高的操作,进入门槛越低越好。如果每次都要给 Codex 解释“你去看哪个文件、用什么脚本、输出什么格式”,那和手动敲命令没有区别,Skill 就失去了意义。

2.2 数据从哪里来:本地会话记录解析

Codex 在本地会保存每一条会话记录,通常是 JSONL 格式,一行一条消息事件,里面包含多个字段,其中就有usage对象,记录着input_tokensoutput_tokens之类的数据。

这里有个容易混淆的点:不是所有行都有usage。大部分用户消息、工具调用消息都不带用量信息,只有模型响应那一条才携带。所以统计脚本不是把每一行都拿过来累加,而是要识别出“这一行是模型完成响应,并且带 usage 字段”,再把它取出来。

不同操作系统的会话目录路径不一样,这是部署时最容易踩的坑。我把路径探测逻辑直接写在脚本里,优先读取系统环境变量,找不到就按常见默认路径去匹配,这样换了电脑也能直接跑。

2.3 看板展示什么:从总量到每日趋势

我设计的看板分三块内容:

区块展示内容解决的痛点
总览总 token 数、总会话数、估算金额快速判断今天是不是“超标”了
按日分组每日 token 消耗柱状图(终端渲染)看趋势,找出峰值日期
按项目/角色分组不同角色消耗排序判断是编码任务多还是聊天任务多

其中最实用的就是“按日分组”。Codex 的会话文件命名通常带有时间戳,可以直接从文件名或文件内首条消息的时间提取日期。按天聚合后,再用简单的print拼字符画柱状图——不需要引入任何第三方图形库,终端里完全够用。

3. 核心实现:SKILL.md 与统计脚本拆解

3.1 Skill 的文件结构与触发词定义

一个完整的 Skill 目录长这样:

~/.codex/skills/token-stats/ ├── SKILL.md ├── token_stats.py └── requirements.txt

SKILL.md是这个 Skill 的入口。Codex 通过它识别你安装了什么能力,里面要写清楚:这个 Skill 是干什么的、什么时候触发、怎么用。建议加上若干触发词,让模型更容易命中。

下面是我整理过的SKILL.md内容,省略了部分注释,核心结构如下:

--- name: token-stats description: 统计 Codex Token 用量,按天汇总输出看板 triggers: - 用量 - token 统计 - token 用量 - 每日用量 - usage --- # Token 统计 Skill 当用户请求查看 Codex Token 用量或每日用量看板时,执行本 Skill。 步骤: 1. 定位 Codex 会话记录目录 2. 运行 token_stats.py 3. 将脚本输出的表格直接展示给用户

注意里面我特意写了“将脚本输出的表格直接展示给用户”——这是对模型行为的约束。没有这一句,模型很可能自己编一个表格出来,而不是老老实实跑脚本。

3.2 Token 统计字段与计算逻辑

统计脚本是整个 Skill 的核心。下面这个是我的实际实现(略作精简),它做的事情是:遍历会话目录下所有 JSONL 文件,提取带usage字段的消息,按天聚合 token 消耗。

#!/usr/bin/env python3 import json import os from pathlib import Path from collections import defaultdict from datetime import datetime # 可以自定义路径,默认按常见位置查找 HOME = Path.home() CANDIDATE_DIRS = [ Path(os.environ.get("CODEX_SESSIONS_DIR", "")), HOME / ".codex" / "sessions", HOME / ".codex" / "log", ] def find_sessions_dir(): for d in CANDIDATE_DIRS: if d.exists(): return d raise SystemExit("未找到 Codex 会话目录,请检查路径") def parse_date_from_file(path: Path) -> str: """优先从文件名里提取日期,兜底用文件的修改时间""" try: parts = path.stem.split("_") date_part = parts[0] if parts else "" datetime.strptime(date_part, "%Y-%m-%d") return date_part except (ValueError, IndexError): ts = path.stat().st_mtime return datetime.fromtimestamp(ts).strftime("%Y-%m-%d") def main(): sessions_dir = find_sessions_dir() daily = defaultdict(lambda: {"input": 0, "output": 0, "sessions": 0}) total = {"input": 0, "output": 0, "sessions": 0} for path in sessions_dir.glob("*.jsonl"): date = parse_date_from_file(path) daily[date]["sessions"] += 1 try: with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue try: obj = json.loads(line) except json.JSONDecodeError: continue usage = obj.get("usage") if isinstance(usage, dict): inp = usage.get("input_tokens", usage.get("input", 0)) or 0 out = usage.get("output_tokens", usage.get("output", 0)) or 0 daily[date]["input"] += inp daily[date]["output"] += out total["input"] += inp total["output"] += out except Exception as e: print(f"警告:{path.name} 读取失败 - {e}") print("=" * 48) print(f"Codex Token 用量看板(总计 {len(daily)} 天)") print("=" * 48) print(f"总 Token: {total['input'] + total['output']:,}") print(f"输入 Token: {total['input']:,}") print(f"输出 Token: {total['output']:,}") print(f"会话总数: {total['sessions']}") print("-" * 48) print(f"{'日期':<12}{'输入':>12}{'输出':>12}{'合计':>14}") for d in sorted(daily.keys(), reverse=True): row = daily[d] total_day = row["input"] + row["output"] print(f"{d:<12}{row['input']:>12,}{row['output']:>12,}{total_day:>14,}") if __name__ == "__main__": main()

这段代码有几个值得说的细节。

第一个是容错。JSONL 文件数量多了之后,偶尔会出现某一行写坏的情况,比如断电、进程被杀。如果不做try/except,脚本会挂在第一个坏行上。这里的选择是“能跳就跳,不影响整体统计”。

第二个是字段兼容性。不同版本的 Codex 对 usage 的字段名并不完全一致,有的叫input_tokens,有的叫input,还有的嵌套在别的地方。我同时兼容了两种最常用的写法,遇到都没有的情况就归零,而不是直接报错。

3.3 看板输出与终端渲染

脚本的输出我特意做成了“冷静但清晰”的风格。第一行是汇总,紧接着是每天的明细表格。列宽对齐用的是 Python 的格式化字符串,>12表示右对齐、宽度 12,数字大一些也不会错位。

有人会问,为什么不直接生成 HTML 或者图片?因为 Skill 的定位是“对话内快速查看”,输出到终端已经足够。真想做可视化排名,可以把脚本改成输出 CSV,再接入自己的报表系统。

我建议不要在 Skill 里塞太重的图形依赖。Python 的richplotly是好看,但每次执行都要加载一堆东西,响应速度会变慢,在终端里反而显得累赘。

4. 实操部署:5分钟接入你的 Codex

4.1 手动安装 Skill 到配置目录

部署步骤其实非常简单,核心就是把你的 Skill 文件夹放到 Codex 能找到的位置。

先确认 Codex 配置目录的位置。在终端里执行:

ls ~/.codex

正常情况下你能看到sessionshistory之类的目录。如果没有skills目录,手动创建一个:

mkdir -p ~/.codex/skills/token-stats

然后把SKILL.mdtoken_stats.py放进去。requirements.txt其实可以省略,因为这个统计脚本只用 Python 标准库,没有任何第三方依赖。保留它只是习惯,方便以后扩展。

提示:如果你用的是 Codex 的容器版或远程开发环境,路径会不一样。先echo $CODEX_SESSIONS_DIR看环境变量,有就优先用这个。

安装完成后,重启 Codex 会话。不要指望正在运行的会话立刻感知新的 Skill,一定要新开一个会话再测试。

4.2 第一次触发与实测记录

新开会话后,直接输入:

打开每日用量看板

如果没有反应,试试触发词更明确的说法:

用 token-stats skill 统计一下 token 用量

第一次跑的时候,Codex 可能会先给你一段解释,比如“正在定位会话目录”,然后运行脚本,把表格展示出来。如果一切正常,你会看到类似这样的输出:

================================================ Codex Token 用量看板(总计 7 天) ================================================ 总 Token: 1,234,567 输入 Token: 900,000 输出 Token: 334,567 会话总数: 23 ------------------------------------------------ 日期 输入 输出 合计 2025-06-18 210,000 80,000 290,000 2025-06-17 150,000 55,000 205,000

如果出现了这个界面,说明整个链路已经通了,从触发词命中到脚本执行、到结果回传,全部正常。

如果你说了触发词但 Codex 没有跑脚本,而是自己编了一段话,大概率是SKILL.md的写法不够“坚定”。回到文件里把描述改得更直接:在步骤里明确写“必须执行 token_stats.py”,然后重新测一次。

4.3 升级玩法:定时日报与多项目汇总

跑通基础版之后,可以考虑两个升级方向。

第一个是加定时日报。在 macOS 或 Linux 上用cron每天下午六点跑一次统计,把结果输出到文件或者推送到消息机器人。这个需求可以写成第二个 Skill,也可以直接在cron里调用脚本本身。

第二个是分项目汇总。Codex 会话里大部分情况下是一单一会话,但有时候你会开着同一个会话连续做好几个任务。要区分项目,可以在会话目录下再建子目录,然后把不同项目放到不同路径下,脚本里按二级目录聚合即可。

我实际操作下来,最常用的还是“每日看板”,因为趋势一旦能看见,你就知道该收敛哪些操作了。

5. 常见问题与避坑指南

5.1 token 统计与 credits 换算的坑

做这个 Skill 的过程中,最容易让人困惑的是“token 和 credits 的区别”。

Codex 登录后,界面上显示的是 credits,跑任务时消耗的也是 credits。但底层模型计费的单位是 token。两者之间不是固定比例,而是按模型、按输入输出方向动态换算的。

具体来说,同样一个请求,输入 token 价格便宜,输出 token 价格贵;模型档次越高,单位 token 折算的 credits 也越多。所以你在本地用脚本统计出 100 万 token,不等于你在官网看到的 credits 消耗就是某一个固定值。

这个 Skill 的价值在于“相对趋势”,而不是“绝对账单”。你想知道今天比昨天多用多少,这个统计足够准确;但如果你想和官方案单逐一对账,那还得引入模型单价表,按会话内记录的模型名逐条计价。后者复杂不少,属于更高阶的需求,我目前也没有完全做自动对账。

5.2 登录态失效与 token exchange failed 的处理

我在测试过程中碰到过几次“报告用量时提示 token exchange failed”的情况。这个错误包含的原文比较长,但核心意思就是:登录凭证已失效,无法调用后台接口。

这类问题通常和长期不活跃、网络切换后的会话过期有关。处理方式是我踩过几次坑之后总结的(注意:这一步只是处理登录失效,不涉及任何网络环境调整):

  1. 先退出当前会话:codex logout
  2. 重新登录:codex login
  3. 登录完成后,重开会话,再次触发“打开每日用量看板”

如果你在用旧版本客户端,升级到新版本后再做上述操作,因为旧版本的会话存储格式与新版本不一定兼容,读取会话目录时可能显示不出数据。

5.3 模型兼容性与 Skill 失效排查

另一个容易踩的坑是:Codex 更新版本后,Skill 突然不触发了。

我遇到过 Codex 升级后,旧会话文件里的消息结构变了,usage字段位置也变了,脚本统计结果变成 0。排查思路很简单:随便选一个 JSONL 文件,用编辑器打开,搜索usage,看看它在什么位置、字段名是什么。如果发现字段名不对,改脚本里的兼容分支就行。

涉及模型本身的问题也要注意。某些新模型标识符在旧的 Codex 客户端里不被支持,会出现“model not supported”之类的报错,这时候登录态是正常的,但任务跑不起来。遇到类似问题,最直接的解法是检查版本号、升级到最新版,再重试。

注意:写 Skill 的时候一定不要指定绝对路径,比如/home/yourname/.codex/...,换一台电脑就废了。用~$HOME派生的相对路径才是稳妥做法。

5.4 几个提升体验的小技巧

最后补充几个实战里发现的小技巧。

  • 触发词别太多。三到五个就够了,写太多反而容易误触发,比如你正常聊“这个函数内存占用怎么优化”的时候,不小心命中了“用量”两个字,Skill 就会跑起来。
  • 输出格式要固定。脚本里我建议把日期格式固定成YYYY-MM-DD,不要用“今天”“昨天”这类描述,因为模型回传展示时可能会改写,一改写统计口径就乱了。
  • 定期清空会话目录不是好习惯。很多人为了“节省空间”删掉旧 JSONL,代价就是历史用量统计直接丢数据。编码会话文件通常不大,留着无妨,真正占空间的往往是日志文件。

写在最后

我做这个 Skill 的过程,最大的感触是:工具能不能用好,往往不在于功能多少,而在于你多快能看到反馈。Codex 本身是个黑盒子,你问它问题、它写代码,中间消耗了多少资源,原本很难感知。现在一句话就能看到每日用了多少 token、哪个项目烧得最多、哪天跑量异常,用量管理从“月末惊吓”变成了“日常习惯”。

后面我还打算把这个 Skill 继续往“自动告警”方向扩展,比如单日 token 超过阈值就输出一条提醒,再配合定时任务推送到聊天软件里。如果你也在用 Codex 做深度开发,建议先把这个统计能力搭起来,看完一周的数据,你会对自己每天到底写了多少行代码、烧了多少 token 有一个全新认识。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 12:21:25

如何将 Graphiti MCP 服务器以 stdio 方式接入 Claude Desktop?

如何将 Graphiti MCP 服务器以 stdio 方式接入 Claude Desktop&#xff1f; 【免费下载链接】graphiti Build Real-Time Knowledge Graphs for AI Agents 项目地址: https://gitcode.com/GitHub_Trending/grap/graphiti Claude Desktop 只支持 stdio 传输&#xff0c;而…

作者头像 李华
网站建设 2026/9/12 12:15:03

如何用 Wand-Enhancer 免费解锁 Wand 游戏修改器的高级功能

如何用 Wand-Enhancer 免费解锁 Wand 游戏修改器的高级功能 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer 是开源的本地补丁工具&a…

作者头像 李华