Policy Group

A policy group may contain multiple policies. It can be a proxy server, another policy group or a built-in policy (DIRECT, REJECT and its variants, or PROXY).

There are seven group types: select, url-test, fallback, load-balance, random, relay and ssid (also written subnet). Section [Proxy Group] declares policy group. The type smart is also accepted and is treated as url-test. A group of any other type — Surge's external, or a type Chute does not know — keeps its members and runs as a select group, with a notice in the log, rather than being rejected.

Manual Select Group

Select which policy will be used on the user interface.

SelectGroup = select, ProxyHTTP, ProxyHTTPS, DIRECT, REJECT

Optional parameters: default= (the member selected at first — its name, or its index counting from 0; Shadowrocket's select= and policy-select-name= mean the same), policy-provider:Name (import members from a proxy provider), filter= / exclude-filter= (regexes applied to provider-supplied members), and HIDDEN=true. Every group type except ssid also takes the subscription and membership parameters.

In the iOS version, the Today widget switches the policy of the first three select groups that are not hidden; how many it shows is set with Use Today Widget to Select Group in the app. In the macOS version, you may switch the policy in the menu bar menu.


Auto URL Test Group

Automatically select which policy will be used by benchmarking the latency to an URL.

AutoTestGroup = url-test, ProxySOCKS5, ProxySOCKS5TLS, url = http://www.google.com/generate_204

Parameters

url: Optional

Chute sends a plain HTTP GET for the URL, through each policy, to port 80 of the URL's host: an https:// scheme or a port in the URL is ignored, so use an http:// URL served on port 80. The test only cares about whether receiving a response data, even if the response is a HTTP error. A member with its own test-url= is probed at that URL instead. When omitted, the default probe URL http://www.gstatic.com/generate_204 is used. proxy-test-url in [General] replaces this default for every group that omits url.

interval: Optional, s (Default: 600s).

How often the policies are retested. A global 1-second timer drives automatic retests every interval seconds, whether or not the policy group is being used. There are two exceptions: a group with lazy=true does not start testing until it is first used, and testing pauses while the group stays idle for longer than idle-timeout. 0 is the same as leaving it out.

tolerance: Optional, ms (Default: 100ms).

Every round tests all the members at once. When the first member to answer is not the one in use, Chute waits up to tolerance milliseconds longer — never past the round's timeout — for the member in use: if it answers within that window it keeps its place, otherwise the group switches to the member that answered first. Until a round has picked a member, the first member to answer is taken directly; a round in which no member answers changes nothing. 0 is the same as leaving it out.

timeout: Optional, s (Default: 5s).

Abandon a policy if not finished in timeout. When timeout is omitted or 0, test-timeout in [General] applies if it is set.

lazy: Optional (true/false, Default: false).

When enabled, policies are only tested on first use rather than on startup.

max-failed-times: Optional (Default: 0, disabled).

Number of consecutive test failures after which a policy is considered unhealthy. This option is only effective for load balance groups, where unhealthy policies are excluded from selection. For url-test and fallback groups the failure count is tracked but does not affect selection. When unset (0), test failures never exclude a policy.

expected-status: Optional (Default: empty).

expected-status=204

Only a reply with an expected status counts as a success: a single code (204), a range (200-299) or a /-separated list of both (200/204/300-399). A policy that replies with another status drops out of that round, which counts as a failure. A value that is none of these is ignored with a warning, and then any reply is accepted. Effective in url-test groups.

idle-timeout: Optional, s.

idle-timeout = 120

When the policy group has not been used (no new connection drew a policy from it) for longer than this duration, the periodic URL tests are paused. Testing resumes once the group is used again. No connections are ever closed by this option.

Also supported: HIDDEN=true, filter=, exclude-filter=, policy-provider:Name.


Fallback Group

Select an available policy by priority. The availability is tested by accessing an URL, just like an auto URL test group. The policy defined in the front has a high priority. Every round tests all the members at once, and the group uses the first member, in the order written, that answered the latest round. Before any round has finished, and after a round in which no member answered, it uses the first member. A round's answers take effect when the round is over — as soon as every member has answered, otherwise when its timeout runs out — so the group never changes members partway through a round. It switches only when a round changes the member in use: the Policy Group Primary Changed notification then names the member in use before and after the switch, and interrupt-exist-connections closes the connections of the member it left.

FallbackGroup = fallback, ProxySOCKS5, ProxySOCKS5TLS, url = http://www.google.com/generate_204

Parameters

url: Optional

Specify which URL will be tested; as in the url-test group, the probe is a plain HTTP GET to port 80 of the URL's host, and a member with its own test-url= is probed at that URL instead. When omitted, the default probe URL http://www.gstatic.com/generate_204 is used. proxy-test-url in [General] replaces this default for every group that omits url.

interval: Optional, s (Default: 600s).

How often the policies are retested. Same semantics as the Auto URL Test Group, except that idle-timeout — like expected-status — is url-test only: a fallback group has no idle pause and keeps testing on the interval.

timeout: Optional, s (Default: 5s).

Abandon a policy if it is not finished until timeout. When timeout is omitted or 0, test-timeout in [General] applies if it is set.

lazy / max-failed-times: Optional.

Same as the Auto URL Test Group. Also supported: HIDDEN=true, filter=, exclude-filter=, policy-provider:Name.


SSID Group

Select a policy according to the current network — its Wi-Fi name, access point, interface type or router. The type may also be written subnet, Surge's current name.

SSIDGroup = subnet, default = ProxyHTTP, cellular = ProxyHTTP, "Home WiFi" = DIRECT, SSID:Office* = ProxySOCKS5, TYPE:WIRED = DIRECT, ROUTER:192.168.1.1 = DIRECT

Parameters

default: Required.

The policy when no matched SSID option has been found.

cellular: Optional.

The policy under cellular network. If not provided, the default policy will be used. More precisely, it is used whenever the device is not on Wi-Fi and no member matched.

default is required. Members are <selector> = <policy> pairs, checked in order; the first match wins. A selector is a network name (quote it when it contains spaces or a colon), SSID:<name>, BSSID:<address>, TYPE:WIFI / TYPE:CELLULAR / TYPE:WIRED or ROUTER:<gateway address>; names may use the * and ? wildcards. MCCMNC: is accepted but never matches. On Apple TV the group always uses default.


Load Balance Group

Distribute requests across multiple proxies using a load balancing strategy.

LBGroup = load-balance, ProxySOCKS5, ProxyHTTPS, url = http://www.google.com/generate_204, strategy = round-robin

Parameters

strategy: Optional (Default: round-robin)

Specify the load balancing strategy:

Strategy Description
round-robin Distribute requests evenly across all proxies in turn
consistent-hashing Route the same hostname consistently to the same proxy
sticky-sessions Keep reusing the last selected proxy for all connections; the sticky choice is global (not per-client) and expires 600 seconds after it was made

url: Optional

url = http://www.google.com/generate_204

Chute sends a plain HTTP GET to port 80 of the URL's host to test proxy availability. When omitted, the default probe URL http://www.gstatic.com/generate_204 is used. Test results only affect selection when max-failed-times is greater than 0; with the default 0, unhealthy proxies are not excluded. proxy-test-url in [General] replaces this default for every group that omits url.

interval: Optional, s (Default: 600s).

interval = 300

How often to re-test proxy availability. 0 is the same as leaving it out.

timeout: Optional, s (Default: 5s).

timeout = 3

Timeout for the availability test request. When timeout is omitted or 0, test-timeout in [General] applies if it is set.

lazy: Optional (true/false, Default: false).

Same as the Auto URL Test Group: testing does not start until the group is first used.

max-failed-times: Optional (Default: 0, disabled).

max-failed-times = 3

Number of consecutive test failures after which a proxy is marked unhealthy and excluded from load balancing. With the default 0, test results never exclude a proxy. If every proxy is unhealthy, all proxies are used again.

HIDDEN: Optional (true/false, Default: false).

HIDDEN = true

When enabled, the apps do not list the policy group: Chute Mac's menu bar menu and the main window's Proxies tab, Chute iOS and its Today widget, Chute tvOS, Chute Android, Chute Dashboard and the Web Console all leave it out. Rules and other groups use it as usual. A hidden group that is currently selected — the policy Global mode is using, for instance — is still listed, and checked, so you can see what is in use. When the HTTP Control API points Global at a select group, the apps' Global lists — which otherwise hold no select groups — list that group too, and check it. The HTTP Control API still returns every group, each with "hidden": true or false.

The key is conventionally written in uppercase, but it is matched case-insensitively, so hidden=true also works. Also available on select, url-test, fallback and ssid groups.

Note: The interrupt-exist-connections parameter is now a global [General] setting. See Misc Options.


Random Group

Shadowrocket's random group: every new connection picks one member at random.

RandomGroup = random, ProxyA, ProxyB, ProxyC

Each connection chooses among the members with equal chance, independently of the connections before it. UDP chooses only among the members that relay UDP; when none does, the group relays no UDP and udp-policy-not-supported-behaviour applies. Members are written as in a select group, policy-provider: references included, and a member keeps its own underlying-proxy. There is no selection to change: the Web Console and the HTTP Control API list its members but refuse a selection change, and default= has no effect. HIDDEN=true hides it as it does other groups.


Relay Group

Chains its members, in the order written, into one path. The first member is dialled directly (or through its own underlying-proxy), each later member is reached through the members before it, and the last member connects to the destination — the order Clash and mihomo use.

RelayGroup = relay, Entry, Exit

A connection through RelayGroup goes from the device to Entry, from Entry to Exit, and from Exit to the destination; the destination sees it coming from Exit.

A relay group needs at least two members, written as in a select group; a member may be a policy or another group. The first member may use any protocol. Every later member reaches its server through the members before it, so it must be one that can be chained — see underlying-proxy; if a member, or the current pick of a member group, cannot be, the connection is refused and logged, never sent directly. A later member's own underlying-proxy is ignored inside the relay: the members before it are its path. A relay group among the members stands for its own members in that place, up to 8 hops in all; if a member group's current pick is another relay group, its hops cannot be spliced in when the connection is made, so the connection is refused and logged. The members after the first are reachable only through the ones before them, and Chute does not ping them directly. WireGuard, AmneziaWG and SSH keep one connection over their own upstream, so they can be the first member but not a later one. A relay group carries UDP when its last member's UDP can go through the members before it, by the rules of underlying-proxy: a VMess, VLESS, Trojan or AnyTLS exit over any members, a Shadowsocks, SOCKS5, Hysteria2, TUIC or MASQUE exit only when the members before it carry UDP. Otherwise UDP sent to it follows udp-policy-not-supported-behaviour. It has no health check and nothing to select.


Subscription and Membership Parameters

These parameters work on select, url-test, fallback and load-balance groups (underlying-proxy on every group except SSID groups):

[Proxy Group]
Airport = select, policy-path=https://example.com/nodes.list, update-interval=86400, policy-regex-filter="^(HK|JP) \d{1,2}$"
Everything = url-test, include-all-proxies=true
Streaming = fallback, HK-Node, include-other-group=Airport, policy-regex-filter="^HK"
  • policy-path=<URL> (Surge) fills the group from a subscription: Chute turns it into a hidden proxy provider with format=auto, whose interval is the group's update-interval (default 86400). policy-regex-filter= keeps only the nodes whose names match. The hidden provider appears in no provider list and is not written to the file; the group line is saved as you wrote it.
  • include-all-proxies=true adds every policy of the [Proxy] section, and include-other-group=<group> (repeatable) adds the members of another group, recursively. Both are expanded once the whole configuration is read; a loop is cut off, and an unknown group name only produces a notice. The members you listed yourself are what gets saved. include-other-group brings over the other group's members and providers, not its filters: the nodes a provider supplies are filtered by the including group's own filter=, policy-regex-filter= and exclude-type=, which is why Streaming above sets one — without it, Streaming would take every node of Airport's subscription.
  • exclude-type=Shadowsocks|Vmess keeps whole protocols out of the members a provider contributes — the usual reason being a client that cannot carry UDP over them. Names are separated by |, matched case-insensitively, and read by alias, so ss and Shadowsocks name the same type. It does not touch the members you listed yourself, and it is written back when the configuration is saved.
  • underlying-proxy=<policy> (Surge Mac 6.9 / iOS 5.22) sends the group's proxy members through one upstream: every proxy policy listed directly or brought in by policy-path, include-all-proxies or include-other-group appears in the group as a derived policy, "Member (via Upstream)", which connects through that upstream in place of the member's own underlying-proxy. The original policy is used as before everywhere else. Members that are policy groups are not affected (they may set their own underlying-proxy), and DIRECT and REJECT stay as they are. If the group is chained through itself, connections through it are refused and logged.
  • external-policy-modifier="key=value,…" (Surge) overrides these parameters on every policy imported through policy-path, as in external-policy-modifier="test-url=http://apple.com/,tfo=true". It only touches policies from the subscription; to send the whole group through an upstream, use underlying-proxy above.
  • Parameters are split at commas outside quotes, so a regex containing a comma — like the one above — must be quoted.
  • Parameters Chute does not know, such as evaluate-before-use, no-alert, icon-url or persistent, are kept and written back, but have no effect.

Proxy Provider

Proxy providers allow you to import proxy lists from external sources (files or URLs). Defined in the [Proxy Provider] section:

[Proxy Provider]
MyProvider = url=https://example.com/proxies.yaml, interval=3600

Parameters

Parameter Required Description
type No http (default) or file. A rule set can also be inline, in a [Ruleset <name>] section; a proxy provider has no inline form, and type=inline written here contributes no members
url Yes for type=http URL to fetch proxy list from
path Yes for type=file Local file path for proxy list
interval No Refresh age in seconds (Default: 86400). Each time the policies load — at engine start and on a configuration reload — a cached copy older than this is fetched again in the background; nothing is refreshed while the engine runs. 0 never refreshes a cached copy, but an initial fetch still happens when no cache exists; a negative value is never fetched at all, leaving the provider inactive unless a last-good cache exists
format No Payload format: native or surge reads a list of [Proxy]-style lines; auto or no value picks by content; mihomo-yaml reads a YAML document and falls back to the line list when the payload is clearly one
filter No Filter regex to include only matching proxy names
exclude-filter No Filter regex to exclude matching proxy names
underlying-proxy No Every node of the provider connects through this policy or group (mihomo's override: dialer-proxy), in place of the node's own upstream. See underlying-proxy
policy No The policy or group the list is downloaded through (mihomo's proxy:); for a group, its pick when the download starts. Without it, or with DIRECT, the list is fetched directly; a name that is not defined refuses the download rather than fetching it directly

A YAML payload is a mihomo-style document with a proxies: (or payload:) list; a line-list payload has one [Proxy]-style line per policy, such as Name = trojan, example.com, 443, password=….

Proxy providers are referenced from policy groups with the policy-provider: prefix:

[Proxy Group]
MyGroup = select, policy-provider:MyProvider
S. Smart Rabbit LLC © All Rights Reserved            updated 2026-09-29 21:57:05

results matching ""

    No results matching ""