What a Clash rule provider does—and what it does not do
A Clash rule provider stores a reusable set of matching rules in a separate file, then lets a profile reference that set by name. Instead of pasting hundreds of domain entries into every profile, you can maintain one hosted rule file and attach it to the profiles that need it. This is useful for personal allowlists, application-specific routing, team policies, and rules that change more often than the rest of your configuration.
A provider is not a proxy server, a subscription, or a policy group. It does not decide where traffic goes by itself. The provider supplies match conditions; a line in the profile’s rules section connects those conditions to an existing policy such as DIRECT, Proxy, or a selector group. If the provider is downloaded successfully but no matching RULE-SET entry appears in the active rules, the file can be present without affecting traffic.
Think of the process as three separate pieces. First, the hosted file contains the rule payload. Second, the profile’s rule-providers section tells Mihomo where to fetch that file, how to interpret it, where to cache it, and how often to refresh it. Third, the ordered rules list decides which policy receives connections that match the provider. Keeping those responsibilities separate makes failures much easier to isolate: a fetch problem is different from a malformed payload, and both are different from a correct rule that is shadowed by an earlier match.
Rule providers are especially useful when you maintain more than one profile or device. A shared provider gives you one place to review a domain set, while each profile can choose its own policy. For example, a work profile might route a provider through a company-approved group, while a personal profile sends the same matches through a different selector. Sharing the match list does not require sharing every other setting in the configuration.
Before building one, decide what kind of data it needs to match. Use a domain provider for domain-oriented entries, an ipcidr provider for IP ranges, and a classical provider when the file needs full Clash rule expressions such as domain, process, or network rules. These behaviors are not interchangeable. A file containing DOMAIN-SUFFIX expressions should not be declared as a domain-only payload, and a plain hostname list should not be treated as a complete set of classical rules.
Build a rule file and host it on GitHub
Choose a format that matches the rules
For a domain provider, keep the payload focused on domain patterns. The following example uses a simple YAML file named social.yaml. Replace the sample domains with entries you actually need, and use quoting where a value contains characters that could be interpreted specially by YAML.
payload:
- '+.community.example'
- 'full:status.community.example'
- '+.media.example'
A leading +. represents the domain and its subdomains in Mihomo’s domain-rule syntax. The full: form targets one exact hostname. Do not add a scheme such as https://, a URL path, or a port to a domain entry: rule matching is based on the supported rule syntax, not on a complete browser address. Check the core version used by your client if you rely on less common rule forms, because a client’s interface and its bundled core may not support identical features.
If you need complete rule expressions instead, create a classical provider. Its payload can contain entries such as DOMAIN-SUFFIX or DOMAIN, with the policy field written as a placeholder because the enclosing RULE-SET line supplies the actual policy. Keeping that placeholder consistent helps readers understand that the provider describes matches rather than hard-coding one profile’s routing choice.
payload:
- DOMAIN-SUFFIX,community.example
- DOMAIN,status.community.example
- DOMAIN-KEYWORD,community-api
Create a GitHub repository for the list, add the YAML file, and commit it to a branch you intend to maintain. A public repository is the straightforward choice for a provider that Clash must retrieve without interactive sign-in. In the GitHub interface, open the file and use its raw-file URL, or construct a raw URL using the repository owner, repository name, branch, and file path. Test that URL in a private browser window: it should return the file contents directly rather than a GitHub page, a sign-in screen, or a 404 response.
Treat the repository as configuration infrastructure, not as a scratchpad. Use descriptive filenames, review edits before merging them, and avoid committing credentials, subscription links, internal hostnames, or other sensitive data. A public raw URL is not an access-control mechanism. Private-repository authentication is not automatically handled by an ordinary provider URL, so do not assume that making a repository private will preserve access for a standard Mihomo fetch.
Choose the URL strategy deliberately. A branch-based raw URL follows later commits on that branch, which is convenient when you want routine changes to arrive on the next refresh. A URL pinned to a specific commit gives you a stable snapshot, which is easier to audit and reproduce but will not pick up later edits until you change the URL. The right choice depends on whether you value automatic updates or a deliberately reviewed version. For a shared or operational profile, record who owns the repository and how changes are reviewed so a broken or unexpectedly expanded rule set is not a mystery months later.
Configure the provider, refresh interval, and route
Add a provider definition to the active profile’s rule-providers section. This example fetches a domain-format YAML file from GitHub and stores a local copy under the profile’s working directory. Adjust the owner, repository, branch, path, and provider name to match your project.
rule-providers:
community-sites:
type: http
behavior: domain
url: "https://raw.githubusercontent.com/OWNER/REPOSITORY/main/rules/social.yaml"
path: ./ruleset/community-sites.yaml
interval: 86400
format: yaml
rules:
- RULE-SET,community-sites,Proxy
- MATCH,DIRECT
The provider key, here community-sites, is an identifier chosen by you. The type: http field tells Mihomo to retrieve the resource over HTTP or HTTPS; behavior describes the payload; url points to the hosted file; path specifies the local cache location; and interval is the refresh interval in seconds. The explicit format: yaml makes the expected file format clear. Keep the provider name in the RULE-SET line exactly the same as the key under rule-providers.
An interval of 86400 requests a daily refresh. A shorter interval can be helpful while testing, but frequent polling usually adds little value for a list that changes only occasionally. It also makes transient network failures more visible and can generate unnecessary requests. Pick a refresh cadence that reflects how quickly the list needs to change, then remember that a refresh is not the same as an immediate push: after editing the GitHub file, the active client may continue using its cached copy until the provider is updated manually or its interval expires.
The path is a local cache path, not another remote URL. Make sure its parent directory can be created and written by the core process. If you run multiple profiles, use paths that do not unintentionally cause unrelated providers to overwrite the same file. When a client manages configuration through a profile editor or merge system, place the provider definition in the configuration layer that actually reaches the running Mihomo core; editing a dormant source file will not change the active runtime.
After the provider definition, insert its RULE-SET entry in the correct position inside rules. In the example, matching provider entries go to Proxy, and only traffic that reaches the final MATCH rule goes to DIRECT. Replace those policies with names that exist in your own configuration. If the selected group is misspelled or absent, the configuration may fail validation or behave differently from what you intended.
Rule order matters because the core evaluates rules from top to bottom and uses the first applicable match. If a broad rule such as DOMAIN-SUFFIX,example appears above your provider and already catches the same host, the provider’s later policy will never get a chance to apply. Put narrow exceptions and targeted provider rules before broader domain rules and catch-all rules. Do not move every provider to the top without checking what it contains: an expansive list can capture traffic that should have been handled by a more specific rule.
If you use an IP-CIDR provider, verify that its entries and behavior match the core’s expected format. IP rules can interact with DNS resolution differently from domain rules. In configurations where an IP rule should not trigger an extra DNS lookup, the supported no-resolve option may be appropriate, but it belongs to the rule expression and should be used only when its effect is understood. Avoid copying a setting from another profile without confirming the rule type and the DNS behavior you want.
Test loading, diagnose routing, and maintain the list
Start with configuration validation before investigating network paths. A YAML indentation mistake can prevent the provider from being parsed at all. Check that rule-providers and rules are at the correct top level, their nested keys are consistently indented, and the provider’s name matches exactly in both sections. Also check that the file begins with the expected payload structure and that its behavior agrees with the content. A successful profile save is useful evidence, but it does not prove that a remote provider was downloaded or that a particular request matched it.
Next, inspect the client’s provider or rule-provider view, if available, and the Mihomo logs. Look for the provider name, the fetch result, the timestamp of the cached update, and any parse or HTTP error. A 404 usually points to an incorrect repository, branch, or file path. A response containing an HTML error page rather than YAML commonly indicates that the URL is a GitHub file-view page instead of a raw-file address, or that the repository is not publicly readable. A TLS or timeout error points toward connectivity, DNS, system time, or an upstream network path rather than necessarily indicating invalid rule syntax.
When a provider loads but traffic still follows the wrong route, test one hostname that is definitely included in the file. Confirm that the hostname matches the intended entry, then inspect the connection log or rule-matching details in your client to see which rule actually won. If an earlier rule matched, reorder the relevant entries and test again. If the provider rule appears to match but its policy is not selected, verify that the referenced group exists and that the active profile contains the rule you edited. A successful fetch proves only that the file arrived; it does not prove that the desired rule was evaluated.
A stale result deserves its own check. Update the provider manually from the client when the interface offers that action, then confirm the update time and inspect the cached or loaded content if the client exposes it. If the manual update fails, open the raw URL independently and compare its current contents with what the client reports. If the URL works in a browser but not in Clash, check whether the core is using a different DNS or proxy path, whether the process can write to the configured cache path, and whether the active profile is the one you edited.
GitHub is convenient for small public rule lists, but it is not a universal availability guarantee. GitHub access may be blocked or unreliable on a network, raw-file delivery can be temporarily unavailable, and an upstream change can affect every profile that tracks a moving branch. Keep the list small, avoid unnecessary refreshes, and retain a known-good copy or commit reference so you can roll back. For business-critical routing, use an approved hosting and change-management process rather than making an informal public repository the only source of truth.
Maintain the list with the same care you would give any policy file. Remove entries that are no longer needed, document unusual patterns, and test both intended matches and nearby domains that should not match. A broad suffix can capture more subdomains than expected; a keyword rule can match unrelated names; and an IP range may include services beyond the one that prompted its addition. Review changes as diffs instead of replacing the file wholesale, and keep the provider’s purpose narrow enough that another operator can understand why each category exists.
Some clients make manually entered rules feel simpler at first, but long inline lists are harder to review, share, and update consistently; hand-maintained external scripts can add another layer of version and cache confusion. A provider-based setup gives you a visible source file, an explicit refresh policy, and a clear place in the ordered routing rules, while Clash V.CORE helps bring those pieces together in a maintained Clash workflow. If you want to manage custom rules without scattering edits across profiles, compare the available options and download Clash V.CORE to try a setup suited to your configuration.