Configuration Reference · mihomo

Clash Configuration Reference
YAML and Runtime Settings

Look up ports, DNS, proxies, proxy groups, rules, and overrides by field. Examples explain how configuration works and do not provide a working proxy service.

New to FlClash? Start with the Getting Started guide to import a subscription, choose a mode, and verify your connection. This page is for users who need to edit configuration, maintain rules, or track down conflicting fields. It explains how settings are parsed, referenced, and merged. Find installers on the download page. For a cross-platform client comparison, start with our top pick, Clash Plus, then compare FlClash and other clients based on your needs.

Updated: March 21, 2026. Values shown are examples, not defaults for every client or core version. Interface labels, feature locations, and the generated runtime configuration depend on the client you use.

1. YAML Structure and Configuration Boundaries

mihomo reads structured configuration; it does not execute the file line by line as a list of commands. A typical file has a mapping as its root, with general settings, DNS options, a proxy list, a proxy group list, and a rules list beneath it. The order of fields in the file usually does not determine which setting takes precedence, but list order can directly affect behavior. Rules are the clearest example: the core checks them from top to bottom, so they are not an informational list you can rearrange freely.

Mappings, Lists, and Indentation

Mappings use colons to separate keys and values; lists use hyphens to introduce items. Indent with spaces, ideally two per level, and never mix in tabs. Align fields at the same level and indent child fields beneath their parent. Put a space after each colon, and use standard ASCII punctuation—not full-width colons or Chinese commas. The line highlighted by an editor is not always where the problem starts: a missing quote on the previous line may not trigger an error until the next one.

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - https://dns.alidns.com/dns-query

proxies: []

proxy-groups:
  - name: Default route
    type: select
    proxies:
      - DIRECT

rules:
  - MATCH,Default route

This example is a starting point for understanding the structure. All traffic ultimately goes direct; it does not provide a proxy connection. proxies: [] means the list is empty, which is different from leaving the field blank. At the root level, dns is a mapping, and nameserver is a list within it. Each item in the proxy group list is itself a mapping, so a single file can use all of these structures. When copying an example, preserve the full hierarchy instead of copying just the line that looks relevant.

Strings and References

Quote passwords, names, paths, and values containing special characters. Pay particular attention to passwords that look like numbers, as well as hash marks, colons, and backslashes. A hash mark can start a comment in an unquoted scalar, while a Windows path inside double quotes may trigger escape processing. Forward-slash paths or correctly quoted single-quoted strings are often easier to check. Write boolean fields as true or false; don't quote every value for consistency, or booleans may be parsed as strings.

Node names, proxy group names, and rule targets are linked by references. When a rule points to a group, its name must match the group's name exactly, including spaces and capitalization. Avoid commas in names where possible, since traditional rule syntax uses commas to separate arguments. Before deleting a node or renaming a group, search for references to it in other groups and rules. Successful parsing does not guarantee that every reference resolves; unresolved references typically surface during configuration validation or loading.

Source Files and the Final Runtime Configuration

The original subscription, the client's local settings, and the file actually loaded by the core are three separate things. A client may rewrite ports, DNS, or TUN settings at startup, or append rules to a subscription. Direct edits to a temporary runtime file may be overwritten on the next refresh or restart. First find the client's configuration management, override, or merge controls. Determine which layer stores your changes, then inspect the generated result. If the interface cannot export the runtime configuration, use logs and the protected controller API to check key fields.

Each snippet explains only the fields it covers. Apart from the structural starting point in this section, don't treat later snippets as complete configurations ready to run. First confirm that the referenced proxies, groups, and providers are defined in the same final configuration.

YAML anchors can reduce duplication, but merge keys are mainly for mappings; don't expect them to automatically concatenate two rule lists. For a configuration you're maintaining for the first time, explicit definitions are easier to troubleshoot than complex reuse. Don't define dns or rules more than once at the same level to try to append values: parsers may handle duplicate keys differently. Instead, consolidate each field into a single definition and use a clearly defined merge process.

2. Ports, Modes, and Traffic Routing

General settings determine how the core accepts connections, selects an outbound route, and handles LAN access. Before making changes, distinguish three paths: an app connects directly to a proxy listening port; the system proxy directs apps that honor system settings to that port; and TUN uses a virtual network interface to capture traffic covered by its routes. These paths can coexist, but troubleshoot them separately to avoid losing track of which layer is responsible after enabling multiple traffic-capture methods.

Listening Ports and Network Access

FieldExamplePurpose and limitations
port7891HTTP proxy listening port.
socks-port7892SOCKS proxy listening port.
mixed-port7890Accepts HTTP and SOCKS proxy connections on the same port.
allow-lanfalseControls whether devices on the LAN can access the proxy.
bind-address"*"Bind address when LAN access is enabled.
moderuleSelects an outbound route according to the rules.
log-levelinfoSets the level of detail in core logs.

If you don't need compatibility with older setups, you can configure just the mixed port. Each listener needs a different port: port and mixed-port cannot use the same address and port at the same time. Browsers, terminals, and other devices configured manually won't update when you change a port. If logs report that an address is already in use, check for another Clash client, an old core process, or a local service using that endpoint instead of repeatedly changing ports and masking the process conflict.

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false

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

TUN is explicitly disabled in the example so you can first verify the app's explicit proxy path. To enable it, set tun.enable to true and confirm that the client has permission to create a virtual network adapter and change routes. Valid stack values depend on the platform and core capabilities; the value's name alone doesn't tell you whether it is compatible. Clients may manage these fields themselves, so check the final runtime configuration even after setting them manually.

Rule, Global, and Direct Modes

mode: rule makes decisions using the rules list. Global mode sends traffic through the selected global policy, while Direct mode is mainly useful for checking whether the proxy route is the problem. Switching to Global mode does not guarantee that all traffic goes through a remote node: the global policy may still select DIRECT. After changing modes, check which group member is actually selected. Existing long-lived connections may keep their original route, so make a new request for testing and close relevant connections before retrying if needed.

LAN sharing requires the listener settings, host firewall, and network topology to allow it. Changing allow-lan alone does not guarantee that other devices can connect; they must use the host's LAN address, not their own loopback address. Before opening a listener, consider whether the network is trusted and configure proxy authentication if needed. Proxy authentication protects the proxy endpoint; it is not the same as credentials for the controller API, and the two are not interchangeable. Never expose the controller API directly to the public internet.

TUN and IPv6: What to Check

auto-route configures relevant routes automatically, while auto-detect-interface helps identify the outbound interface. Neither resolves every conflict involving multiple network adapters, virtual machines, or other VPNs. If connections loop, check whether the proxy server's own outbound traffic is being captured again and whether other software keeps rewriting the default route. Desktop service permissions and mobile VPN authorization are different mechanisms; don't apply one platform's permission steps unchanged to another.

Top-level ipv6 and dns.ipv6 belong to different layers. The former affects the core's use of IPv6; the latter controls how DNS handles AAAA queries. When troubleshooting, note whether the system has a working IPv6 route, whether the node supports IPv6 egress, and whether DNS returns IPv6 addresses. Turning off one setting doesn't prove the entire connection path now uses IPv4. Base changes on connection logs and actual DNS results.

3. DNS and Fake-IP Settings

DNS settings affect both the resolution of destination domains and, potentially, the resolution of proxy server addresses. First identify who is making the query, which upstream the core uses, how the upstream's domain gets its initial address, and which route the query takes. A webpage loading successfully doesn't prove the DNS path is working as expected: the app may use a cache or built-in encrypted DNS. Start troubleshooting with a new query and check resolution behavior at the app, system, and core levels separately.

Listeners, Upstreams, and Initial Resolution

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - https://dns.alidns.com/dns-query
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  nameserver-policy:
    "+.example.com":
      - https://dns.alidns.com/dns-query

enable turns on the core's DNS module, and listen sets its listening endpoint. The example's loopback address and nonstandard port are for local use only; setting this field does not automatically send all system DNS requests there. Traffic capture may instead be handled by the client, system DNS settings, or TUN DNS hijacking. Likewise, any:53 in TUN cannot necessarily capture requests an app sends directly to an encrypted DNS service; those are usually ordinary encrypted connections.

nameserver specifies upstreams for regular queries. default-nameserver is used when an initial lookup is needed, such as resolving the domain of an encrypted DNS service. proxy-server-nameserver handles proxy server domain lookups, helping prevent a loop where resolving the node domain depends on the proxy connection, which itself depends on resolving the node domain. The example uses public DNS resolvers; choose upstreams based on network reachability and privacy needs. When switching, first make sure the new upstream is reachable from your current network.

Fake-IP and Real Address Resolution

Fake-IP mode returns a synthetic address from a pool to the app, while the core keeps a mapping between that address and its domain. When it captures the subsequent connection, it restores the domain and applies the rules. This preserves domain-based routing context, but only if both the synthetic address and the connection traffic pass through the same core. If a request bypasses the core and connects directly to the synthetic address, or the core restarts while the app still has an old cached address, the connection may fail. That doesn't necessarily mean the node itself is unavailable.

fake-ip-filter tells the core not to use synthetic addresses for certain domains. The example lists common LAN suffixes, but filtering an entry does not automatically make internal records available from a public upstream; you may also need to route those queries to an internal DNS server. Don't add every domain to the filter just to fix one LAN device—that changes the normal domain-restoration path. Identify the failing domain first, add the narrowest possible entry, then clear app and system caches before retesting.

redir-host returns the real resolved address to the app and uses available information to route the connection. The main difference from Fake-IP is how addresses are returned and associated with domains; neither is simply faster or safer. Test scenarios that rely on displaying real addresses, special LAN discovery, or an app's own address checks with your actual traffic-capture setup. For more on how they work, see Fake-IP vs. redir-host.

Check DNS and Traffic Routing Separately

nameserver-policy selects a DNS upstream based on the domain, while the rules list selects an outbound route based on connection details. Resolving a domain through a particular DNS server does not mean connections to that domain will use the same proxy policy. If DNS upstream connections also need to follow rules, look into respect-rules. Before enabling it, make sure proxy server domains have an independent, working resolution path and check that upstream domains won't create a dependency loop. Avoid stacking multiple mechanisms before you understand the direction of each query.

After DNS results change, existing connections and app or system caches may still hold the old state. Test with a new request and record the queried domain, returned address, matching DNS policy, and final outbound route. This helps distinguish cache differences from settings that haven't taken effect.

When configuring fallback, read the associated filter conditions too. It is not simply a list of backup servers tried one by one in order. Geographic routing also depends on the availability of geolocation databases. If you're new to configuration, start with one reachable regular upstream and a separate resolution path for proxy nodes. Once those work, add more complex policies. If queries time out, determine whether the upstream is unreachable, initial resolution failed, or traffic capture is missing before changing every DNS field.

4. Proxies and Protocol Settings

proxies is an inline list of proxy nodes. Each item defines an outbound route that a proxy group can reference. A node needs at least a unique name, a protocol type, and the server and authentication details required by that protocol. Protocol fields are not interchangeable: a password does not make Shadowsocks encryption settings, Trojan TLS parameters, and another protocol's user identifier equivalent. Use the parameters supplied by your service provider rather than combining similar-looking lines from different tutorials.

Core Fields and Protocol Context

proxies:
  - name: Example-SS
    type: ss
    server: proxy.example.com
    port: 8388
    cipher: aes-128-gcm
    password: "your-password"
    udp: true

  - name: Example-Trojan
    type: trojan
    server: proxy.example.com
    port: 443
    password: "your-password"
    sni: proxy.example.com
    skip-cert-verify: false
    udp: true

The reserved domains and sample passwords in these examples won't connect to a real service. Replace them with the full parameters from your provider. server can be a domain or address, and port is the remote service's listening port; it is unrelated to the local mixed-port. name is a local reference label and is not used for remote authentication. You can rename nodes to make groups easier to read, but update every group that references the old name or the node won't be selectable.

The Shadowsocks cipher must match the server's setting; changing DNS won't usually fix an authentication failure. Trojan generally uses TLS, and sni specifies the server name in the TLS handshake. Don't change it to an arbitrary reachable website just because the connection timed out. If you connect by address but the certificate is issued to a domain, use the name specified by the service. Address, port, authentication, and TLS identity are separate layers and should be checked independently.

TLS, Transport, and UDP

skip-cert-verify: false keeps certificate verification enabled. To investigate certificate errors, check the system time, certificate chain, name match, and whether the connection reached the intended server. Disabling verification may hide the error, but it doesn't prove the server's identity is correct. Some protocols enable TLS with tls; others already include TLS behavior. Don't assume every type accepts the same switch. An unsupported or misplaced field may be ignored rather than producing an obvious error.

For WebSocket, HTTP/2, or other transports, options must match the server setup. A WebSocket path usually goes in ws-opts.path; additional request headers belong in the relevant headers mapping. The connection address, TLS server name, HTTP Host header, and request path can all differ, but those differences should reflect the actual deployment—not arbitrary combinations. Setting the correct node type alone does not provide the required transport settings.

udp: true allows the node to handle the relevant UDP traffic; it cannot give UDP support to a server that doesn't have it. If webpages work but voice calls, games, or QUIC connections fail, check the app's traffic-capture path, core protocol support, remote service, and network intermediaries separately. Disabling QUIC for an app can help isolate the issue, but it doesn't prove UDP is working again. Distinguish UDP forwarding from DNS requests too, as they may take entirely different routes.

Importing Nodes and Protecting Sensitive Data

Subscription nodes may not appear directly under proxies; they may be loaded dynamically through a proxy provider. A raw share link, an encoded collection of nodes, and a full Clash configuration are different formats. Renaming a file extension does not turn it into YAML. If import fails, first check whether the response is a login page, error page, or unsupported format, then inspect the protocol fields. For a systematic checklist, see Subscription Import Failures and Parse Errors: A Checklist.

Before sharing a configuration snippet, remove server identity details, passwords, user IDs, subscription URLs, and any accompanying access tokens. Even if a node name isn't sensitive, a full subscription link may grant access to an account. Field names, nesting, protocol type, and error text are usually enough for troubleshooting; don't publish authentication values. For auto-updating subscriptions, avoid maintaining long-term inline copies of nodes. Keep the subscription as the source and use the client's override layer for local rules and group selection.

Duplicate node names make references ambiguous, especially after merging multiple subscriptions. Before adding another source, check for existing nodes and groups with the same names, as well as providers using the same path. If the client supports name prefixes or filters, apply them consistently at the source level instead of renaming every node by hand. Keep sources, authentication parameters, and policy references separate so updating one doesn't require editing every other part.

5. Proxy Groups and Providers

Proxy groups organize nodes or other groups into outbound targets that rules can reference. They determine how to select a route, not how to identify the type of connection. A common structure sends a rule to a service-specific group, which then selects a manual or automatic group; the automatic group gets its nodes from a provider. This hierarchy reduces the impact of node changes on rules, but it must not contain cycles or there will be no definite final route.

Manual Selection and Automatic Testing

proxy-providers:
  Local nodes:
    type: file
    path: ./providers/local.yaml
    health-check:
      enable: true
      url: https://www.gstatic.com/generate_204
      interval: 600

proxy-groups:
  - name: Automatic route
    type: url-test
    use:
      - Local nodes
    url: https://www.gstatic.com/generate_204
    interval: 600
    tolerance: 50

  - name: Default route
    type: select
    proxies:
      - Automatic route
      - DIRECT
    use:
      - Local nodes

providers/local.yaml must exist, and its root must include a proxies list containing real nodes. The sample nodes in the previous section are for checking structure only. Paths are usually resolved relative to the core's working directory, and the client may further restrict file access. If a file can't be found, check the actual working directory rather than assuming the path is relative to the file you're editing. File providers help demonstrate references; remote subscriptions typically use the HTTP type and an update URL.

select lets users choose a member manually. url-test selects an available route based on test results. fallback checks members in order for an available route, while load-balance distributes connections according to the selected strategy. Automatic tests only measure performance to the test target; they don't guarantee availability for every website, streaming service, or business application. Use a stable, reachable test target and avoid pages that depend on a specific login session.

Intervals, Tolerance, and Group Members

The example's interval is in seconds; tolerance is the latency margin used for automatic selection, shown in milliseconds. Tolerance can prevent frequent switching when results fluctuate slightly, but it can't fix unstable nodes or a poor test target. Health checks generate real network requests, so don't use very short intervals for a large subscription without good reason. Clients may adjust checks in the background or while the device sleeps; an interface update time doesn't prove every check ran on schedule.

proxies lists explicit member names, while use references proxy provider names. Both can appear in the same group, but they mean different things: the former references known nodes or groups, and the latter adds nodes from a provider. Provider health checks and proxy group tests also operate at different levels. Even if they use the same test URL, their results and timing aren't necessarily equivalent. If a group is empty, check provider loading first, then filters; don't assume every node is down.

Nested groups must form a directed, acyclic structure. For example, a service group can reference a default route, which can reference an automatic route, but the automatic route should not reference the service group again. Too many layers also make the current selection harder to understand. Draw the reference chain from the rule target to the final node when troubleshooting. If the correct rule matches but traffic still goes direct, check whether any group in the chain allows and has selected DIRECT, rather than checking only the outermost group.

Remote Providers and Persistent Updates

An HTTP provider typically needs a url, a path, and an update interval. A subscription URL is a form of access credential; don't include it in a public repository or public logs. Use a unique cache path for each source, or one provider may overwrite another. When an automatic update fails, distinguish a failed remote request from the usability of the local cache. Nodes still appearing in the interface doesn't mean the latest subscription was fetched successfully—or that cached nodes are still working.

If you filter by name, check the regular expression's scope, case sensitivity, and whether provider updates changed node names. A filter that matches nothing leaves an automatic group with no candidates; shortening the test interval won't help. Disable the filter first to confirm nodes load, then narrow the results gradually. Saving group selections requires a persistence mechanism supported by the client or core, such as profile.store-selected. It saves selection state; it doesn't replace subscription updates or recreate deleted nodes.

Stable group names and updateable node sources are easier to maintain than a copied subscription. Point local rules to stable group names and update nodes through providers to reduce the impact of subscription changes on your rules.

6. Rule Syntax and Matching Order

In rule mode, rules is an ordered list of matches. Each rule usually consists of a type, match criteria, and a target; some types also support extra parameters. The first matching rule determines the outbound route, and later rules are not evaluated as alternatives. Rule maintenance is therefore about ordering first and rule count second. Adding large rule sets does not automatically improve routing accuracy. Overlapping conditions and broad matches placed too early can hide more specific policies.

Domains, Addresses, and the Catch-All

rules:
  - DOMAIN,printer.example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,Default route
  - DOMAIN-KEYWORD,example,Default route
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - MATCH,Default route

DOMAIN matches an exact domain, DOMAIN-SUFFIX matches a domain and its subdomains, and DOMAIN-KEYWORD matches a keyword in the domain. Keyword matches are usually broader and can route unrelated domains through the same policy, so prefer an exact domain or suffix when the service boundary is clear. The example puts an exact domain first so the later keyword rule can't match it prematurely. A rule target must be an existing node, proxy group, or built-in outbound.

IP-CIDR matches an IPv4 destination range; use IP-CIDR6 for IPv6 ranges. no-resolve prevents the core from triggering a domain lookup solely to evaluate this type of rule. It doesn't mean the connection will never need DNS, or that the rule can't match when the real destination address is already available. LAN bypass rules also depend on connection context. In Fake-IP mode, don't treat a synthetic address as the real server address the app ultimately accesses.

Rule Sets and Match Types

rule-providers:
  Local domains:
    type: file
    behavior: domain
    format: yaml
    path: ./rules/local-domains.yaml

rules:
  - RULE-SET,Local domains,DIRECT
  - MATCH,Default route

This snippet requires a real rule file, which could contain the entries shown below. A domain behavior rule set contains domain entries only; don't append a proxy group to each entry. Specify the target in the main configuration's RULE-SET rule. The classical behavior uses entries with rule types, while ipcidr is for address ranges. The behavior, file format, and contents must agree. Renaming a downloaded set doesn't make it compatible with a different behavior.

payload:
  - "+.example.com"
  - "printer.example.org"

The provider name in RULE-SET must match a key under rule-providers; it is neither a local path nor a remote URL. When sets overlap, priority is still determined by their position in the main rules list. HTTP rule providers also involve caching and updates, so record both the loaded rules and their update time during troubleshooting. A successful remote update only confirms that the resource was fetched; it doesn't prove the set contains the domain you need.

Process Rules and Platform Differences

Rules based on process names, executable paths, or app identifiers depend on the platform and permissions, as well as the core's ability to identify which process owns a connection. A process rule working on desktop doesn't mean a mobile system provides the same process information. If expected process details are missing from the logs, check runtime permissions and client support first. Domain and address rules are usually more consistent across platforms; use process rules as a tested supplement, not your only routing criteria.

GEOIP and geolocation domain sets depend on the relevant databases and how they are loaded. A missing database, changed source, or failed update can affect matching. If a rule doesn't match, verify the target information and resource status before changing the rule syntax. Don't assume one address returned for a domain is its permanent, exclusive address: CDNs, regional DNS, and service migrations can all change it. For precise routing, maintain domain-based boundaries and use connection logs to identify other domains involved in the request.

MATCH is a catch-all rule and usually belongs at the end; placing it earlier prevents later rules from matching. Put custom exceptions before the broader rules they need to override, but they don't always have to be the first line. After each change, make a new connection and check the rule type, match, proxy group, and final node. If the correct rule matches but access fails, investigate the node or DNS instead of adding duplicate rules. Rule decisions and route availability are separate issues that need separate checks.

7. Subscription Overrides and Configuration Merging

Subscriptions are usually maintained by an external source, while local needs may include listening ports, LAN settings, DNS, extra rules, and proxy group selections. Overrides keep these local changes in a separate layer and apply them again after a subscription update. They don't modify the subscription server, and they aren't a universal YAML feature. Clients may handle mappings, lists, and empty values differently, so confirm the merge behavior before deciding whether an override should contain a complete object or just selected fields.

Identify Who Owns Each Field

Ports and TUN are often managed in client settings, nodes and providers usually come from the subscription, and service rules may combine subscription content with local additions. If two layers manage the same field, the final value depends on the order in which the configuration is generated. A switch in the interface doesn't prove that the source file was changed, and a value in the source file doesn't prove it remains unchanged at runtime. Compare the original subscription, local overrides, and final runtime file side by side, noting the source of each important field.

StructurePossible merge behaviorRisks to check
Scalar fieldsThe later value replaces the earlier one.Client settings may be generated again after overrides are applied.
Mapping fieldsRecursive merge or full replacement.Adding only DNS subfields may discard existing upstreams.
Rules listReplace, prepend, or append.Rules appended after MATCH may never match.
Proxy group listFull replacement or handling by name.Matching names don't guarantee that members are merged automatically.
Empty values and empty listsClear, ignore, or preserve.An empty value does not necessarily remove a field.

Merging Mappings vs. Replacing Lists

This is a partial override snippet intended only to adjust DNS and logging. Whether it preserves other DNS fields from the subscription depends on whether the client recursively merges mappings or replaces them entirely. With full replacement, omitting nameserver may leave DNS misconfigured. Export or inspect the merged result before applying it; a successful save doesn't prove the result is correct. Some clients have a dedicated DNS override setting, which may also prevent a field with the same name in the general override from supplying the final value.

# Partial override example; merge behavior depends on the client.
log-level: info
dns:
  enable: true
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - https://dns.alidns.com/dns-query

Lists need more care than mappings. Putting a rules list with just two entries in a general override may replace all subscription rules instead of adding two. Adding a proxy group list may also remove the subscription's existing groups, breaking many rule references. Prefer client features that explicitly support prepended rules, appended rules, or a dedicated merge control. If the only option is full replacement, maintain the complete list and account for subscription structure changes.

Rule additions also have a placement problem. Subscription rules usually end with MATCH, so adding domain exceptions after it won't work. Insert exceptions before the broader rules they need to override. If an exception targets a new local group, make sure that group and its members are included in the generated configuration first. Rules, groups, and providers form a complete reference chain; saving just one part doesn't create a working local customization.

Client Differences and Post-Update Checks

Clash Plus, Clash Verge Rev, FlClash, and other clients manage subscription configuration in different ways. Don't reuse the same snippet across clients without checking it first. Look for controls related to configuration management, overrides, rule additions, or runtime configuration, and read their documentation. Test merge behavior with a field that won't affect connectivity, such as the log level. Once you confirm the runtime value changes, add a domain rule you can observe, then move on to DNS and traffic capture. This makes it easier to identify which layer causes a difference.

Before updating a subscription, save your local overrides and a working configuration copy—but never upload a copy containing credentials to a public location. After updating, check that stable group names still exist, providers haven't been renamed, node filters return results, and rule targets are valid. Subscription changes can affect more than nodes; group hierarchies and rule resources may also change. If an update breaks your setup, comparing the before-and-after structures is usually more useful than repeatedly importing the subscription. For initial startup checks, see the First Install and Initial Setup Checklist.

Don't edit temporary runtime files generated by the client. Keep persistent changes in an override layer the client supports, save a rollback copy, and confirm your changes survive a subscription refresh.

YAML & anchors, aliases, and merge keys don't replace the client's cross-file merge process. They reuse structures only while parsing the current YAML document; they can't determine how an external subscription should be updated. Don't rely on duplicate top-level keys for overrides or assume an empty object will always clear existing settings. Keep overrides small, state exactly which fields should change, and include a way to verify every change.

8. Configuration Validation and Troubleshooting

Troubleshoot configuration in layers: file parsing, reference resolution, listener startup, DNS, outbound connections, and rule decisions. Each layer has different failure signals; not every problem means the subscription is broken. If loading fails, fix syntax and fields first. If loading succeeds but there's no traffic, check traffic capture. If traffic flows but DNS fails, check DNS. If DNS works but the remote connection fails, check the node. If the connection works but takes the wrong route, check rules and group selection. This order helps avoid unrelated changes.

Static Checks and Core Validation

When editing files outside the client, start with your editor's YAML checks for indentation, quotes, and duplicate keys. Passing a general YAML parser only confirms valid syntax; it doesn't validate protocol fields or references. Also validate the configuration with the actual mihomo core, ideally the same version used by your client. Checking with a different core may mislead you because field support can vary. If the client doesn't provide a way to run core commands, don't replace its program files just to validate a configuration.

# Check in a separate test directory; set the path to the actual file location.
mihomo -t -d ./mihomo-check -f ./config.yaml

# Use an explicit HTTP proxy to test the listener and basic request path.
curl -I --proxy http://127.0.0.1:7890 https://example.com

# Resolve the target domain through the proxy to test the SOCKS request path.
curl -I --proxy socks5h://127.0.0.1:7890 https://example.com

# Test the local DNS listener used in this example.
nslookup example.com 127.0.0.1

The final DNS command uses the system tool's default DNS port; it does not query the 1053 port shown earlier. If no DNS service is listening on the standard local port, use a tool that supports a custom port, such as the one below. This distinction matters: a timeout when querying the wrong port doesn't mean the core's upstream is unreachable. Command availability depends on your operating system and installed tools; in the terminal, also confirm that you're running the actual curl program.

dig @127.0.0.1 -p 1053 example.com A

-t tests the configuration, -d specifies the working directory, and -f specifies the configuration file. Relative resources referenced by the configuration must be available in the specified working directory. A missing provider file during testing is not the same as a YAML syntax error. Also check whether the client's working directory differs when running normally. Don't start a second core on the same proxy ports for testing; the resulting port conflict could mask the original problem.

Check the Decision Path with a New Connection

First use an explicit proxy to verify the listener and basic outbound connection, then enable the system proxy, and finally test TUN. This separates whether an app honors system proxy settings from whether the core itself works. A successful HTTP request doesn't prove that UDP, IPv6, or every app works; test each relevant use case separately. Whether SOCKS resolves a domain locally or at the proxy changes what the result tells you. In this example, socks5h makes the proxy resolve the target domain so you can compare it with local resolution.

For each connection, check the target domain or address, matching rule, outer proxy group, nested group selection, and final node. After changing a rule or group selection, make a new connection rather than refreshing a page that may reuse an existing one. If the client can close individual connections, use that to reset your test—but don't interrupt every active connection if you haven't saved your work. DNS changes also interact with caching; after a Fake-IP change, an app using an old cached address may behave differently from the new configuration.

Log Levels and Minimal Rollbacks

Use a moderate log level day to day, and temporarily increase detail while troubleshooting. Look for the first error that caused the failure before later knock-on messages; for example, failed resolution of a remote domain can make every subsequent connection attempt time out. Port conflicts usually happen during startup, while TLS identity errors happen during the remote handshake, and the fixes are different. For help interpreting fields, see Common mihomo Log Errors and Troubleshooting Order. Remove credentials and subscription details before sharing logs.

Change one type of variable at a time, and record its previous value, why you changed it, and the test result. If something breaks, revert the latest change instead of reinstalling the client, replacing the subscription, and changing DNS all at once. If a minimal direct configuration works but the full one doesn't, restore providers, groups, rules, and traffic capture step by step. The first module that fails is usually the right place to investigate further. A working minimal configuration proves the basic environment is functional; it doesn't mean every removed remote node is healthy.

Final verification should include at least one configuration reload, one client restart, and one subscription refresh. Confirm that the configuration parses, persistent settings are restored, and overrides survive updates. Then check that LAN listeners and controller API access have the intended scope and that the log level is back where you expect it. To review the setup steps, return to the Getting Started guide. To switch clients, choose an installer for your operating system on the download page. Save a known-good local baseline so you have a clear rollback point for future changes.

Download Clash