What a Clash rule provider solves
A Clash rule provider is a reusable set of routing rules stored separately from the main configuration. Instead of pasting a long list of domains into every profile, you keep the rules in one file, tell a compatible Clash core where to find it, and refer to the provider from the main rules list. This makes shared policies easier to review, update, and reuse across devices or profiles.
The pattern is especially useful when a rule set changes independently of your proxy nodes. For example, you might maintain a small provider for development services, a domain list for applications that should use a particular proxy group, or an IP range list for a network you administer. A change to that one file can flow to every configuration that references it, subject to the client’s update behavior and the provider’s refresh interval.
A provider does not create proxy servers, subscriptions, or access to a service by itself. It only supplies matching rules. The action still comes from the rule that references the provider, such as Proxy, DIRECT, or a named proxy group in your configuration. If the target group does not exist, or the provider is never reached because an earlier rule matches first, downloading the file successfully will not produce the routing result you expect.
There is also an important compatibility distinction. Rule-provider fields and supported formats can vary between Clash-derived cores and client versions. Mihomo supports the provider style shown here, but an older or different core may reject a field, use a different syntax, or fail to load the provider altogether. Check the core version used by your client before copying a configuration. A client’s interface label alone does not guarantee that its embedded core supports every current Mihomo feature.
Prepare a GitHub-hosted rule file
Start with a repository that you control or are authorized to use. For a public repository, place the rule file in a clearly named directory such as rules/, and use a filename that describes its purpose. Keep the file focused: a provider for a handful of developer domains is easier to test than a single catch-all list that mixes unrelated applications, IP ranges, and routing decisions.
For a domain-behavior provider, the file is YAML and contains a top-level payload list. Each item is a domain rule supported by the core, such as DOMAIN, DOMAIN-SUFFIX, or DOMAIN-KEYWORD. For example:
payload:
- DOMAIN-SUFFIX,developer.example
- DOMAIN,downloads.example.net
- DOMAIN-KEYWORD,docs-portal
These example domains are placeholders, not recommendations for a real service. Replace them with hostnames you are entitled to route and have verified from your own traffic or the service’s documentation. A domain suffix can match more hosts than one exact domain, so choose the narrowest rule that meets your goal. Avoid adding a broad suffix simply because it appears to fix one request; that can unintentionally send unrelated services through the same route.
Commit the file and inspect the raw-file address on GitHub. A normal repository page is designed for browsing and is not the file URL a rule provider should fetch. The provider URL generally follows this pattern:
https://raw.githubusercontent.com/OWNER/REPOSITORY/BRANCH/rules/developer.yaml
Replace each uppercase placeholder with the actual owner, repository, branch, and path. Open the resulting address in a browser or retrieve it with a command-line HTTP client and confirm that the response is the raw YAML content. A login page, repository HTML, 404 response, or error document is not a valid rule file, even if the URL looks plausible.
A public repository is convenient for clients that must fetch the file without interactive credentials. Do not place subscription URLs, API tokens, private hostnames, or other secrets in a public repository. A private repository may require authentication that a standard provider fetch cannot supply, depending on the core and setup. If the file must remain private, use an authenticated hosting method supported by your deployment rather than embedding a token in a URL that may appear in logs or configuration backups.
Configure the provider and reference it
Add a provider definition under the top-level rule-providers key in the main configuration. Then add a RULE-SET entry under rules to specify which policy should apply when a provider rule matches. The following example illustrates the relationship between the two sections:
rule-providers:
developer-sites:
type: http
behavior: domain
format: yaml
url: "https://raw.githubusercontent.com/OWNER/REPOSITORY/main/rules/developer.yaml"
path: ./ruleset/developer.yaml
interval: 86400
rules:
- RULE-SET,developer-sites,Work
- MATCH,Proxy
Here, developer-sites is the provider’s local name. The value after RULE-SET must match that name exactly, and Work must be the name of an existing proxy group or other valid target in your configuration. The local path gives the core a place to store the downloaded file. Keep it within a directory the application can write to; paths and working directories can differ between desktop clients, Android, containers, and router installations.
The behavior field describes the kind of rules in the provider. Use domain for domain-oriented entries like the example above. Use ipcidr when the list contains IP network ranges and classical when you need a broader mix of supported rule types. The behavior should agree with the contents: labeling a domain list as an IP CIDR provider does not convert its entries, and a mismatch can cause validation or parsing errors. Confirm the allowed rule types for the core you actually run.
The format field is set to yaml because the remote file uses the YAML payload structure. Some Mihomo versions and deployments also support a compiled format such as mrs; do not change formats unless the downloaded file is actually in that format and your core supports it. A filename extension alone does not establish the file’s contents or compatibility.
The interval is expressed in seconds. In this example, 86400 requests an update interval of one day. It is not a promise that every device will refresh at an exact clock time: the core must be running, the URL must be reachable, and the update must succeed. Treat the interval as a refresh policy, not as a GitHub-side scheduling service. After first adding a provider, use the client’s configuration validation or reload function and check provider status before assuming it has loaded.
Finally, rule order matters. Rules are evaluated in order, and the first matching rule determines the result. Put a provider reference before a broad rule that would otherwise capture the same traffic, such as a general GEOIP or catch-all rule. At the same time, do not move it above a deliberate exception that should take priority. Read the full rule list from top to bottom and test a hostname that is actually included in the provider.
Choose an update workflow you can maintain
Automatic fetching makes a GitHub-hosted provider convenient, but it also means a repository change can alter live routing after the next successful refresh. Decide how much change you want to accept automatically. For a small personal list, updating the default branch may be a reasonable trade-off. For a shared or production configuration, review changes before clients consume them and retain a known-good revision that you can restore.
There are two common ways to manage the URL:
| Approach | Advantages | Trade-off |
|---|---|---|
Track a branch such as main |
Simple URL; new reviewed commits can become available without editing the Clash configuration. | The content can change while the URL stays the same, so clients may receive a new policy at their next successful refresh. |
| Pin a commit or release reference | Reproducible content; you can identify exactly which rule revision a client should fetch. | Updates require changing the reference in the configuration or publishing a new release target. |
For either approach, use Git history as an audit trail. Make a focused commit for each meaningful change, explain why a rule was added or removed, and review the diff before merging. If several people maintain the list, require a second review for broad suffixes, large IP ranges, or changes that could redirect authentication and update traffic. A concise changelog helps you connect a routing regression to the exact rule edit instead of guessing which client update caused it.
Keep local copies of known-good files or use Git tags and releases to make rollback straightforward. If a new commit breaks access, reverting the offending change is generally safer than layering increasingly broad exceptions into each device’s main configuration. Where the rules affect other users, communicate the intended scope and a rollback plan before changing the published provider.
Consider the repository’s availability as part of the design. GitHub hosting can be unavailable from a particular network, blocked by a local policy, or temporarily unreachable from a client. A provider that cannot refresh may continue using a cached copy, depending on core behavior and the circumstances. That can preserve service in the short term but also leave stale rules in place. Check the client’s logs and provider status rather than assuming an unsuccessful update means the new file was applied.
Test downloads, parsing, and actual matches
When a provider does not behave as expected, separate the problem into three questions: can the client reach the URL, can the core parse the returned file, and does the rule match the traffic you intended? Testing these layers separately is faster than rewriting the entire configuration after every error.
- Verify the raw URL. Open it from a network comparable to the client’s network. Confirm that it returns the expected YAML directly, not a GitHub page, redirect to an access prompt, 404 response, or rate-limit message.
- Check the file structure. Confirm that the YAML has a top-level
payloadkey, valid indentation, and entries compatible with the configured behavior. YAML indentation is structural; tabs, misplaced commas, or an unexpected list shape can prevent parsing. - Validate the main configuration. Check that the provider name, URL, local path, behavior, and format are spelled correctly. Make sure the
RULE-SETreference uses the same provider name and the target policy exists. - Inspect logs and provider status. Look for download failures, HTTP status codes, parsing errors, and timestamps. Redact credentials and private URLs before sharing logs publicly.
- Test a known hostname. Choose a domain explicitly present in the file, create a fresh connection, and inspect the client’s connection details to confirm which rule and policy handled it.
A browser successfully opening the URL is useful evidence, but it is not a complete test. The client may use a different network path, DNS resolver, or proxy state from your browser. Conversely, a client can display a cached provider even when its latest refresh failed. Record whether the file is newly fetched or locally cached, and compare the timestamp or content revision when the interface provides that information.
If a rule appears in the provider but traffic still takes the wrong route, check the destination hostname shown by the client. An application may contact an API hostname, a redirect host, a content-delivery domain, or a separate authentication endpoint that is not in the list. Add only the missing hostnames you have verified, and then check whether a higher-priority rule or a broader rule later in the configuration changes the result. IP-based connections, DNS behavior, and application-specific connection reuse can also make an apparently correct domain rule harder to observe in a single test.
When the provider stops updating, first confirm that the client is online and that the URL still returns the raw file. Then check whether the provider’s stored path is writable, whether the configured interval has elapsed, and whether logs show a network or parser error. A successful manual configuration reload may be necessary after editing the main YAML, while provider refresh controls vary by client. Avoid repeatedly lowering the interval as a first response: frequent requests do not repair an invalid file, inaccessible repository, or unsupported format.
Roll out changes safely
Before sharing a provider, test it with a narrow set of domains and a clear destination policy. Confirm both the expected match and an unrelated domain that should remain unaffected. Review the rule order, validate the YAML, and preserve the previous working revision. These checks are particularly important when a provider is used by several profiles, because one small edit can influence every client that references the same moving branch.
When comparing approaches, manually copied rule lists are easy to start with but tend to drift between profiles and become difficult to audit. Some client-specific lists are convenient yet tied to one application’s update workflow. A GitHub-hosted provider gives you a reviewable history, a reusable URL, and a practical route to scheduled refreshes, while Clash-compatible clients make the resulting policy observable through their rule and connection views. If you want to build and test this workflow on a desktop or mobile client, start with a compatible Clash download and keep your configuration changes under version control.