SagerNet / SagerNet/sing-box

Feature request: optional `hidden` field for outbound groups (like mihomo's proxy-group `hidden`)

Open
#4,483 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
38.1k
Forks
4.6k
Avg merge
19d 15h
Merged PRs (30d)
1

Description

Problem

Since 1.14.0 every non-empty group is shown on the Groups page of the graphical clients (3439be1bb, "Do not hide groups containing only a single item"). Before that, groups with fewer than two items were filtered out on the service side (len(g.Items) < 2 in daemon/started_service.go, previously in experimental/libbox/command_group.go).

Showing single-item groups by default is a reasonable change (#4292 asked for exactly that). But some single-item groups are intentional. A selector option's display name is the tag of the outbound it references, so the only way to give an option a short readable label is to wrap the real outbound into a single-item selector whose tag is the label. In my config I use such wrappers to expose long technical outbound tags under short names:

{ "tag": "Region", "type": "selector", "outbounds": ["US", "JP"] },
{ "tag": "US", "type": "selector", "outbounds": ["vless-us-chicago-01"] },
{ "tag": "JP", "type": "selector", "outbounds": ["ss-jp-tokyo-02"] }

Up to 1.13 these wrapper groups were invisible automatically; on 1.14 each of them is rendered as its own degenerate one-item card, cluttering the group list.

Proposed behavior

Add an optional hidden field (boolean, default false) to group outbounds (selector, urltest) — same as mihomo's proxy-group hidden (adapter/outboundgroup/parser.go, reported for all group types via the Clash API and respected by dashboards such as metacubexd/zashboard):

{ "tag": "US", "type": "selector", "outbounds": ["vless-us-chicago-01"], "hidden": true }
  • hidden groups are skipped in daemon.(*StartedService).readGroups(), so graphical clients do not render their cards;
  • the Clash API GET /proxies response includes "hidden": true for them (mihomo-compatible), so external dashboards can filter them out;
  • nothing else changes: a hidden group can still be used in rules, as detour, and as a member of other groups (its tag still appears as an option label inside the parent), and its selection is still cached.

This keeps the new 1.14 default (nothing is hidden implicitly) while giving config authors explicit control.

References
  • Behavior change: 3439be1bb, #4292

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with daemon/started_service.go and trace how selector and urltest groups are read for the Groups page. Then inspect the Clash API GET /proxies path and the outbound group configuration handling. Done means hidden defaults to false, hidden groups are omitted from graphical group output, the API reports hidden, and hidden groups remain usable elsewhere.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, networking
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
66/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.