Clash Rule-Providers: Advanced GitHub Rules Configuration

NT-06.1What Rule Providers Do in a Clash Configuration

A rule provider is an external or local rule set that Clash loads as a named resource and then references from the main rules list. Instead of placing hundreds or thousands of domain and IP rules directly inside one profile, you keep those rules in separate files and connect them through the rule-providers section. Clash Verge, Clash Verge Rev, Clash for Windows, ClashX, Clash for Android, and mihomo-based clients may expose the feature through different interfaces, but the configuration concept is the same: define a provider, assign it a behavior, and call it with a RULE-SET rule.

This separation is useful for more than keeping YAML short. It lets you maintain different traffic categories independently, such as streaming services, local networks, developer platforms, advertising domains, or private corporate services. The main profile controls policy groups and matching order, while each provider contains a focused collection of match conditions. Updating a provider therefore does not require rewriting the node list, proxy groups, DNS settings, or TUN settings in the rest of the profile.

A provider is not a proxy group and does not decide whether traffic is proxied by itself. It only answers the question “does this destination match this rule set?” The policy written after the provider name supplies the action. For example, RULE-SET,streaming,Streaming means that a destination matching the provider named streaming is sent to the proxy group named Streaming. If that group does not exist, the provider may load correctly but the rule still cannot perform the intended routing.

Keep the Three Names Separate

The provider key, the rule-set reference, and the policy group are different names. In RULE-SET,streaming,Streaming, the first streaming must match a key under rule-providers, while the second Streaming must match a name under proxy-groups. Treating them as interchangeable is a common cause of rules that appear to load but never route traffic correctly.

NT-06.2Designing the Provider YAML

Each provider is normally declared under a unique key. The provider object describes where the file comes from, how its entries should be interpreted, and where the client should cache it locally. A remote HTTP provider generally uses type, behavior, format, url, path, and interval. The exact support level depends on the Clash core and client version, so a configuration intended for mihomo should be tested in the actual client rather than assumed to work identically in every legacy Clash fork.

FieldRolePractical Notes
typeSource method for the providerhttp downloads a remote file; file reads a local file; inline stores rules in the profile when supported by the core
behaviorMeaning of each rule entryCommon values are domain, ipcidr, and classical
formatFile representationUse yaml, text, or a core-supported binary format such as mrs
urlRemote download addressUse a raw file endpoint that returns the rule file itself, not an HTML repository page
pathLocal cache locationUse a stable path inside the client's working directory and avoid paths that are cleared on every startup
intervalRefresh interval in secondsChoose a sensible interval; frequent checks do not make an unavailable host more reliable

The following example uses three providers with different behaviors. The URLs are placeholders; replace them with the raw endpoints generated by your own Git hosting or deployment service. The important part is the relationship between the behavior, file format, and rule contents.

rule-providers:
  streaming:
    type: http
    behavior: domain
    format: yaml
    url: https://raw.example.invalid/catalog/streaming.yaml
    path: ./ruleset/streaming.yaml
    interval: 86400

  private-network:
    type: http
    behavior: ipcidr
    format: yaml
    url: https://raw.example.invalid/catalog/private-network.yaml
    path: ./ruleset/private-network.yaml
    interval: 86400

  development:
    type: http
    behavior: classical
    format: text
    url: https://raw.example.invalid/catalog/development.list
    path: ./ruleset/development.list
    interval: 86400

proxy-groups:
  - name: Streaming
    type: select
    proxies:
      - Proxy
      - DIRECT

  - name: Development
    type: select
    proxies:
      - Proxy
      - DIRECT

rules:
  - RULE-SET,private-network,DIRECT
  - RULE-SET,streaming,Streaming
  - RULE-SET,development,Development
  - MATCH,Proxy

A domain provider normally contains domain values rather than complete classical rules. Depending on the selected file format, the provider may be represented as a YAML rule list or a supported text list. An IP-CIDR provider contains network ranges such as private subnets, and a classical provider can contain complete rule expressions such as DOMAIN-SUFFIX, DOMAIN-KEYWORD, IP-CIDR, or PROCESS-NAME when the running core supports those rule types.

# streaming.yaml
payload:
  - '+.media.example'
  - '+.video.example'
  - 'stream.example'

# private-network.yaml
payload:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

# development.list
DOMAIN-SUFFIX,packages.example
DOMAIN-SUFFIX,registry.example
DOMAIN-KEYWORD,code-host

Do not mix formats casually. A file containing classical expressions should not be declared as a plain domain provider, because the core may interpret every line as a domain value or reject the provider during parsing. Likewise, an IP-CIDR provider should contain valid CIDR notation, and IPv6 entries may require the corresponding IPv6 option in the final rule invocation depending on the core and configuration. If a provider fails to load, inspect the client log before changing unrelated proxy settings.

NT-06.3Hosting and Updating Rule Sets Through GitHub

GitHub is convenient for rule maintenance because each provider can live in a separate file, changes are tracked, and updates can be reviewed before publication. A practical repository layout might look like this:

rules/
  streaming.yaml
  private-network.yaml
  development.list
  regional-classical.list
README.md

Keep the repository focused on rule data rather than placing a complete Clash profile in every file. The main configuration should own proxy groups and global behavior. The repository should own the entries that belong to each category. This boundary makes it easier to reuse the same provider with several profiles and reduces the chance that a provider update will unexpectedly replace a user's node or DNS configuration.

  1. Create one file for one traffic category. Use names based on purpose, such as streaming.yaml or private-network.yaml, rather than names tied to a temporary proxy group.
  2. Choose the provider behavior before writing entries. Use domain for domain-focused lists, ipcidr for network ranges, and classical when complete Clash rule expressions are required.
  3. Validate indentation, quoting, and line endings locally. YAML is sensitive to indentation, while text providers should not contain accidental headings or explanatory prose inside the rule body.
  4. Commit the change with a clear message and review the difference. Look for accidental deletions, duplicated entries, overly broad keywords, and private addresses that should not be distributed publicly.
  5. Publish the file through a raw file endpoint. Opening a repository page in a browser is not enough; Clash needs the response body containing the provider data.
  6. Update the provider manually in the client and inspect the log. Confirm that the file was downloaded, parsed, and stored at the configured path.

For a stable deployment, avoid changing the file path every time the list is updated. The client uses the path as its cache location, and a stable path makes manual refreshes and offline startup behavior easier to understand. A long refresh interval such as one day is usually adequate for lists that change occasionally. Very short intervals can create unnecessary requests and may make rate limits or temporary hosting failures more visible without improving routing quality.

Raw Hosting Is Still a Dependency

A public repository does not guarantee that every network can reach its raw download endpoint. If the client log shows a timeout, HTTP error, redirect problem, or HTML content instead of rule data, test the endpoint from the same device and network. Consider a trusted mirror or another HTTP host when the raw service is unreliable in the target environment, and keep the provider URL consistent across profiles.

Branch-based URLs are simple to maintain, because every commit to the selected branch updates the provider automatically after the next refresh. For stricter change control, use a URL that identifies a reviewed commit or a release artifact, then update that reference deliberately after testing. A pinned reference improves reproducibility but requires an explicit maintenance step. The appropriate choice depends on whether the provider is a personal list that changes often or a shared production policy that should change only after review.

NT-06.3.1Validate the File Before Publishing

Validation should cover both syntax and routing meaning. A syntactically valid domain list can still be dangerous if it contains a broad keyword that catches unrelated services. Check that domain suffixes begin and end as intended, that CIDR ranges are not wider than necessary, and that classical rules use policy-independent match expressions. Then load the provider in a test profile and inspect representative destinations in the client’s connections or rule-match panel.

After an update, test at least one domain that should match, one domain that should not match, and one destination covered by a higher-priority local rule. This catches the two most common deployment mistakes: the provider was never loaded, or it loaded successfully but is placed in a rule order where another rule wins first.

NT-06.4Matching Order, Modular Policies, and Troubleshooting

Clash evaluates the main rules list from top to bottom. The first matching rule determines the policy, so a provider reference placed too low may never be reached. This matters especially when broad rules such as GEOIP, IP-CIDR, or MATCH appear before a specialized provider. The final MATCH rule is normally a deliberate fallback and should remain last unless there is a specific reason to use another terminal rule.

rules:
  # Specific exceptions first
  - DOMAIN,router.lan,DIRECT
  - RULE-SET,private-network,DIRECT

  # Purpose-specific providers next
  - RULE-SET,development,Development
  - RULE-SET,streaming,Streaming

  # Broader geographic or network policies afterward
  - GEOIP,LAN,DIRECT,no-resolve
  - GEOIP,CN,DIRECT

  # Terminal fallback
  - MATCH,Proxy

The no-resolve option shown on a rule is useful when an IP-based decision should not trigger an additional DNS lookup. Use it only when its behavior fits the rule and DNS design. It is not a universal fix for DNS problems, and it does not turn a domain provider into an IP provider. Domain matching and IP matching remain separate concerns; if a destination is represented only by an IP address, a domain-only provider may not match it.

Modular providers should also have clear ownership. Keep local bypasses in a small local provider, service-specific domains in separate providers, and network ranges in an IP-CIDR provider. Avoid one enormous “everything” list because it becomes difficult to determine why a destination matched and difficult to review changes. Smaller files make rollback easier and allow different profiles to select only the categories they need.

SymptomLikely CauseCheck First
Provider shows a download errorEndpoint is unreachable, redirected, rate-limited, or returns an HTML pageOpen the raw endpoint and inspect the client log
Provider downloads but rules never matchBehavior does not describe the file contents, or another rule appears firstCompare behavior with the entries and review rule order
Configuration fails to parseYAML indentation, quoting, or an unsupported field is invalidValidate the complete profile and check the mihomo version
Some domains bypass unexpectedlyThe list is incomplete, a keyword is too narrow, or the destination uses an IPTest the exact hostname and inspect the connection’s matched rule
Old behavior remains after an updateThe cached provider was not refreshed or the client is using another profileConfirm the active profile, refresh the provider, and inspect its cache path

When a rule does not behave as expected, isolate the layers in order. First confirm that the intended profile is active. Next confirm that the provider is listed and has a successful update timestamp. Then verify the provider’s behavior and file contents. Finally inspect the rule order and the policy group selected by the matching rule. Switching temporarily to Global mode can help distinguish a node problem from a rule problem, but it does not prove that a provider is correct.

Before sharing a configuration, remove access tokens, private hostnames, internal CIDR ranges, and other sensitive data. A Git repository gives you change history, not automatic privacy. Review every committed provider as if it were a public policy document. Once the files are validated, keep a small change log describing why a domain or range was added, and periodically remove obsolete entries. Reliable rule routing comes from precise data, compatible provider declarations, predictable matching order, and a hosting path that the client can actually reach.

Put the Rule-Provider Workflow Into Practice

Choose a Clash client with mihomo-compatible rule-provider support, import your profile, and verify each hosted provider from the client’s update and connection logs.

Download Client
Download Clash