[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80945":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":11,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":14,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":15,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":16,"fork":16,"defaultBranch":17,"hasWiki":18,"hasPages":16,"topics":19,"createdAt":9,"pushedAt":9,"updatedAt":20,"readmeContent":21,"aiSummary":22,"trendingCount":14,"starSnapshotCount":14,"syncStatus":23,"lastSyncTime":24,"discoverSource":25},80945,"cliproxyapi-usage-dashboard","zhanglunet\u002Fcliproxyapi-usage-dashboard","zhanglunet","Local token usage and quota dashboard for CLIProxyAPI",null,"Python",32,9,1,0,40,false,"main",true,[],"2026-06-11 04:07:22","# CLIProxyAPI 用量统计面板\n\n这是一个面向 [CLIProxyAPI](https:\u002F\u002Fgithub.com\u002Frouter-for-me\u002FCLIProxyAPI) 的本地用量统计和可视化面板。\n\n它会持续从 CLIProxyAPI 的 Redis 兼容用量队列中采集每次请求记录，写入本地 SQLite，并通过网页展示：\n\n- 每次任务\u002F请求的 token 消耗\n- 今日总消耗\n- 最近 1 小时、5 小时、24 小时、7 天消耗\n- 按账号统计的请求数、token 消耗和失败数\n- 按模型统计的 token 消耗\n- Codex \u002F ChatGPT 账号的 5 小时与 7 天余量\n\n默认只监听 `127.0.0.1`，适合放在个人电脑或本地开发机上使用。\n\n## 面板预览\n\n![CLIProxyAPI 用量统计面板脱敏预览](docs\u002Fdashboard-preview.svg)\n\n上图是脱敏预览图，使用模拟账号和模拟数值，不包含真实邮箱、真实 token、真实密钥或真实用量数据。\n\n## 设计目标\n\n这个项目解决三个问题：\n\n1. CLIProxyAPI 可以代理多个 Codex \u002F GPT 账号，但日常使用时不容易看清每个账号实际消耗了多少。\n2. ChatGPT \u002F Codex 账号有 5 小时和 7 天窗口限制，需要一个聚合视图快速判断哪个账号还能用。\n3. CLIProxyAPI 的用量队列是短期队列，适合实时消费，不适合长期统计；因此需要落库保存。\n\n本项目的设计原则：\n\n- **本地优先**：所有用量数据保存在本机 SQLite，不上传到第三方服务。\n- **最小依赖**：只依赖 Python 标准库，不需要安装 Redis 客户端或 Web 框架。\n- **脱敏发布**：仓库只包含源码、模板和说明，不包含 API key、OAuth token、数据库或日志。\n- **可长期运行**：提供 macOS LaunchAgent 模板，采集器和面板可以开机自启。\n\n## 架构图\n\n```mermaid\nflowchart LR\n  Client[Codex \u002F OpenAI 兼容客户端] --> Proxy[CLIProxyAPI]\n  Proxy --> Provider[Codex \u002F ChatGPT 账号池]\n  Proxy --> Queue[Redis 兼容用量队列]\n  Queue --> Collector[usage_dashboard.py collect]\n  Collector --> DB[(SQLite usage.sqlite)]\n  Collector --> Quota[ChatGPT wham\u002Fusage 余量接口]\n  Quota --> DB\n  DB --> Server[usage_dashboard.py serve]\n  Server --> Browser[本地网页面板 127.0.0.1:8320]\n```\n\n## 数据流\n\n```mermaid\nsequenceDiagram\n  participant C as 客户端\n  participant P as CLIProxyAPI\n  participant A as 上游账号\n  participant Q as 用量队列\n  participant W as 采集器\n  participant D as SQLite\n  participant B as 浏览器面板\n\n  C->>P: \u002Fv1\u002Fchat\u002Fcompletions\n  P->>A: 转发请求\n  A-->>P: 返回结果和 token usage\n  P-->>C: 返回 OpenAI 兼容响应\n  P->>Q: 写入本次请求用量事件\n  W->>Q: RPOP queue\n  W->>D: 写入 usage_events\n  W->>A: 定期查询 5h \u002F 7d 余量\n  W->>D: 写入 quota_snapshots\n  B->>D: 查询汇总、明细和余量\n```\n\n## 统计逻辑\n\n### 每次请求\n\n采集器会把 CLIProxyAPI 队列里的每条事件写入 `usage_events` 表，核心字段包括：\n\n- 时间：`timestamp`、`local_date`、`local_hour`\n- 账号：`source`、`auth_index`\n- 模型：`model`\n- 接口：`endpoint`\n- 状态：`failed`\n- 耗时：`latency_ms`\n- token：`input_tokens`、`output_tokens`、`reasoning_tokens`、`cached_tokens`、`total_tokens`\n\n### 时间窗口\n\n网页面板支持以下窗口：\n\n- 今天：从本地时区当天 00:00 开始\n- 最近 1 小时\n- 最近 5 小时\n- 最近 24 小时\n- 最近 7 天\n\n### 账号余量\n\n采集器会定期读取本地 Codex OAuth 文件中的 access token，并查询 ChatGPT 后端的 `wham\u002Fusage` 接口，保存每个账号的：\n\n- 账号是否可用\n- 5 小时窗口已用百分比和剩余百分比\n- 7 天窗口已用百分比和剩余百分比\n- 对应窗口的重置时间\n- credits balance\n\n## 前置条件\n\n- Python 3.9+\n- 已安装并运行 CLIProxyAPI\n- CLIProxyAPI Management API 已启用\n- CLIProxyAPI 用量统计已启用\n\n建议在 CLIProxyAPI 配置中启用：\n\n```yaml\nusage-statistics-enabled: true\nredis-usage-queue-retention-seconds: 3600\n```\n\n`redis-usage-queue-retention-seconds` 用于延长队列保留时间，避免采集器短暂停止时丢失事件。\n\n## 安装\n\n```bash\nmkdir -p ~\u002F.cli-proxy-api\u002Fusage-dashboard\ncp usage_dashboard.py ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002F\ncp config.example.json ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fconfig.json\nchmod 700 ~\u002F.cli-proxy-api\u002Fusage-dashboard\nchmod 600 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fconfig.json\n```\n\n编辑：\n\n```bash\n~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fconfig.json\n```\n\n填入你的 CLIProxyAPI Management API 明文密钥：\n\n```json\n{\n  \"cliproxy_host\": \"127.0.0.1\",\n  \"cliproxy_port\": 8317,\n  \"management_key\": \"replace-with-your-management-key\",\n  \"poll_interval_seconds\": 2,\n  \"quota_refresh_seconds\": 300,\n  \"dashboard_host\": \"127.0.0.1\",\n  \"dashboard_port\": 8320\n}\n```\n\n也可以用环境变量覆盖：\n\n```bash\nexport CLIPROXY_MANAGEMENT_KEY=\"your-management-key\"\n```\n\n初始化数据库：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py init\n```\n\n## 手动运行\n\n打开第一个终端，启动采集器：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py collect\n```\n\n打开第二个终端，启动网页服务：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py serve\n```\n\n浏览器访问：\n\n```text\nhttp:\u002F\u002F127.0.0.1:8320\n```\n\n## macOS 后台运行\n\n复制 LaunchAgent 模板：\n\n```bash\nmkdir -p ~\u002FLibrary\u002FLaunchAgents\ncp launchd\u002Fcom.cliproxyapi.usage-collector.plist ~\u002FLibrary\u002FLaunchAgents\u002F\ncp launchd\u002Fcom.cliproxyapi.usage-dashboard.plist ~\u002FLibrary\u002FLaunchAgents\u002F\n```\n\n把 plist 里的 `\u002FUsers\u002FYOUR_USER` 替换成你的真实 home 目录。\n\n加载服务：\n\n```bash\nlaunchctl bootstrap gui\u002F$(id -u) ~\u002FLibrary\u002FLaunchAgents\u002Fcom.cliproxyapi.usage-collector.plist\nlaunchctl bootstrap gui\u002F$(id -u) ~\u002FLibrary\u002FLaunchAgents\u002Fcom.cliproxyapi.usage-dashboard.plist\n```\n\n检查状态：\n\n```bash\nlaunchctl print gui\u002F$(id -u)\u002Fcom.cliproxyapi.usage-collector\nlaunchctl print gui\u002F$(id -u)\u002Fcom.cliproxyapi.usage-dashboard\n```\n\n卸载服务：\n\n```bash\nlaunchctl bootout gui\u002F$(id -u) ~\u002FLibrary\u002FLaunchAgents\u002Fcom.cliproxyapi.usage-collector.plist\nlaunchctl bootout gui\u002F$(id -u) ~\u002FLibrary\u002FLaunchAgents\u002Fcom.cliproxyapi.usage-dashboard.plist\n```\n\n## 命令行查询\n\n查看今日汇总：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py report today\n```\n\n查看最近 5 小时：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py report 5h\n```\n\n强制刷新账号余量：\n\n```bash\npython3 ~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage_dashboard.py quota --force\n```\n\n## API\n\n网页服务同时提供本地 JSON API：\n\n```text\nGET \u002Fapi\u002Fhealth\nGET \u002Fapi\u002Fsummary?range=today\nGET \u002Fapi\u002Fsummary?range=5h\nGET \u002Fapi\u002Fquota\nGET \u002Fapi\u002Fquota?force=1\nGET \u002Fapi\u002Frequests?limit=100\n```\n\n`range` 支持：\n\n- `today`\n- `1h`\n- `5h`\n- `24h`\n- `7d`\n\n## 数据文件\n\n默认文件位置：\n\n```text\n~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fconfig.json\n~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Fusage.sqlite\n~\u002F.cli-proxy-api\u002Fusage-dashboard\u002Flogs\u002F\n```\n\n其中：\n\n- `config.json` 包含本地管理密钥，不能提交。\n- `usage.sqlite` 包含账号名和用量统计，不能提交。\n- `logs\u002F` 可能包含运行错误信息，不能提交。\n\n## 安全与脱敏\n\n仓库不应包含以下内容：\n\n- CLIProxyAPI Management API 明文密钥\n- CLIProxyAPI API key\n- OAuth `access_token`\n- OAuth `refresh_token`\n- OAuth `id_token`\n- 本地 `config.json`\n- SQLite 数据库\n- 日志文件\n- 真实账号邮箱\n\n本仓库的 `.gitignore` 默认排除：\n\n```text\nconfig.json\n*.sqlite\n*.sqlite-shm\n*.sqlite-wal\nlogs\u002F\n__pycache__\u002F\n*.pyc\n.DS_Store\n```\n\n发布前建议执行：\n\n```bash\ngit grep -n -I \"refresh_token\\|id_token\\|gho_\\|Bearer [A-Za-z0-9]\\|chatgpt_account_id\"\n```\n\n如果命中真实值，不要发布，先清理 git 历史。\n\n## 限制\n\n- 只能统计采集器启动之后的请求，历史数据无法补回。\n- CLIProxyAPI 的队列是短期队列，采集器长时间停止会丢失期间事件。\n- 账号余量查询依赖 ChatGPT 后端接口，接口变更时可能需要调整。\n- 面板默认不做多用户认证，应保持监听 `127.0.0.1`。\n\n## 许可证\n\nMIT\n","该项目是一个面向CLIProxyAPI的本地用量统计和可视化面板，用于监控和展示Codex\u002FChatGPT账号的token消耗情况。其核心功能包括从CLIProxyAPI的Redis兼容用量队列中采集请求记录，并将这些数据存储于本地SQLite数据库，通过网页界面提供详细的用量统计信息，如每次请求的token消耗、今日总消耗以及按不同时间窗口（1小时、5小时、24小时、7天）的统计数据。此外，它还能显示各账号及模型的使用情况与剩余额度。此项目特别适合需要在本地环境下对多个AI服务账号进行管理和监控的开发者或个人用户，设计上强调本地优先、最小依赖原则，易于部署且支持长期运行。",2,"2026-06-11 04:02:58","CREATED_QUERY"]