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
- NixOS: use the flake module when you want a declarative service.
- Debian/Ubuntu: use
uvfor a foreground smoke test, then a small systemd service. - Docker: use the GHCR image when you want an isolated runtime or Docker Desktop support.
- Windows: use Docker Desktop first. Native Python foreground execution is supported for smoke tests and personal use, but Windows Service installation is not provided.
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
- Install
uvwith the method recommended for your distro or from the upstream installer, then useuv tool install codex-quota-monitor==0.2.0. - Debian/Ubuntu, Fedora, Arch Linux, and openSUSE users can still choose the distro
pipxpackage when they prefer that installer.
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'