Rule priority in a nutshell: rules are checked from top to bottom, and the first match wins

Custom Clash rules don’t automatically get higher priority just because they’re more specific. In rule mode, Clash checks them in list order: the first matching rule determines the outbound policy for a connection, and later rules are ignored. Put exact-domain exceptions first, broader domain-suffix rules after them, and MATCH at the very end. Reordering rules is often a more direct fix for routing problems than repeatedly switching nodes.

This guide covers common Clash rule syntax and explains mihomo (Clash Meta) usage where rule providers are involved. Configuration editors, override behavior, and supported fields vary by client and core version, so don’t assume an extension is available based on the client’s name alone. Start with DOMAIN, DOMAIN-SUFFIX, IP-CIDR, and MATCH to verify routing, then add more rules as needed.

System proxy and TUN mode determine how traffic reaches the core; rules determine which outbound to use once it gets there. Enabling TUN doesn’t raise a rule’s priority. If app traffic never reaches Clash, even a correct rule won’t appear in the connection log.

Rule syntax: type, match value, outbound policy

Rules usually go under the YAML configuration’s rules: list. The common format is type,match value,outbound policy, though some rule types accept additional parameters. Start each list item with a hyphen, indent with spaces, and don’t use tabs. The snippet below can be added to an existing configuration; it’s not a complete configuration with proxies, ports, and DNS settings:

rules:
  - DOMAIN,login.example.org,DIRECT
  - DOMAIN-SUFFIX,example.org,REJECT
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - MATCH,DIRECT

DIRECT sends traffic directly, and REJECT blocks the connection. Both are built-in outbound policies. These examples use the reserved example domain to show rule order: login.example.org goes direct, other domains under example.org are rejected, and connections that match neither rule go direct under the final rule.

When using a policy group, make sure its name exists in the configuration

If your proxy-groups section contains a policy group named “Select Node,” you can use that name as an outbound policy. For example: DOMAIN,api.example.org,Select Node. This isn’t a built-in name: copying the example without defining the group can cause configuration validation or loading to fail.

  • Keep just one top-level rules: key in each configuration. Add rules to the existing list instead of appending a duplicate key at the end of the file.
  • Use English commas when copying rules. Chinese commas can make a line unrecognizable to the parser.
  • When a rule points to a policy group, the group’s selection or health-check logic determines the final node. A rule match and node availability are two separate things to check.

DOMAIN vs. DOMAIN-SUFFIX: put exceptions before broader matches

TypeExample ruleWhat it matches
DOMAINDOMAIN,api.example.org,DIRECTThis exact domain only
DOMAIN-SUFFIXDOMAIN-SUFFIX,example.org,DIRECTThe root domain and its subdomains
DOMAIN-KEYWORDDOMAIN-KEYWORD,example,REJECTConnections with this string anywhere in the domain

A suffix isn’t just any matching string at the end

DOMAIN-SUFFIX,example.org,DIRECT matches example.org, www.example.org, and a.b.example.org, but it shouldn’t match notexample.org as a subdomain. To match a domain and all its subdomains, use the root domain directly. Don’t add https://, a path, or *..

A domain in a rule isn’t a full URL. https://example.org/account includes a protocol and path, so it can’t be used directly in DOMAIN. Standard domain rules also can’t distinguish between paths such as /account and /images on the same site. HTTPS paths are encrypted application-layer data, so domain-based routing can’t filter by webpage path.

Avoid unintended matches with keyword rules

DOMAIN-KEYWORD is convenient, but it often matches more than expected. The word “example” could appear in domains unrelated to example.org. Use DOMAIN when you know the exact domain, or DOMAIN-SUFFIX to cover a site and its subdomains. Don’t use a short keyword when you can specify the intended scope.

rules:
  - DOMAIN,download.example.org,DIRECT
  - DOMAIN-SUFFIX,example.org,REJECT
  - MATCH,DIRECT

This order makes the download subdomain an exception. If you move the suffix rule to the first line, the download domain will match the reject rule first, and the more specific DOMAIN rule below it won’t get another chance. Clash doesn’t automatically move exact domains ahead of broader rules.

IP-CIDR and no-resolve: target addresses and DNS lookups

IP-CIDR matches the destination IPv4 address against a network range. For example: IP-CIDR,192.168.1.0/24,DIRECT,no-resolve. Here, /24 is the network prefix length, covering 192.168.1.0 through 192.168.1.255. Use /32 to match a single IPv4 address. For IPv6, use IP-CIDR6; a single IPv6 address uses /128.

rules:
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - MATCH,DIRECT

These are examples of common private address ranges, not a complete solution for handling special-purpose addresses. Corporate networks, custom routers, and VPNs may use additional ranges. If a destination range should be reached through a company tunnel, don’t assume a direct connection will work just because the address is private.

no-resolve doesn’t disable DNS

When a connection has a domain name but no destination IP available for matching, an IP rule may trigger a DNS lookup to check whether the address falls within its network range. Adding no-resolve means the rule won’t initiate an extra lookup for that domain. The rule can still match if a destination IP is already available or the app connects directly to an IP address.

Conversely, when sending traffic to a known private IP directly, no-resolve can prevent an extra lookup just for that network rule. It doesn’t stop apps from making their own DNS queries, or guarantee that a connection will never need name resolution. Fake IP, DNS mapping, and sniffing settings affect what the core can see, so check the actual connection log when troubleshooting.

MATCH and rule providers: keep the fallback rule last

MATCH matches every remaining connection, so it takes just two main fields: MATCH,outbound policy. If it’s at the top of the list, all domain rules, IP rules, and rule providers below it are ignored. A common order is “exact exceptions → category rules → required IP rules → MATCH,” but the actual list order still determines which rule takes effect.

Rule providers don’t have a higher priority of their own

mihomo lets you manage rule providers with rule-providers and reference them using RULE-SET. A provider is evaluated at the position where its reference appears in rules. A large provider doesn’t automatically outrank individual rules listed before it.

  • To exempt a domain from a rule provider, put an exact-match rule for that domain before the relevant RULE-SET reference.
  • Before using a provider, make sure its name is defined and its behavior matches the data it contains. For example, domain lists and CIDR lists use different content formats.
  • A failed provider update isn’t the same as having no matching entries. Check the loading logs first, then investigate rule order.

Rule provider formats, logical rules, and other extensions differ across original Clash branches and mihomo. When switching cores, don’t just copy the RULE-SET line. Check the provider definition too, and use the current core’s configuration validation to confirm what it supports.

Choose a fallback policy that fits your traffic

This guide uses MATCH,DIRECT so the example doesn’t depend on an external policy group. That doesn’t mean every subscription should send unmatched traffic direct. If unclassified connections should use a proxy, change the final rule to the name of an existing proxy policy group. Preserving the subscription’s original fallback behavior and adding exceptions gradually usually makes changes easier to troubleshoot.

Rules disappear after a subscription update: check overrides and merge order

Direct edits to a downloaded subscription YAML may be overwritten the next time the subscription updates. For long-term changes, use the client’s local override, configuration merge, or scripting features. Menus and merge behavior vary by client, so check the current subscription’s options for a local extension feature. Don’t assume every “Edit” button creates a persistent override.

  1. Back up the working configuration first. Note the active subscription, current mode, and original final rule so you can restore them after testing.
  2. Add one easy-to-observe exact-match rule first. For example, temporarily reject a domain you control for testing. Don’t add hundreds of rules at once.
  3. Check the final active configuration. If the merge appends your custom rules after the existing MATCH, they won’t match even though they appear in the file.
  4. Reload, then update the subscription again. Confirm the local rules are still present and in the right place to verify that the changes persist.

Override tools may replace, prepend, or append the rules list, with very different results. Replacing all of rules discards the subscription’s original routing logic; appending rules may put them after the fallback. Understanding the client’s merge behavior matters more than simply seeing a “Saved” message.

How to troubleshoot rules that don’t work: mode, connection, match, outbound

Don’t judge a change only by whether a webpage loads. Caching, existing long-lived connections, and browser connection reuse can skew the results. After reloading the rules, close the site’s existing connections and make a new request. If needed, end the relevant connection in the client’s connection list; there’s no need to disconnect every working app first.

SymptomCheck firstWhat to do
No connection for the destination appearsWhether the app uses the system proxy and whether TUN is actually intercepting trafficFix how traffic enters the core before changing match rules
Connection shows the Global or Direct mode policyCurrent proxy modeSwitch to Rule mode and start a new connection
Connection matches MATCHWhether the domain matches, an IP is available, and the rules are loadedCheck the connection details and the final rule list
A broader suffix rule matches firstWhether the exact-match exception comes laterMove the exception above the broader rule
The expected policy matches, but the request failsThe policy group’s current node and connectivity to the destinationCheck routing success separately from outbound connection failure

Compare before and after using the same destination

If your mixed port is actually set to 7890, use the command below to send a test request explicitly through the local HTTP proxy. If your port is different, use the value shown in your client. On Windows, use curl.exe to avoid ambiguity with the alias of the same name in older PowerShell versions. This command is for testing a request; it doesn’t guarantee a particular latency or success rate:

curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.org/

Then check the destination domain, matched rule, policy group, and final outbound in the connection details. This test verifies the explicit HTTP proxy route, not TUN interception or UDP forwarding. If an app connects directly to an IP, domain rules may not have a domain to match. mihomo sniffing can supply additional information for supported protocols and configurations, but it can’t recover the domain from every encrypted connection.

For reliable maintenance, keep a known-working configuration, change one small group of rules at a time, check the match details for a new connection, and then confirm the rules persist after a subscription update. For more on subscriptions, DNS, and TUN mode, see the complete Clash guide. For common connection issues, start with the FAQ rather than assuming every network problem comes down to rule syntax.