YAML Structure and Configuration Boundaries
Bottom line: a configuration file describes objects that reference one another; it isn't a list of settings you can arrange arbitrarily. Top-level fields control listening, resolution, and forwarding. Proxies provide connection exits, proxy groups organize exit selection, and rules direct requests to a policy. When reading an unfamiliar config, first check that these four layers are present, then verify that names match. A valid individual line doesn't prove the whole file will work as intended. For example, a rule that references a nonexistent proxy group won't produce a usable configuration, even if the indentation is perfect.
Top-Level Maps, Lists, and Nesting
YAML uses indentation to show hierarchy. Use two spaces consistently and avoid tabs. enable under dns: is a DNS subfield; aligning it with the top-level mode won't preserve its meaning. Lines starting with a hyphen are list items. The name, type, and server fields for a single proxy must be at the same mapping level. A space is usually required after a colon; don't replace the ASCII colon with a full-width punctuation mark. Indentation guides in a code editor are more reliable than counting spaces by eye.
# Standalone direct-connection example; no remote proxy nodes included
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
proxies: []
proxy-groups:
- name: PROXY
type: select
proxies:
- DIRECT
rules:
- GEOIP,CN,DIRECT
- MATCH,PROXY
This example illustrates the structure; it doesn't provide proxy access by itself: the PROXY group contains only DIRECT, so connections still go directly. For actual use, add valid proxies or a proxy provider to the group. An empty list, [], means the field exists but has no entries yet; that's different from removing the field entirely. When extending a config, start with a loadable skeleton and add one type of object at a time, so you can pinpoint which change caused an error.
Strings, Booleans, and Name References
Ports and intervals are usually numbers; switches use true or false, not words like “enabled.” Quote proxy names, passwords, and strings containing a colon or hash to prevent them from being interpreted as mappings or comments. To include a single quote in a single-quoted string, double it; backslashes in double-quoted strings may be treated as escape characters. Take extra care when copying Windows paths; single quotes can prevent unintended escaping. Comments help people read the file but don't change how fields take effect.
Don't define dns or rules more than once in the same mapping. Parsers handle duplicate keys differently: some reject the file, while others keep the later value. Duplicate keys are not a merge mechanism. Keep policy names unique, and reference them exactly, including capitalization, spaces, and symbols. If you rename a proxy, update its name in proxy groups; if you rename a group, update rule targets and any other groups that reference it.
Files, Profiles, and Runtime Configuration
A Profile in a client is a configuration source and its management record. It may point to a local file or come from a remote subscription. The saved subscription content may not be what the core ultimately reads: the client may apply port settings, merge rules, or run scripts afterward. When troubleshooting, distinguish the “raw subscription,” “local editable copy,” and “runtime configuration.” Changes to a downloaded cache file may be lost on the next update; editing a Profile that isn't selected won't affect the current connection.
Before saving a config, keep a copy you can roll back to and note which Profile is selected. Save as UTF-8 in a plain text editor; avoid rich-text formats, full-width spaces, and automatic quote replacement. A file extension can help a client identify the format, but changing it to .yaml won't turn a web page into a configuration file. If an import shows HTML, a login prompt, or subscription quota details, fix the source first instead of adjusting indentation. For switching and managing multiple configurations, see Profiles and Multi-Config Management.
Ports, Bind Addresses, and Traffic Entry Points
Bottom line: a listening port creates an entry point; it doesn't automatically route every app through the proxy. An app must connect to that entry point, or traffic must be sent to the core through a mechanism such as the system proxy or transparent forwarding. The common mixed-port accepts both HTTP and SOCKS proxy connections on one port, making it convenient to configure across desktop apps. port and socks-port create separate HTTP and SOCKS entry points. Enable them separately only when you need distinct entry points; otherwise, you add listeners that are harder to track.
Choosing a Port and Checking for Conflicts
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
This example allows connections from this device only, making it a good starting point for a single machine. A port number isn't a performance setting or the remote server's port. After changing the local listening port, update it in your browser, terminal, and any other apps with a manual proxy setting. Don't assign one port to multiple listening fields or let two proxy clients compete for the same address and port. If the core reports that an address is already in use, quit the old process or change the listener before reloading; switching proxies repeatedly won't fix a local bind failure.
| Field | Purpose | What to Check |
|---|---|---|
mixed-port | Combined HTTP and SOCKS entry point | Correct protocol and address in the app |
port | Dedicated HTTP proxy entry point | Not the remote proxy's port |
socks-port | Dedicated SOCKS proxy entry point | Whether the app supports SOCKS |
allow-lan | Whether LAN devices can connect | Pair the bind address with firewall settings |
bind-address | Address the proxy listener binds to | Loopback address or LAN interface |
On Windows, use Get-NetTCPConnection -LocalPort 7890 to check the corresponding TCP listener. On Linux, use ss -lntp; on macOS, use lsof -nP -iTCP:7890 -sTCP:LISTEN. Some process details require elevated permissions. Check the address, port, and process together; matching port numbers alone don't prove that the proxy is running. A service bound to a loopback address can't be accessed directly from another device.
Local Proxy Access and LAN Sharing
To let other devices on your LAN connect, enable allow-lan only after understanding the access boundary, and bind to an address that covers the relevant interface. Other devices should use the LAN address of the machine running the client, not their own 127.0.0.1. The local firewall, wireless client isolation, and routing between subnets can all affect connectivity. First confirm that the local machine can connect through the listener, then test from a LAN device. This helps distinguish a core issue from network isolation.
Proxy authentication and proxy-node authentication are different things: the former controls who can use the local entry point; the latter is used to connect to a remote service. After enabling listener authentication, connecting apps must support it and use the corresponding username and password. Some system proxy settings can't represent these credentials fully, so you may need to configure the proxy in the app itself. If sharing fails, don't leave all firewall rules disabled to troubleshoot; check only the required interface, source address, and port.
System Proxy, Terminal, and TUN Boundaries
A system proxy usually provides an address to apps that follow system settings, but not every program does. Command-line tools often rely on environment variables or their own flags. Use the command below to specify an HTTP proxy explicitly, so stale environment variables aren't mistaken for a core issue. A successful test only proves that this request used the specified entry point; it doesn't show that other apps are connected or that routing works correctly for every domain.
curl --proxy http://127.0.0.1:7890 https://example.com/
TUN is a virtual network interface. It involves system permissions, routing, DNS interception, and other network software; it isn't a necessary follow-up to opening a regular listening port. Enable it according to the client documentation only if an app doesn't support proxies or you need broader traffic interception. If the system proxy works but the terminal doesn't, see Troubleshooting Browsers and Command-Line Apps Separately. When choosing a client, start with Clash Plus on the download page, then compare other clients by platform and required features.
Proxy Modes, Logs, and the Control Interface
Bottom line: mode determines how a forwarding policy is selected; it doesn't create proxies or capture app traffic. Rule mode uses the rule list, global mode uses the currently selected global policy, and direct mode connects straight to the destination. Before changing modes, confirm that traffic is reaching the core and that a usable policy exists. Switching to global mode won't fix a failed listener, an empty subscription, or an unreachable remote server; it only helps determine whether the issue is related to rule-based selection.
rule, global, and direct modes
mode: rule
log-level: info
ipv6: false
rule is suited to ongoing routing by domain, address, and app needs. global bypasses normal rule selection and uses the current global policy, so check what's selected in the client's global group. If that selection is direct, global mode won't magically use a proxy. direct is useful for testing connections without a proxy exit. None of the three modes replaces system entry-point settings; apps that never reach the core won't change routes when you switch modes.
Change only one variable at a time when testing. For example, if a site fails, keep the proxy and DNS settings unchanged, switch from rule mode to global mode, and start a new connection. If global works but rule mode doesn't, check which rule matched and its target group. If both fail, check the proxy and DNS next. Changing the proxy, mode, and DNS all at once makes it hard to identify what fixed the issue. Existing persistent connections may keep using the old exit, so close them before testing again.
| Mode | Policy Source | Typical Use |
|---|---|---|
rule | First matching entry in rules | Maintain routing by specific needs |
global | Current selection in the global policy | Isolate the effect of rule-based routing |
direct | Connect directly | Compare against the local network |
Using log-level for Troubleshooting
Use info to keep key runtime details available for everyday use; switch to debug briefly when you need to trace specific requests. warning and error produce progressively less output, while silent leaves little to troubleshoot with. The log level won't improve proxy speed, and verbose logging can add overhead. After capturing a reproducible issue, restore your usual level to avoid accumulating unnecessary data.
Start by sorting log errors by stage. Errors during configuration parsing point to file contents; listener failures point to local addresses or permissions; resolution errors after a request reaches the core point to the DNS path; dial or handshake failures call for checking the exit and protocol settings. The word “timeout” can refer to a DNS query, a TCP connection, or a TLS handshake, and each requires a different investigation. Don't replace every field based on a single error message.
A useful reproduction record includes the active Profile, mode, matched rule, selected policy, and errors around the same time. Before sharing logs, remove subscription URLs, credentials, personal domain names, and LAN topology details. See Runtime Logs and Common Errors for a suggested reading order. If the target request doesn't appear in the logs, go back to checking the entry point instead of investigating a rule that never ran.
The Control Interface Is Not a Proxy Entry Point
external-controller lets a client or dashboard manage the core, including querying status, switching policies, and changing some runtime settings. It can't be used as an HTTP proxy address in a browser. Desktop clients usually manage this interface and its credentials themselves; avoid overriding them in a subscription without a good reason. When running the core manually, bind to a loopback address by default. For remote management, add authentication and restrict network access; don't treat the management port as an ordinary LAN-sharing port.
The top-level ipv6 field affects how the core uses IPv6, while a field with the same name under DNS belongs to DNS configuration. Changing just one doesn't tell you what the whole network stack will do. Whether to enable IPv6 depends on the local network, proxy service, and app requirements; disabling it isn't a universal optimization. If failures occur only with a particular address type, check the resolved addresses and actual connection path separately, then adjust the field at the relevant level.
DNS, Fake-IP, and Resolution Paths
Bottom line: DNS configuration can involve app queries, core resolution, and proxy-node hostname resolution; checking a single server address isn't enough. Apps may use system DNS or send encrypted queries themselves. The core may also resolve names to connect to a destination or proxy node. So changing nameserver doesn't mean every query will use that list. First establish where a request originates, who receives it, and who uses the result; then decide whether to change the listener, interception, or upstream selection.
How DNS Enablement and Listening Work
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
nameserver:
- https://dns.alidns.com/dns-query
fake-ip-filter:
- "*.lan"
- "*.local"
This snippet creates a DNS listener on the local machine, but doesn't change the system DNS setting automatically. Traditional system DNS settings generally can't specify a nonstandard port, so simply setting the system address to a loopback address won't send queries to 1053. You need DNS interception in the client, a TUN feature that supports it, or another explicit forwarding mechanism. If the device already runs a DNS service, check for address and port conflicts first so a failed listener isn't mistaken for an unreachable upstream.
default-nameserver can resolve the hostnames of DNS services, helping with the “which comes first, the hostname or its resolution?” problem; it usually uses directly reachable IP addresses. nameserver is the main upstream list, and whether it can be reached depends on network connectivity and outbound settings. Encrypted DNS changes how queries are transported, but doesn't prove they go through a proxy or that the remote service is reachable on the current network. More upstreams don't automatically mean more accurate results; start with a combination you can verify easily.
fake-ip vs. redir-host
fake-ip assigns a synthetic address to a query and keeps a mapping between the domain and that address. When a connection uses the synthetic address, the domain is recovered for processing. This helps preserve domain information, but requires DNS queries and subsequent traffic to go through the same processing chain. If an app receives a synthetic address and bypasses the core to connect directly, the connection will usually fail. redir-host returns the actual resolved address and follows a different compatibility path; these aren't simply two speed settings.
fake-ip-filter excludes specified domains from the synthetic-address flow. It's useful for local service discovery or apps that require real addresses. The LAN suffixes in the example are a starting point, not a complete list for every environment. Filtering a domain doesn't add a direct-connection rule or select the right LAN DNS automatically. For issues with printers, internal domains, or local services, check the source of the DNS result, the returned address, and the connection route instead of expanding the filter and stopping there.
Choose Upstreams by Domain and Prevent DNS Loops
nameserver-policy can route specific domains to an upstream, such as sending internal domains to a LAN resolver. Use matching syntax supported by the core; this isn't a second rules list where every rule expression can be copied. proxy-server-nameserver handles proxy-node hostname resolution, keeping the basic DNS needed to establish an exit on its own path. If the proxy server's hostname can't be resolved, the connection can't be established even if the destination website resolves correctly.
Before enabling options such as respect-rules, which route DNS requests according to routing rules, define a separate resolution path for proxy-node hostnames. If a DNS request must go through a proxy, but that proxy needs the same DNS request to connect, you can create a loop. Don't introduce rule-based DNS routing, multiple upstreams, complex filters, and layered fallback all at once. First confirm that a basic upstream is reachable, then add constraints one by one and check the logs for the order of resolution and dialing.
fallback and its related filter settings aren't always-on backup switches; result selection depends on the filter criteria. Copying address ranges and regional settings from a different network can change resolution in unexpected ways. During troubleshooting, record the queried domain, response address, upstream, and matched policy. If only some apps fail, check whether they use their own DNS and bypass the system. For quick answers to specific symptoms, see the FAQ instead of enabling every DNS option at once.
Proxy Fields and Proxy Providers
Bottom line: every proxy field must match the protocol parameters provided by the server; similar names don't make fields interchangeable. proxies is a list of proxy objects. Common fields include a name, type, server address, and port; authentication, encryption, transport, and TLS fields vary by protocol. Successfully importing a subscription only proves that the client accepted the config structure. It doesn't prove the server is reachable or that authentication and handshake settings are correct.
Common Fields and Protocol-Specific Fields
# Structure example: example.com and credentials are illustrative only
proxies:
- name: Example Exit
type: socks5
server: proxy.example.com
port: 1080
username: "your-username"
password: "your-password"
udp: true
proxy-groups:
- name: PROXY
type: select
proxies:
- Example Exit
- DIRECT
This example shows how a SOCKS5 proxy is referenced by a group; it doesn't provide a working proxy service. name is a local identifier. Changing it won't alter the server, but it will affect references elsewhere. server is the remote address, and port is the server's listening port; neither can be replaced with the local mixed-port. Use the username and password supplied by the service. Don't add authentication fields just to fill them in if the server doesn't use that authentication method.
type determines how the remaining fields are interpreted. Shadowsocks encryption and passwords, VMess or VLESS user IDs, Trojan authentication and TLS, and transport parameters for other protocols each have their own requirements. Don't mix fields from different protocols in one proxy to try to make it compatible. If an unknown-field error appears, first check whether the current core supports the protocol and field, then check the subscription format. Simply deleting every field mentioned in an error may leave the config loadable but unable to connect if a required transport parameter is removed.
TLS, Transport, and UDP
A proxy that uses TLS may include a server name, application-layer protocol negotiation, and certificate options. The server name is generally used for the handshake and certificate validation; it doesn't have to match the connection address. The address, TLS server name, and host field in WebSocket headers may each serve a different purpose. Use the combination provided by the server. Don't enter an arbitrary reachable website domain in these fields: a plausible-looking domain doesn't mean the server will accept the handshake.
If certificate verification fails, check the system time, server name, certificate validity, and server configuration. Skipping verification weakens confirmation of the remote identity and shouldn't be kept as a general fix. WebSocket, gRPC, and other transports also require matching paths, service names, or headers; a mismatch at any layer may cause the connection to close. Keep the original server parameters for comparison, rather than comparing only the proxy names shown in the client interface.
udp: true allows UDP on the corresponding proxy; it can't add UDP support to a server that doesn't provide it. Also confirm that the app entry point, proxy group, proxy protocol, and remote service all support the traffic you need. If websites work but games or voice calls fail, first distinguish TCP from UDP; a successful HTTP probe doesn't verify every app. Conversely, lack of UDP support doesn't mean ordinary HTTPS requests must fail.
proxy-providers vs. a Full Subscription
# Provider snippet: the local file must already exist and contain a proxies list
proxy-providers:
local-nodes:
type: file
path: ./providers/local-nodes.yaml
proxy-groups:
- name: PROXY
type: select
use:
- local-nodes
proxies:
- DIRECT
proxy-providers keeps proxy sources separate. A group references a provider with use, rather than adding the provider name to a regular proxy list. A file-based source requires an existing file in the provider format; a network source also needs a valid URL, save location, and update settings. A complete Profile usually includes DNS, rules, and groups too, so don't assume a full subscription can be used as a provider file containing only proxies. Check which output formats the source supports.
A provider downloading successfully and its proxies being connectable are separate things. The first depends on the download path and content format; the second depends on the protocol and exit. If the service returns a login page, error text, or an empty list, check subscription authorization, expiry, and response content first. Subscription URLs may contain access credentials; don't paste them into public logs or online conversion tools. If every proxy fails, use a step-by-step troubleshooting sequence from subscription to exit to identify the failing layer.
Whether a client can edit a type of proxy and whether the core supports its fields are two separate questions. When choosing clients such as Clash Plus, Clash Verge Rev, or FlClash, check which core they currently use and what they can import. A field not shown in the interface may still work, and a field the interface accepts isn't necessarily supported by the server. When maintaining proxies, keep the original parameters from a trusted source and customize routing and rules around them to avoid manually rewriting authentication details.
Proxy Groups, Automatic Selection, and References
Bottom line: a proxy group selects an exit. After a rule points to a group, the group's current selection still determines the final proxy. proxy-groups organizes proxies, other groups, or providers. First decide what users need to choose, such as a fixed exit, automatic selection, or failover, then pick a group type. Adding every group type won't automatically improve reliability; it can make the actual exit harder to explain.
select and Nested Policies
# A direct group illustrates a loadable structure; add actual proxies as needed
proxy-groups:
- name: Manual Selection
type: select
proxies:
- DIRECT
- name: PROXY
type: select
proxies:
- Manual Selection
- DIRECT
rules:
- MATCH,PROXY
select lets a user or control interface choose the current option and suits apps that need a fixed exit. In the example, a rule first points to PROXY, which may then point to “Manual Selection,” and finally to DIRECT. Trace this reference chain to understand what happens to a real connection. A group name is just a label, not a guarantee of behavior. A group called “Auto” with type select won't test proxies and pick one automatically.
Avoid circular references between nested groups, such as Group A referencing Group B while Group B references Group A. Name groups to distinguish purpose from source: purpose groups might be for work, media, or a default exit, while source groups might correspond to a provider. This way, subscription updates that change proxy entries won't require updates to every rule. Keep nesting shallow enough that you can explain the final exit in a few steps; otherwise, the selected name in the interface may conceal a multi-level route.
url-test, fallback, and load-balance
url-test selects a candidate based on probe results, making it suitable when automatic switching is acceptable. fallback focuses more on candidate order and availability, for cases where you want to prefer one exit and switch only when it fails. load-balance distributes connections among candidates according to a policy; it doesn't combine their bandwidth for one download. Use caution with groups that may change exits for logins, payments, or sessions that need a stable source address.
# Snippet: the local-nodes provider must be defined under proxy-providers
proxy-groups:
- name: Automatic Selection
type: url-test
use:
- local-nodes
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
In the example, interval sets the probe interval, while tolerance reduces frequent switching caused by small differences. Neither is a proxy speed rating. Choose a probe URL that's reliably reachable from the current network and exit, with a response suitable for connection testing. A failed probe may mean the test destination is restricted, not that the proxy fails for every destination. Compare with real app requests instead of choosing a policy for every use case based on a single column of test results.
| Type | How It Selects | What to Watch For |
|---|---|---|
select | Manual selection | Check whether the current selection persists |
url-test | Selects based on probe results | Probe results aren't actual throughput |
fallback | Checks candidates in order | Set the priority order deliberately |
load-balance | Distributes connections by policy | Doesn't guarantee a fixed exit for the whole session |
Candidate Lists, Filters, and Probe Scope
Use proxies for explicit proxy or group names, and use to reference proxy providers. These sources can be combined, but watch for duplicate entries or empty candidate lists. When filtering names with filter or similar settings, check that the regular expression matches actual proxy names, not the provider name. If the subscription provider renames proxies, a filter that used to work may suddenly return nothing. If an automatic group has no proxies, check provider contents first, then filter results, and finally probe settings.
A health check tells you whether a specific probe target can complete a request under given conditions; it isn't a general score for a proxy across all protocols and destinations. Frequent concurrent probes create extra connections, which can be a concern on mobile networks, low-power devices, or services with usage limits. If both the provider and group layers run checks, look for duplicate probes. Use only the frequency needed to establish availability; don't shorten the interval just to keep the interface constantly refreshed.
Keep the groups that rules point to stable, and change proxies within the groups. If a website sometimes uses different exits, first check whether an automatic group switched, whether the app opened multiple connections, or whether the domain followed different rule paths. Then investigate the server if needed. For tasks that need a fixed exit, create a separate manual group instead of mixing it with everyday automatic selection. Compare group-selection interfaces across clients in the client selection guide, based on your platform requirements.
Rule Syntax, Match Order, and Rule Providers
Bottom line: rules are processed from top to bottom, and the first match determines routing for that request. Priority isn't inferred from the length of the rule text. When maintaining rules, put specific exceptions before general rules and leave the catch-all rule last. Before adding a rule, identify what it should match: a domain, destination address, source address, or process. Which information a rule can use depends on the entry point and system environment; don't assume every connection includes a full domain and process name.
Domain Rules and Policy Targets
# Snippet: the PROXY policy group must already be defined
rules:
- DOMAIN,login.example.com,PROXY
- DOMAIN-SUFFIX,example.com,PROXY
- DOMAIN-KEYWORD,internal,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,PROXY
DOMAIN matches an exact domain, DOMAIN-SUFFIX matches a domain suffix and its subdomains, and DOMAIN-KEYWORD checks whether the domain contains a keyword. Keyword rules usually cover a wider range and can catch unrelated domains, so prefer an exact domain or suffix for precise matching. Don't include https://, a path, or a port; those are other parts of a URL, not values for a domain rule.
The last part of a rule is its target policy, which can be a built-in action or a defined proxy or group. For maintainability, rules usually point to a purpose-based group rather than a proxy whose name may change in a subscription update. DIRECT means connect directly; REJECT denies the request. Policy names must exactly match their definitions. A misspelled group name isn't a “no match”; it's a broken configuration reference to fix during load validation.
Address Matching and no-resolve
IP-CIDR matches IPv4 networks; use the corresponding IP-CIDR6 for IPv6 networks. If a request arrives as a domain and a rule needs a real address to match, the core may resolve it. The trailing no-resolve prevents the core from resolving the domain specifically for that IP rule. It doesn't stop matching connections that already have a destination address, nor does it disable DNS globally. Adding it mechanically to every address rule can change existing routing behavior.
GEOIP classifies addresses using an IP database, so results depend on its contents and updates. Domain classification with GEOSITE requires the corresponding resources and core support. The regional direct-connection example illustrates syntax; it isn't a default policy for every network. Database classifications don't establish where a service is actually located or guarantee that its address is reachable. Configure exceptions for enterprise networks, cross-region services, and self-hosted addresses as needed instead of relying on one classification for everything.
rule-providers and RULE-SET
# The file must already exist and its content format must match behavior
rule-providers:
local-domains:
type: file
behavior: domain
format: yaml
path: ./rules/local-domains.yaml
rules:
- RULE-SET,local-domains,DIRECT
- MATCH,PROXY
Rule providers keep updatable match data in separate files, which the main config references with RULE-SET. behavior indicates whether the content contains domains, IP ranges, or traditional rule expressions; don't infer it from the file extension alone. A YAML domain provider typically lists domain match entries under payload. A rule set using traditional behavior needs the corresponding rule expressions; don't repeat the target policy from the main config on every line.
Even after a rule-set file downloads successfully, check that its format matches its behavior. Treating a plain-text domain list as YAML, or parsing a complete rule list as domain behavior, can produce errors or unexpected results. Network-based rule sources also depend on reachable update requests and writable cache files. If an update fails, keep the usable cache and troubleshoot the fetch issue instead of immediately resetting the whole main config and losing other parts that were working.
Trace Rules from Connection Records
Test a new rule with a new connection, and record the requested domain, matched rule, and final policy. A browser page often makes separate requests to the main domain, login services, static assets, and APIs. If only part of the page loads, inspect those connections individually; a single rule for the address-bar domain may not be enough. If a connection shows only an IP, check whether the app resolves names itself, whether DNS reaches the core, and whether the current entry point preserves domain information.
Process rules also depend on platform, permissions, and entry point. The same config may not get the same process metadata on another device, so don't rely on process rules as the only cross-platform matching method. When troubleshooting, find the earliest rule that could match, confirm the group selection, then verify the exit. If rule mode fails but global mode works, trace that route instead of adding broad keyword rules in bulk. After a temporary exception works, narrow its scope and document its purpose.
Subscription Overrides, Configuration Merging, and Load Validation
Bottom line: keep maintainable customizations separate from subscription content that remote updates can replace, and validate the final runtime configuration. Clients may provide overrides, merges, extensions, or scripts, but these are client-specific configuration-generation mechanisms, not one YAML standard shared by every client. When moving to another client, check the application order and merge semantics again. Copying a file called “override” doesn't guarantee the result will be the same.
How Scalars, Maps, and Lists Merge
Scalar fields such as mode and mixed-port are generally overwritten by the later value. Maps such as dns may be merged key by key or replaced entirely. Lists such as rules and proxies may be replaced, prepended, or appended. Check the client documentation and generated output to determine what actually happens. Knowing only that a feature is called “merge” isn't enough to tell whether existing proxies or rules will be preserved.
# Conceptual example: an override entry point for clients that support prepending rules only
# Do not append this as a second top-level rules list
rules:
- DOMAIN,work.example.com,DIRECT
If the client replaces the existing rules with this content, all subscription rules may be removed. If it appends the content after the existing MATCH, the new rule may never get a chance to match. Use the client's supported prepend-rules feature or construct the order explicitly in a script, then inspect the final list. DNS merging needs the same care: when changing an upstream list, confirm whether other subfields are preserved. Otherwise, changing one address might also clear listener or mode settings.
Check Write Order and Keep Names Stable
Keep a simple record of each source: which proxies and rules come from the subscription, which ports are set globally by the client, which DNS settings and exceptions come from overrides, and whether a script modifies proxy groups afterward. If multiple entry points edit the same field, consolidate changes where possible. A mode that keeps reverting, a port that changes after saving, or rules that disappear after every update often means a later generation step overwrote an earlier one, not that the editor failed to save.
Keep the names of groups referenced by custom rules stable, and confirm they're still generated after subscription updates. If a custom group references a specific proxy that the provider regularly renames, that proxy may no longer be available after an update. A safer approach is to use a stable purpose-based group to connect to the provider or the client's proxy collection. Before a script modifies a field, verify its type; don't assume every subscription has the same list structure. If an object is missing, fail with a clear message rather than generating a partial config.
Syntax Checks, Load Checks, and Live Connections
# For environments with the mihomo command-line program installed
mihomo -t -f ./config.yaml
Command-line tests can uncover parsing and initialization issues. Keep the working directory, resource paths, and permissions as close as possible to the actual launch environment. Missing provider files, GeoIP databases, or other resources can cause failure even when the YAML syntax is correct. Desktop clients can use their own configuration checker first; a different core's results may not reflect the current client environment. Passing a check means the config can potentially load, not that a remote proxy is reachable.
Validate in three stages: first confirm the config is selected and loads successfully; next confirm the listener is active and app requests reach it; finally check DNS, rules, group selection, and the remote handshake. Keep one reproducible request as a reference at each stage. If only existing connections still follow the old route after a change, establish a new connection. If no new requests appear in the logs, return to the entry-point layer. If the logs show the right policy but the handshake fails, check the proxy parameters and server status.
Recovery Steps for Common Failures
If the config errors immediately, revert the last change and check indentation, duplicate keys, missing references, and field types. If it loads but connections fail, compare a direct request with one made through the specified proxy, then inspect the policy that actually matched. Don't conflate the two problems. If the failure began only after an automatic update, compare proxy names, provider format, and rule targets before and after. If it happens only in one client, check its override order, core capabilities, and system permissions.
After resolving an issue, document the conditions that made it work in a comment or maintenance note—for example, which traffic needs an exception, why a particular DNS path is used, or which rule must come first. Don't record real credentials or turn a temporary workaround into the permanent default. For first-time setup, follow the Getting Started guide through a complete connection. For interface issues, check the FAQ. To switch clients, choose a platform-specific option on the client downloads page, and keep the original config until the new setup is verified.