1. YAML Structure and Config Loading
Config Files vs. Runtime State
A Clash config defines listening ports, DNS resolution, available proxies, and traffic rules. It is more than a list of nodes: without policy groups and rules, nodes alone usually cannot provide the traffic routing you expect. The GUI client imports, saves, and starts the config; the kernel reads the generated config and handles connections. The original subscription, the client’s saved local config, and the file the kernel actually loads may all differ.
Before editing, check which config is active in the client, then look for options such as Edit, View Runtime Config, or Open Config Folder. Labels vary between clients, but the goal is the same: identify the file your changes will affect. Don’t rely on the filename alone; config.yaml could be a cache or startup template. If a change has no effect, first check whether the config was reloaded before assuming the field is unsupported.
Indentation, Mappings, and Lists
YAML uses indentation to define nesting. Use two spaces per level and never tabs. Put a space after each colon to separate a key from its value, and use a hyphen followed by a space for list items. Top-level dns, proxies, proxy-groups, and rules are separate sections. An indentation mistake may still parse while putting a field in the wrong place. Passing a syntax check is only the first step; make sure the structure means what you intend.
# Basic local-direct config for checking structure and listening ports
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
proxies: []
proxy-groups:
- name: Proxy
type: select
proxies:
- DIRECT
rules:
- MATCH,Proxy
This config has no remote proxies and its only policy group is the built-in DIRECT, so all traffic goes direct. It’s useful for isolating issues from a complex subscription, but it can’t verify whether a remote proxy service works. When you add a proxy, add its name to a policy group and check that your rules point to that group. Adding an entry under proxies alone won’t make existing traffic use it.
Strings, Booleans, and Duplicate Keys
Write numeric ports as integers and use true or false for switches. Quote text containing a hash, a colon followed by a space, a special prefix, or anything that could be interpreted as another data type. Passwords should also be treated as strings. A hash in the right position starts a comment, which is ignored at runtime. Commas in rules are part of the rule string’s syntax, not YAML key-value separators; don’t split a rule into separate fields.
Do not define the same key more than once at the same mapping level. For example, writing dns near the top of a file and adding another dns at the end is not a reliable way to merge settings: the parser may reject the file or keep only one section. Put all child items in a single mapping instead. Node names, policy group names, and reference strings must also match exactly. Full-width spaces, trailing spaces, and differences in capitalization can all cause references to fail.
Use an Editing Workflow You Can Undo
Save a copy of the original config, then change one thing at a time. Save, reload, and check the logs after each change. If your client has a config test, use it first; with a command-line kernel, run the structural check below. Make sure the executable and path match your system. A config check does not test network access or verify node credentials. When a test fails, start with the first clear error; later errors may be cascading effects.
mihomo -t -f ./config.yaml
This guide focuses on common mihomo config conventions. The original Clash, older forks, and different GUI clients may have compatibility differences, so don’t assume a config for your current kernel works in every client. To identify the kernel and client projects first, read How Clash, Clash Meta, and mihomo Fit Together, then decide which fields to keep.
2. Ports, Modes, and General Options
Listening Ports: Where Traffic Enters
port opens an HTTP proxy listener, socks-port opens a SOCKS proxy listener, and mixed-port accepts both types of proxy request on one port. For most desktop setups, a mixed port is enough; configure other listeners only if an app needs them. These ports are local entry points, not remote proxy server ports. After your browser connects to the local proxy, the kernel selects a remote exit according to your policy.
| Option | Purpose | What to check |
|---|---|---|
mixed-port | Combined HTTP and SOCKS listener | Keep system proxy and app port in sync |
allow-lan | Allow connections from the LAN | Check the bind address and firewall |
mode | Choose the operating mode | Only rule mode routes traffic by rules |
log-level | Set the log verbosity | Restore the normal level when troubleshooting is done |
external-controller | Set the controller listen address | Separate from the proxy traffic listener |
When you change a port, update the client’s system proxy settings or the proxy address in each app. An address-in-use error means another process has claimed the same listener, or an old kernel process is still running. Check the client and logs, stop duplicate instances, and only then decide whether to change ports. Changing the port while leaving the old system proxy address in place can make the kernel start normally while web pages remain unreachable.
Three Modes, Not Three Network Switches
mode: rule routes connections according to rule order; global uses the selected global policy; direct sends connections handled by the kernel directly. These modes only affect traffic that reaches the kernel, not every network request on your device. If you enable rule mode without setting a system proxy, app proxy, or suitable traffic-capture method, browser requests may never reach the kernel, so no rules will match.
mixed-port: 7890
allow-lan: false
bind-address: "127.0.0.1"
mode: rule
log-level: info
ipv6: false
profile:
store-selected: true
This example binds listeners to the local machine and saves policy group selections. At startup, a client may rewrite these fields based on its UI settings. If the mode shown in the UI differs from the subscription, check the final runtime config. Switching modes may not recreate existing connections; test with a new request and, if needed, close old connections on the client’s connections page. See Rule, Global, and Direct Modes Explained for more on when to use each mode.
LAN Sharing and the Controller
allow-lan: true lets other devices connect, but access also depends on bind-address, your firewall, and network isolation settings. If you only need the client on this device, keep LAN access disabled to limit exposure. To share the proxy with a phone or another computer, connect to the client device’s LAN address, not the other device’s loopback address. Restrict access to trusted devices and configure proxy authentication if needed.
external-controller is a management interface for dashboards and clients, not a mixed proxy port. It can change policies and read connection details, so it should usually bind to a loopback address and use client-managed authentication. Don’t put the controller port in your system proxy settings to fix web access, and never expose it directly to the public internet. Proxy authentication and controller authentication are separate mechanisms and cannot replace each other.
Logs, IPv6, and Traffic Capture
For everyday use, start at info level. Temporarily increase verbosity while troubleshooting, then restore it when you’re done. Excessive logs are harder to review and may contain domains and connection details; remove subscription URLs and sensitive information before sharing them. The top-level ipv6 option and a setting with the same name under DNS operate at different levels. Changing one does not prove IPv6 is disabled across your device, and does not replace checking system network settings.
TUN is a separate way to capture traffic. It involves a virtual network interface, routes, permissions, and DNS interception; it does not start working just because you set a mixed port. Desktop clients, mobile OS interfaces, and server command-line environments also require different permissions and setup. Start by getting a regular proxy listener working, then test TUN separately. That gives you a known-good connection path if permissions or routes fail, and makes it easier to isolate the cause.
3. DNS and Fake-IP Options
First, Find Out Which Component Resolves Domains
DNS settings determine how the kernel resolves domain names and tracks the relationship between a domain and its connections. The browser, operating system, app, and kernel may all take part in resolution, so setting dns.enable: true does not mean every device request is now handled by the kernel. With a system proxy, some domains may be sent along with proxy requests. TUN often requires DNS interception and system routes, while an app’s built-in encrypted DNS may take a different path.
dns.listen is the address where the kernel serves DNS queries; it is not an upstream DNS server. The system won’t automatically discover a high-numbered local listener. A client or network setting must send queries to it. This example shows how the fields fit together and does not configure TUN traffic capture. Whether the encrypted resolver in the example is reachable depends on your network; choose a service that is reliable and suitable for your environment.
dns:
enable: true
listen: "127.0.0.1:1053"
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
fake-ip-filter:
- "*.lan"
- "*.local"
- "localhost"
Fake-IP Keeps Domain Associations
enhanced-mode: fake-ip returns a mapped address to the app. The kernel later uses that mapping to recover the domain and select a policy. This address is not the target website’s real server address, so seeing it in system lookup results does not mean DNS has been poisoned. What matters is that the connection returns to the kernel holding the mapping. If one instance handles the DNS query and another receives the connection, the address may exist but still fail to connect correctly.
fake-ip-range is an address pool, not a remote proxy address or a subnet to add to your proxy bypass list. If it conflicts with your LAN, virtual network interface, or another tool’s routes, review the whole setup instead of choosing an arbitrary range that looks unused. After a DNS mode switch or kernel restart, apps may still cache old mappings. Reconnect, clear relevant app or system caches if needed, and then check whether the change helped.
fake-ip-filter lists domains that should not receive mapped addresses, such as some LAN names or services that need real addresses. Adding a domain here does not guarantee a direct connection; rules still determine the exit. An overly broad filter can change DNS behavior for many domains and make troubleshooting harder. If a service fails, first confirm that it depends on a real address, then add the most specific domain possible instead of excluding all domains.
Upstreams, Bootstrap DNS, and Node Resolution
default-nameserver is mainly used to resolve the domain names of upstream DNS servers, so an encrypted resolver can be reached before it has an IP address. nameserver is the upstream used for regular queries. They are not interchangeable just because their names sound similar. If an upstream is specified by domain, a working bootstrap resolver is needed during network startup. If bootstrap resolution fails, encrypted DNS usually cannot connect either.
If a remote proxy server is specified by domain, its name must also be resolved. mihomo provides fields such as proxy-server-nameserver to choose an upstream for resolving proxy server addresses. A dependency loop can occur if DNS traffic needs the proxy while the proxy connection itself needs DNS to find the server. First make sure node domains can resolve through an independently reachable path, then route other queries through the proxy if needed.
nameserver-policy can assign upstream resolvers by domain or supported match patterns, for example when internal and public domains need different DNS services. It controls where DNS queries go, not where application connections exit; rules still determine traffic routing. Before using DNS options that interact with rules, confirm the proxy server resolution path is complete to avoid a circular dependency between DNS and traffic policies.
Narrow Down DNS Problems by Symptom
If only LAN services fail, check the filter list and internal resolvers. If all domains fail, check upstream reachability and whether queries reach the listening port. If you get an address but can’t connect, check the rules and exit. Don’t blame every timeout on Fake-IP: a wrong port, failed node authentication, or a remote connection refusal can look similar. Use the Connected but No Internet troubleshooting checklist to test the entry point, DNS, and exit separately.
4. Proxy Nodes and Protocol Options
Separate Common Fields from Protocol-Specific Fields
proxies is a list of static nodes, with each entry describing a remote connection method. Common fields include the display name name, protocol type, server address server, and remote listening port port. This port comes from the service provider and is unrelated to your local mixed port. The name is used in policy group references; the server field is used to connect. Don’t put a subscription URL or dashboard login address in the server field.
Authentication and transport fields vary by protocol and are not interchangeable. Shadowsocks commonly uses an encryption method and password; Trojan uses a password and relies on TLS. Other protocols may require a user ID, flow setting, or specific transport options. Fill in fields supported by the protocol provided by your service. Changing only type does not convert a node to another protocol and may produce a config that loads but can never complete a handshake.
proxies:
- name: "Example SS"
type: ss
server: ss.example.com
port: 443
cipher: aes-128-gcm
password: "your-password"
udp: true
- name: "Example Trojan"
type: trojan
server: trojan.example.com
port: 443
password: "your-password"
sni: trojan.example.com
skip-cert-verify: false
udp: true
These examples illustrate field syntax; the domains and credentials won’t work for real connections. Don’t infer a protocol or encryption method just because a port is commonly used for secure traffic. A server can use a custom port. The client and server must agree on protocol, authentication, transport, and TLS settings. Get credentials from a trusted service config; don’t guess missing fields from a screenshot.
TLS Names and Server Addresses
The server address determines where the connection goes. The TLS name is used during the handshake and certificate name verification. They may be the same or set separately as required by the server. Don’t change sni in the Trojan example to a popular website domain just because the connection fails. For protocols that use a different field name, such as servername, follow that protocol’s definition instead of adding every TLS name field and expecting the kernel to figure it out.
skip-cert-verify: false keeps certificate verification enabled. If you see a certificate error, check the device clock, server name, certificate validity, and provider settings first. Disabling verification may change the error, but it bypasses a security safeguard used to identify the server and is not a routine fix. For certificates in a private environment, first establish how the certificate trust chain is configured, then choose an appropriate client setting.
Transport, UDP, and Resolution
Some protocols also require transport settings such as network, ws-opts, or grpc-opts. Paths, request headers, and service names are part of the server’s configuration and can’t be omitted just because the domain matches. A WebSocket path is not the same as a regular website URL. If a handshake fails, compare your settings with the provider’s original parameters and check whether transport options were lost during subscription conversion, copying, or client import.
udp: true allows the node to handle the relevant UDP traffic, but does not guarantee that the entire path supports it. The app entry point, capture method, remote protocol, server config, and network firewall can all affect the result. If web pages load but voice chat or games fail, check separately whether the traffic reaches the kernel and whether the remote exit supports the required transport. Don’t just keep toggling the node’s UDP option. Some UDP-based proxy protocols also require the underlying network to allow those connections.
If a node uses a domain for its server address, the domain must resolve before the remote connection can start. If the log shows the correct node name but server resolution fails, check the node resolution upstream in the DNS section. If it connects to an address and then authentication is rejected, check the password and protocol. Reading errors by stage—resolution, connection, handshake, authentication, and application request—is more useful than simply deciding a node is unavailable, and makes it easier to describe the problem to your provider.
Node Maintenance and Sensitive Information
Duplicate node names make references ambiguous and can leave stale names after a subscription update. Keep static node names unique, and update policy group and rule references when you rename one. For large, frequently changing node lists, use proxy providers described later instead of copying the whole list by hand. To switch clients, visit the download page and choose your platform. Clash Plus is a good starting point for a typical GUI client; first confirm that its kernel supports the protocols you need.
5. Policy Groups and Exit Selection
Policy Groups Give Rules a Reusable Target
proxy-groups gives rules a stable target name. Rules can point to Proxy while you switch nodes within the group, without editing each domain rule. Group candidates can be individual nodes, other policy groups, or built-in policies. Think of them as a directed reference graph: a request matches a rule, enters a group, then follows the group’s current selection to its final exit. Groups do not all handle the same connection at once.
Use select for manual selection, such as a main entry point, work setup, or service that needs a fixed exit. url-test automatically picks a candidate based on probe results; fallback tries candidates in order until it finds one that works; load-balance distributes connections according to a supported strategy. An automatic group is not the right default for everyone. Consider whether exits can change, sessions need to persist, and nodes belong to the same service environment.
proxy-groups:
- name: Proxy
type: select
proxies:
- Automatic Selection
- DIRECT
- name: Automatic Selection
type: url-test
proxies:
- "Example SS"
- "Example Trojan"
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
rules:
- MATCH,Proxy
This example depends on the two nodes defined in the previous section; the policy group alone will not work. The probe URL is for availability checks, not a proxy server or a complete test of a specific website. If it can’t be reached on your network, every candidate may appear unavailable. Choose a stable probe target that suits your environment, and confirm probes go through the intended nodes rather than judging group selection by how quickly an app page loads.
What Automatic Probe Options Actually Do
interval usually sets the probe interval in seconds. In automatic selection, tolerance can reduce unnecessary switching when results differ only slightly. Shorter intervals aren’t always better: frequent probes add requests and drain power, especially on mobile devices. Some automatic groups also support options such as lazy checks. Their behavior depends on the group type and kernel implementation; don’t assume every unused group is probed at the same rate.
A successful probe only means a node can reach the probe target. It doesn’t prove that every website, protocol, or account session will work. If a service is affected by region, login state, or exit restrictions, test a new connection to that service itself. After automatic selection changes exits, existing connections may keep using their old route. Seeing multiple exits at once doesn’t necessarily mean the config is conflicting; connection lifetimes may simply differ.
Nested Groups and Reference Constraints
Nested groups are useful for separating manual choices from automatic selection. For example, a main group can let you switch manually between an automatic group and direct access, while the automatic group selects a node. Don’t make groups reference each other or include themselves as candidates; that creates a cycle. To find a broken name, follow the rule target step by step: does the target group exist, does each candidate group exist, and does the final node exist? Keep going until you find a leaf that can actually connect.
Use use to add candidates from a proxy provider, and filter to select by name. A filter expression is a match condition, not a node category label. If a subscription renames nodes, a filter that used to work may return nothing. If an automatic group has no candidates, check that the provider loaded and that the filter isn’t too restrictive before changing the probe interval. Clear the filter to confirm candidates are available, then narrow the match gradually.
Saved Selection Doesn’t Pin All Traffic
profile.store-selected can save manual group selections, but clients may persist state their own way. After an update changes a group name, an old selection may no longer match; deleting a candidate node may also trigger a fallback. To keep a service on a specific exit, use stable group and node names, and put that service’s rule before general rules. Don’t rely only on the main group selection in the UI: a more specific rule may point to a separate group.
The built-in DIRECT means direct connection, and REJECT means block. Neither is a remote node you need to define. Before adding direct access to an automatic probe group, consider whether it will win simply because the probe succeeds easily, defeating the purpose of using a proxy. If an automatic selection is unclear, first pin a known-good node in a manual group and verify the service works. Then restore automatic policies one at a time to separate node issues from group logic.
6. Rule Syntax and Match Order
Rules Run Top to Bottom; the First Match Wins
rules is an ordered list. The kernel checks connections in sequence and applies the first matching policy; it does not keep searching for a more specific rule. Put specific domain rules near the top, broader address rules later, and use MATCH at the end for anything left over. If you put the catch-all first, most later rules will never run. This can make routing behave very differently from what you expect even when the config passes a syntax check.
A common rule has three parts—type, match value, and policy target—separated by commas. MATCH has no match value, so it only takes a target. The target can be a node, policy group, or built-in policy, but it must exist in the kernel config. Full-width punctuation, invisible spaces, or extra quotes from copying can break references. Group related rules and add short comments to make the list easier to maintain.
rules:
# LAN names and private IP ranges
- DOMAIN-SUFFIX,lan,DIRECT
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
# Route the example domain through Proxy
- DOMAIN-SUFFIX,example.com,Proxy
# Requires a working GeoIP database
- GEOIP,CN,DIRECT
# All unmatched connections
- MATCH,Proxy
Domain Rules and IP Rules
DOMAIN matches an exact domain and is useful for one host. DOMAIN-SUFFIX matches a domain and its subdomains. DOMAIN-KEYWORD matches a keyword anywhere in the domain, so it can catch unrelated services. Don’t use a short keyword just because it resembles the service name. A service may also rely on multiple domains; matching its home page as expected doesn’t mean login, image, and API requests use the same exit.
IP-CIDR matches an IP range; IPv6 ranges usually use IP-CIDR6. If a connection starts with a domain, an IP rule may need a resolved address to match. The trailing no-resolve prevents this rule from actively triggering a lookup just for its IP match. It doesn’t erase an address that already exists or guarantee that no other resolution step will occur. Adding it mechanically to every rule may change behavior that depends on IP matching.
GEOIP and GEOSITE depend on their respective data resources. Before using them, make sure the kernel has loaded the required data. Geographic and site categories reflect how data maintainers classify entries; they don’t permanently guarantee a service’s ownership, server location, or accessibility. If a category doesn’t suit a specific service, add a more precise domain rule before it instead of layering broad, conflicting rules throughout the config.
Process Rules and the Limits of Connection Data
mihomo also supports rules based on process name and path, but access to process information depends on the OS, permissions, capture method, and lookup settings. A desktop app on the local machine may be identifiable, while a proxy request from another device on the LAN usually won’t include that device’s full process details. If a correctly written rule doesn’t match, first check whether the connection log contains the information it needs; don’t immediately conclude that the rule type is unsupported.
The app’s name may also differ from the name of the process that makes a connection. Browser helper processes, update services, and background components can connect independently, so don’t base process rules on a window title alone. For a fixed exit for a work app, first verify routing with its specific service domains, then see whether process rules can cover the remaining connections. Add complex logical rules only after basic routing works, and keep simple conditions you can test independently.
Verify Rules in Connection Logs
To test a rule, first confirm rule mode is active, then open the client’s connections or logs page and make a new request to a target. Check the matched rule and final policy chain. Seeing that a page loads won’t tell you whether it used a rule, connected directly, or reused an existing connection. After changing rules, make a new connection and, if needed, close long-lived connections in the target app. Otherwise, an old connection using its previous route may look like the rule didn’t update.
If the wrong rule matches, first look for a broader rule above it, then check whether the domain came from the expected source, and finally verify the target group’s current selection. Don’t switch the entire config to global mode as a permanent fix; it can only help determine whether the issue is related to rule routing or the exit. If global mode works but rule mode doesn’t, adjust the specific rule using the match log. See Proxy Modes Explained for a comparison.
Rule order matters inside a rule set, too, and the rule set’s position in the main config determines when it is checked against other rules. Put a small number of stable personal exceptions before public rule sets, then keep a clear catch-all at the end. For each new rule, consider what it will override, especially keyword, geographic, and all-port matches. If an exact domain will do, there’s usually no need to include an entire network or every app.
7. Proxy Providers and External Rule Sets
Keep Updateable Resources Separate from the Main Config
proxy-providers declares proxy providers, while rule-providers declares rule sets. Both keep frequently updated content out of the main config, but their payloads differ. A full subscription file is not automatically a rule set, and a domain list is not a proxy list. The main config specifies where resources are, how to load them, and how to reference them. Each resource supplies nodes or rules; the content only affects runtime when the references are complete.
For initial troubleshooting, start with a local file and confirm its format and references before adding remote updates. This separates download issues from parsing issues. Local paths are resolved according to the kernel’s working directory and client path restrictions, not necessarily relative to the file open in your editor. Some clients copy files into their own config directory and won’t sync changes to the original. Check where the runtime config actually points.
# Related sections in the main config
proxy-providers:
local-nodes:
type: file
path: ./providers/nodes.yaml
proxy-groups:
- name: Proxy
type: select
use:
- local-nodes
rule-providers:
local-direct:
type: file
behavior: domain
format: yaml
path: ./rules/direct.yaml
rules:
- RULE-SET,local-direct,DIRECT
- MATCH,Proxy
A proxy provider file should have its own proxies list. If a server returns a full config, whether it can be read as a provider depends on its contents and the kernel’s handling; don’t expect every top-level setting to apply. The safest approach is to use the provider only for its node payload. Changes to node names affect manual selections and filters, so check the group candidates after an update instead of relying only on a success notification.
# ./providers/nodes.yaml
proxies:
- name: "Example SS"
type: ss
server: ss.example.com
port: 443
cipher: aes-128-gcm
password: "your-password"
udp: true
Rule Set Behavior Must Match Its Contents
behavior: domain is for domain payloads, ipcidr for IP ranges, and classical for traditional rule syntax. format specifies the file format, such as YAML or a supported text or binary format. Behavior and format are separate settings. A .yaml extension doesn’t mean the content is a valid domain rule set. If parsing fails, inspect the actual payload instead of only renaming it in the main config.
# ./rules/direct.yaml
payload:
- "example.org"
- "+.example.net"
The domain payload above uses syntax for a domain rule set; entries with a plus sign and a dot match a domain and its subdomains. With classical, the payload usually includes a rule type and match condition, such as a domain suffix. Set the exit policy where the main config references it with RULE-SET. Copying complete rules with policies into a provider can duplicate targets or break the format, so check what the target behavior requires before converting.
Remote Updates Involve More Than a URL
An HTTP provider generally also needs a download URL, a save path, and an update interval, usually in seconds. The URL must return the expected resource body. A login page, access notice, or error document may look like a successful network request but still fail to parse. Subscription URLs may contain personal access credentials. Keep them in your own config, not in screenshots, public repositories, or public issue reports.
Give each resource its own cache path so two providers don’t overwrite the same file. Whether the kernel can use a cache after a remote update fails depends on whether the cache exists, is valid, and how the client manages it. A new device has no old cache, so startup failures may look different from those on a long-running device. One device working for now doesn’t prove the subscription server is healthy.
Provider health checks test whether its nodes are reachable. They relate to, but aren’t the same as, the automatic selection checks in policy groups. Enabling frequent checks at multiple layers can duplicate probes. Decide which layer handles updates, which checks health, and which selects a node, then set reasonable intervals. Also consider whether remote resources are fetched through a proxy: if nodes haven’t loaded yet, a resource that depends on one may create a startup loop.
Troubleshoot Update Failures by Type
If the log shows a request timeout, DNS failure, or certificate error, check the resource download path. If the content was retrieved but a field or payload error appears, inspect the content format. Don’t keep resetting the network in the second case, or blindly change rule set behavior in the first. See Subscription Update Failures and Auto-Refresh Settings for more download scenarios. After fixing the issue, reload and verify a rule match—not just that the download completed.
8. Subscription Overrides, Merging, and Troubleshooting
Source Config, Overrides, and Final Config
A subscription update usually fetches the source file again, so direct edits to a subscription cache may disappear on the next update. Overrides keep personal settings in a separate layer that the client applies when generating the runtime config. This is mainly a GUI client feature; there is no universal override switch shared by all kernels. With Clash Plus, Clash Verge Rev, or FlClash, check each client’s config management and merge behavior. Don’t copy a script from one client into another without checking compatibility.
A common setup uses the remote subscription for nodes and basic rules, the client for runtime settings such as listening ports and the controller, and personal overrides for DNS, policies, or exceptions. The client controls the order and may apply multiple overrides in sequence. The runtime config is the source of truth, not the text in a single editor view. If a UI setting gets overwritten, map out the layers and find which one writes the field last.
Merging Mappings Is Not the Same as Replacing Lists
Scalar fields are usually overwritten by new values; mappings may merge recursively; lists may be replaced, appended, or handled in a client-specific way. YAML itself does not define one merge behavior for every client. Be especially careful with rules, proxies, and proxy-groups: assuming a full replacement will append can remove all subscription rules or nodes. Before saving, confirm whether the current interface expects a complete config or a patch.
# Illustrates fields to override; not a universal override file format
mode: rule
log-level: info
dns:
enable: true
enhanced-mode: fake-ip
profile:
store-selected: true
This snippet shows the intended changes, but whether you can paste it directly depends on the client’s override documentation. If the client replaces the entire dns mapping, it may remove the existing upstreams and filter list. If it merges recursively, fields you omit may remain. After applying it, inspect the final DNS section and make sure the upstreams are intact. Don’t treat a short example as a universal override for every subscription, or try to simulate a merge with duplicate top-level keys.
Specify Where Rules Should Be Inserted
When adding personal rules, decide whether they belong before or after the existing list. Precise exceptions usually go before public rules; the catch-all belongs at the end. If a client only appends rules, adding a personal domain rule after the existing MATCH means it will never run, even if saving succeeds. Use the client’s supported prepend or full-list replacement mechanism, then verify the rule’s position in the runtime config. If you rebuild the list, keep any existing rules you still need.
Nodes and policy groups also have dependencies: a group referenced by a new rule must exist; nodes and providers referenced by a group must load; remove references before deleting a node. Treat a rename as a reference migration, not just a display-name change. After an automatic subscription update, a missing target often means a personal rule still uses an old group name. A stable personal group as an intermediate layer can insulate rules from upstream node renames, but check that its candidates still work.
Verify Changes in Four Stages
Stage 1: Check parsing—indentation, data types, duplicate keys, and unsupported fields that could stop startup. Stage 2: Check references—rule targets, group candidates, provider names, and resource paths. Stage 3: Check traffic capture—whether requests reach this kernel, the system proxy port matches, and TUN permissions and routes work. Stage 4: Check the network—node resolution, remote connection, TLS, authentication, and the target service. Move one stage at a time; don’t skip the basics.
If the config loads but no requests appear in the logs, check the app proxy and traffic capture entry point first. If requests appear but use the wrong policy, check rule order and group selection. If the policy is right but the connection fails, check the node and DNS. Error timestamps matter: an old entry doesn’t necessarily mean the latest change still fails. Note the time after reloading, make one new test request, and inspect its logs. That’s clearer than switching several nodes and reviewing everything afterward.
After sleep, network changes, or an unexpected client exit, check for a leftover system proxy, a virtual network interface that wasn’t restored, or an old kernel still holding a port. Exit one client before switching to another to avoid two traffic-capture setups running at once. Don’t keep changing config fields to fix platform installation or permission problems. For a reinstall, visit the client downloads page; to restore your first connection, return to the Getting Started guide.
Keep a Reproducible Rollback Point
After each change, keep a copy of the previous config, the reason for the change, and the test result; there’s no need to copy every historical cache. If a problem appears, revert the latest change and check whether it resolves the issue before trying changes one by one. When sharing troubleshooting details, include the client, kernel type, capture method, failure stage, and relevant snippets with sensitive information removed. Never publish a full subscription. Identifying the request, matched rule, and failure stage is much more useful than simply saying you can’t get online.