Clash Rule Providers: Advanced YAML Rules and GitHub Hosting

Why Use Clash Rule Providers? Demystified

A RULE-SET entry in the primary rules list connects the named provider to a policy such as DIRECT, REJECT, or a proxy group that already exists in the profile. If whichever one of those pieces is missing or inconsistent, the rule set may not load or may not route the traffic you intended.

If you have ever pasted a long list of domains into the rules: section of a Clash profile, you have already seen the problem rule providers solve. The profile grows harder to review, updating one service can mean editing a large file, and a typo near the top can change the route for traffic far below it.

A Clash rule provider moves a group of related rules into a separate file and lets the primary profile reference that file by name. Your everyday configuration stays readable while the rule set can be maintained and updated independently.

One more angle:Providers are especially useful when you have to keep several policies distinct: advertising domains ought to be rejected, a set of work services ought to go direct, and selected streaming or developer destinations ought to use a proxy group.

You are able to refresh one provider without rewriting unrelated rules, reuse a well-organized set across profiles, and inspect the provider file in version control before it reaches your active configuration. That separation is valuable even for a small personal profile: it makes a change easier to explain, test, and undo.

A provider is not a new routing policy by itself. It supplies rules to the core, and the primary profile still decides where matching traffic goes. The rule that references a provider names both the provider and its destination policy.

Check the core, not just the UI. Provider fields and accepted file formats depend on the core and its version.

Numerous current clients execute Mihomo, but a client name or a “Clash-compatible” label alone does not prove that every Mihomo feature is available. Confirm the selected core and consult its documentation when a field is rejected.

A detail worth adding:The order of that rule among the rest of rules: remains important: Clash evaluates rules from top to bottom and uses the first applicable match. A correct provider placed after a broad rule may never get a chance to affect a connection.

It also helps to separate three things that are often confused. The provider definition tells the core where to get the file, what kind of rules it contains, where to cache it, and how often to refresh it. The provider file contains the actual rule entries.

A Working YAML Example and What Each Field Does at a Glance

Likewise, Proxy must exactly match a policy defined in proxy-groups or another valid destination in your profile. A provider can load successfully while its routing rule still points to a nonexistent policy, so validate both parts somewhat than stopping at a successful download.

The following example uses a domain-based provider hosted in a public GitHub repository. It is a fragment for a Mihomo-style profile, not a full configuration: keep your existing proxies and proxy-groups sections, and make sure the referenced policy name exists.

rule-providers:
  example-services:
    type: http
    behavior: domain
    url: "https://raw.githubusercontent.com/your-name/clash-rules/main/providers/example-services.yaml"
    path: ./ruleset/example-services.yaml
    interval: 86400

rules:
  - RULE-SET,example-services,Proxy
  - MATCH,DIRECT

Said differently:The example uses Proxy as that policy; if your profile calls the group Auto or something else, substitute its exact name.

The URL must point to the raw YAML file, not the GitHub repository page that displays it in a browser. Replace your-name and the repository path with a repository and file you control or trust. The type: http setting tells Mihomo to retrieve the provider over HTTP or HTTPS.

The behavior: domain setting describes the content as a set of domain entries, somewhat than a collection of full routing rules. The path is a local cache location used by the core. The interval is measured in seconds, so 86400 means one day.

payload:
  - '+.service.example'
  - '+.api.example.net'
  - 'login.example.org'

In practice that means:A corresponding provider file for the example could look like this:

Keep the provider file valid YAML and match its entries to the selected behavior. In a domain provider, list domain patterns somewhat than adding full rule lines such as DOMAIN-SUFFIX,example.com; that form belongs in a classical rule set.

A leading +. is commonly used for a domain and its subdomains in Mihomo domain lists, while a plain hostname is useful when you only want to match that exact name. If you intend to match a parent domain and all its subdomains, use a pattern that expresses that scope clearly and test it against real connection-log entries.

Worth noting:The order in the example is deliberate. The provider rule appears before the catch-all MATCH,DIRECT line, so a domain in the provider can be routed to Proxy before unmatched traffic falls through to direct. If you put MATCH,DIRECT first, it would catch every connection and the provider would be effectively unreachable.

The same issue can occur with broad rules such as a country-wide direct rule or a general domain suffix placed above a more specific provider. Decide which rule ought to win, then position it accordingly.

Use one naming convention and keep it consistent. The key example-services under rule-providers is the provider name, and the same name appears after RULE-SET. A misspelling in either location can prevent the rule from resolving.

Host Rule Files on GitHub Without Making Refreshs Fragile Broken Down

For a shared deployment where reproducibility matters, a versioned release or an immutable commit-based URL can make the fetched contents easier to audit, although you must refresh the URL deliberately when you approve a new version. Choose the model that fits your refresh process, and document who is allowed to change the provider.

One more angle:GitHub is a handy place to host a small rule provider because it gives you a readable history, an easy way to review changes, and a steady repository path when you control the project. Create a repository, add the provider file, and use the file’s raw URL in the profile.

A public repository is necessary for a core to fetch the file without an auth flow. Do not place subscription links, credentials, private hostnames, or other sensitive data in a public rule repository; a rule set ought to contain routing data, not secrets.

Organize files so that the URL is easy to understand and unlikely to change accidentally. For example, a repository might use a providers/ directory with separate files for services, work domains, and advertising domains.

A detail worth adding:Keep filenames descriptive, use lowercase names with hyphens, and avoid repeatedly moving files after a profile has been deployed. If you rename a branch, directory, or file, refresh every profile that points to the old raw URL. A repository page can still look correct to you while the old raw URL returns a not-found response to Clash.

Version control is more than a backup. Before committing a change, review the diff and ask what new traffic could match the added pattern, what traffic could stop matching after a deletion, and whether the change accidentally broadens a domain rule.

Make small commits with useful messages, such as “Add login host for service example,” somewhat than replacing an entire list without explanation. If a new provider version breaks routing, the Git history makes it possible to identify the last known-good file and restore it instead of trying to reconstruct a previous configuration from memory.

Said differently:The interval value controls how often the core checks for provider refreshs; it is not a guarantee that a remote file will be fetched at a precise second. A shorter interval can help when you intentionally publish frequent changes, but it creates more requests and does not make a bad edit safer.

For a mostly steady personal list, a daily or longer interval is often sufficient. If you are actively testing changes, use the client’s provider-refresh action or restart the relevant core when appropriate, then confirm in the logs that the new file was actually downloaded and parsed.

Consider whether you want a moving branch URL or a deliberately pinned revision. A URL that follows the repository’s primary branch is handy because future commits become available without changing the profile. That convenience also means a careless or compromised commit can affect clients at their next refresh.

Publish safely: validate the YAML locally, commit the change, open the raw file URL in a browser, and then refresh the provider in Clash.

A successful browser response only confirms that the URL is reachable; the core still needs to parse the file and accept its behavior.

Validate Rule Order and Test the Result From the Ground Up

This is especially useful when a provider contains numerous entries: a single overly broad domain pattern can affect more traffic than its short YAML line suggests. A brief review and a repeatable test set are typically faster than diagnosing an unexpected route after every device has already refreshed.

In practice that means:Make provider changes in a controlled sequence somewhat than changing the provider, DNS mode, proxy group, and catch-all rules at the same time. First confirm that the provider file is reachable and that the core accepts the profile.

Then inspect the live connection list while visiting one hostname that ought to match the provider and one hostname that ought to not. Check the destination, matched rule, and selected policy shown by the client. These observations tell you whether the provider was loaded, whether the intended rule matched, and whether the selected policy behaved as expected.

Test both sides of the rule. If service.example ought to go through Proxy, a connection to that host ought to show a provider or rule-set match and the expected group or node. A separate unrelated hostname ought to continue to follow the later rules in the profile.

Worth noting:If both connections hit the same broad rule, inspect ordering before changing the provider contents. If neither connection appears in Clash, the application may be bypassing the system proxy, using a different client profile, or not being captured by the current proxy mode.

When you use a domain provider, remember that matching depends on the hostname the core can see. An application may connect to an IP address straight away, use an alias, or follow a redirect to a different domain. A rule for a website’s primary hostname does not on its own cover every API, auth, media, or download host used behind the scenes.

Use the connection log to discover actual destinations, then add only the hosts needed for the behavior you want. Avoid turning one missing host into an unnecessarily broad suffix rule without checking what else that suffix includes.

One more angle:Profile validation ought to happen before activation whenever your client offers a test or parse function. A YAML indentation failure can make the entire profile invalid, not merely the new provider.

Use spaces somewhat than tabs, keep nested fields aligned, and compare the indentation of rule-providers and rules with the rest of the profile. A YAML editor may show valid syntax while the core rejects a semantically invalid field, so the core’s own validation result and runtime log remain the final checks.

For a shared setup, test a staged copy of the profile first. Point that copy at the candidate provider, refresh it, and reproduce a small set of known connections. Only promote the change to a daily-use profile after confirming the expected match and fallback behavior.

Troubleshoot Rule-Set Loading Failures from the Logs Demystified

Hosting a small, reviewed provider gives you a visible change history and lets you keep policy choices in the primary profile, while a Clash client with Mihomo support makes provider refreshes, rule inspection, and log-based troubleshooting easier to manage from one UI. If you want a practical place to bring in and test that workflow, choose a Clash client to download and try it with a non-critical profile first.

A detail worth adding:When a provider does not work, launch with the core log and classify the failure instead of immediately editing several fields. A network or HTTP failure points toward the URL, DNS, TLS, GitHub availability, or a blocked connection. A not-found response typically means the repository, branch, directory, or filename in the raw URL is wrong.

A successful HTTP response followed by a parse or behavior failure points toward the provider file’s YAML structure or a mismatch between the declared behavior and the entries it contains. The wording varies by core version, so use the first relevant failure line and the provider name as your starting point.

If the log indicates that the provider cannot be downloaded, open the exact raw URL from the same network and verify that it returns the file itself somewhat than a GitHub HTML page. Check for a private repository, a renamed out of the box branch, an incorrect letter case in the path, or a temporary TLS and DNS problem.

Said differently:Then try the client’s refresh action and examine the new log entries. A browser test from your laptop is useful, but it does not prove that a remote device or a different network can reach the same endpoint.

If the download succeeds but the rules do not match, verify four names and relationships: the provider key in rule-providers, the provider name in RULE-SET, the policy destination, and the actual hostname shown in the connection log. Next, check whether the rule is below a broader rule that already catches the connection.

Finally, confirm that the provider uses the right behavior. A domain list and a classical list have different expected content; changing the label without changing the file structure does not convert one format into the other.

In practice that means:A provider can also load correctly but appear stale. Check its configured refresh interval, the last refresh time displayed by the client if available, and whether the core is using a cached file. Trigger a manual refresh and inspect the log for a successful fetch somewhat than assuming that saving the profile initiated a network request.

If a new commit does not appear, compare the raw file with the version expected by the profile and consider repository caching or a URL that points to a different branch. Avoid deleting the cache as a first response; first establish whether the problem is the remote content, the fetch, or the local copy.

For diagnosis, change one variable at a time and keep a known-good version of both the primary profile and provider file. If you have to roll back, restore the previous commit or URL, refresh the provider, and confirm that the old behavior returns.

Worth noting:This separates a bad rule change from an unrelated network outage or client refresh. Record the core version and the relevant log message when asking for help, but redact subscription URLs, access tokens, private domains, and other sensitive details before sharing screenshots or logs.

A number of community rule collections are handy but may have unclear ownership, infrequent reviews, or a scope that does not match your traffic; by hand embedding every rule in one profile can be just as hard to maintain once several devices depend on it.