Core versions: distinguish the original, Premium, and mihomo first

mihomo is the successor name of the original Clash.Meta project and is also commonly called the Clash Meta core. It retains Clash’s YAML configuration system while expanding protocol, DNS, rule-provider, and traffic-capture capabilities. Switching to a client powered by mihomo is more than changing the interface: the program that parses your config, establishes connections, and applies rules has changed.

“Original Clash” can refer to two different things: the open-source Dreamacro/clash core and Clash Premium from the original ecosystem. Their feature sets are not identical. In particular, TUN and rule providers cannot simply be described as features “missing from the original and available only in mihomo.” The original project stopped being maintained in 2023, but old guides and subscription templates are still in circulation. When migrating, check the actual core version you’re running.

  • Client: Handles subscription imports, the system tray, system proxy settings, and config generation—for example, a desktop interface for managing configurations.
  • Core: Handles protocol handshakes, DNS queries, rule matching, and outbound connections. The client version number does not tell you the core version.
  • Subscription: May contain a complete config or just a list of nodes. Don’t assume both belong in the same provider field.

Feature comparison: more protocols do not mean configs are fully interchangeable

FeatureOriginal Clash familymihomo
Common proxy protocolsSupports Shadowsocks, VMess, Trojan, and more, depending on the versionRetains common protocols and adds VLESS, Hysteria2, TUIC, and more
VLESS and REALITYThe original core cannot use the corresponding mihomo config directlySupports these combinations, provided the transport, TLS, and server settings all match
rule-providersPremium supports rule providers; this does not apply to every open-source original buildSupports rule providers, with more format and behavior options
Domain sniffingNo sniffer configuration system that fully corresponds to mihomo’sCan try to extract domain names from protocol metadata in supported traffic
TUN traffic captureAvailable in Premium, with differences across platforms and versionsSupports TUN; actual traffic capture still depends on permissions, routing, and the system environment
Basic routing rulesCommon types include DOMAIN, DOMAIN-SUFFIX, and IP-CIDRRetains the basic syntax while adding rule types and ways to combine rules

This table describes feature boundaries, not guarantees that apply to every version. New server-side features, specific transport combinations, and rule-set formats may require a recent mihomo release. If you see “unsupported proxy type,” check which core the client is actually running—don’t rely on “Meta” appearing in the installer name.

Migration checklist for VLESS and Hysteria2

For VLESS, set the node type to type: vless. If the server uses REALITY, you’ll also need the correct reality-opts, public key, short ID, server name, and matching client fingerprint. The flow must match the server config too. Changing the type of an existing VMess node to VLESS does not convert the protocol.

For Hysteria2, set the node type to type: hysteria2. Its config is not interchangeable with Hysteria v1. Set the authentication value, port, SNI, obfuscation, and bandwidth options to match the server; your network must also allow the relevant UDP traffic. Being able to open TCP websites does not mean the Hysteria2 UDP handshake can reach the server.

  • Ask your subscription provider for an output format compatible with mihomo instead of repeatedly hand-editing the full subscription.
  • Don’t use the global setting skip-cert-verify: true to mask a certificate name or trust-chain error.
  • Nodes may contain passwords, UUIDs, or authentication tokens. Redact them before sharing logs, and remove tokens from subscription URLs too.

Migrating rule sets: understand providers, behavior, and file contents

proxy-providers supply nodes; rule-providers supply match conditions. Reference the former with use in a proxy group and the latter with a RULE-SET rule. If you put a node subscription URL in a rule provider, it may download successfully but still won’t give you usable routing rules.

Here’s an example using local files. Keep the config file and the rules directory in the same config working directory. If the client uses a separate working directory for its core, use that actual directory instead. This example shows how to load rule files only; it contains no proxy nodes and cannot make outbound proxy connections.

Rule provider in the main config

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

rules:
  - RULE-SET,local-domains,DIRECT
  - MATCH,DIRECT

Contents of rules/local-domains.yaml

payload:
  - '+.example.com'
  - 'example.org'

Entries with behavior: domain are domain patterns; you can’t put complete rules such as DOMAIN-SUFFIX,example.com directly in them. With behavior: classical, you can use supported classic rule entries in payload, such as DOMAIN-SUFFIX,example.com. The outer RULE-SET rule specifies the policy to apply.

  • domain: For domain-matching data; best for a list of domains only.
  • ipcidr: For IP ranges such as 192.168.0.0/16; don’t mix in domains.
  • classical: For supported classic rule types; the content format differs from the other two.

YAML, plain text, and MRS are different storage formats. MRS is mihomo’s binary rule-set format, supporting the domain and ipcidr behaviors; it is not a general-purpose interchange format for the original core. During migration, check behavior, format, and the actual content returned by the remote source. Changing a file extension to .yaml does not change its internal format.

Rules are still matched in order. Moving MATCH up means later rules won’t run; putting a broad DIRECT rule before proxy rules can also change existing routing. Successful loading only proves the content can be parsed—it doesn’t prove the match order is what you intended.

Sniffer: adds domain clues, but doesn’t decrypt traffic

Some connections reach the core with only a destination IP. mihomo’s sniffer can try to extract domain clues from supported HTTP, TLS, and QUIC traffic to help with rule matching; related options may also change the connection destination. It is not an HTTPS decryption proxy and won’t expose TLS-encrypted content or guarantee a domain can be extracted from every connection.

sniffer:
  enable: true
  override-destination: false
  sniff:
    HTTP:
      ports: [80, 8080]
    TLS:
      ports: [443]
    QUIC:
      ports: [443]

This config limits HTTP inspection to ports 80 and 8080, and TLS and QUIC inspection to port 443. It explicitly disables destination overrides. This makes it easier to observe sniffing and rule-matching results first, without also introducing destination-rewrite variables. Expand the port range only if your use case calls for it; don’t inspect every port just to be “more thorough.”

If a specific site stops working with sniffing enabled, first disable sniffer.enable to compare results with only one variable changed. Then check whether the relevant domain belongs in skip-domain. Mechanisms such as ECH in TLS can reduce the domain information visible to the sniffer. Sniffing is not a substitute for DNS routing: if client DNS bypasses the system, address that in the DNS config or traffic-capture path.

DNS and TUN: keep the basic fields, but recheck runtime requirements

Concepts from older configs such as dns.enable, enhanced-mode: fake-ip, and fake-ip-filter are still supported in mihomo. Fake-IP maps domains to reserved addresses, then restores the corresponding domain information for later connections. It does not mean “all DNS goes through the proxy,” and it won’t automatically capture encrypted DNS enabled separately in a browser.

Don’t copy new DNS fields in isolation

nameserver-policy directs queries for specific domains to chosen resolvers; proxy-server-nameserver resolves proxy node hostnames; respect-rules makes DNS upstream connections follow routing rules. After enabling these, check the separate resolution path for proxy node hostnames. Otherwise you can create a circular dependency: you need the proxy to resolve the node, but need to resolve the node to establish the proxy.

Early in the migration, keep the DNS upstreams you know work. First verify that domains resolve and the intended rules match, then introduce these fields one at a time. Don’t merge two clients’ DNS snippets wholesale: duplicate keys may be overwritten, and a client may inject its own listen address or policy before startup.

TUN failures usually involve more than YAML syntax

  • Permissions: Creating a virtual network interface or changing routes may require administrator privileges, a system service, or specific network permissions.
  • Routing: Automatic routing must coexist with VPNs, virtual machine networks, and other traffic-capture software to avoid competing routes.
  • DNS hijacking: The port 53 rules in dns-hijack do not capture every DoH or DoT request.
  • System proxy: Used by apps that follow the system proxy settings. TUN captures traffic at the virtual network interface; it is a separate setting.

When troubleshooting, turn off TUN first and test a node through an explicitly specified local proxy port. Then enable TUN separately. This helps distinguish an unavailable node from a system traffic-capture failure, instead of repeatedly changing node passwords to fix a routing problem.

Migrate an old config: verify the minimal setup, rules, and traffic capture in sequence

Don’t start migration by copying every advanced field at once. Record the original client’s listen ports, operating mode, proxy-group selections, and core version, then make a copy you can roll back to. The steps below work for checking a core manually and for diagnosing issues with client-generated configs.

  1. Identify the core in use. In a standalone environment, run mihomo -v. In a client, check the core details or startup logs to distinguish the client version from the core version.
  2. Check config syntax. In the config directory, run mihomo -t -f ./config.yaml. If file providers use relative paths, also verify the core’s working directory. Passing a syntax check doesn’t mean remote nodes can connect.
  3. Set a fixed local entry point. For example, use mixed-port: 7890 and keep allow-lan: false. Port 7890 is used in this example; it is not the default for every client.
  4. Test one node. Select a known-working node and request a destination through the local proxy before enabling automatic proxy groups. This prevents health checks and node switching from masking the issue.
  5. Restore rules and DNS. Enable rule providers one at a time, then check connection logs for the matched rule, proxy group, and final node—not just whether a webpage opens.
  6. Enable TUN and sniffing last. Change only one feature at a time, and keep the logs and active config from before and after any failure.
mihomo -v
mihomo -t -f ./config.yaml
curl --proxy http://127.0.0.1:7890 --head https://example.com

The curl commands above assume curl is installed locally and explicitly send requests through port 7890. In Windows PowerShell, if curl maps to a different command, use curl.exe. An HTTP response means this request path works; it does not prove that all domains, UDP traffic, or TUN traffic is working.

Legacy syntax to check first

  • Legacy keys: Restructure Proxy, Proxy Group, and Rule from older templates as proxies, proxy-groups, and rules to match the current config structure. Don’t rely on legacy compatibility handling.
  • Proxy-group references: Every group referenced in rules must exist, with matching capitalization and spacing. If you remove an old group, update the final MATCH rule too.
  • Protocol-specific fields: Don’t paste JSON fields from another core directly into mihomo YAML. The field hierarchy and names may differ between config systems, even for the same protocol.
  • Controller API: external-controller is for a different purpose than the proxy listen port. Bind it to a loopback address for local management only. For remote access, set authentication and restrict network access.

Troubleshooting: check config loading, connectivity, and routing separately

SymptomCheck firstHow to verify
Unsupported proxy typeThe core actually running and the subscription output formatCheck the core version and the node’s type field
Rule provider failed to loadFile path, response content, behavior, and formatOpen the actual file and confirm it isn’t an error page or a node subscription
Config loads, but the node times outAddress, port, authentication, TLS, and UDP reachabilityTest one fixed node without enabling automatic switching
Manual proxy works, but TUN does notPermissions, routing, DNS capture, and other VPNsDisable conflicting traffic capture and test domain and IP connections separately
Changes disappear after restartSubscription updates and client config mergingMove custom settings into the client’s persistent override mechanism

mihomo’s main advantage is broader protocol support and more configurable features—not automatic compatibility for old configs in every environment. A reliable migration means verifying node connectivity, DNS resolution, rule matching, and system traffic capture separately, then restoring routine subscription updates. For help choosing a client, see the client comparison. For first-time setup and system permissions, see the cross-platform guide.