manual · zero to pro

The Complete Clash Handbook

This is the most in-depth page on the site: nine chapters build on each other, starting from core concepts and working through rule-based routing, TUN mode, and day-to-day maintenance. If you just want to get online as fast as possible, start with the setup guide for the shortest path; whenever you hit an unfamiliar term, check the glossary. This page is best read start to finish, or jumped around using the chapter index below. Grab installers from the Downloads page.

9 chapters, step by step mihomo kernel Reusable YAML examples
CH 1

Core concepts: kernel, client, and config file

Clash is a rule-based proxy kernel driven entirely by a config file. It has no GUI of its own — on launch it reads a YAML config, opens a handful of local ports, matches every incoming connection against a rule list, and decides whether that connection goes direct, through a specific proxy node, or gets rejected outright. Every toggle, node list, and mode switch you see in a client is just a wrapper around this config and matching flow — once you get this, every chapter after it clicks into place.

The original Clash kernel is no longer maintained. The de facto standard today is the community-maintained Mihomo kernel (often called Clash Meta). Mihomo is fully compatible with the original config format while adding more proxy protocols, rule types, and DNS features. Every client listed on the Downloads page either bundles Mihomo directly or uses a compatible config format, so this handbook's examples assume Mihomo's behavior throughout.

Client and kernel are two separate layers. The kernel handles actual traffic forwarding; the client manages the kernel for you — downloading your subscription, generating the config, launching the kernel process, setting the system proxy, and showing node latency. Switching clients won't change how you think about the kernel, and config files are largely portable between clients, which is exactly why concepts come before software choice.

A complete config has five main pieces: port declarations, the node list (proxies), proxy groups (proxy-groups), rules (rules), and DNS settings. The skeleton looks like this:

mixed-port: 7890        # Combined HTTP/SOCKS listening port
mode: rule              # Run mode: rule / global / direct
log-level: info

proxies: []             # Node list, usually filled by your subscription
proxy-groups: []        # Proxy groups: selectable strategies built from nodes
rules:                  # Rules: matched top to bottom, first hit wins
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

The rule engine follows one hard-and-fast rule: it checks rules from top to bottom, and the first match decides where that connection goes — nothing below it gets checked. So rule order is priority order: specific rules go first, catch-all rules go last. That principle runs through all of Chapter 6.

Proxy groups are the key abstraction that sets Clash apart from simple proxy tools. A rule's target isn't a specific node — it's a group, and the group decides which node to actually use, either picked manually or auto-selected by latency. Subscription updates and node changes happen inside the group, so your rules never need to change. That's what makes a config maintainable long-term.

Last, the ports: by default the kernel only listens on the loopback address 127.0.0.1, and your browser or system proxy has to hand traffic to that port before the kernel does anything. Both the port number and listen address are configurable — you only need to open them up for LAN sharing, covered in Chapter 5.

Too many terms to keep track of?

Terms like mixed-port, GEOIP, and fake-ip each get their own entry in the glossary, organized by category — keep a tab open for quick reference while reading.

CH 2

Choosing a client: platform and needs

Before picking a client, answer three questions: what OS are you on, do you need TUN mode to catch all traffic, and how much time are you willing to spend tweaking config? Answer those and your options narrow fast. Here's a quick-reference table of the clients listed on our downloads page, matching the Downloads page exactly:

PlatformTop pickAlternativeNotes
WindowsClash PlusClash Verge Rev / FlClash / Clash NyanpasuClash for Windows is discontinued, archive only
macOSClash PlusClash Verge Rev / FlClashClashX Meta is discontinued; check chip architecture
AndroidClash PlusClash Meta for Android / FlClash / SurfboardDirect APK installs; match CPU architecture
iOSClash Plus(App Store)Official site clashplus.io, install straight from the App Store
LinuxClash Verge RevFlClashShips deb / rpm packages, bundles Mihomo
Server / routerMihomo kernelNo GUI — runs via command line and config file

Clash Plus is the top pick across the board: it covers Windows, macOS, Android, and iOS, and it's the only option on this list actually listed on the App Store — iOS users don't have a real second choice. Its menu keeps subscriptions, modes, and node selection in one place, defaults are beginner-friendly, and advanced options aren't stripped out, making it a solid first client.

Clash Verge Rev is the main choice for Linux desktops, and the default target for this handbook's Linux examples. It bundles Mihomo directly, ships deb and rpm packages, and supports config overrides, Merge scripts, and service mode — TUN permission handling is also unusually well done. Users who want to dig into config detail will appreciate what it exposes.

FlClash is built with Flutter, so its desktop and mobile interfaces are nearly identical — if you switch between phone and computer often and want consistent muscle memory, it's the least friction. Clash Nyanpasu is another actively maintained Windows fork with a snappier interface and feature set close to Verge Rev, a solid backup option.

On Android, besides Clash Plus, Clash Meta for Android stays closest to the kernel's native behavior, with settings that map directly to kernel fields — good if you want to see what's actually happening under the hood. Surfboard takes the lightweight route: import a subscription and go. Clash for Windows and ClashX Meta are both discontinued — existing users can keep running what they have, but new setups shouldn't start there.

Servers and routers don't need a GUI at all — just run the bare Mihomo kernel: one binary plus a config directory is enough to run indefinitely, managed with systemd. Details in Chapters 8 and 9.

Quick recommendation

If you're not sure, follow the first column: Clash Verge Rev on Linux desktop, Clash Plus everywhere else. Start using it now — you can always switch later once your needs are clearer, since config and subscriptions travel with you.

CH 3

Installation and first launch

Grab every installer from its platform's card on the Downloads page. Linux users should confirm their distro and CPU architecture first: most mainstream desktop distros run x86_64 (amd64) — match the architecture tag in the package name, and don't install an arm64 build on an Intel or AMD machine.

Ubuntu / Debian family

Download the .deb package and install it locally with apt — apt resolves and pulls in dependencies automatically, which avoids the dependency headaches you'd get with a plain dpkg install:

sudo apt update
sudo apt install ./clash-verge-rev_amd64.deb

Don't drop the ./ prefix in the command — it tells apt this is a local file, not a package name from a repository. Once installed, you'll find the icon in your app menu, or you can just type the program name in a terminal to launch it.

Fedora family

sudo dnf install ./clash-verge-rev.rpm

dnf handles dependencies the same way. If it flags a missing webkit2gtk-style package, just confirm the install — that's a system library needed for GUI rendering, not a problem with the app itself.

Arch family

# Install locally from a pre-built binary package
sudo pacman -U clash-verge-rev.pkg.tar.zst

# Or build from the AUR (paru shown here)
paru -S clash-verge-rev

The AUR route rolls forward automatically with system updates but takes longer to build; either path produces the same result, so pick whichever fits your workflow.

Other platforms

On Windows, double-click the installer and follow the prompts; on first launch the firewall will ask whether to allow network access — choose Allow, or the kernel won't be able to listen on its port. On macOS, drag the app into Applications; if Gatekeeper blocks the first open, go to System Settings → Privacy & Security and click Open Anyway — and make sure you grab the Apple Silicon or Intel build as appropriate. On Android, install the APK directly and grant "install unknown apps" permission to your browser or file manager once when prompted. On iOS, search the App Store for Clash Plus.

First-launch checklist

Whatever the platform, spend a minute after first launch confirming three things: one, an icon shows up in the tray or status bar, meaning the main process is alive; two, open the client's log view and confirm you see kernel startup output, not a red error; three, find "launch on startup" in settings and enable it if you want it. Linux desktop users whose client offers a "service mode" should install it now — it registers a system service to launch the kernel with the right permissions, which you'll need for TUN mode in Chapter 7.

Crashes right after launch?

Don't reinstall yet. Instant crashes are usually leftover config or permission issues — the troubleshooting notes in Fixing Clash Client Crashes on Launch break it down by crash timing, with matching log locations and fix commands for each case.

CH 4

Subscriptions and config files

A subscription is really just a URL: your provider hosts a node list at that address (usually a full Clash config, or a node list your client can convert), and the client fetches it periodically, saving it as a local config file the kernel then loads. Once you get that "subscription = source of a remote config" relationship, updates, overrides, and troubleshooting dead subscriptions all make sense.

Importing a subscription

The flow is the same everywhere: copy the full subscription link from your provider, open the client's Subscriptions or Profiles page, paste it into the input field, and hit Import or Download. Once it succeeds, a new profile entry appears — enable it, then head to the Proxies page to see your node list. If the node list comes up empty, something failed during download or parsing — don't just retry the same action; work through the troubleshooting steps below instead.

Updating a subscription

Providers rotate nodes over time, so subscriptions need periodic updates. Most clients let you set an auto-update interval (e.g. every 24 hours), or you can hit the update button manually anytime. One gotcha worth knowing: updating a subscription overwrites the local file with the remote content — any custom rules you edited directly into the subscription file will vanish on the next update. The right approach is to use your client's override or Merge feature to keep custom content in a separate file that gets merged in automatically on update, covered in Chapter 9.

Troubleshooting failed imports

When a subscription import fails, check things in order: is the link complete (trailing parameters get truncated more often than you'd think), does opening the link in a browser return plain text instead of a 404 or a webpage, does the provider restrict by User-Agent (some only return a config to Clash-family UAs), and is the returned content valid YAML? The full checklist is in Troubleshooting Clash Subscription Link Failures and Parse Errors.

Where the config file lives

Clients store your subscription inside their own config directory — on Linux, usually under ~/.config or ~/.local/share in a folder named after the client, while the bare kernel defaults to ~/.config/mihomo/config.yaml. Knowing this location matters for two reasons: backups, and being able to inspect the raw file when the client's UI misbehaves, to tell whether the problem is your config or the app.

If you'd rather manage config by hand, you can skip subscriptions entirely: write your own config.yaml, list your nodes under proxies, and import it as a "local file." This gives you the most freedom but demands the deepest understanding of each field — it's best to get comfortable with subscriptions first, then transition gradually.

Your subscription link is a credential

Subscription URLs usually carry a token tied to your account — anyone with the link can use your traffic quota. Never post it on public forums, in screenshots, or in code repositories; if you suspect it's leaked, reset the subscription address with your provider right away.

CH 5

Proxy modes and ports

The kernel has three run modes, set via the mode field. Rule mode is the everyday default: every connection is checked against the rule table, direct traffic stays direct and proxy traffic goes through a proxy, balancing speed and reliability. Global mode sends everything through the proxy exit — handy for quickly checking "is this actually a routing rule problem?", but not something to leave on long-term, since it routes local traffic through an overseas node needlessly, wasting speed and bandwidth. Direct mode sends everything without a proxy — the equivalent of temporarily disabling Clash without quitting the app. Switching between the three modes to compare behavior is one of the fastest ways to isolate a problem.

Ports: where traffic comes in

Mode decides where traffic goes; ports decide how it gets in. Modern configs recommend declaring a single mixed-port (7890 by convention): it accepts both HTTP and SOCKS5 traffic on one port, so browsers, the system proxy, and command-line tools can all point to it — no need to maintain separate port and socks-port settings.

The number one reason "Clash is running but my browser isn't proxied" happens is that traffic never actually reaches this port. The "system proxy" toggle in desktop clients does exactly one thing: point the OS proxy settings at 127.0.0.1:7890. Leave it off, and the kernel just sits there listening with nothing to do. GNOME users can check this under Settings → Network → Network Proxy, KDE under System Settings → Network → Proxy — both should show the loopback address and port number.

Terminal apps ignore the system proxy

A lot of command-line tools on Linux (curl, git, package managers) don't read the desktop environment's proxy settings at all — they only check environment variables. To proxy the current terminal session temporarily:

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

Adding this to ~/.bashrc makes it permanent, but a shell function you toggle on demand is usually better — it avoids every terminal request hanging once the proxy goes offline. To confirm it's working: curl -I https://www.google.com should return headers quickly.

LAN sharing and port conflicts

Listening only on 127.0.0.1 by default means only the local machine can use the proxy. Set allow-lan to true and open up the bind address, and other devices on the same LAN — phones, streaming boxes — can treat this machine as their proxy server. For the full setup, firewall rules, and security tradeoffs, see Sharing a Clash Proxy Over LAN with mixed-port. Another common issue is an address already in use error at startup — something else is already holding port 7890. See Fixing Clash Port-in-Use Errors for the full fix. After changing mixed-port, remember to update the port everywhere else too — system proxy settings and environment variables — or you'll end up with the confusing "some apps work, some don't" scenario.

CH 6

Rule-based routing: syntax and organization

Rule-based routing is the heart of Clash. Each rule has three parts: type,match,target — the target can be a proxy group, or the built-in DIRECT or REJECT. The rule from Chapter 1 applies here too: rules match top to bottom, first hit wins. Common rule types:

TypeMatches againstExample
DOMAINExact domain matchDOMAIN,ap.example.org,PROXY
DOMAIN-SUFFIXDomain plus all subdomainsDOMAIN-SUFFIX,github.com,PROXY
DOMAIN-KEYWORDDomain contains keywordDOMAIN-KEYWORD,google,PROXY
IP-CIDRTarget IP falls in a subnetIP-CIDR,192.168.0.0/16,DIRECT,no-resolve
GEOIPIP geolocation databaseGEOIP,CN,DIRECT
PROCESS-NAMEProcess name that initiated the connectionPROCESS-NAME,steam,DIRECT
MATCHCatch-all (matches anything)MATCH,PROXY

Two details worth calling out. First, IP-based rules trigger DNS resolution: if a connection's target is still a domain name, the kernel has to resolve it to an IP before it can check against IP-CIDR, which can add latency or leak the lookup. Adding no-resolve to rules meant purely for internal subnets — so they only match connections that were already IPs — is standard practice. Second, MATCH must be the last rule: it's the catch-all for anything nothing else matched, and whatever group it points to decides where unfamiliar traffic ends up by default.

Proxy groups: where rules point

Rules point to a group, not a node, and the group type decides the selection strategy: select for manual picking, url-test for automatic latency testing, fallback to try nodes in order until one works, load-balance to spread requests across multiple nodes. Groups can nest inside each other too — a manual group containing an auto-test group inside it is the most common setup: leave it on auto most of the time, switch to manual when you need to:

proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - AUTO
      - DIRECT
  - name: AUTO
    type: url-test
    url: https://www.gstatic.com/generate_204
    interval: 300
    proxies: []        # Subscription nodes are usually injected via a provider

rules:
  - DOMAIN-SUFFIX,openai.com,PROXY
  - DOMAIN-KEYWORD,github,PROXY
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

These five rules form a minimal, ready-to-use skeleton: the first two send domains that clearly need a proxy into the PROXY group, the third allows local network traffic through, the fourth sends IPs geolocated to mainland China direct, and the last one catches everything else through the proxy. Extending it day to day just means inserting more specific domain rules above these.

One maintenance habit worth repeating: don't write custom rules directly into the subscription file (the next update will wipe them out) — inject them via your client's override mechanism, placed before the subscription's own rules. Rules closer to the top take priority, so "my rules first, subscription rules in the middle, GEOIP and MATCH at the bottom" is a stable layout. GEOIP matching relies on a local database, which will misjudge locations if it goes stale — see Chapter 8 for how to update it.

CH 7

TUN mode: catching all traffic

The system proxy has a built-in limitation: it's just a "suggestion" that applications can choose to follow or ignore. Browsers respect it; plenty of games, chat apps, and anything running over UDP simply don't check proxy settings at all. TUN mode takes a different approach: the kernel creates a virtual network interface and, with matching routing rules, redirects the whole system's outbound traffic through it — apps have no idea it's even happening. From their point of view, the network just looks like this. If you want every app routed with no exceptions, TUN is the answer.

Example configuration

tun:
  enable: true
  stack: system          # Options: system / gvisor / mixed
  auto-route: true       # Automatically configure the routing table
  auto-detect-interface: true
  dns-hijack:
    - any:53             # Intercept DNS queries sent to port 53

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 119.29.29.29

Breaking it down: stack selects the virtual interface's protocol stack implementation — system relies on the OS and performs well, gvisor is a userspace implementation with fewer compatibility issues, and mixed splits the difference. On Linux, start with system. auto-route and auto-detect-interface handle adding and removing routes automatically, so traffic goes through the virtual interface while the kernel's own outbound traffic still uses the physical interface — skip these and you'll be maintaining routes by hand, which is an easy way to lock yourself out of the network.

Why TUN has to handle DNS itself

TUN only sees IP-layer traffic — if DNS resolution still happens at the OS level, the kernel only ever sees raw IPs and loses the ability to route by domain, which is why dns-hijack intercepts DNS queries too. fake-ip goes one step further: the kernel returns a fake IP from a reserved range for every domain lookup, the app connects using that fake IP, and the kernel reverse-maps it back to the domain to run rule matching — skipping a real DNS lookup and cutting latency. The tradeoff is that a handful of apps that validate IPs directly may misbehave; switch to redir-host mode or add a fake-ip-filter exception for those domains.

Permissions on Linux

Creating a virtual interface and modifying routes requires CAP_NET_ADMIN. Desktop clients make this painless via "service mode": the client registers a system service that launches the kernel with elevated privileges, and TUN becomes a single toggle in the UI. If you're running the bare kernel, you can use setcap to grant the binary that capability directly, skipping sudo every time:

sudo setcap 'cap_net_admin,cap_net_bind_service=+ep' /usr/local/bin/mihomo

Three common pitfalls: first, running TUN and the system proxy at the same time double-processes traffic — just turn off the system proxy toggle. Second, switching networks (unplugging Ethernet, changing Wi-Fi) can cause NetworkManager to rewrite routes and break connectivity — restart TUN to let auto-route rebuild them. Third, if the kernel exits unexpectedly before cleaning up its routes, you can end up with no internet access even after closing Clash — the same "toggle it off and on" or restarting network services fixes it. Once TUN is on, verify it's working by running any command-line tool that doesn't support proxy settings and checking whether its process name shows up in the client's connections view.

Turn it on only when you need it

For mostly browser-based use, the system proxy is enough — TUN gives you full traffic capture but adds real troubleshooting complexity. It's best to get rule mode running smoothly first, then bring in TUN as a single new variable.

CH 8

Daily maintenance: updates, logs, and backups

Once your setup is running, there's not much ongoing maintenance — but a few habits will keep the odds of "it suddenly stopped working" as low as possible.

Three things to update regularly

First, your subscription: turn on auto-update or check it manually once a week — providers won't notify you individually when nodes change. Second, the GeoIP / Geosite databases: the GEOIP,CN,DIRECT rule from Chapter 6 depends on a local database to determine IP location, and a stale one can misroute traffic in either direction — most clients offer a one-click update, and bare-kernel setups can just replace the database files in the config directory and restart. Third, the client itself: upgrade it through whatever installed it — apt if you used apt, rolling updates if you used the AUR. Don't mix installation sources on the same machine; that's a recipe for the classic "uninstall didn't fully clean up, two versions conflicting" mystery.

Get comfortable reading logs

Logs are your first stop when troubleshooting. Setting log-level: info is fine for everyday use; switch it to debug temporarily when digging into a problem, then switch it back once resolved (debug logging is noisy and hurts performance). A few log lines are worth recognizing on sight: dial tcp ... i/o timeout usually points to an unreachable node, connection refused usually means the target port is closed or blocked by a local firewall, and rule-match lines tell you exactly which rule a connection hit and which group it was routed through — when routing doesn't behave as expected, check this line before touching your rules blindly. Line-by-line breakdown in Understanding Clash Log Output.

Backup and recovery

The only thing really worth backing up is the config directory: your subscription address, override files, and custom rules all live there. Include it in your regular backup routine, and restoring is just unpacking it back to the original path on a new machine or after a reinstall. For a bare kernel, one command does it: tar czf mihomo-backup.tar.gz ~/.config/mihomo. For a client, check the config directory path in settings first, then archive it.

Launch on startup

Desktop clients just need the autostart checkbox in settings. On a server, hand the bare kernel to systemd with a unit file:

# /etc/systemd/system/mihomo.service
[Unit]
Description=mihomo daemon
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then sudo systemctl enable --now mihomo registers and starts it in one step, and journalctl -u mihomo -f follows the logs live. Restart=on-failure automatically relaunches the process if it crashes — essential for anything running unattended long-term.

One last general troubleshooting principle: change one thing at a time. If you changed the port, test the port before touching anything else; if you switched nodes, test the node first. Change three settings at once and if something breaks, you'll have no idea which one caused it. For launch failures specifically (crashes, blank windows, kernel won't start), see the breakdown in Fixing Clash Client Crashes on Launch.

CH 9

Going further: from competent to expert

After the first eight chapters, everyday use should be friction-free. This chapter maps out directions for going deeper — each has a clear payoff, so pick whichever matches your needs; you don't need all of them.

Direction one: overrides and config merging

Chapter 4 mentioned that subscription updates overwrite local edits — overrides are the fix: keep custom ports, TUN settings, and private rules in a separate override file that the client merges in automatically every time it loads the subscription. Clash Verge Rev offers two forms — Merge (field-level YAML merging) and scripts (rewriting the final config programmatically). Merge covers the vast majority of cases; scripts are for the genuinely unusual ones. Once you've got overrides working, your personal setup is fully decoupled from your subscription — switch providers or subscriptions and none of your customization is lost.

Direction two: splitting out providers

proxy-providers and rule-providers pull nodes and rules out of the main config into their own remote or local files, each with its own update schedule. Rule sets are especially useful: the community maintains domain lists organized by purpose, and referencing a rule set by name instead of writing out every domain shrinks a rule table from hundreds of lines to a dozen, with much better readability and maintainability.

Direction three: the external control API

Adding external-controller: 127.0.0.1:9090 to your config opens up a full RESTful API — switching nodes, checking connections, and testing latency can all be done via HTTP requests. Pair it with a community web dashboard and you can manage a running kernel entirely from a browser — the standard setup for server deployments, and the best way to understand exactly what a client is doing on your behalf: every button in a client's UI is really just a call to this same API underneath.

Direction four: bare-kernel server deployment

Combine the systemd unit from Chapter 8, the external control API from this chapter, and TUN mode from Chapter 7, and you have a full gateway or software router setup: point your LAN devices at this machine as their gateway, route the whole household through one place, and skip installing anything on individual devices. This touches core routing and DNS infrastructure, so test it in a VM first before going live, and keep a management path into the box that doesn't route through itself.

How to use these resources going forward

Suggested order: check the glossary first for concept questions (organized into kernel/client, proxy protocols, rules and routing, network and ports, and config fields); revisit the setup guide for step-by-step flows; work through the relevant troubleshooting article for specific issues; quick common questions are usually already answered in FAQ-style content. This handbook itself will keep getting updated as the kernel and client ecosystem evolves — if anything here doesn't match what you see in your client, trust the client's current UI, but the underlying logic will stay the same.

There's no shortcut to mastery, but there's a clear tell: you can look at a log line and know exactly which part of the pipeline it's from, glance at an unfamiliar config and predict how it'll route traffic, and know which mode to switch to first and which line to check when something breaks. Once you're there, this handbook has done its job — good luck.