Skip to main content
EN

Home / Blog / Config Basics

Extending a subscription with Merge, so your edits survive updates

Config Basics2026-07-091192 words3 min read
Extending a subscription with Merge, so your edits survive updates

When you want to add one rule of your own to a subscription, the intuitive move is to open the config file and edit it. Then the subscription auto-updates overnight and your change is gone.

The correct approach is the extended config (Merge): keep your changes in a separate file that gets merged in every time the subscription is loaded.

How the mechanism works

How the final config is assembledDownload the subscriptionthe original config.yamlRead the extended configthe merge file you wroteMerge by the rulesprepend goes first, append goes lastProduce the runtime configwhat the core actually usesRepeat on every subscription updateyour changes always survive
The original subscription file is never touched; your changes live in a separate file

Where to find it in Clash Verge: Profiles page → "Global Extended Config" at the top right, or ⋯ → Extended Config on a specific profile card (which applies to that subscription only).

Three kinds of operation

prepend-*: insert at the top

prepend-rules:
  - DOMAIN-SUFFIX,mycompany.com,DIRECT
  - DOMAIN-SUFFIX,example.com,🚀 Select

Because rules match top to bottom, prepend rules have the highest priority and override any judgement the subscription made.

This is the standard way to correct a routing mistake.

append-*: add at the end

append-rules:
  - DOMAIN-SUFFIX,slow-site.com,DIRECT

Rules appended after MATCH never fire, because MATCH catches everything. So append-rules has limited real use; the append forms are mainly for proxy-groups and proxies.

Overriding a top-level field directly

Fields written without a prefix replace the subscription's field of the same name:

mixed-port: 7899
mode: rule
log-level: warning
ipv6: false
unified-delay: true
tcp-concurrent: true

The fields you can use

FieldMeaning
prepend-rules / append-rulesRules
prepend-proxies / append-proxiesNodes
prepend-proxy-groups / append-proxy-groupsPolicy groups
rule-providersRule sets (merged with existing ones)
proxy-providersNode providers
Top-level sections such as dns / tun / snifferWhole-section replacement

A collection of useful snippets

1. Correcting a routing mistake

The most common case: a site is taking the wrong route.

prepend-rules:
  # force through the proxy
  - DOMAIN-SUFFIX,anthropic.com,🚀 Select
  - DOMAIN-SUFFIX,openai.com,🚀 Select
  # force direct (so a foreign IP does not trip fraud checks)
  - DOMAIN-SUFFIX,icbc.com.cn,DIRECT
  - DOMAIN-SUFFIX,alipay.com,DIRECT
  - DOMAIN-SUFFIX,12306.cn,DIRECT
  # intranet
  - DOMAIN-SUFFIX,mycompany.com,DIRECT
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve

2. Adding a policy group of your own

prepend-proxy-groups:
  - name: "🔧 My group"
    type: select
    proxies: ["DIRECT", "🚀 Select", "♻️ Auto"]

prepend-rules:
  - DOMAIN-SUFFIX,some-site.com,🔧 My group

3. Adding your own server

You have a machine of your own alongside the subscription:

prepend-proxies:
  - name: "My VPS"
    type: trojan
    server: my.example.com
    port: 443
    password: "pwd"
    udp: true

prepend-proxy-groups:
  - name: "🏠 Self-hosted"
    type: select
    proxies: ["My VPS", "DIRECT"]

Note that a newly added node does not automatically join the policy groups already in the subscription. To make it appear in the main select group, either override that group's definition or use Mihomo's include-all so the group collects it automatically.

4. Global performance settings

unified-delay: true      # unified latency calculation, comparable across protocols
tcp-concurrent: true     # concurrent handshakes for multi-IP domains
find-process-mode: strict  # enables PROCESS-NAME rules
global-client-fingerprint: chrome   # present a Chrome TLS fingerprint
profile:
  store-selected: true   # remember the node you picked by hand
  store-fake-ip: true    # cache fake-ip mappings across restarts

store-selected: true is genuinely useful — without it, every config reload resets your manual node choice to the default.

5. Ad blocking

rule-providers:
  my-reject:
    type: inline
    behavior: domain
    payload:
      - "+.doubleclick.net"
      - "+.googlesyndication.com"
      - "+.adservice.google.com"

prepend-rules:
  - RULE-SET,my-reject,REJECT

6. Forcing BitTorrent traffic direct

Many providers forbid BitTorrent traffic, and routing it through them risks your account:

prepend-rules:
  - PROCESS-NAME,qbittorrent.exe,DIRECT
  - PROCESS-NAME,Transmission.exe,DIRECT
  - PROCESS-NAME,aria2c.exe,DIRECT
  - DST-PORT,6881-6889,DIRECT

Process rules need find-process-mode: strict to work at all.

7. Enabling domain sniffing

Some traffic arrives with only an IP and no domain (clients that connect to addresses directly). Sniffing recovers the name from the TLS handshake, so domain rules become usable again:

sniffer:
  enable: true
  force-dns-mapping: true
  parse-pure-ip: true
  sniff:
    HTTP:
      ports: [80, 8080-8880]
      override-destination: true
    TLS:
      ports: [443, 8443]
    QUIC:
      ports: [443, 8443]
  skip-domain:
    - "+.push.apple.com"
    - "+.apple.com"

Merge order and conflicts

The order the final config is built in11. The subscription's original configthe base22. The global extended configapplies to every subscription33. A single subscription's extended configapplies only to that one, higher priority44. Temporary interface actionsthe node you switched to by hand
Later layers override earlier ones; prepend fields insert rather than replace

If both the global extension and a per-subscription extension define prepend-rules, both sets take effect, with the per-subscription ones placed first.

Debugging an extended config

Look at the merged result

Clash Verge writes the effective configuration to a runtime file. ⋯ → Open File on a profile card shows the original subscription; to see the merged result, look in the config directory for clash-verge.yaml or runtime.yaml (the name varies slightly by version).

Search for the rule you added; finding it means the merge worked.

When the config fails to load

Common mistakes in an extended configA tab was used for YAML indentation — it must be spacesA referenced group name does not match the subscription (emoji, spaces, capitalisation)prepend-rules was written as prepend_rules with an underscoreA policy named in a rule does not exist — this fails the entire configThe dns section was written only partially — whole-section replacement then loses the original settings

When something breaks, clear the extended config entirely, confirm the subscription itself loads, then add your sections back one at a time to find the culprit.

About Script mode

Besides Merge, some versions also support processing the config with JavaScript:

function main(config) {
  // add a DIRECT option to every select group
  config["proxy-groups"].forEach(g => {
    if (g.type === "select" && !g.proxies.includes("DIRECT")) {
      g.proxies.push("DIRECT");
    }
  });
  // insert a rule
  config.rules.unshift("DOMAIN-SUFFIX,example.com,DIRECT");
  return config;
}

Script mode is more capable but easier to get wrong — a single exception fails the whole config. If Merge can do it, use Merge.

In short

  • Never edit the downloaded subscription file directly; use the extended config
  • prepend-rules is the standard way to fix routing, with the highest priority
  • Top-level fields replace whole sections — write dns and you must write all of it
  • store-selected: true is worth adding, so reloads do not lose your manual choice
  • Group names must match the subscription exactly, emoji included

Related: the YAML structure explained and the rule type reference.


Related docs