Install

简体中文

Codex Quota Monitor connects to an existing CLIProxyAPI deployment. It does not install or manage CPA for you.

The 0.2.0 PyPI and GHCR commands require the v0.2.0 release to be tagged and published. If you are previewing the repository before that tag exists, use the source install or local Docker build paths shown below.

Read the security self-audit before mounting production management keys or auth files. Keep the first evaluation loopback-only and use read-only secret mounts.

Choose A Path

PyPI With uv

Install uv first if it is not already available:

curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install codex-quota-monitor==0.2.0

To preview the source before the tag is published, install from the repository:

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

If you prefer the traditional Python tool installer, pipx install codex-quota-monitor==0.2.0 and the same git+https://... source URL are also supported. Both uv and pipx installs expose cqm as an equivalent short alias for codex-quota-monitor.

Run it against your existing CPA endpoints:

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 \
  --state-db ~/.local/state/codex-quota-monitor/history.sqlite3

When --state-db is enabled, the Stats tab can show stored history and you can move that native history between machines:

codex-quota-monitor export-history --state-db ~/.local/state/codex-quota-monitor/history.sqlite3 --output backup.json
codex-quota-monitor import-history --state-db ~/.local/state/codex-quota-monitor/history.sqlite3 backup.json

Native history backups are schema-versioned. Current imports expect backup schema version 2; import older backups with the matching older monitor first, then upgrade the SQLite DB in place.

Open http://127.0.0.1:4515/.

Runtime logs are written to stderr. Keep the default text logs for local foreground runs, or add --log-format json when a service manager or collector should receive one JSON object per line. --access-log off disables HTTP request access lines without disabling runtime warnings.

Before turning it into a service, run:

cqm print-config
cqm doctor

Config File

CLI flags override environment variables, and environment variables override TOML config files. By default the monitor reads /etc/codex-quota-monitor/config.toml and ~/.config/codex-quota-monitor/config.toml when they exist; pass --config /path/to/config.toml to use one explicit file or --config off to disable config files.

Generate starter files without writing system paths:

cqm init --mode user
cqm init --mode system
cqm init --mode docker

Use --output-dir ./codex-quota-monitor-starter to write files to a staging directory. init never writes inline management keys; keep secrets in a key file with restrictive permissions. For a bare CPA endpoint, that file must contain the same plaintext value as CPA remote-management.secret-key. Recent CPA versions return 404 on /v0/management/* when the secret is empty.

Rootless User Service

This is the lowest-friction path for a single Linux user:

uv tool install codex-quota-monitor==0.2.0
mkdir -p ~/.config/codex-quota-monitor ~/.local/state/codex-quota-monitor ~/.config/systemd/user
codex-quota-monitor init --mode user --output-dir /tmp/cqm-user
install -m 0600 /tmp/cqm-user/config.toml ~/.config/codex-quota-monitor/config.toml
install -m 0644 /tmp/cqm-user/codex-quota-monitor.user.service ~/.config/systemd/user/codex-quota-monitor.service
codex-quota-monitor --config ~/.config/codex-quota-monitor/config.toml doctor
systemctl --user daemon-reload
systemctl --user enable --now codex-quota-monitor

Inspect or stop it with:

systemctl --user status codex-quota-monitor --no-pager
journalctl --user -u codex-quota-monitor -n 100 --no-pager
systemctl --user restart codex-quota-monitor
systemctl --user disable --now codex-quota-monitor

For boot-time user services on machines without an interactive login, enable linger with loginctl enable-linger "$USER" if that fits your host policy.

Distro Notes

The generated systemd units are ordinary Linux units; the main distro-specific difference is how Python, uv, or pipx are installed.

System Service

Create a dedicated user and state directory:

sudo useradd --system --home /var/lib/codex-quota-monitor --create-home --shell /usr/sbin/nologin codex-quota-monitor
sudo install -d -o codex-quota-monitor -g codex-quota-monitor /var/lib/codex-quota-monitor

Install the package into a venv owned by that user:

sudo -u codex-quota-monitor python3 -m venv /var/lib/codex-quota-monitor/venv
sudo -u codex-quota-monitor /var/lib/codex-quota-monitor/venv/bin/python -m pip install --upgrade pip
sudo -u codex-quota-monitor /var/lib/codex-quota-monitor/venv/bin/python -m pip install codex-quota-monitor

The repository includes copyable templates in examples/codex-quota-monitor.config.toml and examples/codex-quota-monitor.service. A minimal unit looks like this:

[Unit]
Description=Codex Quota Monitor
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=codex-quota-monitor
Group=codex-quota-monitor
ExecStart=/var/lib/codex-quota-monitor/venv/bin/codex-quota-monitor --config /etc/codex-quota-monitor/config.toml
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/codex-quota-monitor

[Install]
WantedBy=multi-user.target

Keep the service loopback-only unless you intentionally expose it through a tunnel, reverse proxy, or firewall rule.

If the service reports Permission denied for auth files, either mount/copy a read-only auth directory that the codex-quota-monitor user can traverse, or add a narrow read-only ACL for that service user. Do not solve this by broadening permissions on an entire home, .config, or secret directory. The monitor only needs read access to auth files and write access to its SQLite state directory.

Docker

The container listens on 0.0.0.0 inside the container. Publish the host port to loopback by default:

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 \
  -e CODEX_QUOTA_MONITOR_LOG_FORMAT=text \
  -e CODEX_QUOTA_MONITOR_ACCESS_LOG=on \
  ghcr.io/xsyxnx/codex-quota-monitor:0.2.0

Mount only the specific management key file and auth-files directory the monitor needs, keep both mounts read-only, and keep /data as the only persistent writable path. For bare CPA, the mounted management key file must match CPA remote-management.secret-key. Do not mount a whole home, .config, or unrelated secret directory into the container.

On Docker Desktop for Windows or macOS, host.docker.internal is built in and --add-host=host.docker.internal:host-gateway is usually unnecessary.

To preview the source before the GHCR release image exists, build locally and replace the image name with codex-quota-monitor:local:

docker build -t codex-quota-monitor:local .

For Compose, start from examples/docker-compose.yml and keep the published host port bound to 127.0.0.1 unless an authenticated reverse proxy protects the dashboard.

LAN Access Through A Reverse Proxy

Do not treat the monitor API as an auth boundary. Keep the app on 127.0.0.1:4515, then expose only the proxy at the root of a dedicated hostname such as https://quota.example/:

codex-quota-monitor doctor --host 127.0.0.1 --allowed-host quota.example

Starter proxy examples are in examples/reverse-proxy/Caddyfile and examples/reverse-proxy/nginx.conf. Add basic auth or your normal access layer before allowing phones, LAN clients, or public tunnels to reach the dashboard. Path-prefix deployments such as https://example/tools/quota/ are not a supported v1 topology; use a dedicated hostname instead.

Windows Foreground Python

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv tool install codex-quota-monitor==0.2.0
codex-quota-monitor --management-base-url http://127.0.0.1:8317 --management-key-file C:\path\to\management-key --gateway-health-url http://127.0.0.1:8317/healthz

This path is for foreground use. Use Docker Desktop for a more repeatable Windows runtime.

Smoke Test

codex-quota-monitor --version
codex-quota-monitor print-config
codex-quota-monitor 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/stats | jq '.sources'
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'