Sometimes the basis for routing is not "which domain is being visited" but "which program is doing the visiting". For instance: proxying one development tool only, or keeping a BitTorrent client off the proxy entirely.
That calls for process rules.
Prerequisite: enable find-process-mode
This is the most common reason a rule you wrote does nothing.
find-process-mode: strictThree values:
| Value | Behaviour | Cost |
|---|---|---|
off | Never looks up processes; every process rule is dead | None |
strict (recommended) | Looks up only when process rules exist | Low |
always | Looks up on every connection, so the log always names the process | Higher |
The advantage of always is that the "Process" column on the connections page always has data, which is very convenient for diagnosis; the cost is a system process-table lookup for every connection.
Basic syntax
rules:
- PROCESS-NAME,Telegram.exe,🚀 Select
- PROCESS-NAME,qbittorrent.exe,DIRECT
- PROCESS-PATH,/usr/local/bin/curl,🚀 SelectPROCESS-NAME vs PROCESS-PATH
Mihomo also supports PROCESS-NAME-REGEX and PROCESS-PATH-REGEX:
- PROCESS-NAME-REGEX,(?i)^(chrome|msedge)\.exe$,🚀 Select
- PROCESS-PATH-REGEX,(?i).*\\JetBrains\\.*,🚀 SelectFinding the process name
Method 1: read it off the connections page (fastest)
Set find-process-mode to always, open the Connections page in Clash Verge, and let the program touch the network once. The "Process" column then shows you the exact name.
This is the reliable method — no guessing, just copy what you see.
Method 2: Task Manager / Activity Monitor
Windows: Task Manager → Details tab; the "Name" column is the process name.
macOS: Activity Monitor → double-click the process → look at "Process Name".
Linux: ps -e -o comm= lists every process name.
Method 3: the command line
# Windows: list every process currently using the network
Get-NetTCPConnection -State Established |
Select-Object -Property OwningProcess -Unique |
ForEach-Object { (Get-Process -Id $_.OwningProcess).ProcessName }# macOS / Linux
lsof -i -P -n | awk '{print $1}' | sort -uPractical uses
1. Forcing BitTorrent clients direct
Many subscription providers forbid BitTorrent traffic in their terms, and routing it through them risks your account. It also wastes your data allowance.
prepend-rules:
- PROCESS-NAME,qbittorrent.exe,DIRECT
- PROCESS-NAME,Transmission.exe,DIRECT
- PROCESS-NAME,aria2c.exe,DIRECT
- PROCESS-NAME,BitComet.exe,DIRECT
- PROCESS-NAME,uTorrent.exe,DIRECT
- PROCESS-NAME,deluge.exe,DIRECTBelt and braces with a port rule:
- DST-PORT,6881-6889,DIRECT2. Sending development tools through the proxy
prepend-rules:
- PROCESS-NAME,git.exe,🚀 Select
- PROCESS-NAME,node.exe,🚀 Select
- PROCESS-NAME,python.exe,🚀 Select
- PROCESS-NAME,docker.exe,🚀 Select
- PROCESS-NAME,go.exe,🚀 Select3. Sending game platforms to a specific node
prepend-proxy-groups:
- name: "🎮 Gaming"
type: fallback
include-all: true
filter: "(?i)IPLC|dedicated|game"
interval: 300
prepend-rules:
- PROCESS-NAME,steam.exe,🎮 Gaming
- PROCESS-NAME,Battle.net.exe,🎮 Gaming
- PROCESS-NAME,EpicGamesLauncher.exe,🎮 Gaming4. Forcing regional software direct
Some applications misbehave through a proxy (region restrictions, fraud checks):
prepend-rules:
- PROCESS-NAME,WeChat.exe,DIRECT
- PROCESS-NAME,DingTalk.exe,DIRECT
- PROCESS-NAME,QQ.exe,DIRECT
- PROCESS-NAME,cloudmusic.exe,DIRECT
- PROCESS-NAME,BaiduNetdisk.exe,DIRECT5. Combining with other conditions
Proxy only when a particular program reaches a particular range:
- AND,((PROCESS-NAME,Telegram.exe),(IP-CIDR,91.108.4.0/22)),🚀 SelectOne program goes through the proxy for overseas destinations and direct locally:
- AND,((PROCESS-NAME,chrome.exe),(GEOIP,CN)),DIRECT
- PROCESS-NAME,chrome.exe,🚀 SelectMind the order: the more specific combined rule has to come before the plain one.
Performance considerations
Process rules are much more expensive than domain rules. Every match requires:
Optimisation advice:
Platform support
| Platform | Supported | Notes |
|---|---|---|
| Windows | ✅ Fully | Needs the exe name; mind the case |
| macOS | ✅ Fully | May need extra permissions |
| Linux | ✅ Fully | Needs read access to /proc |
| Android | ⚠️ Partially | Per-app proxy is the better tool |
| Router / gateway | ❌ | Traffic comes from other devices, so there is no local process |
Do not use process rules on Android — CMFA and FlClash both offer a graphical per-app proxy that selects by package name, which is both more accurate and less work.
Diagnosing a rule that does nothing
The fastest way to verify: set find-process-mode to always, open the connections page, let the program touch the network, and read the Process column.
- Column empty → the core cannot see the process; check permissions
- Column populated but different from your rule → change the rule to match what is shown
- Column matches, but the Rule column shows a different rule fired → an ordering problem; move yours up with
prepend-rules
In short
find-process-mode: strictis the prerequisite; without it nothing works- Copy the process name off the connections page rather than guessing
- Under the system proxy, command-line traffic never reaches the core, so process rules only affect those tools under TUN
- Use SRC-IP-CIDR for gateway scenarios, where process rules are useless
- Process rules are relatively costly; put them late, and prefer domain rules where possible
Related: the rule type reference and the developer proxy cheat sheet.
Related docs
Syntax, matching behaviour and relative cost for every rule type, what no-resolve actually does, why rule order decides everything, and how to find which rule a connection matched.
Replacing hundreds of hand-written rules with external lists. The difference between the domain, ipcidr and classical behaviors, text versus yaml, how to set the update interval, and what to check when a rule set does nothing.
A complete configuration that serves a corporate VPN intranet, direct local access and proxied overseas services at the same time, covering domains and IP ranges, DNS routing, and the conflicts that come up.