cpa-warden is an interactive CLIProxyAPI (CPA) auth inventory scanner, uploader, and maintenance tool for local operations against a specific CPA management environment.
It currently relies on three management flows: GET /v0/management/auth-files for inventory, POST /v0/management/api-call against https://chatgpt.com/backend-api/wham/usage for usage probing, and POST /v0/management/auth-files for auth-file uploads.
From a user perspective, the script:
- fetches the current auth inventory
- stores local state in SQLite
- probes usage concurrently
- uploads local auth JSON files concurrently in upload mode
- exports current
401and quota-limited results - optionally deletes, disables, or re-enables accounts in maintenance mode
- can refill accounts to a minimum valid threshold after maintenance
- Interactive mode by default when no
--modeis provided in a TTY - Non-interactive
scan,maintain,upload, andmaintain-refillworkflows for repeatable runs - External JSON configuration for sensitive values such as
base_urlandtoken - Concurrent usage probing through the CLIProxyAPI
api-callendpoint - Concurrent auth-file uploads with local SQLite deduplication guards
- Optional external register-command hook when refill still cannot meet threshold
- Local SQLite state tracking across runs
- JSON exports for invalid and quota-limited accounts
- Short production output with optional Rich progress display in TTY sessions
- Full debug-level logs written to a file on every run
cpa-warden is built for a specific CPA management setup, not as a generic account-management platform. It is already usable for real local operations, but it is still an early-stage open-source project. Treat it as an operator-focused maintenance tool for known CPA environments, not a universal solution for arbitrary auth systems.
Maintenance mode can delete or disable remote accounts. Upload mode can create new remote auth entries and optionally force overwrite attempts by name. maintain-refill can execute an external register command when enabled. Review your configuration carefully before running destructive actions, especially when using --quota-action delete, --upload-force, --auto-register, or --yes.
- Python 3.11+
- uv
uv syncCopy the example configuration first:
cp config.example.json config.jsonAt minimum, set:
base_urltoken
config.json is ignored by git and should never be committed.
Example configuration:
{
"base_url": "https://your-cpa.example.com",
"token": "replace-with-your-management-token",
"target_type": "codex",
"provider": "",
"probe_workers": 100,
"action_workers": 100,
"timeout": 15,
"retries": 3,
"delete_retries": 2,
"quota_action": "disable",
"quota_disable_threshold": 0.0,
"delete_401": true,
"auto_reenable": true,
"reenable_scope": "signal",
"upload_dir": "",
"upload_workers": 20,
"upload_retries": 2,
"upload_method": "json",
"upload_recursive": false,
"upload_force": false,
"min_valid_accounts": 100,
"refill_strategy": "to-threshold",
"auto_register": false,
"register_command": "",
"register_timeout": 300,
"register_workdir": "",
"db_path": "cpa_warden_state.sqlite3",
"invalid_output": "cpa_warden_401_accounts.json",
"quota_output": "cpa_warden_quota_accounts.json",
"log_file": "cpa_warden.log",
"debug": false,
"user_agent": "codex_cli_rs/0.76.0 (Debian 13.0.0; x86_64) WindowsTerminal"
}Boolean-like config values are parsed strictly. Valid forms are: true/false, 1/0, yes/no, on/off (case-insensitive). Invalid values fail fast at startup.
Important configuration keys:
base_url: CLIProxyAPI management base URLtoken: CLIProxyAPI management tokentarget_type: filter records byfiles[].typeprovider: filter records by theproviderfieldprobe_workers: concurrency for usage probingaction_workers: concurrency for delete / disable / enable actionstimeout: request timeout in secondsretries: retry count for retryable probe failures (timeouts, network errors,429,5xx)delete_retries: retry count for failed delete actions (network errors,429,5xx, etc.)quota_action: action for quota-limited accounts, eitherdisableordeletequota_disable_threshold: auto-disable threshold by remaining quota ratio (0~1);0keeps legacy behavior (disable only when exhausted)delete_401: whether maintenance mode deletes401accountsauto_reenable: whether recovered accounts are re-enabled automaticallyreenable_scope: scope for auto re-enable,signalormanaged(default:signal)upload_dir: source directory foruploadmode (.jsonfiles only)upload_workers: concurrent workers foruploadmodeupload_retries: retry count for upload failuresupload_method: upload request type,jsonormultipartupload_recursive: whetheruploadmode scans subdirectories recursivelyupload_force: whether to upload even when remote file name already existsmin_valid_accounts: minimum valid-account threshold inmaintain-refillmoderefill_strategy: refill rule inmaintain-refill,to-thresholdorfixedauto_register: whether to invoke an external register command when still below thresholdregister_command: external register command template (logic stays outside this repo)register_timeout: timeout (seconds) for external register commandregister_workdir: optional working directory for external register commanddb_path: local SQLite state database pathinvalid_output: JSON export path for invalid401accountsquota_output: JSON export path for quota-limited accountslog_file: runtime log file pathdebug: enable more verbose terminal logginguser_agent: User-Agent used forwham/usageprobing
Interactive mode:
uv run python cpa_warden.pyNon-interactive examples:
scan scenarios:
- Baseline inventory and usage probe without changing remote state:
uv run python cpa_warden.py --mode scan - Troubleshoot probing behavior with verbose terminal logs:
uv run python cpa_warden.py --mode scan --debug - Focus on a specific account segment (type + provider):
uv run python cpa_warden.py --mode scan --target-type codex --provider openai
maintain scenarios:
- Standard maintenance pass using configured defaults:
uv run python cpa_warden.py --mode maintain - Review maintenance results without deleting
401or auto re-enable:
uv run python cpa_warden.py --mode maintain --no-delete-401 --no-auto-reenable - Treat quota-limited accounts aggressively by deleting them:
uv run python cpa_warden.py --mode maintain --quota-action delete - Disable accounts early when remaining quota ratio drops to 10%:
uv run python cpa_warden.py --mode maintain --quota-disable-threshold 0.1 - Re-enable only accounts previously managed by this tool:
uv run python cpa_warden.py --mode maintain --reenable-scope managed - Run destructive maintenance non-interactively (skip confirmation):
uv run python cpa_warden.py --mode maintain --quota-action delete --yes
upload scenarios:
- Upload auth files from a single directory:
uv run python cpa_warden.py --mode upload --upload-dir ./auth_files - Bulk upload across nested folders with higher concurrency:
uv run python cpa_warden.py --mode upload --upload-dir ./auth_files --upload-recursive --upload-workers 50 - Use multipart upload and force same-name overwrite attempts:
uv run python cpa_warden.py --mode upload --upload-dir ./auth_files --upload-method multipart --upload-force
maintain-refill scenarios:
- Maintain first, then refill only the gap to target capacity:
uv run python cpa_warden.py --mode maintain-refill --min-valid-accounts 200 --upload-dir ./auth_files - Maintain first, then refill with a fixed-size upload batch:
uv run python cpa_warden.py --mode maintain-refill --min-valid-accounts 200 --refill-strategy fixed --upload-dir ./auth_files - Enable external register fallback when refill still misses threshold:
uv run python cpa_warden.py --mode maintain-refill --min-valid-accounts 200 --upload-dir ./auth_files --auto-register --register-command 'python /opt/register-machine/register.py'
Available CLI options:
--config--mode--target-type--provider--probe-workers--action-workers--timeout--retries--delete-retries--user-agent--quota-action--quota-disable-threshold--db-path--invalid-output--quota-output--log-file--debug--upload-dir--upload-workers--upload-retries--upload-method--upload-force--no-upload-force--min-valid-accounts--refill-strategy--auto-register--no-auto-register--register-command--register-timeout--register-workdir--delete-401--no-delete-401--auto-reenable--no-auto-reenable--reenable-scope--upload-recursive--no-upload-recursive--yes
scan only reads inventory, probes usage, updates the local SQLite state, and exports current results. It does not change remote account state.
maintain always runs a full scan first, then applies configured actions:
- delete
401accounts if enabled - disable or delete quota-limited accounts
- re-enable recovered accounts if enabled
Note: default reenable_scope=signal means auto_reenable can also re-enable manually disabled accounts if they currently satisfy the recovered condition. Use reenable_scope=managed to limit re-enable to accounts this tool previously marked as quota_disabled.
Deletion flows require confirmation unless --yes is provided.
upload reads .json files from upload_dir, validates content, and uploads them concurrently to /v0/management/auth-files.
It keeps upload state in SQLite and ensures each {base_url, file_name, content_sha256} tuple is uploaded only once, preventing duplicate uploads under concurrent runs.
If any file fails validation or upload, the command exits with a non-zero status.
maintain-refill runs maintain first, then checks valid accounts with strict rules (disabled=0, non-401, non-quota-limited, and no probe error).
If valid accounts are below min_valid_accounts, it uploads additional auth files from upload_dir based on refill_strategy:
to-threshold: upload only the gap (min_valid_accounts - current_valid)fixed: upload a fixed count equal tomin_valid_accountswhenever triggered
If still below threshold and auto_register=true, it invokes register_command (external logic) with:
- CLI arguments appended by this tool:
--count <N> --output-dir <upload_dir> - environment variables:
CPA_REGISTER_COUNT,CPA_REGISTER_OUTPUT_DIR
External registration logic is intentionally out-of-repo; this project only provides the hook.
Filtering behavior:
target_typematchesfiles[].typeprovideris a case-insensitive exact match against theproviderfield
Classification rules:
401:unavailable == trueorapi-call.status_code == 401quota limited:api-call.status_code == 200and either (1) the effective quota signal is exhausted (limit_reached == true) or (2) remaining quota ratio is<= quota_disable_threshold; forplan_type=proit prefers Spark fromadditional_rate_limits(metered_feature=codex_bengalfox, fallback:limit_namecontainsSpark) when Spark has a usablelimit_reachedsignal, otherwise it falls back to top-levelrate_limitrecovered: account is currently disabled, and now the same effective signal reportsallowed == trueandlimit_reached == false
Probe retry rules:
429and5xx: retry with backoff up toretries- other
4xx: fail fast without retry
Default output artifacts:
cpa_warden_state.sqlite3: local SQLite state databasecpa_warden_401_accounts.json: exported invalid401accountscpa_warden_quota_accounts.json: exported quota-limited accountscpa_warden.log: runtime log file
- Production terminal output stays short
- If the session is a TTY, production mode prefers a Rich progress display
--debugordebug: trueenables more verbose terminal logging- The log file always keeps full debug-level details
cpa_warden.py: main entrypointconfig.example.json: example configurationpyproject.toml: project metadata and dependencies.github/workflows/ci.yml: basic CI checks
See CONTRIBUTING.md.
See CHANGELOG.md.
See SECURITY.md for responsible disclosure guidance.
MIT. See LICENSE.