拆解claude-usage VS Code扩展:Python服务器启动、端口分配与状态保持的完整原理
【免费下载链接】claude-usageA local dashboard for tracking your Claude Code token usage, costs, and session history. Pro and Max subscribers get a progress bar. This gives you the full picture.项目地址: https://gitcode.com/gh_mirrors/cl/claude-usage
claude-usage是一个本地 Claude Code 令牌用量统计仪表盘,它的 VS Code 扩展版把完整的 Python Web 仪表盘一键嵌入编辑器侧边栏:自动定位 Python 解释器与安装位置、启动本地 HTTP 服务器、分配空闲端口,并在 Webview 中展示 token 用量、花费与会话历史——全程数据不出本机,无 API 调用、无遥测。
一键启动:Python 服务器是如何跑起来的
点击活动栏的量表图标后,扩展实际执行了一条四步流水线:定位仪表盘启动方式 → 定位 Python 解释器 → 分配端口 → 派生进程并探测就绪。整条流程集中在 extension.ts 的doStartup()中。
安装模式判定:五级优先级兜底
install-mode.ts 中的resolveInstallMode()负责回答第一个问题——"用什么程序来跑仪表盘",按顺序尝试:
- 你在设置中显式配置的
claudeUsage.cliPath(显式配置永远优先); - 扩展包内自带的
python/cli.py——打包时由 copy-python.js 从仓库根目录复制进去,是市场安装用户最常命中的路径,只需系统装有 Python 即可; - PATH 上的
claude-usage命令(Homebrew 公式安装的用户); - 当前工作区文件夹里的
cli.py(旧版"把克隆仓库作为工作区"的用法); - 扩展目录同级目录的
cli.py(开发者从源码 F5 调试的场景)。
全部落空时才显示友好的错误提示,而不是静默崩溃。找不到 Python 时,提示语还会按平台给出针对性建议——比如提醒 Windows 用户安装时勾选 "Add Python to PATH"。
定位 Python 解释器:不经过 shell 的 PATH 遍历
clone 模式下需要python3 /path/to/cli.py dashboard ...这样的调用,解释器得自己找。python-locator.ts 不启动任何 shell,而是手动遍历PATH环境变量的每个目录,依次尝试python3、python(Windows 上补.exe变体)。这样做既避开了命令注入风险,又让单测可以直接打桩。唯一硬性要求是 Python 3.8+。
进程派生:状态机与"不被骗"的就绪探测
server-manager.ts 用一个清晰的状态机管理 Python 进程的生命周期:
stopped → starting → ready(超时或进程提前退出则转入failed);ready后进程退出转exited;dispose()统一回到stopped。
三个细节值得展开 👇
- 就绪探测严于"返回 200":defaultProbe 只认 200 OK 且响应 JSON 里含有仪表盘
/api/data端点特有键(如all_models),防止被恰好占用同一端口的其他本地服务"骗过"; - 并发调用合并:快速双击图标时,startupInFlight 这个 Promise 会把重复的启动请求合并到同一次,避免双进程互踩、留下孤儿进程;
- 只绑定 127.0.0.1:代码注释写明了原因——历史上暴露过
0.0.0.0配置,但那会把你的用量数据暴露到局域网,属于隐私问题。
服务器 Python 侧的入口是 cli.py,配套 scanner.py 扫描本机 JSONL 会话日志、dashboard.py 渲染页面。扩展派生时附带--no-browser参数,阻止它按 CLI 习惯再弹出一个系统浏览器窗口。
端口分配:从"每次随机"到"稳定复用"
这是整个扩展最微妙的设计点。端口选择看似简单,实则有两个陷阱:写死端口会与其他程序冲突;每次随机取端口虽不冲突,但端口一变,副作用就来了——
仪表盘是以 iframe 嵌入侧边栏的,而 Webview 的 localStorage(折叠卡片状态、更新检查缓存)以 iframe 的源http://127.0.0.1:端口为键。端口一变,本地状态就被无声清空。
port-allocator.ts 用两级策略解决:
- 首选稳定复用:resolveStablePort() 先读 workspaceState 里保存的上次端口(extension.ts 中的
LAST_PORT_KEY),试探绑定确认它仍空闲就直接复用; - 兜底交给操作系统:没有缓存或缓存被占用时,pickFreePort() 用标准手法——把临时服务器绑定到端口 0,让 OS 现场分配一个空闲端口后读出。
配置里手动钉住的端口会被原样尊重;normalizeConfiguredPort()还会把越界值(如 80、65536)宽容地视为"自动分配"而非报错。对应的 port-allocator.test.ts 覆盖了四条路径:钉住的端口原样返回、空闲的缓存端口被复用、缓存端口被占用时换新端口、无缓存时全新分配。
状态保持:状态机、Webview 与 localStorage 的三层配合
"状态保持"在这里横跨三个层面,各由不同机制负责:
| 层面 | 机制 | 位置 |
|---|---|---|
| 进程状态 | stopped/starting/ready/exited/failed五态状态机,进程退出自动流转 | server-manager.ts |
| 侧边栏 UI 状态 | 就绪后 iframe 指向本地服务器;失败时渲染状态页 + Retry 按钮 | sidebar.ts |
| 浏览器级状态 | 复用端口 → iframe 源稳定 → localStorage 跨窗口重载存活 | extension.ts |
侧边栏本身是一个 Webview,只有两种形态:iframe 指向本地服务器,或状态/错误页。iframe 带沙箱属性,CSP 的frame-src只放行 127.0.0.1 与 localhost,并开了allow-downloads让仪表盘的 CSV 导出能正常下载。
四个内置命令则与状态流转一一对应(声明见 package.json):
- Claude Usage: Open Dashboard:启动或聚焦;服务器已是
ready时直接刷新,不重复派生; - Claude Usage: Restart Server:先等待进行中的启动落定,再杀旧进程重启,避免杀掉半路进程留下孤儿;
- Claude Usage: Rescan Transcripts:重载 iframe 触发增量扫描;
- Claude Usage: Show Logs:打开输出通道,可看到 Python 路径、安装模式、完整派生命令与 stdout/stderr——排障第一入口。
故障兜底:启动失败时会发生什么
失败路径同样被精心设计:
- 进程在就绪前提前退出、或 20 秒内未响应(较默认 10 秒特意放宽——首次启动要建库、回填历史会话主题,冷启动可能偏慢),状态转
failed,进程被dispose()清理; - 侧边栏随即显示错误 +Retry / Show Logs按钮,弹窗也给出同款选项——用户无需去命令面板里翻找;
ServerManager整体回到stopped干净状态,保证任何失败之后都能原样重试。
小结
claude-usage VS Code 扩展把"扩展里托管本地服务器"这件事中最容易翻车的部分做成了三层保险:五级安装模式判定保证找得到程序,"稳定复用 + OS 分配"两级端口策略保住本地状态,五态状态机让进程生命周期随时可控。下次点击量表图标时,这一整套流程会在几秒内静默完成——而你的用量数据,从未离开过这台电脑 🎯
延伸阅读:install-mode.test.ts(安装模式优先级单测)、server-manager.test.ts(用假进程驱动状态机的单元测试)、python-locator.test.ts。
【免费下载链接】claude-usageA local dashboard for tracking your Claude Code token usage, costs, and session history. Pro and Max subscribers get a progress bar. This gives you the full picture.项目地址: https://gitcode.com/gh_mirrors/cl/claude-usage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考