Advanced Config 13 min read

Clash Configuration File: YAML Structure Explained, from Core Settings to proxy-groups and rules

A section-by-section guide to a complete config.yaml, covering top-level keys, dns, proxies, proxy-groups, rule-providers, rules, and the order they belong in.

First, distinguish YAML files, subscriptions, and core configuration

config.yaml is a common configuration filename, though the extension can also be .yml. YAML represents key-value pairs, lists, and nested structures; Clash or mihomo interprets those fields. A file that parses as valid YAML may still contain node protocols, DNS options, or rule types unsupported by the core currently in use.

Clash Meta is now maintained under the name mihomo. Client apps may package different cores and expose settings in different places. This guide focuses on mihomo configuration; features such as inline rule sets should not be assumed to work with older Clash cores. To check compatibility, first confirm which core is running on the client's About or Core Info screen—not just the client app's name.

  • Full configuration subscription: May include ports, DNS, nodes, proxy groups, and rules; updates may change any of these.
  • Proxy provider: Supplies nodes through proxy-providers for local proxy groups to reference. It is not the same as a complete configuration.
  • Client override: Merges or replaces fields in addition to subscription content. The client determines the merge order.

A complete config.yaml you can validate

This configuration only sets a local mixed port and a direct-routing policy; it contains no proxy servers. Use it to check field nesting, policy references, and rule order. Loading successfully does not mean you have a proxy connection. The inline rule set in this example requires a mihomo core that supports type: inline.

# Core entry points
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false

# DNS module; no separate DNS listening port is configured
dns:
  enable: true
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - '*.lan'
    - 'localhost'
  nameserver:
    - 223.5.5.5
    - 1.1.1.1

# No remote proxy nodes configured
proxies: []

# Policy group names are referenced by rules
proxy-groups:
  - name: Select exit
    type: select
    proxies:
      - DIRECT

# Inline rule set; no separate rule file needed
rule-providers:
  Example domains:
    type: inline
    behavior: domain
    payload:
      - '+.example.com'

# Rules are checked top to bottom; the last one is the catch-all
rules:
  - DOMAIN,localhost,DIRECT
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - RULE-SET,Example domains,Select exit
  - MATCH,Select exit

This file does not enable the system proxy or TUN. To route an app's requests through the mixed port, set that app's HTTP proxy to 127.0.0.1:7890. Once a connection reaches the core, the rules select “Select exit.” That group currently contains only DIRECT, so traffic still goes straight to its destination.

Configuration order and rule evaluation order are not the same

Whether the top-level dns section comes before or after proxies usually does not change the configuration's meaning. Organizing sections as “entry point → DNS → nodes → proxy groups → rule sets → rules” makes dependencies easier to check. The order that does affect matching is the order of entries in rules. Candidate order in a proxy group also affects how options appear in the UI, so not every list can be treated like a freely sortable dictionary.

Core settings: ports, operating mode, and logging

FieldExample valueWhat it does
mixed-port7890Accepts HTTP and SOCKS proxy connections on the same port.
allow-lanfalsePrevents other devices on the local network from using this machine's proxy.
moderuleRules determine which policy handles each connection.
log-levelinfoLogs routine activity; switch to debug temporarily when troubleshooting.
ipv6falseDisables IPv6 support in the relevant core features; it does not change your operating system's network settings.

mixed-port: 7890 does not route all system traffic through Clash. The system proxy only affects apps that honor that setting; apps that connect directly may bypass it. TUN uses a virtual network adapter and routing to capture connections—these are two different traffic entry points.

external-controller is the listening address for the management API, not a proxy address to enter in a browser. For example, you could set a local management port to 127.0.0.1:9090, but it cannot use 7890 on the same address as the mixed port. A client may manage the controller itself, so check its requirements before overriding this setting.

dns: resolution modes, upstream servers, and Fake-IP

dns is a top-level mapping. Fields inside it, such as enable and nameserver, must be indented one level further than dns:. The example's nameserver lists two upstream DNS addresses. Providing two addresses does not guarantee that queries will fall back from the first to the second in order; actual behavior depends on the core and other DNS settings.

Fake-IP addresses are not proxy node addresses

With enhanced-mode: fake-ip, the core assigns synthetic addresses to eligible domain lookups and maps them to subsequent connections. The example address pool, 198.18.0.1/16, is not a remote server address and should not go in a node's server field. For LAN apps that need real DNS answers, add domains to fake-ip-filter as needed.

  • dns.enable: true enables the core's DNS module; it does not mean the operating system sends all DNS queries to it.
  • dns.listen opens a separate DNS listener. This example leaves it unset to avoid using an additional port.
  • dns.ipv6: false controls how the core handles AAAA queries. It does not mean the system will never make IPv6 connections.
  • Encrypted DNS protects the relevant DNS resolution path. It does not replace proxy rules or guarantee that every DNS query exits through the proxy.

If domains fail to load but their IP addresses work, first check whether DNS queries reach the core and whether the upstream server is reachable. Then check Fake-IP mappings and routing. Switching proxy nodes repeatedly may not address the actual problem.

proxies and proxy-groups: define nodes and selection logic separately

proxies is a list of nodes. A node typically includes name, type, server, and port, plus the authentication and transport settings required by its protocol. Fields are not interchangeable across protocols: for example, a password field cannot replace a UUID required by another protocol. Get actual values from your service provider or your own server configuration.

proxy-groups defines how to choose an exit, not remote servers. Although proxies appears here too, it is only a list of candidate names. Each name must match a defined node, another referenceable proxy group, or a built-in policy such as DIRECT.

Common proxy group types

  • select: Choose a candidate manually in the client. Use it when you want to pick a specific node or go direct.
  • url-test: Automatically chooses a candidate based on probes to a specified URL. A latency test does not reflect the actual loading speed of every website.
  • fallback: Selects an available candidate based on candidate order and health checks. Useful for failover.
  • load-balance: Distributes connections according to the configured strategy. It does not split one download across multiple nodes to combine their bandwidth.

This example uses select, so it does not need a probe URL. If you switch to an automatic testing group, you also need a test URL suited to your network and a check interval; for example, interval: 300 means 300 seconds. Changing only type while omitting the parameters that type requires is not enough.

Referencing subscription nodes through proxy-providers

When using a proxy provider, a proxy group usually references the provider name with use instead of putting a subscription URL in its proxies list. The provider's output must also match the expected format; a regular full-configuration subscription may not work as a proxy provider. Keep the reference chain clear: rules point to a proxy group, and the group selects a node.

rule-providers and rules: rule set contents and where they are matched

rule-providers stores reusable rule sets; rules determines when to use them and which policy handles a match. Defining a rule set named “Example domains” does not route traffic by itself—you must also add a rule such as RULE-SET,Example domains,Select exit.

The behavior setting determines what goes in payload

behaviorContent exampleNotes
domain+.example.comUse domain rule set syntax; don't add a target policy to each line.
ipcidr192.168.0.0/16Contains IP ranges; do not mix in domains.
classicalDOMAIN-SUFFIX,example.comUses rule expressions; specify the target policy where the set is referenced.

This example uses type: inline, with the rule set contents directly under payload. Remote HTTP rule providers also require a download URL, cache path, update interval, and the correct format; don't paste a remote file's contents into the URL field. If an older core does not support inline providers, rewrite them as regular rules only after confirming the behavior will be equivalent.

Rules are checked top to bottom; the first match wins

For example, to route Example domains through “Select exit” and send all other connections direct, write:

rules:
  - DOMAIN-SUFFIX,example.com,Select exit
  - MATCH,DIRECT

DOMAIN matches an exact domain; DOMAIN-SUFFIX matches that domain and its subdomains. MATCH is a catch-all rule and usually belongs last. Move it to the first line and the domain rules below it will never get a chance to match. When adding rules, edit the existing list rather than appending a second rules: section at the end of the file.

The no-resolve option at the end of an IP rule means the core will not resolve a domain to an IP just to match that rule; it does not disable DNS globally. If a connection already has a destination IP, it may still match the relevant IP range. This example lists only some local address ranges—do not treat these three entries as a complete LAN rule set.

Where to put TUN settings—and why one switch isn't enough

tun is a top-level section, like dns and rules; it must not be nested inside a proxy group. A typical desktop configuration looks like this, but support also depends on the core, operating system, and how the client captures traffic:

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

auto-route configures relevant routes automatically, while auto-detect-interface identifies the outbound interface. Enabling TUN usually requires administrator privileges or the client's service mode. Android clients commonly create a VPN interface through the system's VpnService, so don't follow desktop permission steps on Android.

any:53 in dns-hijack redirects eligible traditional DNS traffic; it does not capture every encrypted DNS request sent by browsers over HTTPS. Corporate VPNs, other virtual adapters, and manual routes may also conflict with automatic routing. First verify the configuration through the system proxy, then enable TUN. This makes troubleshooting easier by avoiding simultaneous changes to the traffic entry point, DNS, and rules.

Before loading: check indentation, references, and client overrides

Common YAML mistakes

  • Indenting with tabs: Use two spaces consistently; align fields at the same level.
  • Missing list dashes: rules, nameserver, and proxy group candidates are lists.
  • Duplicate top-level fields: Two dns: entries do not automatically merge; the parser may report an error or keep only one.
  • Unquoted special characters: Quote passwords, names containing special characters, and values that could be interpreted as another data type.
  • Case or name mismatch: Select exit and Select exit are not reliably treated as the same reference. Check for trailing spaces when copying.

Validate with the core, then check what actually takes effect

If the mihomo command-line program is installed, run this from the configuration directory:

mihomo -t -f ./config.yaml

On Windows, you can run .\mihomo.exe -t -f .\config.yaml, provided the program is in the current directory. A successful test means the configuration passes validation with that core; it does not confirm that node authentication is correct, the network is reachable, or system traffic is being proxied.

  1. Run a configuration test first. Address line numbers, unknown fields, and policy reference errors reported in the log.
  2. Load the configuration in the client. Confirm that the mixed port is 7890 and that no port conflict is reported.
  3. Make a request from an app configured to use the proxy, then check the matched rule and resulting policy in the connection list.
  4. If the file specifies mode: rule but the UI shows a different mode, check whether the client's global settings or runtime API are overriding the file.
  5. Finally, update the subscription once and check that your custom rules are still there. Make sure persistent changes are saved in the override layer.
Download Clash