Clash Rule Providers: Build and Host Custom Rules on GitHub

Turn scattered domain rules into version-controlled Clash rule providers. Get working YAML examples, GitHub hosting steps, validation tips, and guidance on keeping rules updated across Mihomo setups.

Understand what a rule provider does

A Clash rule provider moves a maintained set of matching rules out of the main configuration file. Instead of pasting dozens or thousands of domain entries into rules, you keep them in a separate file, tell Mihomo how to fetch and interpret that file, and reference it with a RULE-SET rule. The main configuration stays easier to review, while the rule list can be updated independently.

A provider does not create proxy nodes or choose a policy by itself. It supplies match conditions. Your main configuration still decides what happens when traffic matches them, such as sending a domain to Proxy, DIRECT, or a policy group with another name. That distinction is useful when debugging: a provider can load correctly while its rules point to a policy group that does not exist, or a valid policy can appear unused because the provider file is invalid or has not refreshed.

Mihomo supports provider behaviors for different rule types. Choose the behavior to fit the contents of the file rather than selecting one arbitrarily:

For a first provider, keep the scope narrow. A domain-only list is easier to test than a large collection that mixes domains, IP ranges, process names, and rule providers from multiple sources. Put one rule per entry, use consistent capitalization, and avoid adding a final policy such as PROXY to the provider itself: routing policy belongs in the main configuration’s rules list.

Create a provider and reference it in YAML

Create a local directory for rule files before adding the provider. Mihomo uses the configured path as the location for its downloaded provider data, so a dedicated folder makes the cache easy to identify and back up. For example, create rules beside your main configuration file, then add a small YAML rule list named custom-domains.yaml:

payload:
  - DOMAIN-SUFFIX,example.com
  - DOMAIN,api.example.net
  - DOMAIN-KEYWORD,video

The sample uses placeholder domains; replace them with rules you are authorized to maintain and actually need. Use DOMAIN-SUFFIX when the intended match includes a domain and its subdomains. Use DOMAIN for one exact hostname. A keyword match is broader: DOMAIN-KEYWORD,video can match more hosts than expected, so test it carefully and prefer a suffix rule when the target domain is known.

Add a provider entry to the main configuration. The URL below assumes a public repository named my-clash-rules, a main branch, and a file at rules/custom-domains.yaml. Replace the owner and repository with your own values.

rule-providers:
  custom-domains:
    type: http
    behavior: domain
    format: yaml
    url: "https://raw.githubusercontent.com/OWNER/my-clash-rules/main/rules/custom-domains.yaml"
    path: ./rules/custom-domains.yaml
    interval: 86400

rules:
  - RULE-SET,custom-domains,Proxy
  - MATCH,Proxy

Here, type: http tells Mihomo to fetch the file over HTTP or HTTPS, behavior: domain describes the rule family, and format: yaml indicates that the response is a YAML document containing a payload list. The path is the local cache path, while interval: 86400 requests an update every 86,400 seconds, or 24 hours. The interval is in seconds, not minutes. A short interval is rarely useful for a list that changes only occasionally and can generate unnecessary requests.

Order matters in the main rules list. Rules are evaluated from top to bottom, so place a provider reference before a broad rule that would otherwise match the same traffic. In the example, the provider appears before MATCH. If an earlier rule already catches the domain, the later provider entry will not change the result. Likewise, the example’s Proxy target is only correct if a policy with that exact name exists. Many subscriptions use names such as PROXY, Node Select, or another localized label; copy the exact name from the active configuration.

Choose a format that matches the file

For a YAML provider, keep the payload field and place each rule as a YAML string in the list. Do not paste a complete Clash configuration into this file: it should contain provider data, not top-level sections such as proxies, proxy-groups, or rules. If you choose a text format for a compatible provider, use the syntax expected by that format and set format accordingly. Do not label a plain-text file as YAML or a YAML document as plain text.

Also avoid duplicating the same rule in several providers unless there is a clear reason. Overlapping entries can make it harder to identify which provider caused a route, and broad keyword rules can unintentionally capture unrelated services. Start with a small list, confirm the result in the client’s connection view or Mihomo logs, and add more entries only when the observed traffic justifies them.

Host and update a public rule file on GitHub

A public GitHub repository can host a simple, version-controlled provider file. It is convenient for personal lists and small shared projects because changes are recorded as commits and can be reviewed before they reach users. It is not the same as a dedicated rule distribution service: availability, rate limits, and delivery behavior depend on the hosting path and network. For a configuration used by multiple people, consider whether a repository’s public access and delivery reliability meet your requirements.

  1. Create a repository. Make a repository for rules rather than mixing the provider into unrelated files. Choose public visibility if clients must fetch the file without authentication. A private repository’s raw file generally cannot be downloaded by an unauthenticated Clash client simply by adding a token to the URL; do not put a personal access token in a shared YAML configuration.
  2. Add the rule file. Create a directory such as rules, then add custom-domains.yaml with the provider document and a short list of tested entries. Use plain UTF-8 text and keep line endings consistent.
  3. Commit a known-good version. Review the change before committing. Confirm that the file has a payload key, valid indentation, no accidental tabs, and no private data. The commit history gives you a way to compare revisions or revert a bad rule set.
  4. Build the raw file URL. Use the raw-content host with the owner, repository, branch, and file path in that order. For example: https://raw.githubusercontent.com/OWNER/my-clash-rules/main/rules/custom-domains.yaml. Put that URL in the provider’s url field, with quotation marks around it.
  5. Test the exact address. Open the raw URL in a browser or fetch it with a command-line tool. The response should be the rule file itself, not a repository page, a sign-in screen, a 404 document, or an HTML error page. Verify the branch name and path character by character if the response is wrong.
  6. Update the repository deliberately. Edit the file, review the diff, and commit the change. Mihomo will fetch it on the next configured update cycle; allow for that interval rather than assuming a new commit is applied instantly.

A branch-based URL such as main always refers to the latest commit on that branch. That is convenient for routine updates, but it also means a bad commit can affect every client that follows it. For higher confidence, test changes with a second provider name or a separate test configuration before replacing a rule file used daily. Keep a copy of the last known-good file so you can restore it quickly if a published change causes unexpected routing.

Do not include subscription tokens, passwords, private hostnames, or user-specific traffic records in a public repository. Rule lists can reveal browsing categories or internal network ranges even when they contain no credentials. Review both the file and the repository history before making a private project public; deleting a line from the latest revision does not necessarily remove it from earlier commits.

Validate the file, fetch, and routing behavior

Test in stages so a failure points to one layer. First confirm that the file is valid and available at the raw URL. Then check that the provider definition parses and can be downloaded. Finally, confirm that the matching traffic reaches the expected policy. A successful configuration test checks syntax, but it does not prove that a remote server will remain reachable or that a specific domain will match the rule you intended.

On a desktop system with Mihomo available as a command-line binary, run a syntax check against the configuration file before applying it. The exact executable name may differ by operating system or client bundle:

mihomo -t -f config.yaml

If validation fails, read the first reported line and inspect the surrounding YAML. Common causes include inconsistent indentation, tabs, a missing colon, a misplaced rule-providers block, or a provider reference whose name differs from the declaration. A syntax test may not fetch every remote provider, so follow it with a runtime check in the client and inspect Mihomo’s log for provider download errors.

You can inspect the raw response independently with curl. This command reports the HTTP status and saves the response locally; replace the sample URL with the exact one configured in YAML:

curl -L --connect-timeout 10 --max-time 30 \
  -o custom-domains.yaml \
  -w "HTTP=%{http_code} SIZE=%{size_download} TIME=%{time_total}\n" \
  "https://raw.githubusercontent.com/OWNER/my-clash-rules/main/rules/custom-domains.yaml"

A 200 status and a non-zero file size are useful signs, but inspect the body as well. A gateway can return an HTML error page with a successful-looking transport exchange, and an empty or incorrectly structured YAML document can still be unusable as a rule provider. If the downloaded file starts with HTML, check the URL, repository visibility, branch, and network access. If the file looks correct but Mihomo rejects it, compare behavior, format, and the entries in payload.

Maintain providers across Mihomo setups

Provider definitions and downloaded data are part of the local configuration environment, not a guarantee that every client stores files in the same physical folder. Desktop clients may manage profiles in an application data directory, while mobile clients may use an app-controlled location. Relative paths such as ./rules/custom-domains.yaml are resolved in relation to the active configuration context. When moving a configuration, check that the client can create or access the referenced directory and that the provider can be fetched again from its URL.

Keep the source-of-truth file in the repository and treat the local provider path as a cache. Do not edit the cached copy inside a client and expect those changes to appear in GitHub; a later download may overwrite them. Make changes to the repository file, commit them, and let each Mihomo instance refresh its own copy. If you need device-specific exceptions, keep them in that device’s main configuration rather than quietly changing the shared provider data.

Update practices should reflect how often the rules actually change. A daily interval such as 86400 seconds is a reasonable starting point for a personal list that receives occasional changes. A static set may need less frequent checks. Avoid setting a very short interval simply to make Git commits appear instantly: it can increase requests without improving the quality of the rules. After changing a file, use a manual refresh for immediate verification, then rely on the normal interval.

For reproducible troubleshooting, record the Mihomo version, the provider URL, the last successful update time, and the commit or revision that was tested. When multiple devices behave differently, compare their provider definitions and core versions before rewriting the rules. The YAML fields may be identical while one installation still has an older cached file, a blocked route to the host, or a client-managed configuration that is not the one currently active.

Finally, keep the provider as small and readable as its purpose allows. Use comments in project documentation or a separate README to explain why an unusual rule exists; do not assume every consumer will infer the reason from a domain name. Review broad keywords, IP ranges, and any rule that changes the route for a large service before publishing. With a narrow scope, a tested raw URL, a clear update interval, and a rollback copy, a custom provider can keep a main configuration compact without making routing behavior opaque.

FlClash Downloads View clients for every platform