Why understanding Clash YAML matters
Every Clash client—whether Clash Verge Rev, Mihomo Party, or Clash Meta on Android—ultimately runs on a single YAML configuration file. Subscription links you paste into the app are just URLs that download this file. Airport providers, community templates, and power users all speak the same language: proxies, proxy-groups, and rules (plus rule-providers for external rule sets).
You do not need to become a YAML expert to use Clash daily. But when a config fails to load, a site routes to the wrong node, or you want to merge a second subscription without breaking your setup, knowing how these three pillars connect saves hours of guesswork. This guide walks through each section from first principles to a working full example, based on the Mihomo kernel used by modern Clash clients in 2026.
Core file structure at a glance
A typical Clash config is not one giant block of nodes. It is a pipeline: nodes define servers, groups organize nodes, and rules decide which group (or DIRECT/REJECT) handles each connection. Supporting sections like dns, listeners, and tun tune behavior, but the routing heart is always those three.
# Minimal mental model — order in a real file may vary
mixed-port: 7890
mode: rule
proxies: # ① Individual proxy nodes (servers)
- name: "HK-01"
type: ss
...
proxy-groups: # ② Policy groups that reference proxies
- name: PROXY
type: select
proxies:
- HK-01
- AUTO
rule-providers: # ③ External rule sets (optional but common)
gfw:
type: http
behavior: domain
url: "https://..."
path: ./ruleset/gfw.yaml
rules: # ④ Ordered routing decisions
- RULE-SET,gfw,PROXY
- GEOIP,CN,DIRECT
- MATCH,PROXY
YAML uses spaces for indentation (tabs will break parsing). List items start with -. String values with special characters should be quoted. Most clients validate syntax on import and show a line number when something is wrong—keep that error message handy when debugging.
Proxy nodes: the proxies section
The proxies array lists every individual server your config can use. Each entry is one node with a unique name and a type that tells Mihomo which protocol handler to use. Names appear in the client UI and inside proxy-groups; avoid duplicate names and characters that confuse YAML parsers.
Common fields across most proxy types include server (hostname or IP), port, and optional udp support. Many protocols add encryption or transport options—cipher and password for Shadowsocks, uuid and alterId for VMess, sni for TLS-based protocols, and so on.
Supported protocol examples
Mihomo supports a wide range of protocols. Subscription converters and airports usually emit the correct schema; below are representative snippets you might see when reading a config by hand.
proxies:
# Shadowsocks
- name: "SS-Tokyo"
type: ss
server: example.jp
port: 8388
cipher: aes-256-gcm
password: "your-password"
udp: true
# VMess (common on older airports)
- name: "VMess-US"
type: vmess
server: us.example.com
port: 443
uuid: 12345678-1234-1234-1234-123456789abc
alterId: 0
cipher: auto
tls: true
network: ws
ws-opts:
path: /path
headers:
Host: us.example.com
# Trojan
- name: "Trojan-SG"
type: trojan
server: sg.example.com
port: 443
password: "trojan-password"
sni: sg.example.com
udp: true
# VLESS + Reality (increasingly common in 2026)
- name: "VLESS-Reality"
type: vless
server: edge.example.com
port: 443
uuid: 12345678-1234-1234-1234-123456789abc
network: tcp
tls: true
servername: www.microsoft.com
reality-opts:
public-key: YOUR_PUBLIC_KEY
short-id: abcd1234
Other supported types include ssr, http, socks5, hysteria, hysteria2, tuic, and wireguard. You rarely add these manually—subscriptions refresh them automatically—but recognizing the type field helps when comparing latency between protocols or troubleshooting handshake errors in logs.
HK-01 or US-West. Emoji in node names can break some older parsers. Keep names stable so your proxy-groups references do not break after a subscription update.
Policy groups: the proxy-groups section
Raw node lists are hard to use. proxy-groups bundle nodes into policy groups that rules and the UI actually reference. When a rule says DOMAIN,google.com,PROXY, the third column is usually a group name like PROXY or Auto Select—not a single server. You pick or auto-select a node inside that group without touching the rules block.
Every group needs a unique name, a type that defines selection behavior, and a proxies list. That list can include node names, other group names (nesting), and built-in keywords DIRECT, REJECT, and sometimes REJECT-DROP.
The four main group types
| Type | Behavior | Typical use |
|---|---|---|
select |
User picks one member manually | Main "Proxy" or "Region Select" group in the app |
url-test |
Periodically tests latency; uses the fastest node | "Auto Select" or "Failover Fast" groups |
fallback |
Uses the first available node in list order | Priority chains when the primary node is down |
load-balance |
Distributes connections across members | Spreading load; less common for personal use |
proxy-groups:
- name: PROXY
type: select
proxies:
- AUTO
- HK-01
- VMess-US
- Trojan-SG
- DIRECT
- name: AUTO
type: url-test
proxies:
- HK-01
- VMess-US
- Trojan-SG
url: http://www.gstatic.com/generate_204
interval: 300
tolerance: 50
- name: Streaming
type: select
proxies:
- Trojan-SG
- VMess-US
- name: Fallback-Chain
type: fallback
proxies:
- HK-01
- VMess-US
url: http://www.gstatic.com/generate_204
interval: 300
For url-test and fallback, url is the health-check target (a lightweight HTTP endpoint), interval is seconds between checks, and tolerance (url-test only) avoids flapping when two nodes have similar latency. Airport configs often ship with pre-tuned values; change them only if you see constant node switching in logs.
Nested groups—like PROXY listing AUTO as a member—are standard. The outer group shows "AUTO" as one choice; expanding it runs the inner url-test logic. This keeps the UI simple while still offering automatic selection.
Rule sets: rule-providers
Writing thousands of DOMAIN-SUFFIX lines by hand does not scale. rule-providers (rule sets) load external lists—domains, IPs, or classical rule snippets—from HTTP URLs or local files. The rules section then references them with RULE-SET,name,POLICY entries.
rule-providers:
reject:
type: http
behavior: domain
url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt"
path: ./ruleset/reject.yaml
interval: 86400
gfw:
type: http
behavior: domain
url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"
path: ./ruleset/gfw.yaml
interval: 86400
cn:
type: http
behavior: domain
url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cn.txt"
path: ./ruleset/cn.yaml
interval: 86400
Key fields: type (http or file), behavior (domain, ipcidr, or classical), url or local path, and interval for auto-update in seconds. The path is where the client caches the downloaded set. Community projects like Loyalsoldier/clash-rules maintain curated cn, gfw, and reject lists compatible with Mihomo.
type: file.
Rules: tying groups to real traffic
The rules array is an ordered list. Mihomo walks from top to bottom; the first match wins and later rules are ignored for that connection. The third column is DIRECT, REJECT, or a proxy-groups name.
rules:
- DOMAIN-SUFFIX,local,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- RULE-SET,reject,REJECT
- RULE-SET,gfw,PROXY
- RULE-SET,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,PROXY
Put specific rules first (LAN, custom domains), then rule sets, then broad GeoIP fallbacks, and end with exactly one MATCH catch-all. For a deeper dive into rule types, matching order, and override tricks, see our Clash Routing Rules Guide.
Built-in actions vs group names
DIRECT— connect without proxy; use for LAN and domestic traffic.REJECT— drop the connection; common for ad/tracker domains viarejectrule sets.PROXY/Streaming/AUTO— must match aproxy-groupsnameexactly.
Complete minimal configuration example
The following stitches all three pillars into a small but realistic config you can study or test in a local profile (replace placeholder credentials with your own server details).
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
dns:
enable: true
enhanced-mode: fake-ip
nameserver:
- 223.5.5.5
- 8.8.8.8
proxies:
- name: HK-01
type: ss
server: hk.example.com
port: 8388
cipher: aes-256-gcm
password: "password"
udp: true
- name: US-01
type: trojan
server: us.example.com
port: 443
password: "password"
sni: us.example.com
proxy-groups:
- name: PROXY
type: select
proxies:
- AUTO
- HK-01
- US-01
- name: AUTO
type: url-test
proxies:
- HK-01
- US-01
url: http://www.gstatic.com/generate_204
interval: 300
rule-providers:
gfw:
type: http
behavior: domain
url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"
path: ./ruleset/gfw.yaml
interval: 86400
cn:
type: http
behavior: domain
url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cn.txt"
path: ./ruleset/cn.yaml
interval: 86400
rules:
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- RULE-SET,gfw,PROXY
- RULE-SET,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,PROXY
Data flow for an overseas site: the domain hits RULE-SET,gfw → matches PROXY group → you use whichever node is selected (or AUTO picks the fastest). A domestic site matches cn or GEOIP,CN → DIRECT. That is the full loop from YAML to live traffic.
Best practices for maintainable configs
- Do not edit subscription files in place. Use client overrides (Merge) to prepend rules or patch groups so updates do not wipe your changes.
- Keep group names stable across subscription refreshes; rules depend on them.
- Prefer RULE-SET + GEOIP over hand-written domain lists for scale and accuracy.
- Validate after every edit; one wrong indent can prevent the entire config from loading.
- Separate concerns: streaming or gaming groups for special nodes; default
PROXYfor general browsing. - Document custom rules in a local merge file with comments (YAML
#) so future you knows why a domain was added.
Debugging when something breaks
- Read the client error on import—it often names the invalid key or duplicate entry.
- Open Logs or Connections and confirm which rule matched (
DIRECTvs your group name). - If nodes exist but rules never proxy, check that
mode: ruleis set and outbound mode in the UI is "Rule." - If a group is empty after sync, the subscription may use different node names; re-select members or fix the group definition in an override.
- Temporarily set
log-level: debugto trace DNS, rule matching, and handshake details—then revert toinfofor daily use.
FAQs
What is the difference between proxies and proxy-groups?
proxies are individual servers. proxy-groups are containers that reference those servers (and other groups). Rules point to group names so you can change the active node in the app without rewriting routing logic.
Do I need to write YAML if I have a subscription?
No for everyday use—the subscription supplies the file. Yes for troubleshooting, custom routing, merging providers, or learning. Reading the structure makes error messages meaningful instead of mysterious.
What is the difference between rules and rule-providers?
rules are the ordered decisions Mihomo applies per connection. rule-providers are external bulk lists you pull in via RULE-SET rules. You need both: providers supply data, rules apply policy.
Why did my edit cause "config load failed"?
Usually YAML syntax (indentation, colons), a typo in a group name referenced by a rule, or duplicate name fields. Revert the last change, fix one section at a time, and use the client's validator.
Many one-click VPN apps hide all of this behind a single connect button—you get simplicity, but no visibility into which server handles which app, no per-site routing, and no way to combine two providers in one policy. Generic proxy switchers expose a node list but leave rule sets and automatic failover as your problem. Clash's YAML model is more upfront, yet that transparency is exactly what makes split routing, auto latency tests, and community rule sets work together in one file. If you would rather skip hand-editing and still get a Mihomo-ready stack, the clients on our download page ship with sensible defaults and override support so you can grow into full config control at your own pace.
Download Clash free and start with a ready-made YAML workflow →