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.

New to Clash? If you have not installed a client yet, start with our Clash Verge Rev Setup Guide to import a subscription first. Come back here when you want to understand what is inside that file.

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.

Naming tip: Use short, region-based names like 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.

Download failures: If a rule-provider URL is unreachable, the cached file is used when available; otherwise rules depending on that set may not match as expected. For unreliable networks, mirror the file locally and switch to 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 via reject rule sets.
  • PROXY / Streaming / AUTO — must match a proxy-groups name exactly.

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,CNDIRECT. That is the full loop from YAML to live traffic.

Best practices for maintainable configs

  1. Do not edit subscription files in place. Use client overrides (Merge) to prepend rules or patch groups so updates do not wipe your changes.
  2. Keep group names stable across subscription refreshes; rules depend on them.
  3. Prefer RULE-SET + GEOIP over hand-written domain lists for scale and accuracy.
  4. Validate after every edit; one wrong indent can prevent the entire config from loading.
  5. Separate concerns: streaming or gaming groups for special nodes; default PROXY for general browsing.
  6. Document custom rules in a local merge file with comments (YAML #) so future you knows why a domain was added.

Debugging when something breaks

  1. Read the client error on import—it often names the invalid key or duplicate entry.
  2. Open Logs or Connections and confirm which rule matched (DIRECT vs your group name).
  3. If nodes exist but rules never proxy, check that mode: rule is set and outbound mode in the UI is "Rule."
  4. 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.
  5. Temporarily set log-level: debug to trace DNS, rule matching, and handshake details—then revert to info for 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 →