A single-page dashboard that aggregates the coding-plan quotas of multiple AI providers (Codex, MiniMax, Volcengine AgentPlan / CodingPlan, Kimi Code, LongCat, Qianwen AI and Google AI Gemini 3.5 Flash) into one self-hosted UI. Each provider supports multiple accounts with independent labels.
一个部署在局域网中的 Coding Plan 配额看板,支持 Codex、MiniMax、火山方舟 CodingPlan / AgentPlan、Kimi Code、LongCat、千问 AI 和 Google AI (Gemini 3.5 Flash)。支持同一平台 多账号,每个账号可添加备注。
- Auto-detects the data source from the imported raw
curlURL — no manual selection needed. / 根据原始curlURL 自动识别数据来源,不需要手工选择产品。 - The server re-executes saved requests on page open, manual refresh, or auto refresh; results are persisted as JSON on the host so they survive container restarts. / 页面打开、刷新或点击刷新按钮时由服务器重新执行已保存的请求;配额结果保存到服务器端 JSON 文件,容器重启后自动恢复。
- First paint shows the cached snapshot then silently refreshes to the latest data; successful refreshes do not pop up any dialog.
- Multi-account support: each imported curl is stored as a separate account with its own ID, label, edit, delete (with double confirm), and reorder controls.
- Per-account Volcengine AK/SK configuration (no curl required); uses HMAC-SHA256 V4
signing against
GetCodingPlanUsage/GetAgentPlanAFPUsage. - Codex supports both the official
/usage+/rate-limit-reset-creditsendpoints and a NewAPI replacement (/api/channel/{channelId}/codex/usage[/reset-credits]). The server merges them into a single Codex card and skips the official requests when a NewAPI variant is configured. - All progress bars show one-decimal usage percentage; each card shows a live countdown to the next reset in the top-right corner.
- Self-contained single-file browser UI (
index.html) with a custom SVG logo and no external favicon dependency.
index.html Single-file frontend
server.py Static file serving + JSON persistence + restricted curl execution
parser.js Parser implementation used by Node tests
docker-compose.yml Container deployment configuration
tests/ Parser and server unit tests
AGENTS.md Coding-agent instructions for this repository
- Linux host / NAS with Docker Engine and Docker Compose v2.
- The host must be able to reach Codex, MiniMax and Volcengine APIs.
- If you import a Codex curl with
--proxy, the proxy must be reachable from the Docker host. - Default listen port is
8080; changePORTindocker-compose.ymlif occupied.
sudo mkdir -p /docker/coding_plan_quota_dashboard/data
sudo chmod 700 /docker/coding_plan_quota_dashboard/data
sudo cp index.html server.py docker-compose.yml /docker/coding_plan_quota_dashboard/cd /docker/coding_plan_quota_dashboard
sudo docker compose up -d
sudo docker compose ps
sudo docker logs --tail=100 coding-plan-quota-dashboard
curl -fsS -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:8080/In Portainer choose the target endpoint, Stacks → Add stack, name it
coding-plan-quota-dashboard, paste the contents of docker-compose.yml and click
Deploy the stack. Because Portainer uses host bind mounts, index.html,
server.py and an empty data/ directory must already exist on the host.
sudo cp index.html /docker/coding_plan_quota_dashboard/index.html
sudo cp server.py /docker/coding_plan_quota_dashboard/server.py
sudo docker restart coding-plan-quota-dashboardFor Compose-level changes use Portainer's Update the stack, or:
cd /docker/coding_plan_quota_dashboard
sudo docker compose up -d --force-recreate/docker/coding_plan_quota_dashboard/data/requests.json # imported curl, contains secrets
/docker/coding_plan_quota_dashboard/data/credentials.json # per-account Volcengine AK/SK
/docker/coding_plan_quota_dashboard/data/snapshot.json # latest quota snapshot
/docker/coding_plan_quota_dashboard/data/results.json # per-account cached API responses
Backup:
sudo tar -czf "coding_plan_quota_dashboard-data-$(date +%Y%m%d-%H%M%S).tar.gz" \
-C /docker/coding_plan_quota_dashboard dataRestore:
cd /docker/coding_plan_quota_dashboard
sudo docker compose down
sudo tar -xzf coding_plan_quota_dashboard-data-YYYYMMDD-HHMMSS.tar.gz
sudo docker compose up -dTreat requests.json and credentials.json as secrets: do not commit them, and
never publish the backup file to a public download location.
Paste the full raw curl in the page and click 保存 curl 并刷新. The server
auto-classifies by URL:
chatgpt.com/backend-api/wham/usage→ Codex usagechatgpt.com/backend-api/wham/rate-limit-reset-credits→ Codex reset credits<newapi-host>/api/channel/{channelId}/codex/usage→ NewAPI Codex usage<newapi-host>/api/channel/{channelId}/codex/usage/reset-credits→ NewAPI Codex reset creditswww.minimaxi.com→ MiniMaxGetCodingPlanUsage→ Volcengine CodingPlanGetAgentPlanAFPUsage→ Volcengine AgentPlan (current endpoint)GetAgentPlanUsageDetails→ Volcengine AgentPlan (legacy endpoint, still supported)www.kimi.com/.../GetSubscriptionStats→ Kimi Codelongcat.chat/api/pay/quota/metering/token-packs/summary→ LongCatcs-data.qianwenai.com/.../data/api.json(containstokenplan) → Qianwen AI TokenPlanfetchAvailableModels(Gemini 3.5 Flash) → Google AI (Antigravity)
Codex official and NewAPI endpoints can coexist; the server merges them into one
card. curl -sS, --proxy and --insecure flags are translated into Python HTTPS
requests — the server never spawns a shell to run curl.
If /usage returns secondary_window: null, the page keeps the 5-hour row visible
and shows "接口未返回" instead of fabricating usage.
- The server does not shell out; imported curl is parsed and re-issued via Python
urllib-style HTTPS requests. - The host allowlist defaults to
chatgpt.com,www.minimaxi.com,console.volcengine.com,www.kimi.com,longcat.chat,cs-data.qianwenai.com; additional NewAPI hosts can be enabled via theNEWAPI_HOSTS(comma-separated) environment variable and are accepted only for the Codex/usageand/usage/reset-creditspaths. - Google AI uses OAuth client pairs loaded from the
GOOGLE_AI_CLIENTSenvironment variable as a JSON array of[client_id, client_secret]pairs. When unset, the server boots with threeREDACTED_*placeholders and the Google AI refresh call will fail until you provide real values; this keeps credentials out of source code. - NewAPI is reached over plain HTTP because it is a LAN service — do not extend this rule to arbitrary external HTTP endpoints.
- When a
codexNewApirequest is saved the refresh automatically skips the officialcodexUsagerequest, and likewise forcodexNewApiCredits→codexCredits. This avoids repeated401noise when the official token is stale. - Raw curl (Token / Cookie / Digest) is stored in
requests.jsonin plaintext, and Volcengine AK/SK is stored incredentials.jsonin plaintext. Never commit real credentials; the README and tests use redacted samples only. - Restrict
8080to a trusted LAN and rotate credentials immediately on leak.
node --test tests/parser.test.js
PYTHONPATH=. python3 -m unittest discover -s tests -p 'test_*.py'
python3 -m py_compile server.pyCI runs the same commands on every push and pull request; see
.github/workflows/test.yml.