【免费下载链接】tokentab
A CLI that reads Claude Code, Codex, and Gemini CLI session logs and works out how much they cost, by model, project, and day.
tokentab 是一个读取 Claude Code、Codex 与 Gemini CLI 本地会话日志,按模型、项目、天数统计 AI 编码开销的工具。本文拆解它的本地 Web 仪表盘源码:不引入任何 Web 框架、不依赖 CDN,断网也能在浏览器里打开一张漂亮的"AI 用量账单"。
💡 为什么"离线"是最硬的约束
这是一个纯本地工具:数据都在你自己电脑上,仪表盘自然也不能依赖任何网络资源。可很多小工具的仪表盘,一跑起来就"破功"——字体要拉 CDN、JS 要拉框架、页面要npm构建,任何一环都需要联网。
tokentab 的解法是两个很小的文件:
| 文件 | 职责 |
|---|---|
| tokentab/web/server.py | 标准库 HTTP 服务器,只监听 127.0.0.1 |
| tokentab/web/page.py | 一段自包含的 HTML 字符串:样式 + 标记 + 原生 JS |
| tokentab/report/serialize.py | 把报告数据转成 camelCase JSON |
page.py 开头的一句注释就把设计目标说清了:no build, no framework, no network——拔掉网线也能打开。
🌐 服务端:只用标准库,一个 Web 服务器最少要写多少行
整个服务器就是ThreadingHTTPServer+ 一个自定义的BaseHTTPRequestHandler,一行框架代码都没有。do_GET 里的路由只有两条:
GET /→ 返回render_page()生成的整页 HTMLGET /api/report?period=week→ 重新读日志、聚合,返回 JSON
每次请求都重新读盘
server.py 顶部注释解释了取舍:数据很小,没有任何理由去缓存,而缓存恰恰意味着可能给你看一份过期的数字。所以"每次请求都从磁盘重读"在这里是特性,不是缺陷。
4 个值得抄的细节
- 只绑定 localhost:L65 写死
127.0.0.1,账单数据不会离开这台机器。 - 端口被占用自动换:指定的端口拿不到时,用
0让操作系统挑一个空闲端口(L64-L67)。 - 安静且抗错:覆写
log_message关掉请求日志(L26-L27);每个请求包在try/except里,一次坏请求只会得到 500,不会杀死整个服务(L47-L48)。 - 自动开浏览器:启动 0.4 秒后用
threading.Timer打开浏览器,失败也只是静默吞掉——"锦上添花,不是刚需"(L74-L75)。
📄 前端:一整个 HTML 字符串画出来的"账单"
整页就是一个原始字符串PAGE_HTML(page.py L11),CSS、标记、JS 全部内联,零外部资源。"离线"这件事,主要靠它保证:
- 只用系统字体:L28-L30 的注释特意强调——只用系统里现成的衬线/等宽字体栈,不碰字体 CDN。
- 零构建:
render_page()(L374-L375)直接返回字符串,没有 node_modules,没有打包器。 - JS 只干一件事:
fetch("/api/report?period=" + p)然后画图,见 load()。顶部 Today / 7 days / 30 days / Month / All 几个按钮,只是切换请求里的period参数,时间范围由 range_for() 在服务端算好。
视觉上也刻意做成一张纸质账单:米色纸底、点状引导线、带边框的"total spend"总额块、底部一枚斜着的"LOCAL COPY"印章——是文档,不是终端(设计说明见 L6-L8)。
🔗 数据链路:从会话日志到一行 JSON
仪表盘本身不含任何业务逻辑,每次请求都走同一条三步流水线,与 CLI 完全一致:
- 采集:collect_all() 读取各工具的本机日志,摊平成带单价的
PricedRecord列表; - 聚合:build_report() 按工具、模型、项目、活动、天分组;
- 序列化:report_to_dict() 转成 camelCase 字典——
--json输出和/api/report接口共用同一种形状(L1-L5)。
这也是为什么"新增一个工具"只是在 tokentab/providers/ 下加一个模块:定价、分组、仪表盘全都只认那一种共享数据形状。
✅ 动手跑起来:3 步启动本地仪表盘
按 README 的说法:
git clone https://gitcode.com/gh_mirrors/tok/tokentab cd tokentab pip install .然后执行python cli.py -web,终端会打印http://localhost:4747并自动打开浏览器;端口想自定义用--port,不想被抢走浏览器就加--no-open(README L56-L64)。
📦 值得抄走的 3 个实现要点
- 标准库优先:整个项目唯一的第三方依赖是 rich,Web 服务器、JSON、URL 解析全来自标准库——安装零负担。
- 新鲜优于缓存:数据小的时候,"每次请求都重读磁盘"比一套缓存层更诚实。
- 离线保证在前端:零 CDN、零框架文件、系统字体——"断网能打开"的最后一公里,往往不在服务器,而在页面悄悄加载的那些资源。
一句话总结:本地仪表盘不需要重型方案,标准库服务器 + 一个自包含 HTML,就已经把"断网可用"这件事做成了。
【免费下载链接】tokentab
A CLI that reads Claude Code, Codex, and Gemini CLI session logs and works out how much they cost, by model, project, and day.
相关推荐
3个关键问题:你的数据仪表盘为什么总是不够用?
3个关键问题:你的数据仪表盘为什么总是不够用? 你是否经历过这样的困境:每天面对海量数据报表,却依然难以快速洞察业务趋势?花费数小时整理数据,最终发现的关键信息
数据库后端前端低代码AI 应用Gogs push 成功但仪表盘 timeline 不更新怎么排查
Gogs push 成功但仪表盘 timeline 不更新怎么排查 通过 SSH 向 Gogs 推送代码时,客户端显示 push 成功,但登录 Gogs 后首页
后端代码托管Hister vs Meilisearch:一个搜全网一个搜本地,开源搜索双雄怎么选?
Hister vs Meilisearch:一个搜全网一个搜本地,开源搜索双雄怎么选? 过去一年,开源搜索领域出现了两种截然不同的"人气选手":一边是主打"50
后端搜索引擎全文检索
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考