# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview VMess domain rotator - automated pipeline that fetches preferred domains from an API, selects the best candidate, and exports runtime files for Sub-Store and V2Ray integration. ## Key Commands ### Development ```bash # Syntax check Python scripts python3 -m py_compile scripts/domain_updater.py python3 -m py_compile scripts/update_vmess_links.py # Manual run (single update) python3 scripts/domain_updater.py --config config.json # Manual run with conditional git commit (commits only if domain changed) bash scripts/run_update_and_commit.sh config.json # Update VMess base64 links with selected domain python3 scripts/update_vmess_links.py --input ./nodes.txt --output ./nodes.updated.txt --domain-file ./runtime/current_domain.txt # Update specific nodes by regex python3 scripts/update_vmess_links.py --input ./nodes.txt --output ./nodes.updated.txt --domain-file ./runtime/current_domain.txt --name-regex "(argo|cf|vm)" # Local smoke test HTTP endpoint for runtime outputs python3 -m http.server 8080 --directory runtime ``` ### Deployment (Debian) ```bash # Install systemd service+timer (uses current git repo directory) sudo bash scripts/install_debian.sh # Install with custom timer interval sudo bash scripts/install_debian.sh --interval 5min # Uninstall (keeps git repository and files) sudo bash scripts/uninstall_debian.sh ``` ## Architecture ### Core Flow 1. `scripts/domain_updater.py` - Main entrypoint that: - Fetches domain candidates from API (configured in `config.json`) - Parses response using JSON path or regex - Optionally scores candidates based on API fields - Optionally healthchecks domains (TLS handshake) - Selects best domain and writes runtime outputs - Falls back to `last_good_domain` from state.json if all checks fail 2. `scripts/run_update_and_commit.sh` - Scheduler entrypoint that: - Runs domain_updater.py - Compares before/after domain - Commits to `runtime-state` branch if domain changed - Pushes to remote if configured 3. `scripts/update_vmess_links.py` - Post-processor for VMess subscription links: - Decodes vmess:// base64 payloads - Updates `add` field with selected domain - Supports node name filtering by regex ### Configuration Structure - `config.json` - Single runtime config file containing: - `api`: endpoint URL, method, headers, timeout - `parser`: JSON paths (`field_paths`) or regex for extracting domains - `domain_filter`: include/exclude patterns (e.g., filter out IPv4 addresses) - `scoring`: ranking logic based on API fields or API order - `healthcheck`: TLS handshake verification settings - `selection`: top_n candidates to consider - `output`: runtime directory and file paths - `v2ray`: template file token replacement (optional) ### Output Files All runtime outputs are written to `runtime/`: - `current_domain.txt` - Plain text domain - `current_domain.json` - JSON payload with domain, timestamp, status, source_count - `state.json` - Persistent state including `last_good_domain` for fallback - `substore_vars.json` - Variables for Sub-Store operator scripts ### Sub-Store Integration `substore/operator_template.js` - Operator script that: - Fetches `current_domain.json` via HTTP using `$substore.http.get` - Caches domain with TTL (5 minutes by default) - Replaces VMess `server` field for nodes matching `NODE_NAME_REGEX` - Must be configured with actual DOMAIN_JSON_URL in production ### Systemd Deployment - Service runs `run_update_and_commit.sh` oneshot - Timer triggers every 1h by default (configurable via install_debian.sh) - Uses current git repository directory (in-place mode only) - Uses the installing user (from SUDO_USER) as service user - Runtime state committed to `runtime-state` branch - No separate service user created - uses existing user's git credentials ## Important Behaviors - **Fallback**: If all healthchecks fail, script uses `last_good_domain` from `runtime/state.json` - **Conditional commits**: `run_update_and_commit.sh` only commits when domain actually changes - **Branch separation**: Runtime state goes to `runtime-state` branch via git worktree - **API order mode**: For vps789 Top20, set `scoring.use_api_order=true` to trust API ranking - **Domain filtering**: Use `domain_filter.exclude_regex` to filter out IPv4 addresses when API returns mixed results - **Sub-Store caching**: Operator uses `scriptResourceCache` with TTL to avoid excessive HTTP requests ## Configuration Notes For vps789 Top20 API specifically: - Use `parser.field_paths: ["data.good[].ip"]` - Enable `scoring.use_api_order: true` to respect API ranking - Set `healthcheck.enabled: false` if you want pure API-based selection - Add IPv4 exclude regex to `domain_filter.exclude_regex` to filter out IP addresses ## Git Workflow - Main branch: `main` (source code) - Runtime branch: `runtime-state` (auto-committed domain updates) - Commits to runtime-state use generic git identity: `vmess-domain-rotator@localhost` - Script creates runtime-state branch automatically if missing