RepoPilotOpen in app →

tindy2013/subconverter

Utility to convert between various subscription format

Mixed

Mixed signals — read the receipts

worst of 4 axes
Use as dependencyConcerns

copyleft license (GPL-3.0) — review compatibility

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2mo ago
  • 19 active contributors
  • GPL-3.0 licensed
Show 4 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 79% of recent commits
  • GPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
  • Use as dependency ConcernsMixed if: relicense under MIT/Apache-2.0 (rare for established libs)

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/tindy2013/subconverter?axis=fork)](https://repopilot.app/r/tindy2013/subconverter)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/tindy2013/subconverter on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: tindy2013/subconverter

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/tindy2013/subconverter shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Mixed signals — read the receipts

  • Last commit 2mo ago
  • 19 active contributors
  • GPL-3.0 licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 79% of recent commits
  • ⚠ GPL-3.0 is copyleft — check downstream compatibility

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live tindy2013/subconverter repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/tindy2013/subconverter.

What it runs against: a local clone of tindy2013/subconverter — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in tindy2013/subconverter | Confirms the artifact applies here, not a fork | | 2 | License is still GPL-3.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 101 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>tindy2013/subconverter</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of tindy2013/subconverter. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/tindy2013/subconverter.git
#   cd subconverter
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of tindy2013/subconverter and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "tindy2013/subconverter(\\.git)?\\b" \\
  && ok "origin remote is tindy2013/subconverter" \\
  || miss "origin remote is not tindy2013/subconverter (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
  && ok "license is GPL-3.0" \\
  || miss "license drift — was GPL-3.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "CMakeLists.txt" \\
  && ok "CMakeLists.txt" \\
  || miss "missing critical file: CMakeLists.txt"
test -f "base/generate.ini" \\
  && ok "base/generate.ini" \\
  || miss "missing critical file: base/generate.ini"
test -f "base/pref.example.ini" \\
  && ok "base/pref.example.ini" \\
  || miss "missing critical file: base/pref.example.ini"
test -f "base/base/all_base.tpl" \\
  && ok "base/base/all_base.tpl" \\
  || miss "missing critical file: base/base/all_base.tpl"
test -f "base/profiles/example_profile.ini" \\
  && ok "base/profiles/example_profile.ini" \\
  || miss "missing critical file: base/profiles/example_profile.ini"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 101 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~71d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/tindy2013/subconverter"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

subconverter is a C++ utility that converts proxy subscription formats between incompatible proxy clients (Clash, Quantumult, Surge, V2Ray, Shadowsocks, etc.). It runs as an HTTP service (listening on port 25500) that accepts a source subscription URL and target format, applies rule definitions from /base/config/, and outputs configuration in the client's native format. The core value is enabling a single subscription source to work across all major proxy clients without manual reconfiguration. Monolithic C++ binary with /base/ directory storing static templates: /base/base/ holds client-specific base configs (clash_provider_test.yml, surge.conf, loon.conf, etc.), and /base/config/ holds rule/ACL definition files (ACL4SSR variants). HTTP server routes requests to conversion logic that selects base template + URL subscription + user-specified config, applies templating (likely Go Template based on CMake detecting 'pongo2' or similar), and outputs the merged result.

👥Who it's for

Users of proxy/VPN clients (Clash, Surge, Quantumult X, Loon) who receive subscriptions in one format but need them converted for a different client. Secondary audience: proxy service providers who need to serve multiple client types from a single subscription backend.

🌱Maturity & risk

Production-ready with active maintenance. GitHub Actions CI/CD is configured (.github/workflows/build.yml, docker.yml), releases are tagged, and Docker images are built automatically. The project has been developed long enough to support 15+ subscription formats and includes extensive base configuration templates. Actively maintained but appears to have a small core contributor base.

Single maintainer risk (tindy2013 is primary owner). Dependency risks are mitigated by C++ static compilation (few runtime deps visible in CMakeLists.txt). The /base/config/ directory contains 50+ ACL4SSR configuration variants that are manually maintained—drift or inconsistency in these templates could produce broken client configs. No visible test suite in the file list suggests limited coverage for conversion edge cases.

Active areas of work

Unable to infer from static file list alone—no recent commit history, issue list, or PR data provided. GitHub Actions workflows exist, suggesting CI pipeline is active. Docker workflow indicates regular image builds. The extensive ACL4SSR config variants (50+ files) suggest ongoing maintenance of rule rulesets.

🚀Get running

git clone https://github.com/tindy2013/subconverter.git && cd subconverter && mkdir build && cd build && cmake .. && make. Run with ./subconverter (listens on 127.0.0.1:25500). Test with curl 'http://127.0.0.1:25500/sub?target=clash&url=<encoded_sub_url>&config=ACL4SSR_Online'

Daily commands: Build: cd subconverter && mkdir build && cd build && cmake .. && make. Run: ./subconverter (default port 25500). Docker: docker build -t subconverter . && docker run -p 25500:25500 subconverter (Dockerfile exists).

🗺️Map of the codebase

  • CMakeLists.txt — Build configuration for the entire C++ project; defines compilation targets, dependencies, and output artifacts for all platforms.
  • base/generate.ini — Primary configuration file that controls subscription format conversion behavior and template selection for output formats.
  • base/pref.example.ini — Example preferences configuration showing all customizable conversion parameters and proxy filtering options.
  • base/base/all_base.tpl — Core template file used as the foundation for all subscription format conversions; defines the conversion logic structure.
  • base/profiles/example_profile.ini — Example profile demonstrating how to define custom conversion rules and output format specifications.
  • .github/workflows/build.yml — CI/CD pipeline that builds, tests, and packages the application for multiple platforms and architectures.
  • base/config/example_external_config.ini — Example external configuration showing remote rule loading and advanced conversion customization capabilities.

🛠️How to make changes

Add Support for a New Proxy Format

  1. Create a new template file in base/base/ directory with the target format name (e.g., base/base/mynewformat.conf) (base/base/mynewformat.conf)
  2. Define the conversion rules and proxy syntax in the template using the subconverter template language (base/base/mynewformat.conf)
  3. Register the new format in base/generate.ini by adding an entry mapping format name to template file (base/generate.ini)
  4. Add format-specific rule sets in base/rules/ directory if custom filtering rules are needed (base/rules/ACL4SSR/Clash/ProxyGFWlist.list)
  5. Rebuild the project using CMakeLists.txt to compile the new format support (CMakeLists.txt)

Create a Custom Conversion Profile

  1. Copy and modify base/profiles/example_profile.ini to define your custom conversion rules (base/profiles/example_profile.ini)
  2. Reference specific templates and rule sets from base/base/ and base/rules/ in your profile (base/generate.ini)
  3. Use base/pref.example.ini as reference for available preference parameters to customize conversion behavior (base/pref.example.ini)
  4. Test the profile by passing it to subconverter API endpoint and validate output format (base/profiles/example_profile.ini)

Add a New Filtering Rule Set

  1. Create a new .list file in base/rules/ACL4SSR/Clash/ directory with domain or IP rules (base/rules/ACL4SSR/Clash/BanAD.list)
  2. Use standard rule format (domain patterns, CIDR blocks, etc.) matching ACL4SSR conventions (base/rules/ACL4SSR/Clash/ChinaDomain.list)
  3. Reference the new rule set in conversion profiles or configurations via base/generate.ini (base/generate.ini)
  4. Create variants in other rule directories (e.g., base/rules/ACL4SSR/) if supporting multiple formats (base/rules/ACL4SSR/Clash/ProxyGFWlist.list)

Modify Build Configuration and Compilation

  1. Edit CMakeLists.txt to add new source files, dependencies, or compilation flags (CMakeLists.txt)
  2. Update .github/workflows/build.yml to define matrix builds for different platforms and architectures (.github/workflows/build.yml)
  3. Modify .github/workflows/docker.yml if containerization changes are needed for deployment (.github/workflows/docker.yml)
  4. Test locally with CMake and verify all workflows pass before committing (CMakeLists.txt)

🔧Why these technologies

  • C++ with CMake — Provides high-performance subscription parsing and conversion with portable cross-platform compilation; critical for handling large proxy lists efficiently.
  • INI/TOML/YAML configuration files — Enables flexible, human-readable configuration of conversion rules, templates, and profiles without recompilation.
  • Template-based format generation — Decouples proxy format specifications from core logic, allowing new proxy formats to be added by creating templates only.
  • GitHub Actions CI/CD — Automates multi-platform builds (Linux, macOS, Windows) and Docker image generation for reliable distribution.
  • ACL4SSR rule sets — Provides pre-built, maintained domain and IP filtering rules for common routing scenarios across multiple proxy formats.

⚖️Trade-offs already made

  • Template-based conversion over compiled format handlers

    • Why: Allows non-developers to add new formats without code changes, significantly reducing maintenance burden.
    • Consequence: Template syntax and parsing adds minor overhead compared to hard-coded format handlers; requires careful template design.
  • External rule set files loaded at runtime

    • Why: Enables rule updates without recompilation and supports multiple rule sources (local and remote).
    • Consequence: Adds I/O latency and requires network access for remote rules; increases initial conversion response time.
  • Supporting many proxy formats (Clash, Surge, Quanx, SingBox, etc.)

    • Why: Maximizes compatibility with diverse proxy ecosystems and user bases across different regions.
    • Consequence: Increased codebase complexity, more templates to maintain, and testing burden across format variants.
  • INI/TOML/YAML configuration over single format

    • Why: Caters to different user preferences and existing ecosystem configurations for maximum compatibility.
    • Consequence: Multiple configuration parsers and validation logic; slightly larger binary footprint and maintenance overhead.

🚫Non-goals (don't propose these)

  • Does not provide real-time proxy health checking or latency testing
  • Not a full-featured proxy client; only converts subscription formats
  • Does not handle user authentication or subscription account management
  • Not a VPN/proxy server; merely transforms subscription data between formats
  • Does not cache generated configurations persistently (stateless operation)
  • Does not provide GUI; API and command-line only

🪤Traps & gotchas

The /base/ directory is critical—if base templates are missing, conversions will fail silently or produce incomplete configs. CMake must find the base/ directory at runtime (likely hardcoded or via CONF_PATH env var, not visible in file list—check binary documentation). ACL4SSR .ini files use a custom rule syntax that is not standard; modifying rules requires understanding this format. The conversion output is heavily dependent on the specific target format (Clash YAML is very different from Surge conf), and mismatches between request parameters and available base templates will cause silent failures. No visible API validation—invalid target or config names may return generic errors.

🏗️Architecture

💡Concepts to learn

  • Dreamacro/clash — Core proxy client that subconverter converts to; understanding Clash YAML structure is essential for debugging conversion output
  • Loyalsoldier/clash-rules — Popular ruleset for Clash; subconverter integrates similar rule definitions from /base/config/ to enable rule-based routing
  • v2fly/v2ray-core — V2Ray is one of the supported source and target formats; understanding V2Ray JSON config structure helps debug conversions
  • ACL4SSR/ACL4SSR — Original ruleset provider that subconverter bundles in /base/config/ACL4SSR_*.ini files; upstream changes here may require syncing
  • chobits/cross — Alternative subscription converter; understanding competing approaches helps identify missing features or architectural improvements

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for subscription format conversion logic

The repo contains multiple subscription format converters (Clash, Surge, Quantumult, Shadowsocks, Sing-box, etc.) in base/base/ but there's no visible test directory structure. Adding unit tests for the core conversion functions would ensure format parity, prevent regressions, and help new contributors understand the conversion specification. This is critical for a utility that converts between formats.

  • [ ] Create a tests/ directory structure mirroring src/ organization
  • [ ] Add test cases for each format converter (Clash, Surge, Quantumult, Shadowsocks, Singbox, Mellow, Loon, Surfboard)
  • [ ] Create fixtures in tests/fixtures/ with sample subscription inputs and expected outputs for each format
  • [ ] Add tests for edge cases: special characters in names, IPv6 addresses, malformed inputs
  • [ ] Integrate test execution into .github/workflows/build.yml

Create automated validation workflow for config templates in base/config/

The repo has 40+ ACL4SSR configuration variants in base/config/ but no CI validation to ensure syntax correctness or prevent configuration drift. Adding a GitHub Action to validate YAML/INI/TOML syntax and check for required keys would catch configuration errors early and prevent broken releases.

  • [ ] Create .github/workflows/validate-configs.yml workflow
  • [ ] Add schema validation for ACL4SSR*.ini files (check required sections: [Rule], [Proxy Group], etc.)
  • [ ] Validate base/base/.yml and base/base/.json files for correct syntax
  • [ ] Add linting for base/config/example_external_config.* files (TOML, YAML, INI validators)
  • [ ] Configure workflow to run on PRs that modify files in base/ directory

Add integration tests for real-world conversion scenarios in .github/workflows/

The repo has docker.yml and build.yml but no workflow that tests actual conversion operations (e.g., converting a sample subscription to multiple formats simultaneously). This would validate that the full pipeline works end-to-end and catch integration issues that unit tests miss.

  • [ ] Create .github/workflows/integration-tests.yml workflow
  • [ ] Build test fixtures with sample proxy URLs (SS, VMess, Trojan, VLESS) in various formats
  • [ ] Test core conversion endpoints: ?target=clash, ?target=surge, ?target=quantumult, etc.
  • [ ] Validate output against format specifications (e.g., Clash config has valid proxy list)
  • [ ] Run against both library build and Docker container to ensure consistency

🌿Good first issues

  • Add a comprehensive test suite: create src/tests/ with unit tests for format conversions (e.g., parse_subscription_url, apply_clash_template, validate_surge_config). The current file list shows no _test.cpp or tests/ directory, so a contributor could add tests for the critical conversion functions.
  • Document the ACL4SSR rule syntax: create docs/RULESET_FORMAT.md explaining the .ini rule syntax used in /base/config/, including examples of domain rules, IP rules, and routing behavior. This would reduce barrier to contributing new rulesets.
  • Add missing target format support: implement conversion for Sing Box (partial support exists in base/base/singbox.json but no documented API endpoint). Add the format to README supported types table and wire it through the conversion pipeline.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 5b8d3af — Use latest macOS version for GitHub Actions (tindy2013)
  • 8a6e7f9 — Correctly format Hysteria2 server_ports for sing-box (#876) (PenXLa)
  • 6d312fe — Delete include/quickjspp.hpp (#872) (IceCodeNew)
  • d02351c — feat: proxyToLoon supports Hysteria2 (#871) (IceCodeNew)
  • 8e042ae — Fix icon-url not correctly appended to generated Surge configs (tindy2013)
  • 82f3467 — Modify rules order so that dns can be routed normally in Global mode. (#844) (ArakawaHenri)
  • b99c679 — Use GitHub-hosted ARM runner (tindy2013)
  • e1c0b95 — Support icon-url in Surge Proxy Groups (tindy2013)
  • c2610a3 — Enhanced Profile Configuration Parsing and Tag Matching in profile.ini (#820) (se7enmuting)
  • e17246d — Feat(hysteria2): support hysteria2 port hopping for clash/singbox results (#817) (topjohncian)

🔒Security observations

  • High · Potential URL/Subscription Format Injection — Core conversion logic (not visible in provided structure). As a subscription format converter, this utility processes user-supplied subscription URLs and formats. Without visible input validation in the file structure, there is risk of injection attacks through malformed URLs, proxy strings, or configuration data that could lead to arbitrary code execution or data exfiltration. Fix: Implement strict input validation and sanitization for all subscription URLs and format conversions. Use allowlist-based validation for proxy protocols and configuration parameters. Consider sandboxing format conversion logic.
  • High · Configuration File Security — base/config/, base/pref.example.*, base/profiles/. Multiple configuration files are stored in the repository (base/config/*.ini, base/pref.example.ini, base/pref.example.toml, base/pref.example.yml). If sensitive information like API keys, authentication tokens, or credentials are included in non-example configs, they could be exposed. The example files may provide templates for malicious configurations. Fix: Ensure no sensitive credentials are committed to the repository. Use environment variables or secure credential management for sensitive data. Mark all example configuration files clearly and document security implications. Consider adding pre-commit hooks to prevent accidental credential commits.
  • Medium · Untrusted Configuration and Rule Loading — base/rules/, base/config/, base/base/. The repository contains numerous rule files (base/rules/ACL4SSR/Clash/*.list) and configuration files that appear to be loaded and processed. If these files are loaded from remote sources or user-controlled paths without proper validation, it could lead to arbitrary rule injection or configuration tampering. Fix: Implement integrity verification (e.g., checksums, digital signatures) for remotely sourced configuration and rule files. Validate file formats strictly before processing. Use allowlists for acceptable configuration sources. Log all configuration/rule file loads for audit purposes.
  • Medium · Potential Command Injection via Proxy Strings — Proxy parsing and generation logic (not visible). As a proxy converter utility, the application likely parses and generates proxy connection strings. If user input is not properly escaped when constructing proxy configurations or commands, it could enable command injection attacks. Fix: Use parameterized/structured approaches for proxy configuration construction rather than string concatenation. Implement comprehensive input validation and output encoding. Never pass user input directly to system commands. Use safe libraries for URL/proxy parsing.
  • Medium · Missing Security Headers and CORS Configuration — Web service configuration (not visible in provided structure). The application appears to be a web service based on the file structure. Without visible security header configuration, the API may be vulnerable to XSS, clickjacking, and other web-based attacks. CORS misconfiguration could allow unauthorized cross-origin requests. Fix: Implement security headers (Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security). Configure CORS restrictively with explicit allowlists. Disable unnecessary HTTP methods. Implement rate limiting and request validation.
  • Medium · Insecure Deserialization Risk — base/base/*.yml, base/config/*.ini, base/config/*.toml, base/config/*.yml. The utility processes multiple configuration formats (YAML, TOML, JSON, INI). If deserialization is performed without proper validation, it could lead to arbitrary code execution through YAML anchors, object instantiation, or other deserialization gadgets. Fix: Use safe deserialization libraries and configure them to prevent arbitrary object instantiation. Avoid YAML features like anchors and aliases for untrusted input. Validate deserialized data against strict schemas. Consider using safer formats like JSON for untrusted input.
  • Low · Insufficient Logging and Monitoring — Project-wide. No visible logging configuration or security event monitoring in the provided file structure. This makes it difficult to detect and investigate security incidents. Fix: Implement comprehensive logging for all important operations, especially conversion requests, file loading, and configuration changes. Log security-relevant events (failed validations, suspicious inputs). Implement alerting for anomalous activity. Ensure logs are protected and retained appropriately.
  • Low · No Visible Dependency Lock File — undefined. The dependency file content was not provided. Without a lock file (package-lock.json, Cargo.lock, etc.), dependency versions Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · tindy2013/subconverter — RepoPilot