Quick Start

简体中文

Requirements

For a bare CPA endpoint, create a key file containing the same plaintext value as CPA remote-management.secret-key. Recent CPA versions disable /v0/management/* with 404 when that secret is empty. If you intentionally use a local proxy that injects Authorization, point managementBaseUrl at that proxy and omit the key file.

Before pointing the monitor at real key or auth files, review the security self-audit. It explains the data flow, residual risks, and local checks for secret redaction.

If you only want to preview the UI first, run demo mode instead:

codex-quota-monitor --demo

--demo serves built-in sample data on 127.0.0.1:4516 by default, so it can run next to a normal 127.0.0.1:4515 monitor. It does not read auth files, management keys, SQLite history, benchmark summaries, or CPA endpoints. The browser Privacy button defaults to showing original text; click it to mask email addresses and token-like strings in the rendered UI. This is display-only: /api/* and /metrics keep their original machine-readable payloads.

Typical local values:

Nix

After v0.2.0 is published, run directly from the release flake:

nix run github:xsyxnx/codex-quota-monitor/v0.2.0#codex-quota-monitor -- \
  --management-base-url http://127.0.0.1:8317 \
  --management-key-file /path/to/management-key \
  --gateway-health-url http://127.0.0.1:8317/healthz \
  --auth-dir /path/to/auth-files

Expose it to the local network only when you mean to:

nix run github:xsyxnx/codex-quota-monitor/v0.2.0#codex-quota-monitor -- \
  --host 0.0.0.0 \
  --allowed-host monitor.lan \
  --port 4515 \
  --management-base-url http://127.0.0.1:8317 \
  --management-key-file /path/to/management-key \
  --gateway-health-url http://127.0.0.1:8317/healthz \
  --auth-dir /path/to/auth-files

Replace monitor.lan with the hostname or IP address browsers will use in the Host header. The dashboard rejects unexpected Host and Origin values.

By default, total 5h capacity is capped by weekly remaining * 6.0. Use --weekly-to-five-hour-multiplier <number> to override it, or --weekly-to-five-hour-multiplier off / none to disable the cap. Reset times use the service’s local timezone by default. Use --display-timezone UTC, --display-timezone Asia/Shanghai, or another IANA timezone when you want a fixed display zone. The dashboard language defaults to --display-locale auto, which follows the browser and currently supports en and zh-CN; set --display-locale zh-CN or --display-locale en for a fixed service default. Use --ui-font-family and --mono-font-family with CSS font-family lists when you want a different service default. The dashboard also has browser-local Preferences that override the service defaults for the current browser only. Fonts are not bundled; names such as "Maple Mono NF CN" work only on devices where that font is installed.

Direct nix run keeps SQLite history disabled by default. Add a writable state DB when you want Trends, ETA, Audit history, or the Stats time-series workbench; the Trends tab shows the latest 6h of stored samples, and Stats uses the same database for token/request curves and JSON/CSV export:

nix run github:xsyxnx/codex-quota-monitor/v0.2.0#codex-quota-monitor -- \
  --state-db ./result/codex-quota-monitor.sqlite3 \
  --management-base-url http://127.0.0.1:8317 \
  --management-key-file /path/to/management-key \
  --gateway-health-url http://127.0.0.1:8317/healthz \
  --auth-dir /path/to/auth-files

For PyPI, Docker, Debian/Ubuntu systemd, and Windows notes, see Install.

Python

uv tool install codex-quota-monitor==0.2.0
codex-quota-monitor init --mode user
codex-quota-monitor \
  --management-base-url http://127.0.0.1:8317 \
  --management-key-file /path/to/management-key \
  --gateway-health-url http://127.0.0.1:8317/healthz \
  --auth-dir /path/to/auth-files

To preview the source before the tag is published, use the source install path:

uv tool install 'git+https://github.com/xsyxnx/codex-quota-monitor.git'

If you prefer pipx, use pipx install codex-quota-monitor==0.2.0 or the same git+https://... source URL. After a Python install, cqm is an equivalent short alias for codex-quota-monitor.

init prints copyable config.toml, rootless systemctl --user service, and next-step smoke checks. It does not write system paths unless you pass --output-dir.

Docker

docker run --rm \
  --add-host=host.docker.internal:host-gateway \
  --read-only \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  --tmpfs /tmp \
  -p 127.0.0.1:4515:4515 \
  -e CODEX_QUOTA_MONITOR_MANAGEMENT_BASE_URL=http://host.docker.internal:8317 \
  -e CODEX_QUOTA_MONITOR_MANAGEMENT_KEY_FILE=/management-key \
  -e CODEX_QUOTA_MONITOR_GATEWAY_HEALTH_URL=http://host.docker.internal:8317/healthz \
  -v codex-quota-monitor-data:/data \
  -v /path/to/management-key:/management-key:ro \
  -v /path/to/auth-files:/auth-files:ro \
  -e CODEX_QUOTA_MONITOR_AUTH_DIR=/auth-files \
  ghcr.io/xsyxnx/codex-quota-monitor:0.2.0

Mount only the specific management key file and auth-files directory the monitor needs, and keep both mounts read-only. The mounted key file must match CPA remote-management.secret-key for a bare CPA endpoint. Do not mount your whole home, .config, or unrelated secret directories into the container.

To preview the source before the GHCR release image exists, build locally with docker build -t codex-quota-monitor:local ..

Shared Client Labels

When CPA usage details identify shared clients by apiName / api_name, add a small JSON label file and use the Stats Client group for friend-level request/token accounting:

{
  "clients": [
    {"apiName": "sk-example-from-cpa", "label": "Alice"},
    {"api_name": "rotated-api-name", "label": "Alice"}
  ]
}

Run with --client-labels-file /path/to/client-labels.json. Keep this file as runtime secret material; unmapped clients are shown as short fingerprints.

Smoke Test

cqm tldr
cqm print-config
cqm doctor
curl -fsS http://127.0.0.1:4515/healthz
curl -fsS http://127.0.0.1:4515/api/v1/status | jq '.summary'
curl -fsS http://127.0.0.1:4515/api/v1/recommendations | jq '.summary'
curl -fsS 'http://127.0.0.1:4515/api/v1/stats/series?range=24h&metric=tokens' | jq '.summary'
curl -fsS 'http://127.0.0.1:4515/api/v1/stats/series?range=24h&group=client' | jq '.breakdown.clients'
curl -fsS http://127.0.0.1:4515/api/v1/diagnostics | jq '.summary'
curl -fsS http://127.0.0.1:4515/api/v1/alerts | jq '.'
curl -fsS http://127.0.0.1:4515/metrics | sed -n '1,20p'

Open http://127.0.0.1:4515/ in a browser after the process starts.

Benchmarking

If you also want to benchmark fast versus baseline, or Team versus Plus quota capacity, see Benchmark guide.