Docs Guide Syntax

Syntax

Mihomo uses YAML as its config file format. Here's a rundown of the syntax rules you'll need when writing your config, including comments, objects/arrays, anchors and references, domain wildcards, and port range syntax.

Basic Rules

YAML is case-sensitive and uses indentation to represent hierarchy. Indentation must use spaces, not tabs — the exact number of spaces doesn't matter, as long as elements at the same level are aligned.

If your editor shows an "indentation looks right but doesn't match" error, chances are a tab character snuck in somewhere — double-check your indentation.

Comments

Everything from # to the end of the line is a comment. The # must be at the start of the line or preceded by a space, otherwise it isn't treated as a comment (e.g. a # inside a URL is unaffected).

config.yaml YAML
port: 7890 # HTTP proxy port
socks-port: 7891
# SOCKS proxy port

Objects & Arrays

Objects are written as key: value, with a space required after the colon. Since YAML is a superset of JSON, you can also write JSON-style syntax directly — all four forms below are exactly equivalent:

Multi-Line Format (Most Common)
YAML Multi-line
tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
Single-Line JSON Format
YAML Single-line
tun: { enable: true, stack: system, auto-route: true, auto-detect-interface: true }

Arrays are written as lines starting with -, and also support the single-line JSON format a: [b, c, d], which is equivalent to the multi-line array:

YAML Array
a:
  - b
  - c
  - d

Anchors & References

& tags a block of config with an anchor, * references that anchor, and << merges the anchor's content into the current object. When writing multiple proxy providers or rule providers, you can write shared fields once and reuse them via anchors, saving a lot of repeated code.

config.yaml YAML
p: &p
  type: http
  interval: 3600
  health-check:
    enable: true
    url: https://www.gstatic.com/generate_204
    interval: 300

proxy-providers:
  provider1:
    <<: *p
    url: ""
    path: ./proxy_providers/provider1.yaml

  provider2:
    <<: *p
    type: file
    path: ./proxy_providers/provider2.yaml

This is equivalent to copying the p anchor's content into both provider1 and provider2. Note that if a field is duplicated during the merge (e.g. provider2 redefines type), your own value takes precedence and won't be overridden by the anchor. Also note that the key name p itself isn't a valid mihomo field — it's only there to hold the anchor, and gets ignored during parsing.

Domain Wildcards

The wildcards described here are specifically for fields like fake-ip-filter and nameserver-policy — they're not the same as DOMAIN-WILDCARD used in routing rules, and the syntax isn't interchangeable.

WildcardMatchesExample
*Matches only a single subdomain level*.baidu.com matches tieba.baidu.com, but not 123.tieba.baidu.com or baidu.com
+Matches any number of levels (prefix form, similar to DOMAIN-SUFFIX)+.baidu.com matches baidu.com, tieba.baidu.com, and 123.tieba.baidu.com all at once
.Matches any number of levels, but not the bare domain itself.baidu.com matches tieba.baidu.com, but not baidu.com

It's a good idea to wrap wildcards in quotes to avoid YAML parsing them as another type:

config.yaml YAML
fake-ip-filter:
  - ".lan"
  - "xbox.*.microsoft.com"
  - "+.xboxlive.com"
  - localhost.ptlogin2.qq.com

Importing Domain Sets

Some fields (like fake-ip-filter) support importing a rule-set or geosite set directly, using the syntax type:set-name:

The rule-set option here only supports rule providers with a domain or classical behavior.

config.yaml YAML
fake-ip-filter:
  - "rule-set:xxx"
  - "geosite:xxx"

Port Ranges

Use - for a port range, and / or , to separate multiple ports/ranges — these can be mixed:

Example Port Range
# Matches the ranges 114-514 and 810-1919, plus port 65530 on its own
114-514/810-1919,65530