Build Mihomo Rule Providers: GitHub Hosting and Auto-Updates

Why Put Mihomo Rules in a GitHub Rule Provider? Explained

A long rules: list is easy to start and surprisingly hard to maintain. You might add a few domains for a work app, a set of network ranges for a game, and exceptions for services that should stay direct. Over time, the profile becomes a mixture of subscription data and personal policy. Every edit then has the same risks: a provider update can overwrite it, a typo can invalidate the whole YAML file, and it is difficult to tell which change caused a routing result to shift.

A Mihomo rule provider moves a reusable set of rules into its own file and lets the core load that file by URL. Hosting the file on GitHub gives you a convenient place to review changes, keep a history, and share a stable raw-content address with more than one device. Your main configuration retains the policy that decides how traffic is routed; the provider holds the list of domains, IP ranges, or complete classical rules that you want to manage separately.

This separation is useful whether you maintain a small personal list or a larger team rule set. You can update a domain list without rewriting a subscription profile, compare the current file with an earlier commit, and test a proposed change before distributing it. It also makes failures easier to isolate: if a route changes, you can inspect the provider file and the rule that references it instead of searching through a very large profile.

There are two independent pieces to configure. The rule-providers section defines a provider’s name, source, format, behavior, local cache path, and refresh interval. A rule inside rules: then references that provider with RULE-SET and chooses a policy or proxy group. Defining a provider does not automatically route its contents, and adding a RULE-SET line without a matching provider name does not create the provider. Keep those two parts together when reviewing or debugging your configuration.

Compatibility check: Rule-provider options depend on the Mihomo version and the client using it. Use a current Mihomo core, confirm that your client has actually selected it, and validate a small example before migrating a large ruleset. Older Clash-compatible cores may reject fields such as format or newer provider behavior options.

Think of GitHub hosting as a delivery mechanism, not as a guarantee that every client will receive exactly the same content at exactly the same moment. The client still needs working DNS and HTTPS access to the host, the URL must return the raw rule file rather than a GitHub web page, and Mihomo must be able to parse the downloaded data. A successful upload alone proves none of those things. The sections below build a small provider, connect it to a profile, and show how to verify both its refresh and its routing effect.

Prepare a Versioned Rule File on GitHub in Detail

Create a repository for rule files, or choose a suitable existing repository. A public repository is the simplest option for a normal Mihomo installation because the core can fetch its raw file over HTTPS without an interactive sign-in. Do not put subscription links, API tokens, private hostnames, or other secrets in a public repository. A rule provider is downloaded by the proxy core; it is not a secure way to distribute credentials.

Start with one file containing a short, focused list. For a domain-behavior provider using YAML, a practical file looks like this:

payload:
  - DOMAIN-SUFFIX,example.org
  - DOMAIN,login.example.net
  - DOMAIN-KEYWORD,service-name

In this example, payload is the YAML field expected by the provider file, and each entry is a rule in Mihomo’s classical rule syntax. Keep the list relevant to one purpose: for example, a work service, a set of streaming domains, or a small collection of personal exceptions. Short lists are easier to review and make it faster to tell whether a particular rule is responsible for a match.

Commit the file with a clear message such as “Add login host for work service.” Git history gives you a useful audit trail: you can see which lines changed, who made the change, and when it was committed. If a new version breaks routing, revert the commit or restore the earlier content while you investigate. For production use, consider separating experimental changes from the version that your daily profile consumes. That could mean testing from a branch first and then merging reviewed changes into the stable branch.

Use the file’s raw URL in Mihomo, not the regular GitHub page URL. A browser page shows repository controls and rendered source; the core needs the file contents themselves. The raw address typically follows a pattern like this:

https://raw.githubusercontent.com/OWNER/REPOSITORY/BRANCH/rules/work.yaml

Replace each placeholder with the real owner, repository, branch, and path. Check the address in a browser or with a command-line HTTP client before adding it to your profile. The response should contain the YAML file, not a GitHub sign-in screen, a 404 page, or an HTML document. If you use a private repository, do not assume that a URL copied from a logged-in browser will work in Mihomo; the core generally does not inherit your browser’s GitHub session. Prefer a suitable public rules repository, or use a deliberately designed authenticated distribution method rather than embedding a personal access token in a profile that may be shared.

A branch URL such as main is convenient when you want every accepted commit to become available to clients. It is also mutable: the same URL can serve different content over time. For more controlled rollouts, use a release artifact or a URL pinned to a reviewed commit, then deliberately update the configured URL when you approve a new version. A pinned URL improves reproducibility but removes automatic adoption of later edits. Choose based on how much review you need, and document the choice so future maintainers understand why a provider does or does not follow the branch tip.

Keep files narrow and named clearly. Names such as work.yaml or media-domains.yaml communicate intent better than rules2.yaml. One provider per purpose also lets you adjust its route, refresh interval, or test procedure without accidentally changing unrelated traffic.

Configure the Provider and Put It in the Right Order Made Clear

Add the provider definition and its matching rule to the active Mihomo profile. This example uses a domain behavior provider, YAML format, and a proxy group named Proxy. Replace the URL, local path, provider name, and policy with values that exist in your own configuration.

rule-providers:
  work-services:
    type: http
    behavior: domain
    format: yaml
    url: "https://raw.githubusercontent.com/OWNER/REPOSITORY/main/rules/work.yaml"
    path: ./ruleset/work-services.yaml
    interval: 86400

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

The provider name, work-services, is the identifier used by the RULE-SET rule. The type: http setting tells Mihomo to fetch the provider from a URL. behavior: domain describes the kind of entries in the file, while format: yaml identifies the file encoding shown above. The path is a local cache location used by the core; choose a writable location appropriate to your installation and avoid placing it somewhere that a cleanup task removes on every launch. The interval is expressed in seconds, so 86400 requests a daily refresh.

Provider behavior must agree with the data you host. A domain provider is for domain entries; it is not a container for arbitrary full rules. If your file needs entries such as DOMAIN-SUFFIX or DOMAIN-KEYWORD, use behavior: classical and keep the classical rules inside the YAML payload. If the provider is intended for IP ranges, use an IP-CIDR behavior and a file format that matches the Mihomo version and the specific provider content. Do not change only the behavior label to silence an error: first make sure the file’s entries actually fit the selected behavior.

The order in rules: is decisive. Mihomo evaluates rules from top to bottom and uses the first matching rule. The provider rule must therefore appear before a broader rule that would already capture the same traffic. For instance, if GEOIP,CN,DIRECT appears above your provider, a matching connection may be sent direct before Mihomo reaches the provider line. Likewise, a broad domain suffix rule above it can make a narrower provider entry appear ineffective. Place specific exceptions first, followed by broader category rules, and leave a catch-all such as MATCH,DIRECT or MATCH,Proxy at the end according to your intended default.

There is no universally correct policy target. A rule provider can point to a named proxy group, a specific proxy, or DIRECT, depending on the configuration and the decision you want to make. Check spelling and capitalization against the actual proxy-groups and proxy names in the active profile. A syntactically valid rule that refers to a group that does not exist can still fail validation or behave differently than intended. Also consider whether a rule should be before or after a local-network exception; routing private addresses through a remote group is often not what users expect.

After saving, reload or activate the profile using your client’s normal configuration workflow. Watch the Mihomo log for YAML parse errors, a provider download failure, or a missing policy name. Then generate a connection to a domain that should match the list and inspect the connection details. The useful evidence is not merely that the browser loaded: verify the requested hostname, the matched rule, and the selected outbound. If the client’s log or connection panel displays a generic rule label, use its provider or rule-provider view to confirm that the provider loaded and contains the expected entries.

Refresh, Test, and Troubleshoot Stale or Failed Providers Under the Hood

The interval is a refresh schedule, not an instruction to contact GitHub for every new connection. A daily interval is a reasonable starting point for a list that changes occasionally. Shorter intervals can make an approved edit appear sooner, but they create more requests and rarely improve a ruleset that changes only once a week. Very long intervals can leave a device using old data after you have corrected a mistake. Pick a value based on how often the source changes and how quickly clients need to adopt it, rather than copying an interval from an unrelated example.

During initial setup, test refresh deliberately instead of waiting for the scheduled interval. Many clients expose a rule-provider or profile update action; use the control that updates the provider or reloads the profile, and check the Mihomo log for the result. Some Mihomo interfaces also expose provider operations through the external controller API. The exact controls depend on the client, core version, and API configuration, so use the client’s current documentation and never expose an unauthenticated controller to an untrusted network. A successful manual refresh should be followed by an inspection of the loaded provider content and a connection test against one of its entries.

For a reliable test, make one harmless, easy-to-recognize change in the GitHub file, such as adding a test subdomain that you control. Commit it, confirm that the raw URL serves the updated version, trigger a refresh, and inspect the active provider. Then create a connection to that test hostname and confirm the expected rule and outbound. Remove the test entry after the check. This sequence separates four questions that otherwise get mixed together: did GitHub serve the new file, did Mihomo download it, did Mihomo parse and activate it, and did rule order allow it to match?

If the provider remains stale, start by comparing the raw file in a browser with the content or update timestamp shown by the client. A branch name in the URL can point to the correct repository but the wrong branch or file path. A cached local copy may also remain active when an update fails, depending on the core and client behavior. Check the log for the requested URL, response status, and parse result before deleting cache files. Deleting a cache can force the core to fetch again, but it will not fix a typo, an inaccessible source, or an invalid payload; preserve a copy of the current file before making manual changes.

When downloads fail, test from the same machine and network where Mihomo runs. A browser can succeed through its own proxy while the core’s HTTP request follows a different route. Check system time, DNS resolution, TLS access to raw.githubusercontent.com, and whether the active proxy rules permit the core to reach GitHub. Captive portals, filtering DNS, corporate firewalls, and temporary GitHub availability issues can all interrupt a fetch. If a command-line request works only after setting a proxy environment variable, that does not prove Mihomo automatically uses that variable; confirm the client’s core routing path and inspect its connection or log view.

A parse failure usually points to a mismatch between the provider declaration and the file. Verify YAML indentation, the required top-level structure, the selected behavior, and whether the URL returns raw YAML rather than an HTML error page. Watch for invisible formatting problems introduced by a text editor, including tabs used for indentation. Keep the test file small until it loads cleanly, then add entries in reviewed batches. If the provider file parses but none of its rules appear to work, check that the provider name in RULE-SET matches exactly, that the target exists, and that no earlier rule captures the traffic first.

Rule ordering is best tested with one known hostname rather than a large collection of real services. Record which rule should match and what outbound you expect, then inspect Mihomo’s connection details after a fresh request. Be aware that applications can reuse existing connections, so an already-open session may not demonstrate the effect of a changed rule. Close and reopen the application or wait for the relevant connection to end before drawing conclusions. For domain rules, also check the hostname actually used by the app: a service may contact a login host, API host, and content-delivery host separately, and adding only the website’s visible domain may not cover the whole workflow.

Keep an eye on cache paths when running multiple clients or profiles. Two separate Mihomo instances should not be configured to write incompatible provider state to the same location. Conversely, a profile that points to a path that is missing or unwritable may fail to persist updates as expected. Use a stable path supported by your client, avoid editing the cached file as though it were the GitHub source of truth, and update the repository instead. That keeps the review history meaningful and makes it possible to reproduce the same configuration on another device.

GitHub-hosted providers make custom rules easier to review than embedding every exception in a large profile, while a hand-maintained local list can be simpler for a single device but harder to share and roll back. Third-party rule bundles can save initial effort, yet they may include broader matches than your use case needs or change without a review process that fits your environment. The practical middle ground is to keep a small, purpose-built source, verify its raw URL, and test the active rule and outbound after each meaningful update. If you want a client workflow that makes profile management and Mihomo rule testing easier to follow than editing files without context, Clash provides clear setup guidance and access to compatible client options; you can browse the downloads and choose the tool that fits your system.