Subscription rules handle the common cases; the gaps are yours to fill: an intranet domain being wrongly proxied, a niche site missing from the lists, per-app routing. Writing rules takes five minutes to learn. They belong in a Merge config (here is why and how); this page is about the syntax.

Example Clash rules: streaming via proxy, banking direct, ads rejected
A typical custom rule block, annotated by purpose

The general shape

TYPE,value,exit[,option]

The exit is a group name (like PROXY), DIRECT or REJECT. Rules match top to bottom and stop at the first hit — internalize that and priority questions answer themselves.

The types you will actually use

TypeExampleNotes
DOMAINDOMAIN,ads.example.com,REJECTExact hostname match
DOMAIN-SUFFIXDOMAIN-SUFFIX,netflix.com,PROXYDomain plus all subdomains — the workhorse
DOMAIN-KEYWORDDOMAIN-KEYWORD,google,PROXYSubstring match; broad, use sparingly
IP-CIDRIP-CIDR,10.0.0.0/8,DIRECT,no-resolveDestination IP range
GEOIPGEOIP,CN,DIRECTCountry by IP; needs the Geo database
PROCESS-NAMEPROCESS-NAME,steam.exe,DIRECTRoute by originating process
MATCHMATCH,PROXYThe catch-all; always the last line

Add no-resolve to IP rules. Without it, domain-based requests trigger a DNS lookup just to evaluate the IP rule — slower, and a potential leak vector.

Three ready-to-paste examples

Force the company intranet direct

prepend-rules:
  - DOMAIN-SUFFIX,corp.example.com,DIRECT
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve

Lightweight ad blocking

prepend-rules:
  - GEOSITE,category-ads-all,REJECT

Catches in-app ads that browser extensions never see. If something legitimate breaks, whitelist its domain with a DOMAIN rule placed above this line.

Keep torrent traffic off the proxy

prepend-rules:
  - PROCESS-NAME,qbittorrent.exe,DIRECT
  - PROCESS-NAME,transmission.exe,DIRECT

RULE-SET: when the list grows

Past a hundred rules, a flat Merge file becomes unmanageable. Mihomo can pull rule lists from external files:

rule-providers:
  my-direct:
    type: http
    behavior: domain
    url: "https://example.com/my-direct.yaml"
    interval: 86400
prepend-rules:
  - RULE-SET,my-direct,DIRECT

Host the list in a GitHub repo and every device shares one maintained source.

Verifying a rule fires

The Connections page is the ground truth: each connection shows the rule it matched and the exit it took. The loop is fast — edit rule, reactivate profile, visit the site, check the page. When a rule seems dead, the usual cause is an earlier rule capturing the traffic first.